TensorFlow深度學(xué)習(xí)筆記 循環(huán)神經(jīng)網(wǎng)絡(luò)實(shí)踐

轉(zhuǎn)載請(qǐng)注明作者:夢(mèng)里風(fēng)林
Github工程地址:https://github.com/ahangchen/GDLnotes
歡迎star,有問(wèn)題可以到Issue區(qū)討論
官方教程地址
視頻/字幕下載

加載數(shù)據(jù)

  • 使用text8作為訓(xùn)練的文本數(shù)據(jù)集

text8中只包含27種字符:小寫(xiě)的從a到z忘闻,以及空格符。如果把它打出來(lái)茉帅,讀起來(lái)就像是去掉了所有標(biāo)點(diǎn)的wikipedia。

  • 直接調(diào)用lesson1中maybe_download下載text8.zip
  • 用zipfile讀取zip內(nèi)容為字符串媒殉,并拆分成單詞list
  • 用connections模塊統(tǒng)計(jì)單詞數(shù)量并找出最常見(jiàn)的單詞

達(dá)成隨機(jī)取數(shù)據(jù)的目標(biāo)

構(gòu)造計(jì)算單元

embeddings = tf.Variable(
        tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
  • 構(gòu)造一個(gè)vocabulary_size x embedding_size的矩陣担敌,作為embeddings容器摔敛,
  • 有vocabulary_size個(gè)容量為embedding_size的向量廷蓉,每個(gè)向量代表一個(gè)vocabulary,
  • 每個(gè)向量的中的分量的值都在-1到1之間隨機(jī)分布
embed = tf.nn.embedding_lookup(embeddings, train_dataset)
  • 調(diào)用tf.nn.embedding_lookup马昙,索引與train_dataset對(duì)應(yīng)的向量桃犬,相當(dāng)于用train_dataset作為一個(gè)id,去檢索矩陣中與這個(gè)id對(duì)應(yīng)的embedding
loss = tf.reduce_mean(
        tf.nn.sampled_softmax_loss(softmax_weights, softmax_biases, embed,
                                   train_labels, num_sampled, vocabulary_size))
  • 采樣計(jì)算訓(xùn)練損失
optimizer = tf.train.AdagradOptimizer(1.0).minimize(loss)
  • 自適應(yīng)梯度調(diào)節(jié)器行楞,調(diào)節(jié)embedding列表的數(shù)據(jù)攒暇,使得偏差最小

  • 預(yù)測(cè),并用cos值計(jì)算預(yù)測(cè)向量與實(shí)際數(shù)據(jù)的夾角作為預(yù)測(cè)準(zhǔn)確度(相似度)指標(biāo)

傳入數(shù)據(jù)進(jìn)行訓(xùn)練

  • 切割數(shù)據(jù)用于訓(xùn)練子房,其中:
data_index = (data_index + 1) % len(data)
  • 依舊是每次取一部分隨機(jī)數(shù)據(jù)傳入
    • 等距離截取一小段文本
    • 構(gòu)造訓(xùn)練集:每個(gè)截取窗口的中間位置作為一個(gè)train_data
    • 構(gòu)造標(biāo)簽:每個(gè)截取窗口中形用,除了train_data之外的部分,隨機(jī)取幾個(gè)成為一個(gè)list证杭,作為label(這里只隨機(jī)取了一個(gè))
    • 這樣就形成了根據(jù)目標(biāo)詞匯預(yù)測(cè)上下文的機(jī)制田度,即Skip-gram
  • 訓(xùn)練100001次,每2000次輸出這兩千次的平均損失
  • 每10000次計(jì)算相似度解愤,并輸出與驗(yàn)證集中的詞最接近的詞匯列表
  • 用tSNE降維呈現(xiàn)詞匯接近程度
  • 用matplotlib繪制結(jié)果

實(shí)現(xiàn)代碼見(jiàn)word2vec.py

CBOW

上面訓(xùn)練的是Skip-gram模型镇饺,是根據(jù)目標(biāo)詞匯預(yù)測(cè)上下文鸽斟,而word2vec還有一種方式桅狠,CBOW,根據(jù)上下文預(yù)測(cè)目標(biāo)詞匯碴开。

實(shí)際上就是將Skip-gram中的輸入輸出反過(guò)來(lái)哼鬓。

  • 修改截取數(shù)據(jù)的方式

    • 構(gòu)造標(biāo)簽:每個(gè)截取窗口的中間位置作為一個(gè)train_label
    • 構(gòu)造訓(xùn)練集:每個(gè)截取窗口中监右,除了train_label之外的部分,作為train_data(這里只隨機(jī)取了一個(gè))
    • 這樣就形成了根據(jù)上下文預(yù)測(cè)目標(biāo)詞匯的機(jī)制异希,即CBOW
  • 分別從embeding里找到train_data里每個(gè)word對(duì)應(yīng)的vector健盒,用tf.reduce_sum將其相加,將相加結(jié)果與train_label比較

# Look up embeddings for inputs.
embed = tf.nn.embedding_lookup(embeddings, train_dataset)
# sum up vectors on first dimensions, as context vectors
embed_sum = tf.reduce_sum(embed, 0)
  • 訓(xùn)練中依舊是調(diào)節(jié)embeding的參數(shù)來(lái)優(yōu)化loss
  • 訓(xùn)練結(jié)果如下圖,可以看到不同單詞的接近程度


代碼見(jiàn):
cbow.py

RNN 造句

整體思路是味榛,以一個(gè)文本中的一個(gè)詞作為train data椭坚,后續(xù)的所有詞作為train label,從而能夠根據(jù)一個(gè)給定詞搏色,預(yù)測(cè)后續(xù)的片段善茎。

訓(xùn)練數(shù)據(jù)

  • BatchGenerator
  • text: 全部的文本數(shù)據(jù)
  • text_size:全部文本的字符串長(zhǎng)度
  • batch_size:每段訓(xùn)練數(shù)據(jù)的大小
  • num_unrollings:要生成的訓(xùn)練數(shù)據(jù)段的數(shù)目
  • segment:整個(gè)訓(xùn)練數(shù)據(jù)集可以分成幾個(gè)訓(xùn)練數(shù)據(jù)片段
  • cursor:重要,
    • 一開(kāi)始記錄每個(gè)訓(xùn)練數(shù)據(jù)片段的起始位置坐標(biāo)频轿,即這個(gè)片段位于text的哪個(gè)index
    • 執(zhí)行next_batch生成一個(gè)訓(xùn)練數(shù)據(jù)的時(shí)候垂涯,游標(biāo)會(huì)從初始位置自增,直到取夠batch_size個(gè)數(shù)據(jù)
  • last_batch:上一個(gè)訓(xùn)練數(shù)據(jù)片段
  • 每調(diào)用一次next航邢,生成一個(gè)num_unrollings長(zhǎng)的array耕赘,以last_batch開(kāi)頭,跟著num_unrollings個(gè)batch
  • 每個(gè)batch的作為train_input膳殷,每個(gè)batch后面的一個(gè)batch作為train_label操骡,每個(gè)step訓(xùn)練num_unrolling個(gè)batch

lstm-cell

  • 為了解決消失的梯度問(wèn)題,引入lstm-cell赚窃,增強(qiáng)model的記憶能力
  • 根據(jù)這篇論文設(shè)計(jì)lstm-cell: http://arxiv.org/pdf/1402.1128v1.pdf
  • 分別有三個(gè)門(mén):輸入門(mén)册招,遺忘門(mén),輸出門(mén)勒极,構(gòu)成一個(gè)cell
    • 輸入數(shù)據(jù)是num_nodes個(gè)詞是掰,可能有vocabulary_size種詞
    • 輸入門(mén):
  input_gate = sigmoid(i * ix + o * im + ib)
- 給輸入乘一個(gè)vocabulary_size * num_nodes大小的矩陣,給輸出乘一個(gè)num_nodes * num_nodes大小的矩陣;
- 用這兩個(gè)矩陣調(diào)節(jié)對(duì)輸入數(shù)據(jù)的取舍程度
- 用sigmoid這個(gè)非線(xiàn)性函數(shù)進(jìn)行激活
  • 遺忘門(mén):
  forget_gate = sigmoid(i * fx + o * fm + fb)

思路同輸入門(mén)辱匿,用以對(duì)歷史數(shù)據(jù)做取舍

  • 輸出門(mén):
  output_gate = sigmoid(i * ox + o * om + ob)

思路同輸入門(mén)键痛,用以對(duì)輸出狀態(tài)做取舍

  • 組合:
  update = i * cx + o * cm + cb
  state = forget_gate * state + input_gate * tanh(update)
  lstm_cell = output_gate * tanh(state)
- 用同樣的方式構(gòu)造新?tīng)顟B(tài)update
- 用遺忘門(mén)處理歷史狀態(tài)state
- 用tanh激活新?tīng)顟B(tài)update
- 用輸入門(mén)處理新?tīng)顟B(tài)update
- 整合新舊狀態(tài),再用tanh激活狀態(tài)state
- 用輸出門(mén)處理state

