Word2vec词向量工具带你发现不一样的《天龙八部》

词向量技术是将词语转化成为稠密向量。在自然语言处理应用中,词向量作为机器学习、深度学习模型的特征进行输入。因此,最终模型的效果很大程度上取决于词向量的效果。

Word2vec 是 Google 在 2013 年开源的一款将词表征为实数值向量的高效工具,利用深度学习思想,通过训练,把对文本内容的处理简化为 K 维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似度。

word2vec输出的词向量可以被用来做很多 NLP 相关的工作,比如聚类、找同义词、词性分析等等。如果换个思路,把词当做特征,那么Word2vec就可以把特征映射到 K 维向量空间,可以为文本数据寻求更加深层次的特征表示。 Word2vec 使用的是 Distributed representation 的词向量表示方式。采用一个三层的神经网络“输入层-隐层-输出层”。有个核心的技术是根据词频用Huffman编码,使得所有词频相似的词隐藏层激活的内容基本一致,出现频率越高的词语,他们激活的隐藏层数目越少,这样有效的降低了计算的复杂度。

简单的理论大概就是上面这些,我比较喜欢《天龙八部》这部小说,“有情皆孽,无人不冤”是这部小说的主旨,人物丰富,情节紧凑,每个人都演绎了“求不得”这出自佛经的三个字。下面我们通过代码分析一下实际是不是这样?

  • 第一步:我们找到《天龙八部》这部小说的txt文件,去掉停用词,然后利用结巴分词整理成能够被Word2vec使用的格式。

整理完的文本,整部小说的第一节标题:第01章 青衫磊落险峰行  如下:

[' ', '青衫', '磊落', '险峰', '行']
  • 第二步:我们先结合词云工具画出小说中出现次数最多的四字成语

貌似不是我们一开始说的那样求不得,看起来整部小说还是非常豪放,充满了江湖的侠义之气,不是我们最初预料的那种悲苦的基调。

  • 第三步:利用Word2vec分析这部小说的人物

1.和段誉最相关的词

[('木婉清', 0.9940025806427002), ('低声', 0.9905248284339905), 
('王语嫣', 0.9902623891830444), ('虚竹', 0.9894589781761169), 
('萧峰', 0.9883322715759277),('阿紫', 0.9870333075523376),
 ('阿朱', 0.9851636290550232), ('快', 0.9846230745315552),
 ('点头', 0.983921468257904), ('笑', 0.9805305600166321)]

除了这几个人物之外,这位公子哥给人的感觉也是温柔多情,“低声”,“点头”,“笑”这三个词语算是有点贴切了,而“快”字说的就是他的凌波微步了。

2.判断段誉和王语嫣的相似度

#判断相似度
model.similarity('段誉', '王语嫣')

0.9902624294045532

看结果说明他们的关系还是非常强的

3.找出与萧峰最接近,与王语嫣最不相近的词

print(model.most_similar(positive=['萧峰'], negative=['王语嫣']))

[('中', 0.6243330836296082), ('内力', 0.5441182851791382),
 ('出', 0.5018132328987122), ('间', 0.4797748029232025), 
('嗤', 0.46751290559768677), ('派', 0.4565170407295227), 
('突然', 0.4523952603340149), ('武功', 0.448074609041214),
 ('签条', 0.4459651708602905), ('少林', 0.4459308385848999)]

4.找出指定长度的相关词

#找出指定长度的相关词
req_count = 20
for key in model.similar_by_word('李秋水'):
    if  len(key[0]) <= 4:
        req_count -= 1
        print(key[0],key[1])
        if req_count == 0:
            break


连声 0.9998010396957397
一点 0.9997679591178894
出尘子 0.999755322933197
跪倒 0.9997552633285522
怒气 0.9997398853302002
摘星子 0.9997320771217346
大怒 0.9997137188911438
头 0.9997084140777588
长 0.9996963739395142
冷 0.9996923804283142

结果还是比较准的

详细代码如下:

import jieba

#加载文本,去除空格
def read_words(path):
    lines = []
    with open (path,'r') as f:
        for line in f:
            line = line.strip()
            if len(line) != 0:
                lines.append(line)
        return lines
    
#加载停用词列表
def stop_words(path):
    with open (path,'r',encoding='utf-8') as f:
        return [line.strip() for line in f]



jieba.suggest_freq('段誉',True)
jieba.suggest_freq('萧峰',True)
jieba.suggest_freq('阿紫',True)
jieba.suggest_freq('乔峰',True)

#jieba.load_userdict('name.txt')

#分词
def cut_words(ready_words):
    sentences = [jieba.lcut(line) for line in ready_words]
    sens = []
    for sentence in sentences:
        sen = []
        for word in sentence:
            if word not in stop_words:
                sen.append(word)
        sens.append(sen)
    return sens
                
ready_words = read_words('天龙八部.txt')
stop_words = stop_words('stop_words.utf8')
token = cut_words(ready_words)

#检验结果
token[0]



#将分词结果变成一个列表
c=[]
for sentence in token:
    for word in sentence:
        c.append(word)

#直接调用统计词频的函数
# from collections import Counter
# top5= Counter(c).most_common(29)
# print(top5)

#统计四字词语
dic_tf = {}
for w in c:
    if  len(w) == 4 and w not in ['耶律洪基','慕容公子','神仙姊姊','慕容先生','不平道人','天山童姥','智光大师','玄苦大师','太皇太后','小无相功']:
        dic_tf[w] = dic_tf.get(w,0) + 1
print(sorted(dic_tf.items(),key=lambda x:x[1],reverse=True)[:20])

dic_tf

#生成词云图
from wordcloud import WordCloud
wc = WordCloud(font_path = 'simhei.ttf',
                   background_color="black",  # 背景颜色
                   max_words=20 # 词云显示的最大词数
                   )

wc.fit_words(dic_tf)

import matplotlib.pyplot as plt
plt.figure()
plt.imshow(wc)
plt.axis("off")
plt.show()

#模型训练
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

from gensim.models import Word2Vec  
model = Word2Vec(token)

model.save('model')  #保存模型
model = Word2Vec.load('model')   #加载模型

#判断与段誉相近的词
print(model.most_similar('段誉'))
#判断相似度
model.similarity('段誉', '王语嫣')
#判断与萧峰相近,与王语嫣不相近的词
print(model.most_similar(positive=['萧峰'], negative=['王语嫣']))
#找出指定长度的相关词
req_count = 20
for key in model.similar_by_word('李秋水'):
    if  len(key[0]) <= 4:
        req_count -= 1
        print(key[0],key[1])
        if req_count == 0:
            break

猜你喜欢

转载自blog.csdn.net/qq_38923076/article/details/82946064