Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[c++]Sztuczna sieć neuronowa - Back Propagation

Ostatnio zmodyfikowano 2016-04-05 17:15
Autor Wiadomość
GGG205
Temat założony przez niniejszego użytkownika
[c++]Sztuczna sieć neuronowa - Back Propagation
» 2016-04-04 15:58:22
Cześć! Robię sztuczną sieć neuronową na konkurs, ale mam problem dokładnie z back propagation. Teorię czytałem na tej stronie: http://edu.pjwstk.edu.pl/wyklady/nai/scb/wyklad3/w3.htm

Mam wątpliwości co do działania mojego algorytmu aktualizowania wag i wyznaczania błędów, nie miałem jeszcze pochodnych więc ciężko było mi zrozumieć wzór na gradient. Jest jakaś osoba, która mogła sprawdzić czy kod jest dobrze napisany?

Back Propagation
C/C++
void Network::backProp( vector < double >& targetVal ) {
    /*
    1.Obliczanie kwadratu odchylenia... zestaw wag, dla których funkcja jest najmniejsza X
    -Wzór: odchylenie kwadratu 0.5*(t-y)^2      error dla wag = (y-t)*f'*f(x)
    2.Obliczenie gradientu(kierunek najszybszego wzorostu wartości) dla wyjścia X
    -Wzór: q * (t - y) * f'(x) * f(x)
    3.Obliczenie gradientu dla wszystkich warstw ukrtych
    -Wzór: q *SUM(w*error)
    4.Modyfikacja wag
    */
   
    Layer & outputLayer = m_layer.back();
   
    //Overal error
    m_error = 0.0;
    for( int i = 0; i < outputLayer.size(); i++ ) {
        cout << "Output neuron: " << i << endl;
        for( int j = 0; j < targetVal.size(); j++ ) {
            m_error += 0.5 * pow(( targetVal[ j ] - outputLayer[ i ].getVal() ), 2 );
            cout << " 0.5*(" << targetVal[ j ] << "-" << outputLayer[ i ].getVal() << ")^2 +" << endl;
        }
        cout << "SUMA: " << m_error << endl;
    }
    cout << "Overal error: " << m_error << endl;
   
    //d: error output
    cout << "Output error: " << endl;
    for( int i = 0; i < outputLayer.size(); i++ )
         outputLayer[ i ].outputError( targetVal[ i ] );
   
    //d: hidden layer
    for( int n_layer = m_layer.size() - 2; n_layer > 0; n_layer-- ) {
        Layer & layer = m_layer[ n_layer ];
        Layer & nextLayer = m_layer[ n_layer + 1 ];
        cout << "Sprawdzam wspolczynik bledu dla warstwy: " << n_layer << " i: " << n_layer + 1 << endl;
        cout << "Ilosc neuronow" << layer.size() << " i " << nextLayer.size() << endl;
        for( int n_neuron = 0; n_neuron < layer.size(); n_neuron++ ) {
            cout << " Neuron: " << n_neuron << endl;
            layer[ n_neuron ].hiddenError( nextLayer );
        }
    }
   
    //Modify weights
    for( int n_layer = m_layer.size() - 1; n_layer > 0; n_layer-- ) {
        Layer & layer = m_layer[ n_layer ];
        Layer & prevLayer = m_layer[ n_layer - 1 ];
       
        cout << endl << "Modyfikuje warste: " << n_layer << endl;
       
        for( int n_neuron = 0; n_neuron < layer.size(); ++n_neuron )
             layer[ n_neuron ].updateWeights( prevLayer );
       
    }
}

Tutaj obliczanie błędu dla Outputu:
C/C++
void Neuron::outputError( double target ) {
    signalError =( target - value ) * Neuron::sigmoidDerivative( value ); //sigmoidDerivative = return exp(-val) / pow((1+exp(-val)),2);
    cout << " Error: " << signalError << endl;
}

