BP神经网络python代码实现#超详细-小白快速入门
注释为当前行的注释或者是下一行的注释。
import numpy as np#科学计算的基础包
# 定义sigmoid函数及其求导,deriv=False时进行前向传播的运算,deriv=True进行反向传播的运算
# 即当derive为假时,不计算导数,反之计算,控制传播方向。
def sigmoid(x, deriv=False):
if (deriv == True):# 求导
return x * (1 - x)#这里x=1/(1+exp(-x)),是sigmoid函数求导后的结果根据前向传播,x=sigmoid(x),求导需要(sigmoid(x)',e,而这里的return语句中的x替换为sigmoid(x)与求导等价
return 1 / (1 + np.exp(-x)) #前向传播
#输入4个样本,每个样本三个特征值
X = np.array([[0, 0, 1],
[0, 1, 1],
[1, 0, 1],
[1, 1, 1]])
print(X.shape)
#每一行对应的类用0,1表示
y = np.array([[0, 1, 1, 0]]).T
print(y.shape)
# 初始化权重weight01的维数与样本特征与神经元的个数有关,random初始化的值在(0,1)的半开区间内,乘2减1后控制w0的值在(-1.+1)区间上
weight01 = 2 * np.random.random((3, 4)) - 1#生成生成3行 4列的随机浮点数,w01左边连3个特征,右边连4个神经元,浮点数范围:(0,1)
weight12 = 2 * np.random.random((4, 2)) - 1#生成生成4行 2列的随机浮点数,w12左边连4个神经元,右边连2个神经元,浮点数范围:(0,1)
weight23 = 2 * np.random.random((2, 1)) - 1#生成生成2行 1列的随机浮点数,w23左边连两个神经元,右边连一个输出值,浮点数范围:(0,1)
# 初始化偏倚
b1 = 2 * np.random.random((1, 4)) - 1#第一个隐层四个神经元
b2 = 2 * np.random.random((1, 2)) - 1#第二个隐层两个神经元
b3 = 2 * np.random.random((1, 1)) - 1#输出层一个神经元
bias1 = np.array([b1[0], b1[0], b1[0], b1[0]])#array是数组函数
print(bias1)
bias2 = np.array([b2[0], b2[0], b2[0], b2[0]])
bias3 = np.array([b3[0], b3[0], b3[0], b3[0]])
# 开始训练
for j in range(60000):#迭代六万次
I0 = X#将x的值给l0,l0为输入层
O0 = I0#4行3列
I1 = np.dot(O0, weight01) + bias1# 默认False,是进行前向传播
O1 = sigmoid(I1)#中间层经过第一层后的值,4行4列
I2 = np.dot(O1, weight12) + bias2# 默认False,是进行前向传播
O2 = sigmoid(I2)#中间层经过第二层后的值,4行2列
I3 = np.dot(O2, weight23) + bias3# 默认False,是进行前向传播
O3 = sigmoid(I3) #输出层的值,4行1列
f3_error = y - O3#输出层的值与期望的值的差异
if (j % 10000) == 0:
print("Error:" + str(np.mean(f3_error)))#每经过一万次迭代输出一次差异值的平均值,以便观察差异值是否减小
f3_delta = f3_error * sigmoid(O3, deriv=True)#w23对错误的贡献,反向传播,误差作为一个权重,误差越大权重越大
#print(f3_delta.shape),(4行1列)
f2_error = f3_delta.dot(weight23.T)#反向传播根据f3_delta得出,矩阵f3_delta乘w23的转置
f2_delta = f2_error * sigmoid(O2, deriv=True)#w12对错误的贡献,反向传播,误差作为一个权重,误差越大权重越大
#print(f2_delta.shape),(4行2列)
f1_error = f2_delta.dot(weight12.T)#反向传播根据f2_delta得出,矩阵f2_delta乘w12的转置
f1_delta = f1_error * sigmoid(O1, deriv=True)#w01对错误的贡献,反向传播,误差作为一个权重,误差越大权重越大
#print(f1_delta.shape),(4行4列)
weight23 += O2.T.dot(f3_delta)# 调整权重,根据反馈过来的结果对w23进行调节 , 因为从后往前,所以先更新w23
weight12 += O1.T.dot(f2_delta)# 调整权重,根据反馈过来的结果对w12进行调节
weight01 += O0.T.dot(f1_delta)# 调整权重,根据反馈过来的结果对w01进行调节
bias3 += f3_delta # 调整偏倚
bias2 += f2_delta
bias1 += f1_delta
print("outout after Training:")
print(O3)