2014-06-22 5 views
7

Sto provando a implementare il calcolo del gradiente per le reti neurali mediante backpropagation. Non riesco a farlo funzionare con errore di entropia incrociata e unità lineare rettificata (ReLU) come attivazione.Backpropagation per l'attivazione dell'unità lineare rettificata con errore di entropia incrociata

Sono riuscito a far funzionare la mia implementazione per errore quadrato con le funzioni di attivazione sigmoid, tanh e ReLU. Errore di entropia incrociata (CE) con gradiente di attivazione sigmoideo è calcolato correttamente. Tuttavia, quando cambio l'attivazione in ReLU, fallisce. (Sto saltando tanh per CE perché riporta valori in (-1,1) range.)

È a causa del comportamento della funzione di registro a valori vicini a 0 (che viene restituito da ReLU circa il 50% del tempo per gli input normalizzati)? Ho cercato di mitiage quel problema con:

log(max(y,eps)) 

ma ha contribuito solo per portare l'errore e gradienti di nuovo a numeri reali - sono ancora differenti da gradiente numerica.

a verificare i risultati utilizzando gradiente numerica:

num_grad = (f(W+epsilon) - f(W-epsilon))/(2*epsilon) 

Il seguente codice MATLAB presenta un'implementazione backpropagation semplificato e condensato utilizzato nei miei esperimenti:

function [f, df] = backprop(W, X, Y) 
% W - weights 
% X - input values 
% Y - target values 

act_type='relu'; % possible values: sigmoid/tanh/relu 
error_type = 'CE'; % possible values: SE/CE 

N=size(X,1); n_inp=size(X,2); n_hid=100; n_out=size(Y,2); 
w1=reshape(W(1:n_hid*(n_inp+1)),n_hid,n_inp+1); 
w2=reshape(W(n_hid*(n_inp+1)+1:end),n_out, n_hid+1); 

% feedforward 
X=[X ones(N,1)]; 
z2=X*w1'; a2=act(z2,act_type); a2=[a2 ones(N,1)]; 
z3=a2*w2'; y=act(z3,act_type); 

if strcmp(error_type, 'CE') % cross entropy error - logistic cost function 
    f=-sum(sum(Y.*log(max(y,eps))+(1-Y).*log(max(1-y,eps)))); 
else % squared error 
    f=0.5*sum(sum((y-Y).^2)); 
end 

% backprop 
if strcmp(error_type, 'CE') % cross entropy error 
    d3=y-Y; 
else % squared error 
    d3=(y-Y).*dact(z3,act_type); 
end 

df2=d3'*a2; 
d2=d3*w2(:,1:end-1).*dact(z2,act_type); 
df1=d2'*X; 

df=[df1(:);df2(:)]; 

end 

function f=act(z,type) % activation function 
switch type 
    case 'sigmoid' 
     f=1./(1+exp(-z)); 
    case 'tanh' 
     f=tanh(z); 
    case 'relu' 
     f=max(0,z); 
end 
end 

function df=dact(z,type) % derivative of activation function 
switch type 
    case 'sigmoid' 
     df=act(z,type).*(1-act(z,type)); 
    case 'tanh' 
     df=1-act(z,type).^2; 
    case 'relu' 
     df=double(z>0); 
end 
end 

Modifica

Afte r altro giro di esperimenti, ho scoperto che utilizzando un softmax per l'ultimo strato:

y=bsxfun(@rdivide, exp(z3), sum(exp(z3),2)); 

e funzione di costo softmax:

f=-sum(sum(Y.*log(y))); 

rendono l'implementaion lavoro per tutte le funzioni di attivazione compresa Relu.

Questo mi porta a concludere che è la funzione di costo logistico (clasifier binario) che non funziona con Relu:

f=-sum(sum(Y.*log(max(y,eps))+(1-Y).*log(max(1-y,eps)))); 

Tuttavia, ancora non riesco a capire dove sta il problema.

risposta

0

Se si utilizza il gradiente discendente, è necessario derivare la funzione di attivazione da utilizzare successivamente nell'approccio di retropropagazione. Sei sicuro del "df = double (z> 0)" ?. Per il logistico e tanh sembra essere giusto.