Obliczanie błędu dla wag:
C/C++
void Neuron::hiddenError( const Layer & nextLayer ) {
    double sum = 0.0;
    for( int n_neuron = 0; n_neuron < nextLayer.size(); n_neuron++ ) {
        sum += weights[ n_neuron ] * nextLayer[ n_neuron ].getSignalError();
        cout << " " << weights[ n_neuron ] << "*" << nextLayer[ n_neuron ].getSignalError() << "+" << endl;
    }
   
    signalError = sum * Neuron::sigmoidDerivative( value );
   
    cout << endl << "d = " << sum << "*" << Neuron::sigmoidDerivative( value ) << endl;
    cout << "======================" << endl
    << "Error: " << signalError << endl
    << "======================" << endl;
}

Modyfikacja wag:
C/C++
void Neuron::updateWeights( Layer & prevLayer ) {
   
    cout << "Aktualny wspolczynnik bledu: " << signalError << endl;
    for( int n_neuron = 0; n_neuron < prevLayer.size(); n_neuron++ ) {
       
        double weightChange = 0.0;
        double oldDeltaWeight = prevLayer[ n_neuron ].deltaWeights[ idNeuron ];
        double gradient = signalError * value; //*learningRate;
        double newDeltaWeight = learingRate * gradient * oldDeltaWeight;
       
        cout << "Gradient: " << gradient << endl;
       
        prevLayer[ n_neuron ].deltaWeights[ idNeuron ] = newDeltaWeight;
        prevLayer[ n_neuron ].weights[ idNeuron ] += newDeltaWeight;
    }
}

Projekt można tutaj pobrać, jest tam też screen z wynikami dla słowa kot: http://speedy.sh/5Ju4c​/Perceptonv2.rarDownload[/a]
Bardzo proszę o pomoc.
P-146970
darko202
» 2016-04-05 12:08:18
zadałeś bardzo trudne pytanie  "czy kod jest dobrze napisany? "
w mojej ocenie "nie"

0. standard dokumentowania kodu
nie
- minimalna, można prawie powiedzieć zerowa ilość komentarzy

1. ze względu przyjęty standard programowania obiektowego w C++
nie
- każda klasa ma swój plik cpp i h


2. ze względu na realizacje zadania
nie realizuje zadania
- do sprawdzenia używasz pętli sumującej //otrzymam np. 5 jest dobrze 
- nie próbujesz porównywać z wzorcem
- tryb uczenia ? na czym polega. jak się już czegoś nauczy to gdzie to pamięta
(wskazany link)
"Jest to jednak proces jednorazowy: wytrenowana sieć neuronowa może zostać "zamrożona" i działać już tylko jako klasyfikator, bez dalszego uczenia (a więc szybko). "

3. algorytm
nie
- gdzie on właściwie jest ?


Przepraszam, ale takie jest moje wrażenie subiektywne
to co przedstawiłeś to oczywiście cos cennego,
ale zacznij jeszcze raz 
- przemyśl algorytm  (bez programowania narysuj schemat - opisz co chcesz osiągnąć - kolejne kroki)
- schemat potrzebnych klas (2 to mało)
- przygotuj ogólny algorytm (bez realizacji wnętrza metod)
  np. 
  zarówka.Zapalam();
  ...
  kontakt.Klik();
  if (zarówka.Miga())
    ...  
  else
  ...
  kontakt.Klik();
  zarówka.Gaszę();
// środek nie jest na tym etapie ważny 

- dodaj komentarze

i taki algorytm przedstaw do oceny
łatwiej wtedy będzie odpowiedzieć na to Twoje "bardzo trudne pytanie"

Powodzenia

P-146989
GGG205
Temat założony przez niniejszego użytkownika
» 2016-04-05 15:28:38
Dzięki za ocenę, jak być najlepszym to najlepiej uczyć się na błędach. Zrobię wszystko co napisałeś.
Ogólnie to chcę osiągnąć klasyfikowanie słów. Osoba podaje zdanie np: Ala ma kota. Na tej podstawie generuje pytanie robiąc lukę. "Ala ma...?" a)Kota/Kot b)Psa/Pies c)Krowe
P-146991
michal11
» 2016-04-05 17:15:32
Jeżeli chcesz używać sieci to nie lepiej skorzystać z już gotowych bibliotek niż męczyć się z robieniem samemu ?
P-146992
« 1 »
  Strona 1 z 1