2012-01-26 31 views
10

Lo scorso semestre ho seguito un corso di apprendimento automatico online da Standford tenuto dal professor Ng. http://www.ml-class.org/course/auth/welcome Ho pensato che fosse piuttosto informativo. Per rispolverare/comprendere meglio le reti neurali ho provato a scrivere il mio in python. Eccolo:Cercando di scrivere la mia rete neurale in Python

import numpy 

class NN: 

    def __init__(self, sl): 

     #sl = number of units (not counting bias unit) in layer l 
     self.sl = sl 
     self.layers = len(sl) 

     #Create weights 
     self.weights = [] 
     for idx in range(1, self.layers): 
      self.weights.append(numpy.matrix(numpy.random.rand(self.sl[idx-1]+1, self.sl[idx])/5)) 

     self.cost = [] 

    def update(self, input): 

     if input.shape[1] != self.sl[0]: 
      raise ValueError, 'The first layer must have a node for every feature' 

     self.z = [] 
     self.a = [] 

     #Input activations. I'm expecting inputs as numpy matrix (Examples x Featrues) 
     self.a.append(numpy.hstack((numpy.ones((input.shape[0], 1)), input)))#Set inputs ai + bias unit 

     #Hidden activations 
     for weight in self.weights:   
      self.z.append(self.a[-1]*weight) 
      self.a.append(numpy.hstack((numpy.ones((self.z[-1].shape[0], 1)), numpy.tanh(self.z[-1])))) #tanh is a fancy sigmoid 

     #Output activation 
     self.a[-1] = self.z[-1] #Not logistic regression thus no sigmoid function 
     del self.z[-1] 

    def backPropagate(self, targets, lamda): 

     m = float(targets.shape[0]) #m is number of examples 

     #Calculate cost 
     Cost = -1/m*sum(numpy.power(self.a[-1] - targets, 2)) 
     for weight in self.weights: 
      Cost = Cost + lamda/(2*m)*numpy.power(weight[1:, :], 2).sum() 
     self.cost.append(abs(float(Cost))) 

     #Calculate error for each layer 
     delta = [] 
     delta.append(self.a[-1] - targets) 
     for idx in range(1, self.layers-1): #No delta for the input layer because it is the input 
      weight = self.weights[-idx][1:, :] #Ignore bias unit 
      dsigmoid = numpy.multiply(self.a[-(idx+1)][:,1:], 1-self.a[-(idx+1)][:,1:]) #dsigmoid is a(l).*(1-a(l)) 
      delta.append(numpy.multiply(delta[-1]*weight.T, dsigmoid)) #Ignore Regularization 

     Delta = [] 
     for idx in range(self.layers-1): 
      Delta.append(self.a[idx].T*delta[-(idx+1)]) 

     self.weight_gradient = [] 
     for idx in range(len(Delta)): 
      self.weight_gradient.append(numpy.nan_to_num(1/m*Delta[idx] + numpy.vstack((numpy.zeros((1, self.weights[idx].shape[1])), lamda/m*self.weights[idx][1:, :])))) 

    def train(self, input, targets, alpha, lamda, iterations = 1000): 

     #alpha: learning rate 
     #lamda: regularization term 

     for i in range(iterations): 
      self.update(input) 
      self.backPropagate(targets, lamda) 
      self.weights = [self.weights[idx] - alpha*self.weight_gradient[idx] for idx in range(len(self.weights))] 

    def predict(self, input): 

     self.update(input) 
     return self.a[-1] 