lstm優(yōu)化

上面的cell中匾七,update絮短,output_gate,forget_gate乐尊,input_gate計(jì)算方法都是一樣的戚丸,
可以把四組參數(shù)分別合并,一次計(jì)算扔嵌,再分別取出:

values = tf.split(1, gate_count, tf.matmul(i, input_weights) + tf.matmul(o, output_weights) + bias)
input_gate = tf.sigmoid(values[0])
forget_gate = tf.sigmoid(values[1])
update = values[2]

再將lstm-cell的輸出扔到一個(gè)WX+b中調(diào)整作為輸出

實(shí)現(xiàn)代碼見(jiàn)singlew_lstm.py

Optimizer

  • 采用one-hot encoding作為label預(yù)測(cè)
  • 采用交叉熵計(jì)算損失
  • 引入learning rate decay

Flow

  • 填入訓(xùn)練數(shù)據(jù)到placeholder中
  • 驗(yàn)證集的準(zhǔn)確性用logprob來(lái)計(jì)算限府,即對(duì)可能性取對(duì)數(shù)
  • 每10次訓(xùn)練隨機(jī)挑取5個(gè)字母作為起始詞,進(jìn)行造句測(cè)試
  • 你可能注意到輸出的sentence是由sample得到的詞組成的痢缎,而非選擇概率最高的詞胁勺,這是因?yàn)椋绻恢比「怕首罡叩脑~独旷,最后會(huì)一直重復(fù)這個(gè)概率最高的詞

