wangc
Feb 18, 2018
前面根据教程用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的时候再认真研究一下吧。