1. 程式人生 > >【機器學習筆記23】神經網路(RNN)

【機器學習筆記23】神經網路(RNN)

基礎迴圈神經網路

在這裡插入圖片描述

迴圈神經網路(RNN)是一個由神經元和權值構成的有向圖,它的當前狀態與前一時刻的狀態和當前輸入決定,因此當前狀態也被稱為工作記憶。迴圈神經網路在時間序列上展開後如上圖所示,用於解決序列化的問題,諸如語音識別、語音合成、文字生成。

例子:利用RNN寫詩,本質上是在訓練後得到各個詞語的使用頻次和關聯規則,RNN可以知道在“秋”後面跟“月”“風”具有更大概率。但它並不知道它所寫的含義,從這個角度將寫詩其實是簡單的。RNN可以做到“吟詩一首”,而做不到“此情此景,我要吟詩一首”:)

模型推導如下

ot=g(Vst)o_t=g(Vs_t) st=f(Uxt+W

st1)s_t=f(Ux_t + Ws_{t-1}) 當前輸入 + 之前的狀態

因此根據上下式不斷的迭代可得到下一時刻

ot+1=g(Vf(Uxt+1+Wst))o_{t+1}=g(Vf(Ux_{t+1} + Ws_t))

雙向迴圈神經網路

在這裡插入圖片描述

在部分模型中光靠前文的推測還不夠,可能還需要後文的資訊反過來判斷。 例如我的手機壞了,我打算___新手機。這裡空格里利用新手機就很容易推測應該為買的可能性更大。

在雙向迴圈神經網路中輸出y1y_1同時取決於A1A_1'A1A_1

模型推導如下

ot=g(Vst+Vst)o_t=g(Vs_t + V's_t') st=f(Uxt+Wst1)s_t=f(Ux_t + Ws_{t-1}) st=f(Uxt+Wst+1)s_t'=f(U'x_t + W's_{t+1}') //差別在這裡,通過後文反推

BPTT訓練方法

TBD

RNN程式碼例子(keras,參考網上部分程式碼)
# -*- coding: utf-8 -*-

"""
說明:

RNN程式碼DEMO,對應的筆記《19.神經網路(RNN)》

作者:fredric

日期:2018-9-22

"""
 
from keras.layers import Dense,Activation
from keras.layers.recurrent import SimpleRNN
from keras.models import Sequential
from keras.optimizers import Adam
import numpy as np
 
### 載入資料
### Test.java是隨便Java專案裡找的一批程式碼合併到一個檔案裡
fin=open('./data/Test.java','rb')
lines=[]
for line in fin:
    line=line.strip().lower()
    line=line.decode('ascii','ignore')
    if len(line)==0:
        continue
    lines.append(line)
fin.close()
text=' '.join(lines)
 
"""
對樣本Test.java中的所有字元生成字典索引,包括:
char2index: '}': 0, 't': 1, 'k': 2 等
index2char: 0: '}', 1: 't', 2: 'k' 等
"""
chars=set([c for c in text])
nb_chars=len(chars)
char2index=dict((c,i) for i,c in enumerate(chars))
index2char=dict((i,c) for i,c in enumerate(chars))
 
SEQLEN=10
STEP=1
 
input_chars=[]
label_chars=[]
 

"""
不段以SEQLEN為長度,STEP為偏移生成input_chars和label_chars
舉例:
以原檔案程式碼package com.fredric為例子,生成

input_chars[0]: package co    label_chars[0]: m 
label_chars[1]: ackage com    label_chars[0]: . 

"""
for i in range(0,len(text)-SEQLEN,STEP):
    input_chars.append(text[i:i+SEQLEN])
    label_chars.append(text[i+SEQLEN])



"""
這裡將輸入向量利用char2index做了一個變換,例如:

第一個輸入的label輸出m,則對應字典中的 9: 'm',因此此時的y值為:
[False False False False False False False False False  True False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False]

同理x的值也被做了上述的變換,重要: 相當於所有的輸入被做了統一的編碼

"""

X=np.zeros((len(input_chars),SEQLEN,nb_chars),dtype=np.bool)
y=np.zeros((len(input_chars),nb_chars),dtype=np.bool)    
for i,input_char in enumerate(input_chars):
    for j,ch in enumerate(input_char):
        X[i,j,char2index[ch]]=1
    y[i,char2index[label_chars[i]]]=1


### 建立RNN網路
HIDDEN_SIZE = 128
BATCH_SIZE  = 128
TRAIN_STEP  = 500

model=Sequential()
model.add(SimpleRNN(HIDDEN_SIZE,return_sequences=False,input_shape=(SEQLEN,nb_chars), unroll=True))
model.add(Dense(nb_chars,activation='softmax'))
adam = Adam(0.001)
model.compile(loss='categorical_crossentropy',optimizer=adam)


### 進行訓練
for step in range(TRAIN_STEP):
    print("current step is #: %d"%(step))
    model.fit(X,y, batch_size=BATCH_SIZE, epochs=1)

### 對輸入字串進行預測 
_test_input = 'public cla'
_test_chars=set([t for t in _test_input])
_test=np.zeros((1, SEQLEN, nb_chars))

for i,ch in enumerate(_test_chars):
    _test[0,i,char2index[ch]]=1

pred=model.predict(_test,verbose=0)[0]
ypred=index2char[np.argmax(pred)]


## 輸出結果是the test input public cla get prediction i,貌似不好
print("the test input %s get prediction %s"%(_test_input, ypred))