2013-08-01 12 views
5

Sto scrivendo una semplice implementazione di MLP con una singola unità di output (classificazione binaria). Ne ho bisogno per scopi didattici, quindi non posso usare l'implementazione esistente :(Implementazione multistrato percettrone: i pesi impazziscono

Sono riuscito a creare un modello fittizio di lavoro e ho implementato la funzione di allenamento, ma l'MLP non converge, anzi, il gradiente per l'unità di uscita rimane alto su epoche, per cui i suoi pesi si avvicinano all'infinito

mia realizzazione:.

import numpy as np 
from sklearn.metrics import confusion_matrix 
from sklearn.metrics import classification_report 

X = np.loadtxt('synthetic.txt') 
t = X[:, 2].astype(np.int) 
X = X[:, 0:2] 

# Sigmoid activation function for output unit 
def logistic(x): 
    return 1/(1 + np.exp(-x)) 

# derivative of the tanh activation function for hidden units 
def tanh_deriv(x): 
    return 1 - np.tanh(x)*np.tanh(x) 

input_num = 2   # number of units in the input layer 
hidden_num = 2   # number of units in the hidden layer 

# initialize weights with random values: 
weights_hidden = np.array((2 * np.random.random((input_num + 1, hidden_num + 1)) - 1) * 0.25) 
weights_out = np.array((2 * np.random.random( hidden_num + 1) - 1) * 0.25) 


def predict(x): 
    global input_num 
    global hidden_num 
    global weights_hidden 
    global weights_out 

    x = np.append(x.astype(float), 1.0)  # input to the hidden layer: features + bias term 
    a = x.dot(weights_hidden)   # activations of the hidden layer 
    z = np.tanh(a)       # output of the hidden layer 
    q = logistic(z.dot(weights_out))  # input to the output (decision) layer 
    if q >= 0.5: 
     return 1 
    return 0 



def train(X, t, learning_rate=0.2, epochs=50): 
    global input_num 
    global hidden_num 
    global weights_hidden 
    global weights_out 

    weights_hidden = np.array((2 * np.random.random((input_num + 1, hidden_num + 1)) - 1) * 0.25) 
    weights_out = np.array((2 * np.random.random( hidden_num + 1) - 1) * 0.25) 

    for epoch in range(epochs): 
     gradient_out = 0.0      # gradients for output and hidden layers 
     gradient_hidden = [] 

     for i in range(X.shape[0]):    
     # forward propagation 
      x = np.array(X[i])      
      x = np.append(x.astype(float), 1.0) # input to the hidden layer: features + bias term 
      a = x.dot(weights_hidden)   # activations of the hidden layer 
      z = np.tanh(a)      # output of the hidden layer 
      q = z.dot(weights_out)    # activations to the output (decision) layer 
      y = logistic(q)      # output of the decision layer 

     # backpropagation 
      delta_hidden_s = []     # delta and gradient for a single training sample (hidden layer) 
      gradient_hidden_s = [] 

      delta_out_s = t[i] - y    # delta and gradient for a single training sample (output layer) 
      gradient_out_s = delta_out_s * z 

      for j in range(hidden_num + 1):     
       delta_hidden_s.append(tanh_deriv(a[j]) * (weights_out[j] * delta_out_s)) 
       gradient_hidden_s.append(delta_hidden_s[j] * x) 

      gradient_out = gradient_out + gradient_out_s    # accumulate gradients over training set 
      gradient_hidden = gradient_hidden + gradient_hidden_s 

    print "\n#", epoch, "Gradient out: ",gradient_out, 
     print "\n  Weights out: ", weights_out 

     # Now updating weights 
     weights_out = weights_out - learning_rate * gradient_out 

     for j in range(hidden_num + 1): 
      weights_hidden.T[j] = weights_hidden.T[j] - learning_rate * gradient_hidden[j] 



train(X, t, 0.2, 50) 

e l'evoluzione del gradiente e pesi per l'unità di uscita sopra epoca:

0 Gradient out: [ 11.07640724 -7.20309009 0.24776626] 
    Weights out: [-0.15397237 0.22232593 0.03162811] 

    1 Gradient out: [ 23.68791197 -19.6688382 -1.75324703] 
    Weights out: [-2.36925382 1.66294395 -0.01792515] 

    2 Gradient out: [ 79.08612305 -65.76066015 -7.70115262] 
    Weights out: [-7.10683621 5.59671159 0.33272426] 

    3 Gradient out: [ 99.59798656 -93.90973727 -21.45674943] 
    Weights out: [-22.92406082 18.74884362 1.87295478] 

...

49 Gradient out: [ 107.89975864 -105.8654327 -104.69591522] 
    Weights out: [-1003.67912726 976.87213404 922.38862049] 

ho provato diversi set di dati, varia il numero di unità nascoste. Ho provato ad aggiornare i pesi con l'aggiunta invece della sottrazione ... Niente aiuta ...

Qualcuno potrebbe dirmi cosa potrebbe essere sbagliato? Grazie in anticipo

+0

Ciao, puoi collegare il sintetizzatore "sintetizzatore", eseguirò il debug e spero di individuare le correzioni richieste, ho già trovato alcune parti mancanti come la necessità di aggiungere un termine di bias che va al livello di output, così come cambiare il meccanismo di aggiornamento del bias che è molto diverso dall'aggiornamento di altri pesi. Grazie – Curious

+3

Ciao, in realtà ho già risolto il problema. Hai ragione, ho mancato il pregiudizio nello strato nascosto. Inoltre, ho riscritto la funzione di backpropagation per la somma dei quadrati di errore. Grazie per il tuo interesse. –

risposta

2

Non credo che dovresti usare la funzione di errore somma dei quadrati per la classificazione binaria. Invece dovresti usare la funzione di errore di entropia incrociata, che è fondamentalmente una funzione di verosimiglianza. In questo modo l'errore diventerà molto più costoso quanto più a lungo la tua previsione sarà dalla risposta corretta. Si prega di leggere la sezione su "Network Training" pp. 235 in "Pattern Recognition and Machine Learning" di Christopher Bishop, questo vi darà una panoramica adeguata su come eseguire l'apprendimento supervisionato su una FFNN.

Le unità di bias sono estremamente importanti, quindi rendono possibile la funzione di trasferimento. per spostarsi lungo la curva x. I pesi cambieranno la pendenza della funzione di trasferimento. curva. Notare questa differenza tra bias e pesi, poiché fornirà una buona comprensione del motivo per cui entrambi devono essere presenti in un FFNN.

Problemi correlati