机器学习入门:第十五章 递归神经网络
前言
BP神經網絡,訓練的時候,給定一組輸入和輸出,不斷的對權值進行訓練,使得輸出達到穩定。但BP神經網絡并不是適合所有的場景,并不真正的體現出某些場景的真正特點。回到經典的概率論問題,拋硬幣問題,假設你已經拋了100次的,90次是正面的,10次是反面的,問現在繼續在拋一次,出現正面的概率是多少?如果沒有前面幾次的經驗,很正常的會認為再次出現正面的概率是50%,但由于我們之前有對這個進行了實驗,即有了經驗了,按照貝葉斯定律,出現正面的概率肯定會大于50%。BP神經網絡也少了對前面結果的一種反饋。
常見,易懂的受到前位影響的算法,加法算法。十位的結果,所到個位結果的影響,因為可能有進位,同樣,百位的結果所到十位的影響。如圖
這種受到前位影響的算法非常的常見,而經典BP神經網絡并不能很好的反映這種算法的特性,需要就經典的BP神經網絡進行優化和改造,也就是引進前位,歷史數據對網絡的影響,使其具備時序性。通過歷史數據的關聯來推測后續的事情。
遞歸神經網絡RNN
從前面加法算法的動態圖中,對現有的BP神經網絡進行改造,也就是加入前位的結果對于后續網絡的影響。
這里把BP神經網絡設計成上圖的形式,很形象的揭示了遞歸神經網絡的特點,前向的結果,作為下一個輸入,影響下一個網絡的結果。遞歸神經網絡,在很多方向已經取得了很好的成果。而一種特殊的遞歸神經網絡Long Short Term 網絡(LSTM),取到的結果最為璀璨,是這個方向的明星。
LSTM結構:
來看看LSTM的實現。關于LSTM可以進一步的參看,http://nicodjimenez.github.io/2014/08/08/lstm.html 和 https://github.com/nicodjimenez/lstm/blob/master/lstm.py,詳細的給出了LSTM的求解過程。
算法的迭代過程在:
http://nicodjimenez.github.io/2014/08/08/lstm.html
https://github.com/nicodjimenez/lstm
算法跟BP神經網絡沒有太大的不同,但要注意的還是各個變量的增量和迭代問題。
使用RNN實現加法過程
在簡化一點的方式如下圖:
如果去掉layer_1層,那么就是一個最簡單的BP神經網絡了。這里引入了layer_1層,使得經典的BP神經網絡多了一個輸入,layer_1層在加法算法中,表示的是前一個輸入就可以反映出加法算法的特性,從結構來看,這個LSTM的變形并不是非常的復雜,但現在就重要的就是如何計算出各個層次的增量,然后進行迭代了。
構建一個二進制的網絡,輸入為兩個節點,一個隱層有16個節點,一個中間層有16個節點用來存放進位。
for position in range(binary_dim):# generate input and outputX = np.array([[a[binary_dim - position - 1], b[binary_dim - position - 1]]])y = np.array([[c[binary_dim - position - 1]]]).T# hidden layer (input ~+ prev_hidden)layer_1 = sigmoid(np.dot(X, synapse_0) + np.dot(layer_1_values[-1], synapse_h))# output layer (new binary representation)layer_2 = sigmoid(np.dot(layer_1, synapse_1))# did we miss?... if so by how much?layer_2_error = y - layer_2layer_2_deltas.append((layer_2_error) * sigmoid_output_to_derivative(layer_2))overallError += np.abs(layer_2_error[0])# decode estimate so we can print it outd[binary_dim - position - 1] = np.round(layer_2[0][0])# store hidden layer so we can use it in the next timesteplayer_1_values.append(copy.deepcopy(layer_1))加數和被加數作為輸入,計算隱層和中間層的誤差,這是一個加法遞歸神經網絡,可以看成進制放在中間層中,這里要記住這個加法器輸入層不是八個節點,而只有兩個,也是一種最小加法器。
訓練時也是使用誤差傳播的方式,這里主要需要解決導數問題python的代碼實現:
# compute sigmoid nonlinearity def sigmoid(x):output = 1/(1+np.exp(-x))return output# convert output of sigmoid function to its derivative def sigmoid_output_to_derivative(output):return output*(1-output)計算中間結果,可以參看LSTM的過程:
for position in range(binary_dim):X = np.array([[a[position], b[position]]])layer_1 = layer_1_values[-position - 1]prev_layer_1 = layer_1_values[-position - 2]# error at output layerlayer_2_delta = layer_2_deltas[-position - 1]# error at hidden layerlayer_1_delta = (future_layer_1_delta.dot(synapse_h.T) + \layer_2_delta.dot(synapse_1.T)) * sigmoid_output_to_derivative(layer_1)# let's update all our weights so we can try againsynapse_1_update += np.atleast_2d(layer_1).T.dot(layer_2_delta)synapse_h_update += np.atleast_2d(prev_layer_1).T.dot(layer_1_delta)synapse_0_update += X.T.dot(layer_1_delta)future_layer_1_delta = layer_1_delta變量的更新:
synapse_1_update += np.atleast_2d(layer_1).T.dot(layer_2_delta) synapse_h_update += np.atleast_2d(prev_layer_1).T.dot(layer_1_delta) synapse_0_update += X.T.dot(layer_1_delta)其中 layer_1_delta變量為兩個變量的和:
layer_1_delta = (future_layer_1_delta.dot(synapse_h.T) + layer_2_delta.dot(synapse_1.T)) * sigmoid_output_to_derivative(layer_1)完整的迭代過程在:
https://iamtrask.github.io/2015/11/15/anyone-can-code-lstm/
在遞歸神經網絡中,跟經典的BP神經網絡在結構上并沒有太多的不同,最關鍵的點,還是在求解增量,進行迭代。
遞歸神經網絡的應用
遞歸神經網絡跟BP神經網絡,最大的不同是引進了時序,可以根據以往的數據來推測未來的事件。這是現在比較熱門的一個方向。比較多的應用實在語音和文本的處理上,網上有相當多的關于遞歸神經網絡的應用,比如寫出像汪峰一樣的歌詞,默寫唐詩,寫冷段子等。但要寫出像樣的歌詞和詩詞,還需要做很多的處理,如果把遞歸神經網絡應用在推薦系統里,也會得到不錯的效果。
參考
http://blog.csdn.net/zzukun/article/details/49968129
http://www.jianshu.com/p/9dc9f41f0b29
http://nicodjimenez.github.io/2014/08/08/lstm.html
https://github.com/nicodjimenez/lstm
http://blog.csdn.net/longxinchen_ml/article/details/51253526
https://github.com/karpathy/char-rnn
http://blog.csdn.net/v_july_v/article/details/52796239
總結
以上是生活随笔為你收集整理的机器学习入门:第十五章 递归神经网络的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小程序二维码生成中的一些坑
- 下一篇: 张宇数学基础30讲——数列极限---笔记