Ma non funziona = (Controllo del costo vs iterazione posso vedere un puntino nel costo e la previsione per la A è lo stesso Qualcuno può aiutarmi a capire il perché.. la mia rete neurale non convergente

Grazie, Ci scusiamo per la quantità di codice (forse qualcuno lo troverà utile)

Update:?.

Invece di utilizzare dati casuali ho un po 'strutturato dati dall'UIC Machine Learning Rep ository. La particolare set di dati è l'area bruciata degli incendi boschivi, nella regione nord-est del Portogallo, utilizzando i dati meteorologici e altro: http://archive.ics.uci.edu/ml/datasets/Forest+Fires Ho modificato i dati in modo che i giorni ei mesi sono stati i numeri: https://docs.google.com/spreadsheet/ccc?key=0Am3oTptaLsExdC1PeXl1eTczRnRNejl3QUo5RjNLVVE

data = numpy.loadtxt(open('FF-data.csv', 'rb'), delimiter = ',', skiprows = 1) 
features = data[:,0:11] 
targets = numpy.matrix(data[:,12]).T 

nfeatures = (features-features.mean(axis=0))/features.std(axis=0) 

n = NN([11, 10, 1]) #The class takes the list of how many nodes in each layer 
n.train(nfeatures, targets, 0.003, 0.0) 

import matplotlib.pyplot 
matplotlib.pyplot.subplot(221) 
matplotlib.pyplot.plot(n.cost) 
matplotlib.pyplot.title('Cost vs. Iteration') 

matplotlib.pyplot.subplot(222) 
matplotlib.pyplot.scatter(n.predict(nfeatures), targets) 
matplotlib.pyplot.title('Data vs. Predicted') 

matplotlib.pyplot.savefig('Report.png', format = 'png') 
matplotlib.pyplot.close() 

Perché il costo scalare intorno a 4000 e perché il Data vs. Predicted non ha alcuna tendenza? È possibile vedere i grafici qui: https://docs.google.com/open?id=0B23oTptaLsExMTQ0OTAxNWEtYjE2NS00MjA5LTg1MjMtNDBhYjVmMTFhZDhm

+0

Ho eseguito il tuo codice su alcuni semplici esempi, e sembra che stia funzionando tutto bene. Nel tuo esempio il costo diminuisce molto velocemente nelle prime cento iterazioni e poi rimane circa lo stesso, il che è, direi, il comportamento previsto – Sonya

+0

Grazie per aver eseguito il mio codice. rete quale è l'output di n.predict (A)? Per me tutti i valori previsti sono gli stessi indipendentemente dalle caratteristiche di input (in genere vicino alla media (Target). Ad esempio Target = [4, 5, 6,7] n .predict (caratteristiche) = [5.5, 5.5, 5.5, 5.5]. – user1068430

+0

Utilizzare i panda per i dati delle serie temporali! – ken

risposta

4

La rete neurale non è stata in grado di addestrare i dati di incendio forestale https://docs.google.com/spreadsheet/ccc?key=0Am3oTptaLsExdC1PeXl1eTczRnRNejl3QUo5RjNLVVE per alcuni motivi.

Prima la funzione numpy.tanh() sigmoid non si comporta come previsto. Il codice dovrebbe essere modificato da:

self.a.append(numpy.hstack((numpy.ones((self.z[-1].shape[0], 1)),numpy.tanh(self.z[-1])))) #tanh is a fancy sigmoid 

A:

self.a.append(numpy.hstack((numpy.ones((self.z[-1].shape[0], 1)), 1/(1+numpy.exp(-self.z[-1]))))) 

Seconda NumPy e matplotlib non stanno giocando bello. Le matrici di Numpy sembrano essere tracciate all'indietro. Questo può essere risolto usando matrix.tolist().Codice modificato da:

matplotlib.pyplot.scatter(n.predict(nfeatures), targets) 

Per:

matplotlib.pyplot.scatter(n.predict(nfeatures).tolist(), targets.tolist()) 

Infine il numero di nodi dovrebbe essere circa il 10% della dimensione esempio. Invece di 10 è meglio usare 50 nodi.

Il codice di rete neurale funzionante è pubblicato sotto con una nuova funzione autoparam che tenta di trovare la migliore velocità di apprendimento e costante di regolarizzazione. Puoi vedere i grafici per il costo di incendio di foresta vs iterazione e dati vs previsti qui: https://docs.google.com/open?id=0B23oTptaLsExMWQ4ZWM1ODYtZDMzMC00M2VkLWI1OWUtYzg3NzgxNWYyMTIy

Grazie per la lettura! Spero che la mia rete neurale possa aiutare le persone.

import numpy 

class NN: 

    def __init__(self, sl): 

     #sl = number of units (not counting bias unit) in layer l 
     self.sl = sl 
     self.layers = len(sl) 

     #Create weights 
     self.weights = [] 
     for idx in range(1, self.layers): 
      self.weights.append(numpy.matrix(numpy.random.rand(self.sl[idx-1]+1, self.sl[idx]))/5) 

     self.cost = [] 

    def update(self, input): 

     if input.shape[1] != self.sl[0]: 
      raise ValueError, 'The first layer must have a node for every feature' 

     self.z = [] 
     self.a = [] 

     #Input activations. Expected inputs as numpy matrix (Examples x Featrues) 
     self.a.append(numpy.hstack((numpy.ones((input.shape[0], 1)), input)))#Set inputs ai + bias unit 

     #Hidden activations 
     for weight in self.weights: 
      self.z.append(self.a[-1]*weight) 
      self.a.append(numpy.hstack((numpy.ones((self.z[-1].shape[0], 1)), 1/(1+numpy.exp(-self.z[-1]))))) #sigmoid 

     #Output activation 
     self.a[-1] = self.z[-1] #Not logistic regression thus no sigmoid function 
     del self.z[-1] 

    def backPropagate(self, targets, lamda): 

     m = float(targets.shape[0]) #m is number of examples 

     #Calculate cost 
     Cost = -1/m*sum(numpy.power(self.a[-1] - targets, 2)) 
     for weight in self.weights: 
      Cost = Cost + lamda/(2*m)*numpy.power(weight[1:, :], 2).sum() 
     self.cost.append(abs(float(Cost))) 

     #Calculate error for each layer 
     delta = [] 
     delta.append(self.a[-1] - targets) 
     for idx in range(1, self.layers-1): #No delta for the input layer because it is the input 
      weight = self.weights[-idx][1:, :] #Ignore bias unit 
      dsigmoid = numpy.multiply(self.a[-(idx+1)][:,1:], 1-self.a[-(idx+1)][:,1:]) #dsigmoid is a(l).*(1-a(l)) 
      delta.append(numpy.multiply(delta[-1]*weight.T, dsigmoid)) #Ignore Regularization 

     Delta = [] 
     for idx in range(self.layers-1): 
      Delta.append(self.a[idx].T*delta[-(idx+1)]) 

     self.weight_gradient = [] 
     for idx in range(len(Delta)): 
      self.weight_gradient.append(numpy.nan_to_num(1/m*Delta[idx] + numpy.vstack((numpy.zeros((1, self.weights[idx].shape[1])), lamda/m*self.weights[idx][1:, :])))) 

    def train(self, input, targets, alpha, lamda, iterations = 1000): 

     #alpha: learning rate 
     #lamda: regularization term 

     for i in range(iterations): 
      self.update(input) 
      self.backPropagate(targets, lamda) 
      self.weights = [self.weights[idx] - alpha*self.weight_gradient[idx] for idx in range(len(self.weights))] 

    def autoparam(self, data, alpha = [0.001, 0.003, 0.01, 0.03, 0.1, 0.3], lamda = [0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1, 3, 10]): 

     #data: numpy matrix with targets in last column 
     #alpha: learning rate 
     #lamda: regularization term 

     #Create training, cross validation, and test sets 
     while 1: 
      try: 
       numpy.seterr(invalid = 'raise') 
       numpy.random.shuffle(data) #Shuffle data 
       training_set = data[0:data.shape[0]/10*6, 0:-1] 
       self.ntraining_set = (training_set-training_set.mean(axis=0))/training_set.std(axis=0) 
       self.training_tgt = numpy.matrix(data[0:data.shape[0]/10*6, -1]).T 

       cv_set = data[data.shape[0]/10*6:data.shape[0]/10*8, 0:-1] 
       self.ncv_set = (cv_set-cv_set.mean(axis=0))/cv_set.std(axis=0) 
       self.cv_tgt = numpy.matrix(data[data.shape[0]/10*6:data.shape[0]/10*8, -1]).T 

       test_set = data[data.shape[0]/10*8:, 0:-1] 
       self.ntest_set = (test_set-test_set.mean(axis=0))/test_set.std(axis=0) 
       self.test_tgt = numpy.matrix(data[data.shape[0]/10*8:, -1]).T 

       break 

      except FloatingPointError: 
       pass 

     numpy.seterr(invalid = 'warn') 
     cost = 999999 
     for i in alpha: 
      for j in lamda: 
       self.__init__(self.sl) 
       self.train(self.ntraining_set, self.training_tgt, i, j, 2000) 
       current_cost = 1/float(cv_set.shape[0])*sum(numpy.square(self.predict(self.ncv_set) - self.cv_tgt)).tolist()[0][0] 
       print current_cost 
       if current_cost < cost: 
        cost = current_cost 
        self.learning_rate = i 
        self.regularization = j 
     self.__init__(self.sl) 

    def predict(self, input): 

     self.update(input) 
     return self.a[-1] 

Caricamento dati, plottaggio, ecc ...

data = numpy.loadtxt(open('FF-data.csv', 'rb'), delimiter = ',', skiprows = 1)#Load 
numpy.random.shuffle(data) 

features = data[:,0:11] 
nfeatures = (features-features.mean(axis=0))/features.std(axis=0) 
targets = numpy.matrix(data[:, 12]).T 

n = NN([11, 50, 1]) 

n.train(nfeatures, targets, 0.07, 0.0, 2000) 

import matplotlib.pyplot 
matplotlib.pyplot.subplot(221) 
matplotlib.pyplot.plot(n.cost) 
matplotlib.pyplot.title('Cost vs. Iteration') 

matplotlib.pyplot.subplot(222) 
matplotlib.pyplot.scatter(n.predict(nfeatures).tolist(), targets.tolist()) 
matplotlib.pyplot.plot(targets.tolist(), targets.tolist(), c = 'r') 
matplotlib.pyplot.title('Data vs. Predicted') 

matplotlib.pyplot.savefig('Report.png', format = 'png') 
matplotlib.pyplot.close() 
7

(. Mi dispiace, non ho abbastanza rep per aggiungere commenti, quindi mi limiterò a mantenere distacco risposte invece)

Sì, sembra strano. Se, tuttavia, dopo l'allenamento si genera una nuova matrice B:

B = numpy.random.rand(5, 4)/5 
Targets = B*X 
print n.predict(B) 
print B*X 

che funzionerà bene (il più delle volte - a volte sarà ancora dare alla media (Targets) come la risposta). Nota: sono passato dall'utilizzo di 100 funzioni a solo 4 nel mio esempio.

Inoltre, non penso che l'esecuzione di 5000 iterazioni su 50 elementi del set di dati possa farti del bene. In generale, dovresti cercare di usare quanti più dati di allenamento puoi - e qui puoi usare quanto vuoi, ma usi anche meno esempi di quelli che possiedi.

Questo è divertente, ci penserò ancora un po ':) Stavo usando la tua rete per un esempio più semplice - come Input I fornito due numeri, e mi aspettavo la loro somma come Output. Ha funzionato più o meno bene.

+0

Ciao. Ho ridotto il numero di iterazioni al valore predefinito 1000 e ottenuto un set di dati strutturato più grande (518 esempi) – user1068430

-1

penso che il pregiudizio deve essere sottratto da qualche parte dagli ingressi ponderati (o impostato su -1). Da quello che vedo nel tuo codice, i neuroni aggiungono tutti gli input, incluso il bias (che è impostato su +1

+0

queste non sono statistiche, il bias deve essere aggiunto e appreso. Potresti spiegare perché pensi che sarebbe d'aiuto? –

Problemi correlati