考虑一个三层的神经网络如下:
并且给参数赋上初值。只考虑一个训练数据X=(0.05,0.10)及Y=(0.01,0.99),将系数w和b向量化,输入层与隐藏层之间的系数记为W1是2*2的系数矩阵, b1是2*1的列向量,隐藏层与输出层之间的系数为W2也是2*2的矩阵,b2是2*1的列向量,输入记为x和y都是2*1的向量。
则前馈的计算过程为:
这里的激活函数选为sigmoid函数
loss函数记为:
为了更新W1,b1,W2,b2,需要计算E关于它们的梯度。为了符号的简单,记:
不加证明地得到BP算法的四个核心公式:
注意,这里的
表示输入x。
学习率记为alpha,则可以根据上述四个式子更新权重,详细代码如下:
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 15 19:58:51 2018
@author: hasee
"""
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
def sigmoid_der(x):
return sigmoid(x)*(1-sigmoid(x))
class BPNetWork(object):
def __init__(self):
self.alpha=0.5 #学习率
self.W1=np.array([[0.15,0.20],[0.25,0.30]]) #输入层到卷积层的系数矩阵
self.b1=np.array([[0.35],[0.35]])
self.W2=np.array([[0.40,0.45],[0.50,0.55]])
self.b2=np.array([[0.90],[0.60]])
self.input=np.array([[0.05],[0.10]])
self.output=np.array([[0.05],[0.9]])
def feedfoward(self):
Z1=np.matmul(self.W1,self.input)+self.b1
A1=sigmoid(Z1)
Z2=np.matmul(self.W2,A1)+self.b2
A2=sigmoid(Z2)
return Z1,A1,Z2,A2
def propogate(self):
z1,a1,z2,a2=self.feedfoward()
delta2=-(self.output-a2)*sigmoid_der(z2)
self.W2-=(self.alpha)*np.matmul(delta2,np.transpose(a1))
self.b2-=self.alpha*delta2
delta1=np.matmul(np.transpose(self.W2),delta2)*sigmoid_der(z2)
self.W1-=self.alpha*np.matmul(np.transpose(self.input),delta1)
self.b1-=self.alpha*delta1
if __name__ == '__main__':
BP=BPNetWork()
BP.__init__()
for i in range(10000):
BP.propogate()
if i%100==0:
_,_,_,a2=BP.feedfoward()
print(a2)