这种方法被称为梯度下降。通过知道哪种方式来改变我们的权重,我们的输出只能得到更准确的结果。
以下是我们将如何计算对权重的增量更改:
通过计算预测输出和实际输出(y)的差值来找出输出层(o)的误差幅度,
将sigmoid激活函数的导数应用于输出图层错误。我们把这个结果称为delta输出和。
使用输出层误差的delta输出总和来计算我们的z2(隐藏)层通过使用我们的第二个权重矩阵执行点积来导致输出误差的程度。我们可以称之为z2错误。
应用我们的sigmoid激活函数的导数(与第2步一样),计算z2层的delta输出和。
通过执行输入层与隐藏(z2)增量输出和的点积来调整第一层的权重。对于第二层,执行隐藏(z2)图层和输出(o)delta输出和的点积。
计算delta输出和然后应用sigmoid函数的导数对于反向传播非常重要。S型的衍生物,也被称为S型素数,将给我们输出和的激活函数的变化率或斜率。
让我们继续Neural_Network通过添加sigmoidPrime(sigmoid的衍生)函数来编写我们的类:
defsigmoidPrime(self,s):
#derivativeofsigmoid
returns*(1-s)
然后,我们要创建我们的backward传播函数,它执行上述四个步骤中指定的所有内容:
defbackward(self,X,y,o):
#backwardpropgatethroughthenetwork
self.o_error=y-o#errorinoutput
self.o_delta=self.o_error*self.sigmoidPrime(o)#applyingderivativeofsigmoidtoerror
self.z2_error=self.o_delta.dot(self.W2.T)#z2error:howmuchourhiddenlayerweightscontributedtooutputerror
self.z2_delta=self.z2_error*self.sigmoidPrime(self.z2)#applyingderivativeofsigmoidtoz2error
self.W1+=X.T.dot(self.z2_delta)#adjustingfirstset(input-->hidden)weights
self.W2+=self.z2.T.dot(self.o_delta)#adjustingsecondset(hidden-->output)weights
我们现在可以通过启动前向传播来定义我们的输出,并通过在函数中调用后向函数来启动它train:
deftrain(self,X,y):
o=self.forward(X)
self.backward(X,y,o)
为了运行网络,我们所要做的就是运行该train功能。当然,我们会想要做到这一点,甚至可能是成千上万次。所以,我们将使用一个for循环。
NN=Neural_Network()
foriinxrange(1000):#trainstheNN1,000times
print"Input:\n"+str(X)
print"ActualOutput:\n"+str(y)
print"PredictedOutput:\n"+str(NN.forward(X))
print"Loss:\n"+str(np.mean(np.square(y-NN.forward(X))))#meansumsquaredloss
print"\n"
NN.train(X,y)
太棒了,我们现在有一个神经网络!如何使用这些训练后的权重来预测我们不知道的测试分数?
预测
为了预测我们的输入测试分数[4,8],我们需要创建一个新的数组来存储这些数据xPredicted。
xPredicted=np.array(([4,8]),dtype=float)
我们还需要按照我们对输入和输出变量所做的那样进行扩展:
xPredicted=xPredicted/np.amax(xPredicted,axis=0)#maximumofxPredicted(ourinputdatafortheprediction)
然后,我们将创建一个打印我们的预测输出的新函数xPredicted。相信与否,我们必须运行的是forward(xPredicted)返回输出!
defpredict(self):
print"Predicteddatabasedontrainedweights:";
print"Input(scaled):\n"+str(xPredicted);
print"Output:\n"+str(self.forward(xPredicted));
要运行这个函数,只需在for循环中调用它。
NN.predict()
如果你想保存你的训练重量,你可以这样做np.savetxt:
defsaveWeights(self):
np.savetxt("w1.txt",self.W1,fmt="%s")
np.savetxt("w2.txt",self.W2,fmt="%s")
最终的结果如下:
importnumpyasnp
#X=(hoursstudying,hourssleeping),y=scoreontest,xPredicted=4hoursstudying&8hourssleeping(inputdataforprediction)
X=np.array(([2,9],[1,5],[3,6]),dtype=float)
y=np.array(([92],[86],[89]),dtype=float)
xPredicted=np.array(([4,8]),dtype=float)
#scaleunits
X=X/np.amax(X,axis=0)#maximumofXarray
xPredicted=xPredicted/np.amax(xPredicted,axis=0)#maximumofxPredicted(ourinputdatafortheprediction)
y=y/100#maxtestscoreis100
classNeural_Network(object):
def__init__(self):
#parameters
self.inputSize=2
self.outputSize=1
self.hiddenSize=3
#weights
self.W1=np.random.randn(self.inputSize,self.hiddenSize)#(3x2)weightmatrixfrominputtohiddenlayer
self.W2=np.random.randn(self.hiddenSize,self.outputSize)#(3x1)weightmatrixfromhiddentooutputlayer
defforward(self,X):
#forwardpropagationthroughournetwork
self.z=np.dot(X,self.W1)#dotproductofX(input)andfirstsetof3x2weights
self.z2=self.sigmoid(self.z)#activationfunction
self.z3=np.dot(self.z2,self.W2)#dotproductofhiddenlayer(z2)andsecondsetof3x1weights
o=self.sigmoid(self.z3)#finalactivationfunction
returno
defsigmoid(self,s):
#activationfunction
return1/(1+np.exp(-s))
defsigmoidPrime(self,s):
#derivativeofsigmoid
returns*(1-s)
defbackward(self,X,y,o):
#backwardpropgatethroughthenetwork
self.o_error=y-o#errorinoutput
self.o_delta=self.o_error*self.sigmoidPrime(o)#applyingderivativeofsigmoidtoerror
self.z2_error=self.o_delta.dot(self.W2.T)#z2error:howmuchourhiddenlayerweightscontributedtooutputerror
self.z2_delta=self.z2_error*self.sigmoidPrime(self.z2)#applyingderivativeofsigmoidtoz2error
self.W1+=X.T.dot(self.z2_delta)#adjustingfirstset(input-->hidden)weights
self.W2+=self.z2.T.dot(self.o_delta)#adjustingsecondset(hidden-->output)weights
deftrain(self,X,y):
o=self.forward(X)
self.backward(X,y,o)
defsaveWeights(self):
np.savetxt("w1.txt",self.W1,fmt="%s")
np.savetxt("w2.txt",self.W2,fmt="%s")
defpredict(self):
print"Predicteddatabasedontrainedweights:";
print"Input(scaled):\n"+str(xPredicted);
print"Output:\n"+str(self.forward(xPredicted));
NN=Neural_Network()
foriinxrange(1000):#trainstheNN1,000times
print"#"+str(i)+"\n"
print"Input(scaled):\n"+str(X)
print"ActualOutput:\n"+str(y)
print"PredictedOutput:\n"+str(NN.forward(X))
print"Loss:\n"+str(np.mean(np.square(y-NN.forward(X))))#meansumsquaredloss
print"\n"
NN.train(X,y)
NN.saveWeights()
NN.predict()
为了看到网络的实际准确程度,我跑了10万次训练,看看能否得到完全正确的输出结果。这就是我得到的:
#99999
Input(scaled):
[[0.666666671.]
[0.333333330.55555556]
[1.0.66666667]]
ActualOutput:
[[0.92]
[0.86]
[0.89]]
PredictedOutput:
[[0.92]
[0.86]
[0.89]]
Loss:
1.94136958194e-18
Predicteddatabasedontrainedweights:
Input(scaled):
[0.51.]
Output:
[0.91882413]