使用唐詩語料庫,經過去噪預處理、分詞、生成搭配、生成主題等過程,生成唐詩。
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
生成唐詩
由於前期並沒有平仄處理,也沒有對唐詩語料庫作過多的要求,因此,生成的唐詩可能對仗不太工整。
輸入的參數除了上述生成的部分文件(如搭配、主題等)外,還需要指定詩句數量、詩句長度、主題和起始詞(若不指定則隨機產生)。
對於給定詩句長度
其中
顯然,對於該問題,可以把目標函數中的乘積部分用
設
其中
初始時
最後最優值爲
而產生下一句詩,則需要考慮縱向搭配。同理我們也可以把產生下一句詩抽象成一個子問題:
\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}
其中
設
其中
初始時
求最優值與最優解方法同上。
相關代碼實現在generate_poem.py
。
輸入:
.\data\collocations_v
.\data\collocations_h
.\data\words.txt
.\data\topic_words
.\data\start_words.txt
輸出:
- 屏幕中輸出隨機生成的唐詩。
實現網站
爲了更好的用戶體驗,可以把隨機和成的唐詩寫成一個網站“古詩生成器”。若是用戶沒有輸入,則隨機生成唐詩;若是用戶輸入第一句詩或更多句詩,則生成剩下的詩。
具體的實現使用Flask框架,由於只是demo,只使用了bootstrap作爲樣式,並未過多設計,具體效果如下圖所示。
總結與展望
總的來說,這個系統生成的唐詩還只是基本符合搭配和主題儘可能相關的要求,平仄、主旨等唐詩的屬性還有待改進。今後可以考慮生成更精確、更有意義的唐詩,如文獻6提供了一種解決方案。期待以後能做出更好的效果!
參考
- “結巴”中文分詞. https://github.com/fxsjy/jieba ↩
- TF-IDF. 維基百科. 最後修訂於2015年9月27日. https://zh.wikipedia.org/wiki/TF-IDF ↩
- sklearn.feature_extraction.text.TfidfTransformer. scikit-learn developers. http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfTransformer.html ↩
- Non-negative matrix factorization. Wikipedia. 最後修訂於2015年12月1日. https://en.wikipedia.org/wiki/Non-negative_matrix_factorization ↩
- sklearn.decomposition.NMF. scikit-learn developers. http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.NMF.html ↩
- He J, Zhou M, Jiang L. Generating chinese classical poems with statistical machine translation models[C]//Twenty-Sixth AAAI Conference on Artificial Intelligence. 2012. ↩