2012-01-26 22 views
10

El último semestre tomé un curso de aprendizaje de máquina en línea de Standford impartido por el profesor Ng. http://www.ml-class.org/course/auth/welcome Pensé que era bastante informativo. Para mejorar las redes neuronales, traté de escribir las mías en python. Aquí está:Intentando escribir mi propia red neuronal en 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] 

Pero no funciona = (Inspeccionar el costo vs. iteración puedo ver un pequeño punto en el costo y la predicción para A es todo lo mismo ¿Puede alguien ayudarme a entender por qué.. mi red neuronal no está convergiendo

Gracias, lo sentimos acerca de la cantidad de código (tal vez alguien le resultará útil)

actualización:?.

En lugar de utilizar datos aleatorios tengo un poco estructurada datos del representante de aprendizaje de máquina UCI Ository. El conjunto de datos en particular es el área quemada de incendios forestales, en la región noreste de Portugal, a partir de datos meteorológicos y otros: http://archive.ics.uci.edu/ml/datasets/Forest+Fires he modificado los datos, de modo que los días y meses eran números: 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() 

¿Por qué el costo tope alrededor de 4000 y por qué los datos Vs. ¿Previsto no tener ninguna tendencia? Se puede ver los gráficos aquí: https://docs.google.com/open?id=0B23oTptaLsExMTQ0OTAxNWEtYjE2NS00MjA5LTg1MjMtNDBhYjVmMTFhZDhm

+0

Ejecuto tu código en algunos ejemplos simples, y parece que está funcionando bien. ¿Por qué? Creo que no está funcionando En su ejemplo, el costo disminuye muy rápido en las primeras cien iteraciones y luego se mantiene aproximadamente igual, que es, diría yo, el comportamiento esperado. – Sonya

+0

Gracias por ejecutar mi código. ¿Cuál es la salida de n.predict (A)? Para mí, todos los valores predichos son los mismos independientemente de las características de entrada (por lo general, cerca del promedio (Objetivos). Por ejemplo, Objetivos = [4, 5, 6,7] n .predict (características) = ​​[5.5, 5.5, 5.5, 5.5]. – user1068430

+0

¡Utilice pandas para datos de series de tiempo! – ken

Respuesta

4

La red neuronal no pudo entrenar en los datos de Forest Fire https://docs.google.com/spreadsheet/ccc?key=0Am3oTptaLsExdC1PeXl1eTczRnRNejl3QUo5RjNLVVE por algunas razones.

Primero, la función sigmoide numpy.tanh() no se comporta como se esperaba. El código debe ser cambiado de:

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

Para:

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

Segunda numpy y matplotlib no están jugando bien. Las matrices numpy parecen estar trazadas hacia atrás. Esto se puede solucionar usando matrix.tolist().Código cambiado de:

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

Para:

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

Finalmente el número de nodos debe ser aproximadamente 10% del tamaño de ejemplo. En lugar de 10, es mejor usar 50 nodos.

El código de la red neuronal funcional se publica a continuación con una nueva función autoparam que intenta encontrar la mejor tasa de aprendizaje y constantes de regularización. Puede ver los gráficos para el costo del incendio forestal frente a la iteración y los datos frente a los valores predichos aquí: https://docs.google.com/open?id=0B23oTptaLsExMWQ4ZWM1ODYtZDMzMC00M2VkLWI1OWUtYzg3NzgxNWYyMTIy

¡Gracias por su lectura! Espero que mi red neuronal pueda ayudar a la gente.

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] 

carga de datos, trazado, etc ...

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

(. En este momento, no tengo representante suficiente añadir comentarios, por lo que voy a seguir publicar respuestas en vez)

Sí, parece extraño. Si, sin embargo, después de entrenar a generar una nueva matriz B:

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

no tendrán ningún problema (la mayoría de las veces - a veces todavía le dará a la media (Objetivos) como la respuesta). Nota: Cambié de usar 100 características a usar solo 4 en mi ejemplo.

Además, no creo que ejecutar 5000 iteraciones en 50 elementos del conjunto de datos le sirva de algo. Por lo general, debe intentar usar la mayor cantidad de datos de capacitación que pueda, y aquí puede usar todo lo que quiera, pero utiliza incluso menos ejemplos de los que tiene.

Esto es divertido, lo pensaré un poco más :) Estaba usando su red para un ejemplo más simple, ya que la Entrada I proporcionó dos números y esperaba su suma como Salida. Funcionó más o menos bien.

+0

Hola. Reduje el número de iteraciones al valor predeterminado 1000 y obtuve un conjunto de datos estructurados más grande (518 ejemplos) – user1068430

-1

creo que el sesgo se debe restar algún lugar de las entradas ponderadas (o establece en -1). Por lo que veo en tu código, las neuronas agregan todas las entradas, incluida la polarización (que se establece en +1.

+0

estas no son estadísticas, el sesgo debe ser agregado y aprendido. ¿Podría explicar por qué cree que ayudaría? –

Cuestiones relacionadas