實(shí)現(xiàn)代碼見(jiàn)lstm.py

Beam Search

上面的流程里署穗,每次都是以一個(gè)字符作為單位寥裂,可以使用多一點(diǎn)的字符做預(yù)測(cè),取最高概率的那個(gè)案疲,防止特殊情況導(dǎo)致的誤判

在這里我們?cè)黾幼址麨?個(gè)封恰,形成bigram,代碼見(jiàn):bigram_lstm.py

主要通過(guò)BigramBatchGenerator類(lèi)實(shí)現(xiàn)

Embedding look up

由于bigram情況下褐啡,vocabulary_size變?yōu)?27*27個(gè)诺舔,使用one-hot encoding 做predict的話(huà)會(huì)產(chǎn)生非常稀疏的矩陣,浪費(fèi)算力备畦,計(jì)算速度慢

因此引入embedding_lookup,代碼見(jiàn)embed_bigram_lstm.py

  • 數(shù)據(jù)輸入:BatchGenerator不再生成one-hot-encoding的向量作為輸入低飒,而是直接生成bigram對(duì)應(yīng)的index列表
  • embedding look up調(diào)整embedding,使bigram與vector對(duì)應(yīng)起來(lái)
  • 將embedding look up的結(jié)果喂給lstm cell即可
  • 輸出時(shí)懂盐,需要將label和output都轉(zhuǎn)為One-hot-encoding褥赊,才能用交叉熵和softmax計(jì)算損失
  • 在tensor里做data到one-hot-encoding轉(zhuǎn)換時(shí),主要依賴(lài)tf.gather函數(shù)
  • 在對(duì)valid數(shù)據(jù)做轉(zhuǎn)換時(shí)莉恼,主要依賴(lài)one_hot_voc函數(shù)

Drop out

  • 在lstm cell中對(duì)input和output做drop out
  • Refer to this article

Seq2Seq

  • 最后一個(gè)問(wèn)題是拌喉,將一個(gè)句子中每個(gè)詞轉(zhuǎn)為它的逆序字符串,也就是一個(gè)seq到seq的轉(zhuǎn)換
  • 正經(jīng)的實(shí)現(xiàn)思路是类垫,word 2 vector 2 lstm 2 vector 2 word
  • 不過(guò)tensorflow已經(jīng)有了這樣一個(gè)模型來(lái)做這件事情:Seq2SeqModel司光,關(guān)于這個(gè)模型可以看這個(gè)分析
    以及tensorflow的example
  • 只需要從batch中,根據(jù)字符串逆序的規(guī)律生成target sequence悉患,放到seq2seqmodel里即可,主要依賴(lài)rev_id函數(shù)
  • 實(shí)現(xiàn)見(jiàn)seq2seq.py
  • 注意榆俺,用Seq2SeqModel的時(shí)候售躁,size和num_layer會(huì)在學(xué)習(xí)到正確的規(guī)律前就收斂,我把它調(diào)大了一點(diǎn)
def create_model(sess, forward_only):
    model = seq2seq_model.Seq2SeqModel(source_vocab_size=vocabulary_size,
                                       target_vocab_size=vocabulary_size,
                                       buckets=[(20, 21)],
                                       size=256,
                                       num_layers=4,
                                       max_gradient_norm=5.0,
                                       batch_size=batch_size,
                                       learning_rate=1.0,
                                       learning_rate_decay_factor=0.9,
                                       use_lstm=True,
                                       forward_only=forward_only)
    return model
  • 參數(shù)含義
    • source_vocab_size: size of the source vocabulary.
    • target_vocab_size: size of the target vocabulary.
    • buckets: a list of pairs (I, O), where I specifies maximum input length
      that will be processed in that bucket, and O specifies maximum output
      length. Training instances that have inputs longer than I or outputs
      longer than O will be pushed to the next bucket and padded accordingly.
      We assume that the list is sorted, e.g., [(2, 4), (8, 16)].
    • size: number of units in each layer of the model.
    • num_layers: number of layers in the model.
    • max_gradient_norm: gradients will be clipped to maximally this norm.
    • batch_size: the size of the batches used during training;
      the model construction is independent of batch_size, so it can be
      changed after initialization if this is convenient, e.g., for decoding.
    • learning_rate: learning rate to start with.
    • learning_rate_decay_factor: decay learning rate by this much when needed.
    • use_lstm: if true, we use LSTM cells instead of GRU cells.
    • num_samples: number of samples for sampled softmax.
    • forward_only: if set, we do not construct the backward pass in the model.

參考鏈接

覺(jué)得我的文章對(duì)您有幫助的話(huà)茴晋,不妨點(diǎn)個(gè)star陪捷?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市诺擅,隨后出現(xiàn)的幾起案子市袖,更是在濱河造成了極大的恐慌,老刑警劉巖烁涌,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苍碟,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡撮执,警方通過(guò)查閱死者的電腦和手機(jī)微峰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)抒钱,“玉大人蜓肆,你說(shuō)我怎么就攤上這事颜凯。” “怎么了仗扬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵症概,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我早芭,道長(zhǎng)穴豫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任逼友,我火速辦了婚禮精肃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘帜乞。我一直安慰自己司抱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布黎烈。 她就那樣靜靜地躺著习柠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪照棋。 梳的紋絲不亂的頭發(fā)上资溃,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音烈炭,去河邊找鬼溶锭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛符隙,可吹牛的內(nèi)容都是我干的趴捅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼霹疫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼拱绑!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起丽蝎,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤猎拨,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后屠阻,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體红省,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年栏笆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了类腮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛉加,死狀恐怖蚜枢,靈堂內(nèi)的尸體忽然破棺而出缸逃,到底是詐尸還是另有隱情,我是刑警寧澤厂抽,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布需频,位于F島的核電站,受9級(jí)特大地震影響筷凤,放射性物質(zhì)發(fā)生泄漏昭殉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一藐守、第九天 我趴在偏房一處隱蔽的房頂上張望挪丢。 院中可真熱鬧,春花似錦卢厂、人聲如沸乾蓬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)任内。三九已至,卻和暖如春融柬,著一層夾襖步出監(jiān)牢的瞬間死嗦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工粒氧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留越除,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓靠欢,卻偏偏與公主長(zhǎng)得像廊敌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子门怪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容