今天偶然在网上看到一篇关于机器写诗的文章(click here),觉得很有意思,于是想自己操作一下。原博主是以宋词为例,那么我就以唐诗为例好了。
首先,我不得不介绍一下一个很受欢迎的中文分词R package, jiebaR(click here)。网上很多教程,感兴趣的朋友可以搜搜。
jiebaR包支持最大概率法(Maximum Probability),隐式马尔科夫模型(Hidden Markov Model),索引模型(QuerySegment)和混合模型(MixSegment)等四种分词模式click here,功能涵盖词性标注(Part-of-Speech tagging或POS tagging, click here ),关键词提取(Automatic Indexing, click here),文本Simhash相似度比较(click here)等功能。
下面我们就自己动手尝试一下一个简单的模型吧。首先,我们在Github(click here)上下载数据并且进行数据清洗,只保留诗文部分,得到《唐诗三百首》(click here)。
接下来导入文件到R中。
1 2 3 4 5 6 |
fileName <- "tangshi2.txt" TS <- readChar(fileName, file.info(fileName)$size) # Transfer character strings to and from connections, without assuming they are null-terminated on the connection. substr(TS, 1000, 1100) # check the content from 1000 to 1100 #Extract or replace substrings in a character vector. |
用jiebaR包对文件进行分词处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# install.packages("jiebaR") library("jiebaR") cc = worker() # 接受默认参数,建立分词引擎 # This function can initialize jiebaR workers ## 相当于: ## worker( type = "mix", dict = "inst/dict/jieba.dict.utf8", ## hmm = "inst/dict/hmm_model.utf8", ### HMM模型数据 ## user = "inst/dict/user.dict.utf8") ### 用户自定义词库 analysis <- as.data.frame(table(cc[TS])) # Functions to check if an object is a data frame, or coerce it if possible. # reorder analysis <- analysis[order(-analysis$Freq),] # simply change the name and formatt names(analysis) <- c("word","freq") analysis$word <- as.character(analysis$word) |
接下来我们再用wordcloud2 package(词云)进行可视化。
1 2 3 |
# install.packages("wordcloud2") library("wordcloud2") wordcloud2(analysis) |
我们可以发现《唐诗三百首》中最常使用的词是字长为1的词。
下面我们看看分词后字数分别为1-4的词的词频
1 2 3 4 5 6 7 8 9 10 11 12 13 |
analysis_1 <-analysis[nchar(analysis$word) == 1,] analysis_2 <-analysis[nchar(analysis$word) == 2,] analysis_3 <-analysis[nchar(analysis$word) == 3,] analysis_4 <-analysis[nchar(analysis$word) == 4,] # remove the CiPaiMing wordcloud2(analysis_1) # one character wordcloud2(analysis_2) # two character wordcloud2(analysis_3) # three character wordcloud2(analysis_4) # three character |
1字长的词词频较高的依然是:“無”,“月”,“在”,“去”,“不”,“與”等
2字长的词词频分布比较均匀,如“萬里”,“不見”,“何處”,“不得”,“將軍”等词频相差不大。
3字长的词中“君不見”和“行路難”明显占多。
唐诗中4字长的词比较少,词频分布比较均匀。
我们用jiebaR中的tag给分词后的数据进行词性标记。词的分类详见词的分类。
1 2 3 4 5 6 |
tagger <- worker("tag") test<-mapply(c, analysis_1, analysis_2, SIMPLIFY=FALSE) example<-mapply(c, test, analysis_3, SIMPLIFY=FALSE) # subset:Return subsets of vectors, matrices or data frames which meet conditions # exclude the author name and header name example_2 <- tagger <= example$word |
我们以杜甫的《望岳》为模板。对模板进行分词和词性标记。其实原理很简单,在模板上根据各个位置的词性从刚刚得到的词库里进行随机匹配。其假设是无限猴子定理(read more, click here!)。同时这样让我想起了用以反驳强AI的“中文房间”(read more, click here!)思想实验。有兴趣的朋友自行百科吧,再次不赘述了。
1 2 3 4 5 6 |
shi <- "岱宗夫如何,齊魯青未了。造化鍾神秀,陰陽割昏曉。盪胸生曾雲,決眥入歸鳥。會當凌絕頂,一覽眾山小。" shi_2 <- tagger <= shi shi_2 length(shi_2) cixing <- attributes(shi_2)$names # attributes: Object Attribute Lists |
准备工作完毕,接下来就是创作了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
write_tangshi <- function(m){ set.seed(m) # Random Number Generation empty <- "" for (i in 1:length(shi_2)){ temp_file <- example_2[attributes(example_2)$name == cixing[i]] temp_file <- temp_file[nchar(temp_file) == nchar(shi_2[i])] empty <- paste0(empty, sample(temp_file,1)) } result <- paste0(substr(empty, 1,5), ",", substr(empty,6,10),"。", substr(empty, 11,15), ",", substr(empty, 16,20),"。", substr(empty, 21,25), ",", substr(empty, 26,30),"。", substr(empty, 31,35), ",", substr(empty, 36,40),"。") } lapply(1:3, write_tangshi) # lapply: Apply a Function over a List or Vector |
得到结果为
[1]
巴人著其間,雨露凌絕頂。
逡巡門磊落,江底何所似。
外繡簾還桃,撫念益涼坼。
繼周青未了,夫人荒居細。[2]
太宗猩其間,干戈青未了。
閒逸尋衰朽,南迴滿秋山。
漢地曲都河,問死生栖蝟。
騰驤凌絕頂,微火不教乖。[3]
太宗脾之中,冷霜春風來。
殞身別壯觀,東城盡曉妝。
江柳共遂北,漲秋池薰羈。
今為歸去來,鋤犁如斗高。
结果还不错,有那么几句看上去还算有诗意。但是还是可以看出来目前的算法不够聪明。因为律诗的声韵格律,情感主题的连贯性均没有考虑进来。
后续工作中可以加入机器学习,同时再模型中考虑主题模型,互信息模型等,训练律诗的声韵、格律、主题、情感。
知乎专栏:炼丹实验室有非常详细的literature review。
传统的机器作诗方法包括:Word Salada,基于模板和模式的方法,基于遗传算法的方法(周昌乐等 2010),基于摘要生成的方法(Generative Summarization Framework, Rui Yan et al, 2013),基于统计机器翻译的方法( Statistical Machine Translation Models, Jing He et al, 2012)。而目前比较先进的方法是基于深度学习(Deep Learning)的生成方法:Recurrent Neural Networks(Xingxing Zhang et al, 2014),Neural Attention-based Model(Q Wang,2016),Recurrent Neural Networks with Iterative Polishing Schema(Rui Yan,2016),Planning based Neural Network(Z Wang,2016),SeqGAN: Sequence Generative Adversarial Nets with Policy Gradient(L Yu,2016)。
目前已经相对比较成熟的产品供大家使用了,例如上海玻森数据的编诗姬和微软亚洲研究院的律诗绝句。有兴趣的朋友可以体验一下。
最近在一席上看了一个关于自然语言处理的演讲,觉得主讲人讲得很生动,有兴趣的朋友可以看看。
详见:顾森 追逐语言的规律(2014) 优酷 (click here!) , YouTube(click here!)
同时自然语言处理的公开课也很多,比较有名的就是
Open Course:CS224n: Natural Language Processing with Deep Learning
You must be logged in to post a comment.
Tingting
2017年3月17日
好有意思呀!点赞!
baoduge
2017年3月18日
嗯嗯,谢谢~!
luo
2017年3月17日
这个结构模型可以运用到照片处理的方式里去的话,也应该很有意思…
baoduge
2017年3月18日
照片处理和文字处理有点点不太一样。不过这个小玩具其实可以往下继续做,还是有很多东西可以加进来的,后面希望有时间可以再写。