|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
[C++] Rete neurale, backpropagation - Uso del peso bias
Buondì.
In ottica di poter riutilizzare le reti neurali, stò scrivendo una libreria in C++. Le funzioni per l'utilizzo del percettrone fanno il loro dovere, ho invece un problema quando vengono aggiunti uno o più layer nascosti. Per allenare una rete di questo tipo utilizzo backpropagation, ma ho innanzi tutto dei dubbi sull'utilizzo del peso bias per ogni neurone. Quello che faccio è aggiungere un neurone fittizio in tutti i layer. Questo varrà sempre 1 e trasferirà sempre uno, mente il suo peso di connessione varia come gli altri. Non so se l'errore che ho dipende dall'uso errato che faccio del bias, o se è un'altro tipo di problema. Non so se postare il codice può essere utile, comunque dovrebbe essere abbastanza chiaro dato il linguaggio utilizzato, il seguente è il metodo di addestramento backpropagation: Codice:
int NeuralNet::Train_BackPropagation(vector<_PRECISION> des_out) {
/* Backpropagation case */
// Verifiy that the hidden layer exists
if(des_out.size() != numOutputNeurons || numHiddenLayers <= 0 || numHiddenNeuronsPerLayer <= 0) return -1;
_PRECISION error, delta_weight, prev_bp_err = 0, cur_bp_err = 0;
for(u_int32_t l = layers.size()-1; l >= 0; l--) { // For each layer, begin from output
prev_bp_err = cur_bp_err;
cur_bp_err = 0;
if(!l) break; // Input layer has no weights
if(l==layers.size()-1) {// Output layer
for(u_int32_t n = 0;n < layers[l]->getNeuronNum();n++) { // For each neuron
// Calculate delta error, dk = (rk - ok)*f'(netk)
if(n==layers[l]->getNeuronNum()-1 && BIAS){ // for only bias neuron
error =
(des_out[n-1] - layers[l]->getNeuron(n)->getPotential())*
layers[l]->getNeuron(n)->trans_func_derivate(layers[l]->getNeuron(n)->getPotential());
} else {
error =
(des_out[n] - layers[l]->getNeuron(n)->getPotential())*
layers[l]->getNeuron(n)->trans_func_derivate(layers[l]->getNeuron(n)->getPotential());
}
for(u_int32_t w = 0;w < layers[l]->getNeuron(n)->getWeightsNum(); w++) {// For each weight
// Calculate delta weight, Dw = Wjk + n*dk*oj
delta_weight = layers[l]->getNeuron(n)->getWeight(w) + l_rate*error*layers[l-1]->getNeuron(w)->getPotential();
// Update weight
layers[l]->getNeuron(n)->setWeight(w,delta_weight);
// Product smmation of current error and current weight
cur_bp_err += layers[l]->getNeuron(n)->getWeight(w)*error;
}
}
} else { // Hidden layers and input
for(u_int32_t n = 0;n < layers[l]->getNeuronNum(); n++) {// For each neuron
// Calculate hidden layer error, remembering the previous propagated error
error = layers[l]->getNeuron(n)->trans_func_derivate(layers[l]->getNeuron(n)->getPotential())*prev_bp_err;
for(u_int32_t w = 0;w < layers[l]->getNeuron(n)->getWeightsNum(); w++) {// For each weight
// Calculate delta weight, Dw = W + n*d*o
delta_weight = layers[l]->getNeuron(n)->getWeight(w) + l_rate*error*layers[l]->getNeuron(n)->getPotential();
// Update weight
layers[l]->getNeuron(n)->setWeight(w,delta_weight);
// Product smmation of current error and current weight
cur_bp_err += layers[l]->getNeuron(n)->getWeight(w)*error;
}
}
}
}
return 0;
}
In questo momento stò cercando invano di addestrare la rete per eseguire l'operazione XOR. Grazie per l'aiuto. |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
La fase in avanti ad esempio la puoi implementare nel seguente modo: Codice:
std::vector<Matrix> W(nLayers);
std::vector<Vector> input(nLayers+1);
/* ... */
for ( size_t i=0 ; i< W.size() ; ++i )
{
input[i+1] = f( W*input[i] );
}
Il feedback si scrive in modo parecchio simile. f e' la versione vettoriale della funzione di attivazione (usarne una specifica per strato compila le cose un po' ma non molto).
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Jul 2005
Città: Bologna
Messaggi: 1130
|
Quote:
__________________
-> The Motherfucking Manifesto For Programming, Motherfuckers |
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Direi lapsus freudiano... come quando scrivo server invece di serve :P
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
Il problema che ho durante l'addestramento per eseguire la XOR è che ho un output del genere, giusto in parte:
Codice:
BIT_1 BIT_2 XOR NET_OUT DELTA ..... 1.000 1.000 0.000 1.048 -1.048 0.000 0.000 0.000 0.970 -0.970 0.000 1.000 1.000 1.018 -0.018 1.000 0.000 1.000 1.022 -0.022 1.000 1.000 0.000 1.045 -1.045 0.000 0.000 0.000 0.972 -0.972 0.000 1.000 1.000 1.017 -0.017 1.000 0.000 1.000 1.021 -0.021 1.000 1.000 0.000 1.042 -1.042 0.000 0.000 0.000 0.974 -0.974 0.000 1.000 1.000 1.016 -0.016 1.000 0.000 1.000 1.020 -0.020 1.000 1.000 0.000 1.040 -1.040 0.000 0.000 0.000 0.976 -0.976 0.000 1.000 1.000 1.016 -0.016 1.000 0.000 1.000 1.019 -0.019 1.000 1.000 0.000 1.037 -1.037 0.000 0.000 0.000 0.978 -0.978 .... Il codice è ora questo: Codice:
int NeuralNet::Train_BackPropagation(vector<_PRECISION> des_out) {
/* Backpropagation case */
// Verifiy that the hidden layer exists
if(des_out.size() != numOutputNeurons || numHiddenLayers <= 0 || numHiddenNeuronsPerLayer <= 0) return -1;
_PRECISION error, delta_weight, prev_bp_err = 0, cur_bp_err = 0;
for(u_int32_t l = layers.size()-1; l >= 0; l--) { // For each layer, begin from output
prev_bp_err = cur_bp_err;
cur_bp_err = 0;
if(!l) break; // Input layer has no weights
if(l==layers.size()-1) {// Output layer
for(u_int32_t n = 0;n < layers[l]->getNeuronNum();n++) { // For each neuron
// Calculate delta error, dk = (rk - ok)*f'(netk)
if(n==layers[l]->getNeuronNum()-1 && BIAS){ // for only bias neuron
error =
(des_out[n-1] - layers[l]->getNeuron(n)->getValue())*
layers[l]->getNeuron(n)->trans_func_derivate(layers[l]->getNeuron(n)->getPotential());
} else {
error =
(des_out[n] - layers[l]->getNeuron(n)->getValue())*
layers[l]->getNeuron(n)->trans_func_derivate(layers[l]->getNeuron(n)->getPotential());
}
for(u_int32_t w = 0;w < layers[l]->getNeuron(n)->getWeightsNum(); w++) {// For each weight
// Calculate delta weight, Dw = Wjk + -(n*dk*oj)
delta_weight = layers[l]->getNeuron(n)->getWeight(w) + -(l_rate*error*layers[l-1]->getNeuron(w)->getValue());
// Product smmation of current error and current weight
cur_bp_err += layers[l]->getNeuron(n)->getWeight(w)*error;
// Update weight
layers[l]->getNeuron(n)->setWeight(w,delta_weight);
}
}
} else { // Hidden layers and input
for(u_int32_t n = 0;n < layers[l]->getNeuronNum(); n++) {// For each neuron
// Calculate hidden layer error, remembering the previous propagated error
error = layers[l]->getNeuron(n)->trans_func_derivate(layers[l]->getNeuron(n)->getPotential())*prev_bp_err;
for(u_int32_t w = 0;w < layers[l]->getNeuron(n)->getWeightsNum(); w++) {// For each weight
// Calculate delta weight, Dw = W + -(n*d*o)
delta_weight = layers[l]->getNeuron(n)->getWeight(w) + -(l_rate*error*layers[l-1]->getNeuron(w)->getValue());
// Product smmation of current error and current weight
cur_bp_err += layers[l]->getNeuron(n)->getWeight(w)*error;
// Update weight
layers[l]->getNeuron(n)->setWeight(w,delta_weight);
}
}
}
}
return 0;
}
ora mantegno questa struttura solo per non dover riscrivere tutto, credo che poi proverò ad utilizzare le matrici. Nella prova che ho fatto con XOR, il bias non lo ho utilizzato, quindi nel codice la var. "BIAS" vale 0. Non ho capito l'errore che faccio. |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
|
|
|
|
|
|
#7 | ||
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
E che coefficiente di apprendimento usi ? (Di solito l'errore calcolato non lo si scala tutto dal peso, ma solo una piccola parte, tipo l'1%). Quote:
Che funzione di attivazione (schiacciamento) stai usando ?
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
||
|
|
|
|
|
#8 | ||
|
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
Quote:
se l'ascio andare l'esecuzione il valore delta assume valori periodici... quindi non si arriva ma all'addestramento... per quanto riguarda l'errore che calcolo, non ho capito bene, la riga dove calcolo l'errore del layer nascosto ad esempio è: Codice:
error = layers[l]->getNeuron(n)->trans_func_derivate(layers[l]->getNeuron(n)->getPotential())*prev_bp_err; calcolo delta e aggiorno: Codice:
// Calculate delta weight, Dw = W + -(n*d*o) delta_weight = layers[l]->getNeuron(n)->getWeight(w) + -(l_rate*error*layers[l-1]->getNeuron(w)->getValue()) Codice:
layers[l]->getNeuron(n)->setWeight(w,delta_weight); Quote:
tutto con funzione sigmoide. c'è qualche erroraccio da qualche parte credo.... thanks. |
||
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
no di delta. Non devi sommare direttamente il delta che trovi ma prima moltiplicarlo per un coefficiente relativamente basso, tipo 0.01 o 0.001 inm modo che il cambiamento dei pesi avventa molto lentamente.
Dal punto di vista matematico la backpropagation non e'altro che un metodo di ottimizzazione dove tu vuoi minimizzare la differenza tra output voluto e ottenuto. La backpropagation lo fa con un metodo a discesa di gradiende ovveo, considera l'errore nel punto attuale (nello spazio dei pesi) e cerca di muoversi verso punti con errore piu'basso. Nel farlo pero'devi muoverti con calma, altrimenti rischi di impantanarti Tu immagina di essere in mezzo ai monti, e il tuo errore e'la tua altitudine. Per minimizzarlo cosa fai ? Ti sposti verso dove la montagna scende, un passo alla volta. Olra, se il passo e'piccolo funziona bene, ma se sei il gatto con gli stivali e fai salti da 500 metri puo' accadere che salti da una parte all'altra della valle, senza scendere di un cm, e poi tornare indietro al punto di prima, e cosi'via. il discorso e'analogo
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Intervallo [0,1] o [-1,1] ?
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Se l'intervallo dei pesi' e' [-1,1], allora la funzione in 0 vale zero. Il che vuol dire che con un input di [0,0] per la funzione XOR il tuo output dovrebbe essere sempre zero. E' anche per questo che si introduce la funzione di bias. Se ottieni per l'input nullo un output non nullo probabilmente c'e' un errore gia' nella fase in avanti (se non usi il bias)
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Mar 2009
Messaggi: 753
|
Quote:
Farò sapere. |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 14:11.




















