使用唐詩語料庫,經過去噪預處理、分詞、生成搭配、生成主題等過程,生成唐詩。
環境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
實現預處理
觀察到給定的唐詩語料庫存在以下雜訊:
詩句**現類似
出現空格、「.」等字元。
詩句**現注釋,用「(」、「)」標出來。
詩句不完整,出現方框字元。
對於前三種情況的雜訊,直接去掉即可。對於最後一種雜訊,直接把這行詩句忽略考慮。(此外,對於第三種雜訊,「(」、「)」不在同一行時未處理。)
由於暫時只需要用到唐詩標題和詩句,故只提取這兩部分內容。
相關**實現在preprocess.py。
輸入:.data唐詩語料庫.txt
輸出:.datapoem.txt
分詞對於中文分詞,這裡採用在工業界上較廣泛應用的「結巴」中文分詞元件1。該分詞元件主要採用以下演算法:基於trie樹結構實現高效的詞圖掃瞄,生成句子中漢字所有可能成詞情況所構成的有向無環圖(dag);採用動態規劃查詢最大概率路徑,找出基於詞頻的最大切分組合;對於未登入詞,採用了基於漢字成詞能力的hmm模型,使用了viterbi演算法。
由於唐詩中的每乙個字基本都是有用的,故停用詞(stop words)主要為標點符號,這裡直接使用預設的停用詞。
生成搭配
搭配包括橫向搭配和縱向搭配。橫向搭配指每句詩中每個詞與下乙個詞的搭配關係,縱向搭配指每兩句詩中,第一句詩中的詞與下一句詩中對應相等長度的詞的搭配關係。
分詞之後把唐詩(不含標題)按句子切割,對句子總數為偶數的唐詩,遍歷每兩句詩,第一句詩中的詞與第二句詩中對應相等長度的詞形成乙個縱向搭配。對每一句詩,每兩個詞形成乙個橫向搭配。
易知,使用似然比、頻率、t檢驗等搭配發現方法都能得到較好結果,這裡為了方便,直接使用頻率來發現搭配。
相關**實現在get_collocations.py。
輸入:.datapoem.txt
輸出:橫向搭配.datacollocations_h
縱向搭配.datacollocations_v
生成主題
對每首詩,提取tf-idf2特徵並構建矩陣3,然後使用非負矩陣分解(non-negative matrix factorization,nmf)45提取唐詩主題類別。考慮到唐詩分類數量有限,這裡只生成10個類,每個類用頻率最高的20個詞來表示。
相關**實現在get_topic.py。
輸入:.datapoem.txt
輸出:主題.datatopics.txt
詞.datawords
每個主題-詞對應的得分.datatopic_words
生成起始詞
對每首詩,分詞後取第一句詩的第乙個詞作為起始詞。統計所有起始詞,並輸出出現超過兩次的詞。
相關**實現在get_start_words.py。
輸入:.datapoem.txt
輸出:起始詞.datastart_words.txt
生成唐詩
由於前期並沒有平仄處理,也沒有對唐詩語料庫作過多的要求,因此,生成的唐詩可能對仗不太工整。
輸入的引數除了上述生成的部分檔案(如搭配、主題等)外,還需要指定詩句數量、詩句長度、主題和起始詞(若不指定則隨機產生)。
對於給定詩句長度l,起始詞start_word和主題topic_id,設a[i]為第i個詞的id,我們可以把產生第一句詩抽象成乙個子問題:
maxs.t.∏i=2ncollocations_h_score[a[i−1]][a[i]]+λ∑i=1ntopic_word[topic_id][a[i]]∑i=1nlen(word[a[i]])=la[1]=start_word
其中collocations_h_score[a[i−1]][a[i]]表示第i−1個詞與第i個詞的橫向搭配分數,λ為平衡引數。若以上問題的最優解為a[i],那麼所生成的較為合理的第一句詩即word[1],word[2],⋯,word[n]。
顯然,對於該問題,可以把目標函式中的乘積部分用log來使其變成求和。於是該問題可以用動態規劃來求解:
設f[i][j]表示長度為i,最後乙個單詞id為j的最大目標函式值,則
f[i][j]=max+λ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
max & prod_^n collocations_h_score[a[i - 1]][a[i]]
& + lambda_1 prod_^n collocations_v_score[pre_a[i]][a[i]]
& + lambda_2 sum_^n topic_word[topic_id][a[i]]
text & len(word[a[i]]) = len(word[pre_a[i]]),i = 1,cdots,n
endmaxs.t.∏i=2ncollocations_h_score[a[i−1]][a[i]]+λ1∏i=1ncollocations_v_score[pre_a[i]][a[i]]+λ2∑i=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+λ2topic_word[j]
其中(k,j)為乙個橫向搭配,(pre_a[i],j)為乙個縱向搭配。
初始時f[0][j]=max+λ2topic_word[j]
求最優值與最優解方法同上。
相關**實現在generate_poem.py。
輸入:.datacollocations_v
.datacollocations_h
.datawords.txt
.datatopic_words
.datastart_words.txt
輸出:螢幕中輸出隨機生成的唐詩。
實現**
具體的實現使用flask框架,由於只是demo,只使用了bootstrap作為樣式,並未過多設計,具體效果如下圖所示。
總結與展望
總的來說,這個系統生成的唐詩還只是基本符合搭配和主題盡可能相關的要求,平仄、主旨等唐詩的屬性還有待改進。今後可以考慮生成更精確、更有意義的唐詩,如文獻6提供了一種解決方案。期待以後能做出更好的效果!
參考「結巴」中文分詞. ↩tf-idf. 維基百科. 最後修訂於2023年9月27日. ↩sklearn.feature_extraction.text.tfidftransformer. scikit-learn developers. ↩non-negative matrix factorization. wikipedia. 最後修訂於2023年12月1日. ↩sklearn.decomposition.nmf. scikit-learn developers. ↩he j,zhou m,jiang l. generating chinese classical poems with statistical machine translation models[c]//twenty-sixth aaai conference on artificial intelligence. 2012. ↩
兒童背誦古詩詞 3
春江花月夜 張若虛 春江潮水連海平,海上明月共潮生 灩灩隨波千萬里,何處春江無月明 江流宛轉繞芳甸,月照花林皆似霰 空裡流霜不覺飛,汀上白沙看不見 江天一色無纖塵,皎皎空中孤月輪 江畔何人初見月,江月何年初照人 人生代代無窮已,江月年年只相似 不知江月待何人,但見長江送流水 白雲一片去悠悠,青楓浦上...
如何鑑賞中國古詩詞
古典詩詞是我國文學遺產的重要組成部分,在高中語文教材中占有一定的分量。在全國語文高考中,古詩詞賞析連考了七年,難度越來越大,題型越來越完善,題量有逐年加大的趨勢,成為高考備考的乙個亮點。無論從教材角度,從高考角度,還是從繼承與創新文學遺產的角度上,培養與提高學生古詩詞的鑑賞能力,成為每乙個語文教師刻...
描寫中秋的有哪些古詩詞
花間一壺酒,獨酌無相親。舉杯邀明月,對影成三人。月既不解飲,影徒隨我身。暫伴月將影,行樂須及春。我歌月徘徊,我舞影零亂。李白 月下獨酌 明月出天山,蒼茫雲海間。長風幾萬里,吹度玉門關。李白 關山月 床前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。李白 靜夜思 御姐聖巴里,夜久侵羅襪。卻下水晶簾,玲瓏...