with sklearn programming neural network example code book python numpy machine-learning neural-network artificial-intelligence

programming - neural network python sklearn



La puerta XOR de la red neuronal no está aprendiendo (2)

Estoy tratando de hacer una puerta XOR utilizando 2 redes perceptron pero por alguna razón la red no está aprendiendo, cuando trazo el cambio de error en un gráfico, el error llega a un nivel estático y oscila en esa región.

No agregué ningún sesgo a la red en este momento.

import numpy as np def S(x): return 1/(1+np.exp(-x)) win = np.random.randn(2,2) wout = np.random.randn(2,1) eta = 0.15 # win = [[1,1], [2,2]] # wout = [[1],[2]] obj = [[0,0],[1,0],[0,1],[1,1]] target = [0,1,1,0] epoch = int(10000) emajor = "" for r in range(0,epoch): for xy in range(len(target)): tar = target[xy] fdata = obj[xy] fdata = S(np.dot(1,fdata)) hnw = np.dot(fdata,win) hnw = S(np.dot(fdata,win)) out = np.dot(hnw,wout) out = S(out) diff = tar-out E = 0.5 * np.power(diff,2) emajor += str(E[0]) + ",/n" delta_out = (out-tar)*(out*(1-out)) nindelta_out = delta_out * eta wout_change = np.dot(nindelta_out[0], hnw) for x in range(len(wout_change)): change = wout_change[x] wout[x] -= change delta_in = np.dot(hnw,(1-hnw)) * np.dot(delta_out[0], wout) nindelta_in = eta * delta_in for x in range(len(nindelta_in)): midway = np.dot(nindelta_in[x][0], fdata) for y in range(len(win)): win[y][x] -= midway[y] f = open(''xor.csv'',''w'') f.write(emajor) # python will convert /n to os.linesep f.close() # you can omit in most cases as the destructor will call it

Este es el error que cambia por el número de rondas de aprendizaje. ¿Es esto correcto? La línea de color rojo es la línea en la que esperaba cómo debería cambiar el error.

¿Algo mal que estoy haciendo en el código? Como no puedo entender lo que está causando el error. Ayuda muy apreciada.

Gracias por adelantado


El error calculado en cada época debe ser una suma total de todos los errores de suma cuadrada (es decir, error para cada objetivo)

import numpy as np def S(x): return 1/(1+np.exp(-x)) win = np.random.randn(2,2) wout = np.random.randn(2,1) eta = 0.15 # win = [[1,1], [2,2]] # wout = [[1],[2]] obj = [[0,0],[1,0],[0,1],[1,1]] target = [0,1,1,0] epoch = int(10000) emajor = "" for r in range(0,epoch): # ***** initialize final error ***** finalError = 0 for xy in range(len(target)): tar = target[xy] fdata = obj[xy] fdata = S(np.dot(1,fdata)) hnw = np.dot(fdata,win) hnw = S(np.dot(fdata,win)) out = np.dot(hnw,wout) out = S(out) diff = tar-out E = 0.5 * np.power(diff,2) # ***** sum all errors ***** finalError += E delta_out = (out-tar)*(out*(1-out)) nindelta_out = delta_out * eta wout_change = np.dot(nindelta_out[0], hnw) for x in range(len(wout_change)): change = wout_change[x] wout[x] -= change delta_in = np.dot(hnw,(1-hnw)) * np.dot(delta_out[0], wout) nindelta_in = eta * delta_in for x in range(len(nindelta_in)): midway = np.dot(nindelta_in[x][0], fdata) for y in range(len(win)): win[y][x] -= midway[y] # ***** Save final error ***** emajor += str(finalError[0]) + ",/n" f = open(''xor.csv'',''w'') f.write(emajor) # python will convert /n to os.linesep f.close() # you can omit in most cases as the destructor will call it


Aquí hay una red de capa oculta con backpropagation que se puede personalizar para ejecutar experimentos con relu, sigmoid y otras activaciones. Después de varios experimentos, se concluyó que con relu la red funcionaba mejor y alcanzaba la convergencia antes, mientras que con sigmoid el valor de pérdida fluctuaba. Esto sucede porque, " el gradiente de sigmoides se vuelve cada vez más pequeño a medida que aumenta el valor absoluto de x ".

import numpy as np import matplotlib.pyplot as plt from operator import xor class neuralNetwork(): def __init__(self): # Define hyperparameters self.noOfInputLayers = 2 self.noOfOutputLayers = 1 self.noOfHiddenLayerNeurons = 2 # Define weights self.W1 = np.random.rand(self.noOfInputLayers,self.noOfHiddenLayerNeurons) self.W2 = np.random.rand(self.noOfHiddenLayerNeurons,self.noOfOutputLayers) def relu(self,z): return np.maximum(0,z) def sigmoid(self,z): return 1/(1+np.exp(-z)) def forward (self,X): self.z2 = np.dot(X,self.W1) self.a2 = self.relu(self.z2) self.z3 = np.dot(self.a2,self.W2) yHat = self.relu(self.z3) return yHat def costFunction(self, X, y): #Compute cost for given X,y, use weights already stored in class. self.yHat = self.forward(X) J = 0.5*sum((y-self.yHat)**2) return J def costFunctionPrime(self,X,y): # Compute derivative with respect to W1 and W2 delta3 = np.multiply(-(y-self.yHat),self.sigmoid(self.z3)) djw2 = np.dot(self.a2.T, delta3) delta2 = np.dot(delta3,self.W2.T)*self.sigmoid(self.z2) djw1 = np.dot(X.T,delta2) return djw1,djw2 if __name__ == "__main__": EPOCHS = 6000 SCALAR = 0.01 nn= neuralNetwork() COST_LIST = [] inputs = [ np.array([[0,0]]), np.array([[0,1]]), np.array([[1,0]]), np.array([[1,1]])] for epoch in xrange(1,EPOCHS): cost = 0 for i in inputs: X = i #inputs y = xor(X[0][0],X[0][1]) cost += nn.costFunction(X,y)[0] djw1,djw2 = nn.costFunctionPrime(X,y) nn.W1 = nn.W1 - SCALAR*djw1 nn.W2 = nn.W2 - SCALAR*djw2 COST_LIST.append(cost) plt.plot(np.arange(1,EPOCHS),COST_LIST) plt.ylim(0,1) plt.xlabel(''Epochs'') plt.ylabel(''Loss'') plt.title(str(''Epochs: ''+str(EPOCHS)+'', Scalar: ''+str(SCALAR))) plt.show() inputs = [ np.array([[0,0]]), np.array([[0,1]]), np.array([[1,0]]), np.array([[1,1]])] print "X/ty/ty_hat" for inp in inputs: print (inp[0][0],inp[0][1]),"/t",xor(inp[0][0],inp[0][1]),"/t",round(nn.forward(inp)[0][0],4)

Resultado final:

X y y_hat (0, 0) 0 0.0 (0, 1) 1 0.9997 (1, 0) 1 0.9997 (1, 1) 0 0.0005

Los pesos obtenidos después del entrenamiento fueron:

nn.w1

[ [-0.81781753 0.71323677] [ 0.48803631 -0.71286155] ]

nn.w2

[ [ 2.04849235] [ 1.40170791] ]

Encontré la siguiente serie de Youtube extremadamente útil para entender las redes neuronales: redes neuronales desmitificadas

Solo hay poco que sé y también eso se puede explicar en esta respuesta. Si desea una mejor comprensión de las redes neuronales, le sugiero que consulte el siguiente enlace: cs231n: Modelando una neurona