唐詩生成器

使用唐詩語料庫,經過去噪預處理、分詞、生成搭配、生成主題等過程,生成唐詩。

csdn下載地址:http://download.csdn.net/detail/lijiancheng0614/9840952
github上repository地址:https://github.com/lijiancheng0614/poem_generator

環境

  • Python 2.7

  • Flask

  • jieba

運行方法

如果是第一次運行,則需要安裝相關的庫及生成初始數據:

pip install flask
pip install jieba
python preprocess.py
python get_collocations.py
python get_topic.py
python get_start_words.py

以後只需要輸入以下代碼即可運行網站:

python index.py

實現

預處理

觀察到給定的唐詩語料庫存在以下噪聲:

  • 詩句中出現類似<img height=32 width=32 border=0 src=/bzk/QLXQ.bmp >的HTML標籤。

  • 出現空格、“.”等字符。

  • 詩句中出現註釋,用“(”、“)”標出來。

  • 詩句不完整,出現方框字符。

對於前三種情況的噪聲,直接去掉即可。對於最後一種噪聲,直接把這行詩句忽略考慮。(此外,對於第三種噪聲,“(”、“)”不在同一行時未處理。)

由於暫時只需要用到唐詩標題和詩句,故只提取這兩部分內容。

相關代碼實現在preprocess.py

輸入:

  • .\data\唐詩語料庫.txt

輸出:

  • .\data\poem.txt

分詞

對於中文分詞,這裏採用在工業界上較廣泛應用的“結巴”中文分詞組件1。該分詞組件主要採用以下算法:基於Trie樹結構實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖(DAG);採用動態規劃查找最大概率路徑,找出基於詞頻的最大切分組合;對於未登錄詞,採用了基於漢字成詞能力的HMM模型,使用了Viterbi算法。

由於唐詩中的每一個字基本都是有用的,故停用詞(Stop Words)主要爲標點符號,這裏直接使用默認的停用詞。

生成搭配

搭配包括橫向搭配和縱向搭配。橫向搭配指每句詩中每個詞與下一個詞的搭配關係,縱向搭配指每兩句詩中,第一句詩中的詞與下一句詩中對應相等長度的詞的搭配關係。

分詞之後把唐詩(不含標題)按句子切割,對句子總數爲偶數的唐詩,遍歷每兩句詩,第一句詩中的詞與第二句詩中對應相等長度的詞形成一個縱向搭配。對每一句詩,每兩個詞形成一個橫向搭配。

易知,使用似然比、頻率、t檢驗等搭配發現方法都能得到較好結果,這裏爲了方便,直接使用頻率來發現搭配。

相關代碼實現在get_collocations.py

輸入:

  • .\data\poem.txt

輸出:

  • 橫向搭配.\data\collocations_h
  • 縱向搭配.\data\collocations_v

生成主題

對每首詩,提取TF-IDF2特徵並構建矩陣3,然後使用非負矩陣分解(Non-negative matrix factorization, NMF)45提取唐詩主題類別。考慮到唐詩分類數量有限,這裏只生成10個類,每個類用頻率最高的20個詞來表示。

相關代碼實現在get_topic.py

輸入:

  • .\data\poem.txt

輸出:

  • 主題.\data\topics.txt
  • .\data\words
  • 每個主題-詞對應的得分.\data\topic_words

生成起始詞

對每首詩,分詞後取第一句詩的第一個詞作爲起始詞。統計所有起始詞,並輸出出現超過兩次的詞。

相關代碼實現在get_start_words.py

輸入:

  • .\data\poem.txt

輸出:

  • 起始詞.\data\start_words.txt

生成唐詩

由於前期並沒有平仄處理,也沒有對唐詩語料庫作過多的要求,因此,生成的唐詩可能對仗不太工整。

輸入的參數除了上述生成的部分文件(如搭配、主題等)外,還需要指定詩句數量、詩句長度、主題和起始詞(若不指定則隨機產生)。

對於給定詩句長度l , 起始詞start_word 和主題topic_id ,設a[i] 爲第i 個詞的id,我們可以把產生第一句詩抽象成一個子問題:

maxs.t.i=2ncollocations_h_score[a[i1]][a[i]]+λi=1ntopic_word[topic_id][a[i]]i=1nlen(word[a[i]])=la[1]=start_word

其中collocations_h_score[a[i1]][a[i]] 表示第i1 個詞與第i 個詞的橫向搭配分數,λ 爲平衡參數。若以上問題的最優解爲a[i] ,那麼所生成的較爲合理的第一句詩即word[1],word[2],,word[n]

顯然,對於該問題,可以把目標函數中的乘積部分用log 來使其變成求和。於是該問題可以用動態規劃來求解:

f[i][j] 表示長度爲i ,最後一個單詞id爲j 的最大目標函數值,則

f[i][j]=max{f[ilen(word[j])][k]+log_collocations_h_score[k][j]}+λtopic_word[j]

其中(k,j) 爲一個橫向搭配。

初始時f[len(start_word_id)][start_word_id]=λtopic_word[start_word_id]

最後最優值爲f[l][j],j ,路徑可通過與ff 同大小的矩陣prepre 來記錄前一個單詞的id。

而產生下一句詩,則需要考慮縱向搭配。同理我們也可以把產生下一句詩抽象成一個子問題:

\begin{array}{cl} \max & \prod_{i = 2}^n collocations\_h\_score[a[i - 1]][a[i]] \\ & + \lambda_1 \prod_{i = 1}^n collocations\_v\_score[pre\_a[i]][a[i]] \\ & + \lambda_2 \sum_{i = 1}^n topic\_word[topic\_id][a[i]] \\ \text{s.t.} & len(word[a[i]]) = len(word[pre\_a[i]]), i = 1, \cdots, n \end{array}

maxs.t.i=2ncollocations_h_score[a[i1]][a[i]]+λ1i=1ncollocations_v_score[pre_a[i]][a[i]]+λ2i=1ntopic_word[topic_id][a[i]]len(word[a[i]])=len(word[pre_a[i]]),i=1,,n

其中pre_a[i] 表示上一句詩的第i 個詞的id,collocations_v_score[pre_a[i]][a[i]] 表示上一句詩第i 個詞與這一句詩第i 個詞的縱向搭配分數,λ1,λ2 均爲平衡參數。同理也用動態規劃來求解:

f[i][j] 表示第i 個詞,最後一個單詞id爲j 的最大目標函數值,則

f[i][j]=max{f[i1][k]+log_collocations_h_score[k][j]+λ1log_collocations_v_score[pre_a[i]][j]}+λ2topic_word[j]

其中(k,j) 爲一個橫向搭配,(pre_a[i],j) 爲一個縱向搭配。

初始時f[0][j]=max{λ1log_collocations_v_score[pre_a[i]][j]}+λ2topic_word[j]

求最優值與最優解方法同上。

相關代碼實現在generate_poem.py

輸入:

  • .\data\collocations_v
  • .\data\collocations_h
  • .\data\words.txt
  • .\data\topic_words
  • .\data\start_words.txt

輸出:

  • 屏幕中輸出隨機生成的唐詩。

實現網站

爲了更好的用戶體驗,可以把隨機和成的唐詩寫成一個網站“古詩生成器”。若是用戶沒有輸入,則隨機生成唐詩;若是用戶輸入第一句詩或更多句詩,則生成剩下的詩。

具體的實現使用Flask框架,由於只是demo,只使用了bootstrap作爲樣式,並未過多設計,具體效果如下圖所示。

隨機生成唐詩
給定第一句生成唐詩

總結與展望

總的來說,這個系統生成的唐詩還只是基本符合搭配和主題儘可能相關的要求,平仄、主旨等唐詩的屬性還有待改進。今後可以考慮生成更精確、更有意義的唐詩,如文獻6提供了一種解決方案。期待以後能做出更好的效果!

參考


  1. “結巴”中文分詞. https://github.com/fxsjy/jieba
  2. TF-IDF. 維基百科. 最後修訂於2015年9月27日. https://zh.wikipedia.org/wiki/TF-IDF
  3. sklearn.feature_extraction.text.TfidfTransformer. scikit-learn developers. http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfTransformer.html
  4. Non-negative matrix factorization. Wikipedia. 最後修訂於2015年12月1日. https://en.wikipedia.org/wiki/Non-negative_matrix_factorization
  5. sklearn.decomposition.NMF. scikit-learn developers. http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.NMF.html
  6. He J, Zhou M, Jiang L. Generating chinese classical poems with statistical machine translation models[C]//Twenty-Sixth AAAI Conference on Artificial Intelligence. 2012.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章