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()
下面是推導時的手稿: