Ho scritto la seguente routine di backpropagation per una rete neurale, usando come esempio il codice here. Il problema che sto affrontando mi confonde e ha spinto al limite le mie capacità di debug.Perché questa implementazione di backpropagation non riesce a formare correttamente i pesi?
Il problema che sto affrontando è piuttosto semplice: mentre la rete neurale si allena, i suoi pesi vengono addestrati a zero senza alcun guadagno in precisione.
ho cercato di risolvere il problema molte volte, verificando che:
- i set di allenamento sono corretti
- i vettori di destinazione siano corretti
- il passo in avanti è la registrazione informazioni in modo corretto
- all'indietro i delta step stanno registrando correttamente
- i segni sui delta sono corretti
- i pesi sono ind eed essere regolato
- delta dello strato di input sono tutti a zero
- non ci sono altri errori o avvisi di overflow
Alcuni dati:
- Gli input di formazione sono una griglia 8x8 di [ 0,16) valori che rappresentano un'intensità; questa griglia rappresenta una cifra numerica (convertito in un vettore colonna)
- Il vettore obiettivo è un'uscita che è 1 nella posizione corrispondente al numero corretto
- I pesi e pregiudizi originali vengono assegnati dalla distribuzione gaussiana
- Le attivazioni sono un sigmoide standard
Non so da dove andare. Ho verificato che tutto ciò che so controllare funzioni correttamente e non funziona ancora, quindi ti sto chiedendo qui. Quello che segue è il codice che sto usando per backpropagate:
def backprop(train_set, wts, bias, eta):
learning_coef = eta/len(train_set[0])
for next_set in train_set:
# These record the sum of the cost gradients in the batch
sum_del_w = [np.zeros(w.shape) for w in wts]
sum_del_b = [np.zeros(b.shape) for b in bias]
for test, sol in next_set:
del_w = [np.zeros(wt.shape) for wt in wts]
del_b = [np.zeros(bt.shape) for bt in bias]
# These two helper functions take training set data and make them useful
next_input = conv_to_col(test)
outp = create_tgt_vec(sol)
# Feedforward step
pre_sig = []; post_sig = []
for w, b in zip(wts, bias):
next_input = np.dot(w, next_input) + b
pre_sig.append(next_input)
post_sig.append(sigmoid(next_input))
next_input = sigmoid(next_input)
# Backpropagation gradient
delta = cost_deriv(post_sig[-1], outp) * sigmoid_deriv(pre_sig[-1])
del_b[-1] = delta
del_w[-1] = np.dot(delta, post_sig[-2].transpose())
for i in range(2, len(wts)):
pre_sig_vec = pre_sig[-i]
sig_deriv = sigmoid_deriv(pre_sig_vec)
delta = np.dot(wts[-i+1].transpose(), delta) * sig_deriv
del_b[-i] = delta
del_w[-i] = np.dot(delta, post_sig[-i-1].transpose())
sum_del_w = [dw + sdw for dw, sdw in zip(del_w, sum_del_w)]
sum_del_b = [db + sdb for db, sdb in zip(del_b, sum_del_b)]
# Modify weights based on current batch
wts = [wt - learning_coef * dw for wt, dw in zip(wts, sum_del_w)]
bias = [bt - learning_coef * db for bt, db in zip(bias, sum_del_b)]
return wts, bias
Con il suggerimento di Shep, ho controllato quello che succede quando la formazione di una rete di forma [2, 1, 1]
per sempre l'uscita 1, e in effetti, i treni della rete correttamente questo caso. La mia ipotesi migliore a questo punto è che il gradiente si sta regolando troppo forte per gli 0 e debolmente sugli 1, risultando in una diminuzione netta nonostante un aumento ad ogni passo, ma non ne sono sicuro.
poiché non hai codificato la topologia della rete, ecco un suggerimento: prova ad allenarti con zero o uno nascosto (ognuno con un nodo), un input e un output, per vedere se fa quello che aspettarsi. – Shep
@Shep In modo interessante, quando si esegue su una rete nnet con forma '[2, 1, 1]', i pesi vengono effettivamente addestrati correttamente. Addestrandolo all'uscita 1, i pesi effettivamente aumentano, e l'uscita converge a 1. Test interessante. – Zyerah
1) Con "i pesi vengono addestrati a zero", si intende che i pesi iniziano come numeri casuali, ma sembrano convergere a zero? 2) Quanto è grande la tua rete attuale? 3) Prova a ridimensionare gli input nell'intervallo [0, 1]. – cfh