手把手 | 用R分析宋词三百首 自己动手写个“机器诗人”
最近中國詩詞大會很受歡迎,才女武亦姝憑借超強的記憶力和超快的反應能力一炮走紅,成為大家心目中的偶像。
在欣賞節目的同時,我也不禁想到,既然古代的詩人能夠創作出這些美好的詩篇,那我是不是也能創作幾首屬于自己的詩詞作品呢?可惜,經過一番嘗試,我發現自身的文學功底不夠,恐怕無法完成這樣艱巨的任務??磥砣撕腿诉€是有很大的差距。
當然,我并沒有氣餒。就像著名的無限猴子定理闡述的那樣,哪怕是讓一只猴子在打字機上隨機地按鍵,只要按鍵的時間足夠長,那么幾乎必然能夠打出任何特定的文字,甚至是莎士比亞的全套著作。我覺得我的編程能力應該比猴子還是要略強一籌,所以打算試試用我熟悉的語言R 來創作幾首『歪詩』。
詞頻分析
既然要創作詩詞,那么就要先了解詩詞中最常出現的詞匯和意象是什么。我在 github 上找到了一些古典中文的語料庫(鏈接),其中有不少唐詩宋詞的文本,只不過是繁體的。我選擇了《宋詞三百首》作為了我的文本庫,對它進行詞頻分析。
其實做法很簡單,大概就是分這么幾步:
把文本拆分成一個一個的單詞;
把單詞按照出現的頻率、次數進行排序
用可視化把結果展示出來
下面的部分我會討論一下具體的操作,不感興趣的觀眾請往后翻到結果的部分。
第一步、第二步。
第一步
-
導入文本庫:
> fileName <- "宋詞三百首.txt" > SC <- readChar(fileName, file.info(fileName)$size)# 大概檢查一下> substr(SC, 1000, 1100)[1] "醒。送春春去幾時回,臨晚鏡。傷流景。往事後期空記省?!鹕成蟻K禽池上暝。雲破月來花弄影。重重簾幕密遮燈,風不定。人初靜。明日落紅應滿徑。\n\n詞牌:青門引\n作者:張先\n詞文:乍暖還輕冷。風雨晚來方定。庭軒寂"
-
用分詞包『結巴R』 (鏈接) 里面的 worker() 公式完成分詞:
> cc = worker()> analysis <- as.data.frame(table(cc[SC]))# 重新排序> analysis <- analysis[order(-analysis$freq),]# 簡單改變一下文件的命名、格式> names(analysis) <- c("word","freq")> analysis$word <- as.character(analysis$word)# 看一下這個分詞文件的開頭> head(analysis) ? ? word freq470 ?作者 ?3106120 詞文 ?3106121 詞牌 ?3101024 ? 又 ? 751014 ? 去 ? 553124 ? 月 ? 54
看來在宋詞三百首中,出現最多的詞語是『作者』,『詞文』,『詞牌』,總共出現了310次。這是因為每首詩詞開始時,文檔中都會介紹這首詩詞的作者、詞文和詞牌,從而干擾了我們的文本分析。
第二步
我用 R 包 wordcloud2把結果簡單地進行了一下可視化:
wordcloud2(analysis)
然后得到了這張圖。
嗯,碩大的一個『詞文』出現了很多次,看來我們在可視化的時候要把它去掉。
我把出現頻率大于300次的詞語刨除之后,根據分詞結果的字數(一字,二字,三字)重新進行了可視化,結果如下:
wordcloud2(analysis[analysis$freq>1& analysis$freq < 300 & nchar(analysis$word) == 1,])wordcloud2(analysis[analysis$freq>1& analysis$freq < 300 & nchar(analysis$word) == 2,])wordcloud2(analysis[analysis$freq>1 & analysis$freq < 300 & nchar(analysis$word) == 3,])
現在的結果就正常多了。我們看到,一個字的詞語中,出現頻率較多的有『誰』,『又』,『人』,『去』,『夢』, 『是』, 『處』,『月』 等等。
兩個字的詞語中,『何處』,『斜陽』,『相思』這些詞使用頻率最多,給我一種在看網絡小說標題的感覺。
三個字的詞語中,出現最多的往往是詞牌名和作者名。
完成了簡短的詞頻分析,下面就要開始最重要的『詩詞創作』部分了!
詩詞創作
準備
創作宋詞,先要明確一個詞牌名。我選擇了李白的《清平樂·畫堂晨起》作為范例。
畫堂晨起,來報雪花墜。高卷簾櫳看佳瑞,皓色遠迷庭砌。盛氣光引爐煙,素草寒生玉佩。應是天仙狂醉,亂把白云揉碎。
R 的中文分詞包『結巴R』的功能中,有一項可以用來分辨詞語的詞性。我將范例進行分詞后,再用這項功能分析一下各部分的詞性。
> cipai <- "畫堂晨起,來報雪花墜。高卷簾櫳 看 佳瑞,皓色遠 迷 庭砌。盛氣光引 爐煙,素草寒生玉佩。應是天仙狂醉,亂把白云揉碎。"> tagger <- worker("tag")> cipai_2 <- tagger <= cipai> cipai_2 ? ? n ? ? ?x ? ? ?x ? ? ?n ? ? ?v ? ? ?a ? ? ?n ? ? ?g ? ? ?v "畫堂" "晨起" "來報" "雪花" ? "墜" ? "高" "卷簾" ? "櫳" ? "看" ?? ? x ? ? ?x ? ? ?a ? ? ?v ? ? ?x ? ? ?n ? ? ?x ? ? ?x ? ? ?x "佳瑞" "皓色" ? "遠" ? "迷" "庭砌" "盛氣" "光引" "爐煙" "素草" ?? ? x ? ? nr ? ? ?x ? ? ?n ? ? ?x ? ? ?d ? ? ?p ? ? nr ? ? ?v "寒生" "玉佩" "應是" "天仙" "狂醉" ? "亂" ? "把" "白云" "揉碎"
其中每個字母代表什么詞性,我也沒有很理解。據我的猜測,n 應該是名詞,x是沒有分辨出來的詞性,v是動詞, a是形容詞,至于『nr』, 『p』, 『d』是什么,實在是猜不出來,在幫助文檔中也沒有找到。如果有朋友知道的話,希望能不吝賜教。
最后,我從之前提煉的宋詞詞頻庫中,選取了至少出現過兩次的一字或兩字詞語,作為詩詞創作的素材庫:
> example <- subset(analysis, freq >1 & nchar(word) <3 & freq < 300)# 提取詞性文件> cixing <- attributes(cipai_2)$names# 將素材庫進行詞性分類> example_2 <- tagger <= example$word
創作
下面,我們終于要開始用 R 創作詩歌了!我自己想了一個創作的算法,可以說很簡單,甚至說有點可笑。
步驟是這樣的:我從范本詞牌的第一個詞開始,隨機在素材庫中選取詞性相同,字數相等的單詞,填入提前設置好的空白字符串中。
舉個例子,原詩的第一個詞是『畫堂』,是個二字的名詞。那么,我就在素材庫中隨機選擇一個二字的名詞,填入這個空間中。然后,繼續分析下一個詞。
具體方程的代碼如下:
> write_songci <- function(m){set.seed(m)empty <- ""for (i in 1:length(cipai_2)){ ?temp_file <- example_2[attributes(example_2)$name == cixing[i]] ?temp_file <- temp_file[nchar(temp_file) == nchar(cipai_2[i])] ??empty <- paste0(empty, sample(temp_file,1)) ?}result <- paste0(substr(empty, 1,4), ",", substr(empty,5,9),"。", ?? ? ?substr(empty, 10,16), ",", substr(empty, 17,22),"。", ? ? ?substr(empty, 23,28), ",", substr(empty, 29,34),"。", ? ? ?substr(empty, 35,40), ",", substr(empty, 41,46),"。")}
結果
做了這么多工作,終于到了驗收結果的部分。請各位來欣賞幾首 R 創作的歪詞作品吧:
> lapply(1:5, write_songci)[[1]][1] "幽香凝佇,春空賞花回。淨關塞旆感春歸,朝天淺爭前度。江聲已失無跡,香非凝笑秋千。過盡細雨歸鴻,欲對蓬萊歸來。"[[2]][1] "流年漏永,春空愁腸覺。穩黃花笮收敗壁,數峰深鋪已斷。寄語舊香非煙,歸夢如夢殷勤。沈沈啼鶯老來,卻把丁香不堪。"[[3]][1] "愁腸簾外,前度芳心困。少陽臺瘞切桃蹊,幾人細鎖新樣。腸斷缺月中酒,潘鬢行遍何曾。歸雁芳草修竹,不對秋水垂下。"[[4]][1] "一川晏殊,阮郎斷鴻展。重暮雲菰訪楊花,畫閣滿聽金尊。敗葉孤城雪滿,晝永隋堤碧雲。無準黃金年光,漸因綺羅開時。"[[5]][1] "煙柳清景,謝娘桃花如。窄蝴蝶琮誤中酒,花間碎掛斷煙。幽夢曉來千樹,蕭娘數峰翩翩。蟲網暗想未醒,曾向丁寧聚散。"
既然是計算機生成的詩,自然談不上什么文學性。不過,雖然大部分內容看上去不知所云,有些詞句還是有些意思的,比如『幽香凝佇』,『愁腸簾外』,『孤城雪滿』等等。之前在調試的時候,還出現過類似于『風煙淚暗霜前, 古岸頻聽金蓮』這樣的詞句,無厘頭之余,莫名地居然還有些押韻。
感想
這篇文章到此就結束了,希望大家讀得還愉快。最后談談自己的感想。
-
很多讀者可能會問,既然用 R 寫出來的詩毫不合文理,為什么還要進行這樣的工作呢?這種練習是不是在侮辱中文和古典詩詞呢?我倒是覺得,我們對語言應該存有一種開放的態度。詩詞說到底,也是一種風雅的文字游戲。我們又何嘗不能抱著游戲的態度,把這個練習當做一個有趣的消遣呢?
-
用計算機代碼作詩的主意并非是我原創。清華大學早在一年前就推出過作詩機器人薇薇,宣稱可以通過圖靈測試。
-
有些詞句,如『何處東風約』,『萬朵千峰映碧垂』等還是略顯生硬,不過比我這里創作的詩詞已經強的太多了。本文的小程序比較簡短,總共只使用了不到50行代碼,可以說是比較粗略的一個版本,僅供大家參考。感興趣的讀者可以設計更精密的算法,使用更高級的統計方法改進創作的質量。
-
古詩詞向來被認為具有很高的藝術價值。今天的我們有越來越多的工具,可以系統化地總結、歸納詩詞的規律,這大概也是過去的詩人怎么也想不到的?;蛟S有一天,計算機真的能學習出作詩的秘訣,給我們帶來更多全新的靈感和更好的詩句。我們拭目以待。
-
原文發布時間為:2017-03-06
本文來自云棲社區合作伙伴“大數據文摘”,了解相關信息可以關注“BigDataDigest”微信公眾號
總結
以上是生活随笔為你收集整理的手把手 | 用R分析宋词三百首 自己动手写个“机器诗人”的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 提网速亟须普及光纤宽带 究竟是谁“偷”走
- 下一篇: 欧盟包装指令94/62/EC详解