2017-11-23 03:50
从下午推导公式到现在,成功完成了四层神经网络的构建和相关代码的编写,用这个神经网络和之前三层的神经网络相比较,发现了一些比较有趣的现象(三层的和四层的神经网络暂时简写为T_rnn和F_rnn,)。
首先,当训练次数较少时,T_rnn的结果更接近理想值,但两者相差并不大,训练次数增加后,F_rnn更接近理想值。
其次,之前忘了给F_rnn写更新b的代码,由此发现了更新b也是挺重要的,未添加代码前,与T_rnn差距在10^(-4)以内,添加代码后,差距在10^(-3)以内,且F_rnn的结果明显更接近理想值(均是在训练80次,alpha值在0.5是取得的数据)。
最后是速度,F_rnn所用的时间要比T_rnn多用0.3倍左右,单F_rnn拥有32个权值,而T_rnn只有16个,因此在连接程度上,F_rnn比T_rnn更加复杂,而速度只比T_rnn慢0.3倍,可见向量化处理的确是有作用的(T_rnn我为了更直观一点,是依次运算单个值的,并未向量化操作)。
下面是这个神经网络的结构图:
该神经网络的python3代码:
import numpy as np
def sigma(z):
return 1/(1+np.exp(-z))
def sigma_da(a):
return a*(1-a)
def run():
x=np.array([0.15,0.6,0.2])#输入
y=0.32#理想输出
np.random.seed(1)#加上这一条语句可以确保每次随机生成的数都一样
#初始化权值矩阵
w1=np.random.random((4,3))
w2=np.random.random((4,4))
w3=np.random.random(4)
#初始化截距项
b1=np.sum(np.random.random(1))
b2=np.sum(np.random.random(1))
b3=np.sum(np.random.random(1))
alpha=0.5#学习率,相当于梯度下降步长
m=100#循环次数
for i in range(m):
'''网络共分4层,输入层x、隐含层l1、隐含层l2、输出层y'''
#计算l1层
netl1=np.array([sum(x*w1[0]),sum(x*w1[1]),sum(x*w1[2]),sum(x*w1[3])])+b1
outl1=sigma(netl1)
#计算l2层 netl2=np.array([sum(outl1*w2[0]),sum(outl1*w2[1]),sum(outl1*w2[2]),sum(outl1*w2[3])])+b2
outl2=sigma(netl2)
#计算输出层
nety=sum(outl2*w3)+b3
outy=sigma(nety)
#总误差
Ey=0.5*(y-outy)*(y-outy)
#反向传播
#输出层误差
delta_y=-(y-outy)*sigma_da(outy)
#l2层误差
delta_l2=np.array([delta_y*w3[0]*sigma_da(outl2[0]),
delta_y*w3[1]*sigma_da(outl2[1]),
delta_y*w3[2]*sigma_da(outl2[2]),
delta_y*w3[3]*sigma_da(outl2[3])])
#l1层误差
delta_l1=np.array([sum(delta_l2*w2[0])*sigma_da(outl1[0]),
sum(delta_l2*w2[1])*sigma_da(outl1[1]),
sum(delta_l2*w2[2])*sigma_da(outl1[2]),
sum(delta_l2*w2[3])*sigma_da(outl1[3])])
#计算输入层和l1层之间的权值矩阵w1对整体误差的偏导
dw1=np.array([delta_l1*x[0],
delta_l1*x[1],
delta_l1*x[2]])
#更新w1
w1-=dw1.T*alpha
#计算截距项b1对整体误差的偏导
db1=sum(delta_l1)
#更新b1
b1-=db1*alpha
#计算l1层和l2层之间的权值矩阵w2对整体误差的偏导
dw2=np.array([delta_l2*outl1[0],
delta_l2*outl1[1],
delta_l2*outl1[2],
delta_l2*outl1[3]])
#更新w2
w2-=dw2.T*alpha
#计算截距项b2对整体误差的偏导
db2=sum(delta_l2)
#更新b2
b2-=db2*alpha
#计算l2层和输出层之间的权值矩阵w3对整体误差的偏导
dw3=delta_y*outl2
#更新w3
w3-=dw3*alpha
#计算截距项b3对整体误差的偏导
db3=delta_y
#更新b3
b3-=db3*alpha
#向屏幕打印训练完成后的结果
print(outy)
if __name__=='__main__':
run()
下面是推导时的手稿: