『TensotFlow』RNN/LSTM古詩生成


往期RNN相關工程實踐文章

『TensotFlow』基礎RNN網絡分類問題

『TensotFlow』RNN中文文本_上

『TensotFlow』基礎RNN網絡回歸問題

『TensotFlow』RNN中文文本_下_暨研究生開學感想

張量分析

預處理結果是二維數據,相當於batch條一維數據,每個數據對應一首詩,每個字是一個scalar;

embedding之后,將每個字映射為一個rnn_size大小的向量,數據變為三維;

經過遞歸神經網絡,輸出維度不變;

將之調整為二維數據,這里面第二維度(即每一行)對應一個字;

全連接映射,將每一個字由rnnsize的向量映射為一個長度為總字數的向量,這樣方便計算loss,實際計算loss時,會將label(二維向量,一行一首詩,字為scalar)拉伸為一維向量,每行只有一個字scalar,one_hot之后和此時數據正好對應,方便計算

SoftMax不改變張量形狀,只是將結果以概率分布的形式輸出

工程分析

代碼見Github

1、文件簡介

LSTM_model.py:LSTM網絡模型,提供了end_points接口,被其他部分調用
poetry_porcess.py:數據讀取、預處理部分,會返回打包好的batch,被main調用
gen_poetry.py:古詩生成程序,擁有可選的風格參數,被main調用
main.py:主函數,既可以調用前兩個程序獲取預處理數據並使用LSTM網絡進行訓練,也可以調用gen_poetry.py生成古詩

2、調用指令

main.py最后有如下指令,

if __name__ == "__main__": words,poetry_vector,to_num,x_batches,y_batches = poetry_porcess.poetry_process() # train(words, poetry_vector, x_batches, y_batches) # gen_poetry(words, to_num) generate(words_, to_num_, style_words="狂沙將軍戰燕然,大漠孤煙黃河騎。")

此時實際上處於生成模式,對於最后的三行, train:表示訓練 gen_poetry:表示根據首字符生成 generate:表示根據首句和風格句生成古詩

訓練時注釋掉后兩行,保留train行,

if __name__ == "__main__": words,poetry_vector,to_num,x_batches,y_batches = poetry_porcess.poetry_process() train(words, poetry_vector, x_batches, y_batches) # gen_poetry(words, to_num) # generate(words_, to_num_, style_words="狂沙將軍戰燕然,大漠孤煙黃河騎。")

生成時不需要修改,但是

generate(words_, to_num_, style_words="狂沙將軍戰燕然,大漠孤煙黃河騎。")

可以替換style_word為任何你想要的風格句,注意最好使用7言或者5言,因為這句會大概率影響到你生成的古詩的句子長度(不絕對),這只是風格提取,你可以輸入任意長度;在運行了腳本后,屏幕會提示輸入起始句,輸入的句子一般5或者7個字,這個由於會拿來直接做首句(由結果示范可以看到),輸入長度不宜過長。

對於上面的兩種情況,修改完成后運行腳本即可,

python main.py

即可顯示結果

3、結果示范

head:床前明月光 + style:黃沙百戰金甲:

床前明月光輝,魏武征夫血絮紅。
數步崩雲復遺主,縞衣東,帝京舉,玉輪還滿出書初。
秋秋慘慘垂楊柳,夢斷黃鶯欲斷腸。
花凋柳映阮家幾,屋前病,歇馬空留門。
當年皆月林,獨往深山有素。
 
 
head:少小離家老大回 + style:山雨欲來風滿樓:

少小離家老大回,四壁百月弄鴉飛。
掃香花間春風地,隔天傾似爛桃香。
近來誰伴清明日,兩株愁味在羅幃。
仍通西疾空何處,軋軋涼吹日方明。
 
 
head:少小離家老大回 + style:鐵馬冰河入夢來:

少小離家老大回,化空千里便成絲。
官拋十里同牛頷,莫礙風光雪片雲。
飲水遠濤飛漢地,雲連城戶翠微低。
一樹鐵門萬象聳,白雲三尺各關高。
同言東甸西游子,誰道承陽要舊憂。
 
少小離家老大回,含顰玉燭拂樓台。
初齊去府芙蓉死,細緩行雲向國天

 

RNN結構補充

 原網絡結構如下,實際上不需要像下面這樣寫了,不過當時費了好大事,所以保留一下原來版本的代碼,

with tf.variable_scope('placeholder'):
    input_vec = tf.placeholder(tf.int32,[None,None])
    output_targets = tf.placeholder(tf.int32,[None,None])

def rnn_network(rnn_size=128,num_layers=2):
    def lstm_cell():
        l_cell = tf.contrib.rnn.BasicLSTMCell(rnn_size,state_is_tuple=True,reuse=tf.get_variable_scope().reuse)
        return l_cell
    cell = tf.contrib.rnn.MultiRNNCell([lstm_cell() for _ in range(num_layers)])
    initial_state = cell.zero_state(batch_size, tf.float32) # 初始化LSTM網絡節點,參數為尺寸
    with tf.variable_scope('LSTM'):
        with tf.variable_scope('embedding'):
            E = tf.get_variable('embedding',[len(words_list) + 1,rnn_size])
            input_embedding = tf.nn.embedding_lookup(E,input_vec)
        output_embedding, last_state = tf.nn.dynamic_rnn(cell, input_embedding, initial_state=initial_state,scope='lstm')
        output = tf.reshape(output_embedding,[-1,rnn_size])
        with tf.variable_scope('output'):
            W = tf.get_variable('W', [rnn_size,len(words_list)+1])
            b = tf.get_variable('b', [len(words_list)+1])
        logits = tf.matmul(output,W) + b
        probs = tf.nn.softmax(logits)
        return logits, last_state, probs, cell, initial_state

另外,直接使用tf.nn.rnn_cell而不是用tf.contrib.rnn也可以。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM