2015-04-04 12 views
5

Ho scritto del codice per implementare il backpropagation in una rete neurale profonda con la funzione di attivazione logistica e l'output di softmax.Backpropagation con unità lineari rettificate

def backprop_deep(node_values, targets, weight_matrices): 
    delta_nodes = node_values[-1] - targets 
    delta_weights = delta_nodes.T.dot(node_values[-2]) 
    weight_updates = [delta_weights] 
    for i in xrange(-2, -len(weight_matrices)- 1, -1): 
     delta_nodes = dsigmoid(node_values[i][:,:-1]) * delta_nodes.dot(weight_matrices[i+1])[:,:-1] 
     delta_weights = delta_nodes.T.dot(node_values[i-1]) 
     weight_updates.insert(0, delta_weights) 
    return weight_updates 

Il codice funziona bene, ma quando sono passato a Relu come la funzione di attivazione ha smesso di funzionare. Nella routine backprop cambio solo la derivata della funzione di attivazione:

def backprop_relu(node_values, targets, weight_matrices): 
    delta_nodes = node_values[-1] - targets 
    delta_weights = delta_nodes.T.dot(node_values[-2]) 
    weight_updates = [delta_weights] 
    for i in xrange(-2, -len(weight_matrices)- 1, -1): 
     delta_nodes = (node_values[i]>0)[:,:-1] * delta_nodes.dot(weight_matrices[i+1])[:,:-1] 
     delta_weights = delta_nodes.T.dot(node_values[i-1]) 
     weight_updates.insert(0, delta_weights) 
    return weight_updates 

Tuttavia, la rete non è più impara, ed i pesi andare rapidamente a zero e rimanere lì. Sono totalmente perplesso.

+0

sei sicuro di avere la giusta rappresentazione della derivata? – Ashalynd

+0

Sono ragionevolmente certo di farlo. La derivata deve essere 0 quando l'input è negativo, 1 quando l'input è positivo. ReLU non è differenziabile a zero, quindi qui presumo che la derivata sia solo zero a zero. – GuillaumeDufay

+0

Se i valori di matrici di peso sono <1, impostare la derivata su 0 o 1 significherebbe che si stanno riducendo in modo sistematico delta_nodes/delta_weights in ogni passaggio successivo. Potresti doverli rinormalizzare? – Ashalynd

risposta

4

Anche se ho determinato la fonte del problema, ho intenzione di lasciarlo nel caso in cui potrebbe essere di beneficio a qualcun altro.

Il problema era che non ho regolato la scala dei pesi iniziali quando ho cambiato le funzioni di attivazione. Mentre le reti logistiche imparano molto bene quando gli input dei nodi sono vicini allo zero e la funzione logistica è approssimativamente lineare, le reti ReLU imparano bene per input moderatamente grandi ai nodi. L'inizializzazione di peso ridotto utilizzata nelle reti logistiche non è quindi necessaria, anzi dannosa. Il comportamento che stavo vedendo era la rete di ReLU che ignorava le caratteristiche e tentava di imparare esclusivamente il bias del set di allenamento.

Attualmente sto usando i pesi iniziali distribuiti uniformemente da -5 a .5 sul set di dati MNIST e sta imparando molto rapidamente.