更多文章欢迎来我的小博客
前面根据教程用Word2Vector方法分析了《权利的游戏》(见此),但其实对《权利的游戏》并没有太多的了解。这里把自己喜欢的《三体》来分析一下。
Word2Vector 分析《三体》
与《权利的游戏》素材不同的是,对于中文的语料,分句和分词的过程需要用到其他的中文nlp专用库,其他的流程都一样。这里着重把不同之处记录下来。
分句
在nltk库中有对英文语料专门的分句器,似乎没有中文的,这里查阅网上,查到了一个人家写的分句函数。
def cut_sentences(sentence): if not isinstance(sentence, unicode): sentence = unicode(sentence) puns = frozenset(u'。!? …') tmp = [] for ch in sentence: tmp.append(ch) if puns.__contains__(ch): yield ''.join(tmp) tmp = [] yield ''.join(tmp)
然后对语料进行分句
raw_sentences = [] for i in cut_sentences(santi_text): raw_sentences.append(i)
分词
分词用到的jieba中文分词库,很容易就可以把语料分词,并且标注词性,便于之后的清洗。
i=0 sentences_with_attr = [] for sentence in raw_sentences: tmp = [(x.word,x.flag) for x in psg.cut(sentence) if len(x.word) >= 2] sentences_with_attr.append(tmp) i=i+1
清洗
这里把一些没有实际意义或者不重要的词清洗掉。
# 要过滤掉的词性列表,这些词性的词都是没有实际意义的词,如连词、代词等虚词,这个列表初始化为空列表,后面根据分析结果手工往里面一个个添加 stop_attr = ["m","x","c","d","f","df","m","p","r","rr","s","u","v","i"] # 获取过滤掉stop_attr里的词性的词后的分词列表 sentences = [] for sentence in sentences_with_attr: words = [x[0] for x in sentence if x[1] not in stop_attr] sentences.append(words)
统计
清洗完了以后很容易可以把全书里所有词汇出现的次数给统计一下。
# 统计在分词表中出现次数排名前500的词的列表,并将结果输出到文件most.txt中,每行一个词,格式为: # 词,出现次数,词性 from collections import Counter c = Counter(words).most_common(2500) with open('most.txt','w+') as f: for x in c: f.write('{0},{1},{2}\n'.format(x[0],x[1],attr_dict[x[0]]))
结果:
程心,1476,n 罗辑,1287,nr 世界,1249,n 地球,971,n 人类,951,n 太空,943,n 三体,910,n 宇宙,904,n 太阳,778,ns 舰队,655,n 飞船,648,n 汪淼,645,nrfg 时间,623,n 文明,573,nr 叶文洁,489,nr 信息,483,n 智子,460,n 太阳系,430,n 面壁,408,n
可以看出三个主角里程心笔墨最多,其次是罗辑,汪淼作为主角存在感就比较低了,叶文洁无意是最重要的配角。
解析《三体》
模型构建和训练的过程与之前一样,现在直接直接跳到激动人心的最终成果—————训练好的《三体》三部曲的词向量模型!
下面把一些有意思的结果展示出来:
santi2vec.wv.most_similar("庄颜")
[('稚气', 0.5974270105361938), ('卢浮宫', 0.5723787546157837), ('雪原', 0.5572832226753235), ('绞痛', 0.5392299890518188), ('蒙娜丽莎', 0.536531388759613), ('思念', 0.5354028940200806), ('山楂树', 0.535396933555603), ('脚印', 0.5283292531967163), ('纯真', 0.5264573097229004), ('画画', 0.5225934982299805)]
santi2vec.wv.most_similar("叶文洁")
[('杨卫宁', 0.6185617446899414), ('志成', 0.5761844515800476), ('遗址', 0.5388633012771606), ('政委', 0.5040754079818726), ('红岸', 0.4925873875617981), ('主控室', 0.49231645464897156), ('大兴安岭', 0.4895886480808258), ('母校', 0.479810506105423), ('树桩', 0.47594404220581055), ('学问', 0.47543618083000183)]
santi2vec.wv.most_similar("北海")
[('延绪', 0.5551995635032654), ('但章', 0.5236247777938843), ('吴岳', 0.4665769934654236), ('特遣队', 0.46631085872650146), ('当章', 0.449232280254364), ('前辈', 0.44880932569503784), ('军徽', 0.4409657120704651), ('瞄准镜', 0.44056135416030884), ('弹夹', 0.43633267283439636), ('收藏者', 0.436320036649704)]
santi2vec.wv.most_similar("大史",topn=50)
结果里的“他妈的”,“哈哈”和“老子”也是233333,着实是把一个痞子警官的形象表现得淋漓尽致。
[('刑警', 0.5401235222816467), ('烟蒂', 0.5207052826881409), ('他妈的', 0.5192327499389648), ('罗兄', 0.5141407251358032), ('保卫人员', 0.5112203359603882), ('坎特', 0.5057969689369202), ('警官', 0.5057923793792725), ('老子', 0.4995124936103821), ('哈哈', 0.49516355991363525), ('聪明人', 0.49482840299606323)]
santi2vec.wv.most_similar("智子")
[('盲区', 0.49024850130081177), ('武士刀', 0.460488498210907), ('茶具', 0.4507940411567688), ('无处不在', 0.4501256048679352), ('低维', 0.4456014633178711), ('综合征', 0.4374358057975769), ('宏观世界', 0.43377238512039185), ('月前', 0.42773574590682983), ('迷彩服', 0.4173460602760315), ('笨办法', 0.40825191140174866)]
总结
训练的结果其实并不是尽如人意。分词的过程中有一些角色的名字被分开了(章北海,云天明),不过这个应该可以用jieba库进行调整的。
可视化的方面,输出的图形上中文字符无法正常显示,
构建的Word2Vector模型,参数方面应该还可以再进行优化,比如输出词向量的维度(size),不知道有什么影响,据说是越多越好,还有训练窗口的大小(window),还有sample参数。这些等回来学完深度学习入门课程,专门看NLP的时候再认真研究一下吧。