先来看一看结果,发现:1.贾宝玉和袭人的关系最近。2.薛宝钗和自己的妈妈关系最近。3.贾宝玉和林黛玉逼格比较统一,薛宝钗属于独树一帜的逼格调性。4.大观园中可以看到邢岫烟经常出没... 还有更多秘密等你自己上手去训练模型并发现...

先来看一看结果,发现:

1.贾宝玉和袭人的关系最近。

2.薛宝钗和自己的妈妈关系最近。

3.贾宝玉和林黛玉逼格比较统一,薛宝钗属于独树一帜的逼格调性。

4.大观园中可以看到邢岫烟经常出没...

还有更多秘密等你自己上手去训练模型并发现...

 

开始写代码!

1from tqdm import tqdm
2#tqdm用来观察进度条,非必须
3import jieba
4import sys
5import os

声明一下,这里自定义了两个词典分别命名为“renming.txt”和“diming.txt”,分别写入了红楼梦中常见人名地名,这里展示一下格式,有需要的可以添加我微信dicey0310

 

python 红楼梦人物关系网络图 红楼梦的人物关系网络_python 红楼梦人物关系网络图

python 红楼梦人物关系网络图 红楼梦的人物关系网络_相似度_02

 

继续写代码!

1os.chdir("C://users//dicey//desktop")
 2# 调用 jieba分词module后,添加单词本(人名等):
 3jieba.load_userdict("renming.txt")
 4jieba.load_userdict("diming.txt")
 5
 6#这里是在百度上下载的红楼梦完整版的txt
 7filename = 'HongLouMeng.txt'
 8text_lines = []
 9with open(filename,encoding='utf-8',errors='ignore') as f:
10    for line in tqdm(f):
11        text_lines.append(line)
12print('总共读入%d行文字'% (len(text_lines)))
13
14#检查一下读入文字的正确性
15print(text_lines[17])

 

把红楼梦的txt版(utf-8编码)一行一行读进来,用tqdm辅助显示进度条:

1data_lines = []
2
3## 分词并添加进列表:
4for line in tqdm(text_lines):
5    one_line = [' '.join(jieba.cut(line, cut_all=False))][0].split(' ')
6    data_lines.append(one_line)

 

开始数据预处理,去除了标点符号、数字、停用词:

1import re
2# 标点符号 (punctuation)
3punct = set(u'''.&#:!),.:;?]}¢'"、。〉》」』】〕〗〞︰︱︳﹐、﹒﹔﹕﹖﹗﹚﹜﹞! .&# &# ),.*:;O?|}︴︶︸︺︼︾﹀﹂﹄﹏、~¢々‖•·ˇˉ―--′’”([{£¥'"‵〈《「『【〔〖([{£¥〝︵︷︹︻︽︿﹁﹃﹙﹛﹝({“‘-—_…0123456789''')
4isNumber = re.compile(r'\d+.*')
5with open('stopwords.txt',encoding='utf-8',errors='ignore') as f:
6    stopwords = f.read()
7filter_words = [w for w in data_words if (w not in punct)
8                and (not isNumber.search(w.lower()))and(w not in stopwords)]

 

引入gensim库,并使用Word2Vec模型构造内部字典树,和训练神经模型:

1import gensim
2model = gensim.models.Word2Vec(iter=1) 
3# an empty model, no training yet
4model.build_vocab(data_lines) #传入语料,构建内部字典树
5model.train(data_lines, total_examples = len(data_lines), epochs = 100) 
6#开始训练神经模型100次
7#epochs表示训练次数

 

注意,上面这块代码也可换做下面这样的简写法:

1import gensim
2model = gensim.models.Word2Vec(data_lines,iter=10)  
3'''
4直接把data_lines喂给World2Vec模型,
510代表会调用句子迭代器运行11次(一般来说,会运行 iter+1 次,默认情况下  iter=5)。
6第一次运行负责收集单词和它们的出现频率,从而构造一个内部字典树。第二次以及以后的运行负责训练神经模型(train)。
7'''

 

开始读入我们关心的人名、地名,并打印结果:

1test_words = ['林黛玉','黛玉','贾宝玉','宝玉','薛宝钗','宝钗','袭人','大观园','潇湘馆','蘅芜苑','妙玉','栊翠庵']
 2#开始读入
 3neighbors = []
 4for test_word in test_words:
 5    neighbors.append(model.most_similar(test_word))
 6#开始打印结果
 7for i in range(len(neighbors)):
 8    str = ' '.join([x[0] for x in neighbors[i]])
 9    print('%s:' % test_words[i])
10    print('\t%s\n' % (str))

 

这里展示部分结果:(每个人名、地名之后跟的是与自己关系最密切/在100维词向量中最相近的名词)

python 红楼梦人物关系网络图 红楼梦的人物关系网络_字典树_03

 

最后我们看一下“黛玉”的坐标(100维),以及“黛玉”和“林黛玉”之间的相似度。

1print(model["黛玉"])
2print(model.similarity("黛玉",'林黛玉'))

python 红楼梦人物关系网络图 红楼梦的人物关系网络_python 红楼梦人物关系网络图_04

python 红楼梦人物关系网络图 红楼梦的人物关系网络_相似度_05

注意:相似度不为1(相似度等于1时代表词向量在每个维度上都完全相等)。是因为叫“林黛玉”时常为正式场合,直呼“黛玉”时一般属于日常情况,相信各位懂得~