Czytałem sporo informacji o sieciach neuronowych i szkoliłem je z odwrotnąpropagacją, głównie this Coursera course, z dodatkowym czytaniem z here i here. Pomyślałem, że mam dość prostą znajomość podstawowego algorytmu, ale moja próba zbudowania przeszkolonej sieci neuronowej nie została opracowana i nie jestem pewna dlaczego.Problemy z wdrożeniem metody propagacji sieci neuronowej
Kod jest w C++ bez wektoryzacji jak na razie.
Chciałem zbudować proste 2 neurony wejściowe, 1 ukryty neuron, 1 neuron wyjściowy, sieć do modelowania funkcji AND. Aby zrozumieć, w jaki sposób koncepcje zadziałały, zanim przejdę do bardziej złożonego przykładu Mój kod propagacji do przodu zadziałał, gdy ręcznie zakodowałem w wartościach wag i błędów.
float NeuralNetwork::ForwardPropagte(const float *dataInput)
{
int number = 0; // Write the input data into the input layer
for (auto & node : m_Network[0])
{
node->input = dataInput[number++];
}
// For each layer in the network
for (auto & layer : m_Network)
{
// For each neuron in the layer
for (auto & neuron : layer)
{
float activation;
if (layerIndex != 0)
{
neuron->input += neuron->bias;
activation = Sigmoid(neuron->input);
} else {
activation = neuron->input;
}
for (auto & pair : neuron->outputNeuron)
{
pair.first->input += static_cast<float>(pair.second)*activation;
}
}
}
return Sigmoid(m_Network[m_Network.size()-1][0]->input);
}
Niektóre z tych zmiennych są dość słabo nazwie, ale w zasadzie, neuron-> outputNeuron jest wektorem parach. Pierwszy to wskaźnik do następnego neuronu, a drugi to wartość wagi. neuron-> input jest wartością "z" w równaniu sieci neuronowej, sumą wszystkich wartości * aktywacji + bais. Sigmoid jest podany przez:
float NeuralNetwork::Sigmoid(float value) const
{
return 1.0f/(1.0f + exp(-value));
}
Te dwa wydają się działać zgodnie z przeznaczeniem. Po przejściu przez sieć wszystkie wartości "z" lub "neuron-> wejściowe" są resetowane do zera (lub po wstecznej propagacji).
Następnie trenuję sieć zgodnie z poniższym kodem psudo. Kod treningowy jest uruchamiany wiele razy.
for trainingExample=0 to m // m = number of training examples
perform forward propagation to calculate hyp(x)
calculate cost delta of last layer
delta = y - hyp(x)
use the delta of the output to calculate delta for all layers
move over the network adjusting the weights based on this value
reset network
Rzeczywisty kod jest tutaj:
void NeuralNetwork::TrainNetwork(const std::vector<std::pair<std::pair<float,float>,float>> & trainingData)
{
for (int i = 0; i < 100; ++i)
{
for (auto & trainingSet : trainingData)
{
float x[2] = {trainingSet.first.first,trainingSet.first.second};
float y = trainingSet.second;
float estimatedY = ForwardPropagte(x);
m_Network[m_Network.size()-1][0]->error = estimatedY - y;
CalculateError();
RunBackpropagation();
ResetActivations();
}
}
}
Dzięki funkcji wstecznej propagacji błędów podane przez:
void NeuralNetwork::RunBackpropagation()
{
for (int index = m_Network.size()-1; index >= 0; --index)
{
for(auto &node : m_Network[index])
{
// Again where the "outputNeuron" is a list of the next layer of neurons and associated weights
for (auto &weight : node->outputNeuron)
{
weight.second += weight.first->error*Sigmoid(node->input);
}
node->bias = node->error; // I'm not sure how to adjust the bias, some of the formulas seemed to point to this. Is it correct?
}
}
}
a koszt obliczany przez:
void NeuralNetwork::CalculateError()
{
for (int index = m_Network.size()-2; index > 0; --index)
{
for(auto &node : m_Network[index])
{
node->error = 0.0f;
float sigmoidPrime = Sigmoid(node->input)*(1 - Sigmoid(node->input));
for (auto &weight : node->outputNeuron)
{
node->error += (weight.first->error*weight.second)*sigmoidPrime;
}
}
}
}
I losowy waga i uruchom go na danych s et:
x = {0.0f,0.0f} y =0.0f
x = {1.0f,0.0f} y =0.0f
x = {0.0f,1.0f} y =0.0f
x = {1.0f,1.0f} y =1.0f
Oczywiście, że nie powinny być szkolenia i badania z tymi samymi danymi określonymi ale chciałem tylko uzyskać podstawowe algortithm wstecznej propagacji błędów i działa. Kiedy uruchomić ten kod widzę wagi/uprzedzenia są następujące:
Layer 0
Bias 0.111129
NeuronWeight 0.058659
Bias -0.037814
NeuronWeight -0.018420
Layer 1
Bias 0.016230
NeuronWeight -0.104935
Layer 2
Bias 0.080982
szkolenia zestaw działa, a średni kwadratowy błąd delta [outputLayer] wygląda somthing jak:
Error: 0.156954
Error: 0.152529
Error: 0.213887
Error: 0.305257
Error: 0.359612
Error: 0.373494
Error: 0.374910
Error: 0.374995
Error: 0.375000
... remains at this value for ever...
a ostateczna ciężary wyglądać następująco: (oni zawsze kończy się na roughtly tej wartości)
Layer 0
Bias 0.000000
NeuronWeight 15.385233
Bias 0.000000
NeuronWeight 16.492933
Layer 1
Bias 0.000000
NeuronWeight 293.518585
Layer 2
Bias 0.000000
Zgadzam się, że może to wydawać się dość okrężną drogą uczenia sieci neuronowych, a realizacja jest (u m oment) bardzo nieoptymalny. Ale czy ktoś może wykryć każdy punkt, w którym podaję błędne założenie, albo implementacja lub formuła są błędne?
EDIT
Dzięki do sprzężenia dla wartości polaryzacji, że zatrzymane ich stosowane do warstwy wejściowej i zatrzymał się przepuszczając przez warstwę wejściowe funkcji esicy. Dodatkowo moja funkcja Sigmoid prime była nieprawidłowa. Ale sieć nadal nie działa. Zaktualizowałem błąd i dane wyjściowe powyżej, co będzie teraz.
dlaczego masz tak wiele błędów? Sieć 2-1-1 powinna mieć łącznie 5 parametrów: 2 wagi między wejściowymi neuronami a ukrytym; 1 waga między odchyleniem w warstwie wejściowej i ukrytym neuronem; 1 waga między ukrytą warstwą a wyjściowym neuronem; 1 waga między odchyleniem w ukrytej warstwie a neuronem wyjściowym. Łącznie 5 odważników. Nawet twój kod pokazuje ci - ty i ty bez tych 2 zbędnych uprzedzeń. – lejlot
Dziękuję za pomoc z uprzedzeniami, zobacz moją odpowiedź na galloguille w celu uzyskania dalszych wyjaśnień. Naprawiłem to, ale nadal mam problemy z siecią neuronową, zawsze trenując wagi do wartości w11 (15,385233), w12 (16,492933), w21 (293,518585). Wszystkie uprzedzenia stają się zerowe. Więc oczywiście jest jeszcze inny problem z kodem. – Davors72