Inoltre, sei sicuro di questo 'd3 = y-Y'? Direi che questo è vero quando usi la funzione logistica ma non per la ReLu (la derivata non è la stessa e quindi non porterà a quella semplice equazione).

È possibile utilizzare la funzione softplus che è una versione fluida di ReLU, che è ben noto alla derivata (funzione logistica).

+1

La derivata della funzione ReLU è: df = 0 per l'input <= 0 e df = 1 per l'input> 0 che in MATLAB è equivalente a 'double (z> 0)'. d3 è il delta dell'ultimo livello ed è la forma corretta. ReLU ha vantaggi rispetto alla funzione softplus: controlla [qui] (http://machinelearning.wustl.edu/mlpapers/paper_files/icml2010_NairH10.pdf) ad esempio. – Pr1mer

2

Ogni funzione di compressione sigmoid, tanh e softmax (nel livello di output) significa diverse funzioni di costo. Quindi ha senso che un RLU (nel livello di output) non corrisponde alla funzione di costo dell'entropia incrociata. Proverò una semplice funzione di costo di errore quadrato per testare un livello di output RLU.

Il vero potere di RLU è negli strati nascosti di una rete profonda poiché non soffre di errore di sfumatura.

+0

Sono arrivato alla conclusione simile dopo aver esaminato diversi articoli su NN. Quando ho bisogno di classificazione, lo strato di output per softmax è composto da unità sigmoidali. Altri livelli (nascosti) rimangono composti da ReLU. – Pr1mer

0

Penso che il difetto risieda nel confronto con i derivati ​​numericamente calcolati. Nella funzione derivata di attivazione, si definisce la derivata di ReLu a 0 come 0. Quando calcola numericamente la derivata su x = 0 indica che è (ReLU (x + epsilon) -ReLU (x-epsilon)/(2 * epsilon)) a x = 0 che è 0.5. Pertanto, definire la derivata di ReLU a x = 0 per essere 0.5 risolverà il problema

0

Ho pensato di condividere la mia esperienza con problemi simili. Anch'io ho progettato il mio multi classificatore ANN in modo che tutti i livelli nascosti utilizzino la funzione di attivazione non lineare RELU e il livello di output utilizzi la funzione softmax.

Il mio problema era legato in parte alla precisione numerica del linguaggio di programmazione/piattaforma che stavo usando. Nel mio caso ho notato che se ho usato "plain" RELU non solo si uccide il gradiente, ma il linguaggio di programmazione ho usato ha prodotto i seguenti softmax vettori di uscita (questo è solo un campione di esempio):

⎡1.5068230536681645e-35⎤ 
⎢ 2.520367499064734e-18⎥ 
⎢3.2572859518007807e-22⎥ 
⎢      1⎥ 
⎢ 5.020155103452967e-32⎥ 
⎢1.7620297760773188e-18⎥ 
⎢ 5.216008990667109e-18⎥ 
⎢ 1.320937038894421e-20⎥ 
⎢2.7854159049317976e-17⎥ 
⎣1.8091246170996508e-35⎦ 

Avviso del i valori della maggior parte degli elementi sono vicini a 0, ma soprattutto notano il valore 1 nell'output.

Ho usato una diversa funzione di errore cross-entropy rispetto a quella che hai usato. Invece di calcolare log(max(1-y, eps)) mi sono attenuto allo standard log(1-y). Quindi, dato il vettore di output sopra, quando ho calcolato log(1-y) ho ottenuto il -Inf come risultato di cross-entropy, che ovviamente ha ucciso l'algoritmo.

Immagino che se il vostro eps non è abbastanza ragionevolmente alto in modo che log(max(1-y, eps)) ->log(max(0, eps)) non cedere troppo piccola log uscita si potrebbe essere in una salamoia simile come me.

La mia soluzione a questo problema era utilizzare Leaky RELU. Una volta iniziato a utilizzarlo, potrei continuare a utilizzare il multi classificatore cross-entropy in contrasto con la funzione softmax-cost che hai deciso di provare.