非格式化数据分析:语义结构分析-Gensim
- Gensim 是一个通过衡量词组(或更高级结构,如整句或文档)模式来挖掘文档语义结构的工具
- 通过检查词出现的频率。gensim读取一段语料,输出一个向量,表示文档中的一个词。
- 该向量表示可被用于训练一个“模型”。模型是从数据生成不同特征的算法集
下面主要使用词向量分析方法
词向量
- word2vec也叫word embeddings,中文名“词向量”,作用就是将自然语言中的字词转为计算机可以理解的稠密向量(Dense Vector)。
- 在word2vec出现之前,自然语言处理经常把字词转为离散的单独的符号,也就是One-Hot Encoder
- 词向量是将独热编码进一步处理(降维)的结果,如根据某段文本内的词频编码为向量
word2vec主要通过计算词向量之间的余弦相似度来分析词之间的距离关系远近(cosA=AC/AB)
Gensim包安装
注:Gensim新版安装需要特定环境否则运行极慢,建议安装特定版本 pip show gensim # 查看版本 pip uninstall gensim # 卸载之前版本 pip install gensim==3.7.1 # 安装特定版本
import numpy as np import pandas as pd # 分词 import jieba import jieba.analyse # gensim # 载入gensim报警告不用管,重新加载一次,或者加上下面语句 # import warnings # warnings.filterwarnings(action='ignore',category=UserWarning,module='gensim') from gensim.models import word2vec
案例天龙八部
- 数据载入
- 分词
- 去停用词
- 分词合并为文本
- 保存分词后文本
- 提取关键词
with open('data/天龙八部.txt', 'r', encoding='utf-8') as f:
mytxt = f.read()
mytxt
分词
# 添加自定义词典
jieba.load_userdict('data/custom.txt')
mytxt = jieba.cut(mytxt)
mytxt
# 去停用词
stop_words = []
with open('data/stopword.txt', 'r', encoding='utf-8') as f:
for line in f.readlines():
l = line.strip()
if l == '\n':
l = '
'
if l == '\u3000':
l = 'u3000'
stop_words.append(l)
stop_words
# 词的字数应该大于1个字
words = [w for w in mytxt if len(w) > 1]
words
# clean stop_words,手工去停用词
fenci2 = [w for w in words if w not in stop_words]
fenci2
# 分词合并为文本
mytext = " ".join(fenci2)
mytext
# 保存分词后文本
with open('temp/天龙八部_分词后.txt', 'w', encoding='utf-8') as f:
f.write(mytext)
提取关键词
词频
with open('temp/天龙八部_分词后.txt', 'r', encoding='utf-8') as f:
fenci1 = f.read()
fenci2 = fenci1.split(' ')
fenci2
pd.Series(fenci2).value_counts()[:30]
# 算法提取去停用词
jieba.analyse.set_stop_words('data/stopword.txt') # 抽取关键词前去掉自定义停用词
TF-IDF算法提取关键字
不需分词直接执行
k = jieba.analyse.extract_tags(fenci1,topK=50, withWeight=True)
TEXT-RANK算法
比较慢
t = jieba.analyse.textrank(mytext, topK=50, withWeight=True, allowPOS=('ns', 'n', 'vn', 'v'))
使用gensim的vord2vec词向量训练
载入数据,转化
sentences = word2vec.Text8Corpus('temp/天龙八部_分词后.txt')
# 训练语料
# min_count:小于该数的单词会被剔除,默认值为5
# size:神经网络的隐藏层单元数,默认为100
# 训练词向量时传入的参数对训练效果有很大影响,需要根据语料来决定参数的选择,好的词向量对NLP的分类、聚类、相似度判别等任务有重要意义
# window:一个句子当前词和预测值之间的最大距离
# workers:多线程
model=word2vec.Word2Vec(sentences, min_count=5, size=100, window=5, workers=4)
model
计算两个词之间的相似度
余弦相似度(C为直角):cosA = = 邻边/斜边 = b/c = AC/AB
model.wv.similarity('乔峰', '阿朱')
model.wv.similarity('乔峰', '王语嫣')
model.wv.similarity('段誉', '王语嫣')
模型训练有随机参数,每次训练的结果会有不同
# 词向量
model.wv.word_vec('段誉')
计算余弦距离最接近 某词 的10个词
y2 = model.wv.most_similar("段誉", topn=20) # 20个最相关的
# 计算多个词的相关词
word = ['乔峰','段誉','慕容复','王语嫣','游坦之','木婉清','鸠摩智','李秋水']
for i in word:
print("{}:".format(i), end="")
for item in model.wv.most_similar(i, topn=10):
print(item[0],end=', ')
print()
# 存储模型
model.save('temp/word2vec_model')
# 加载模型
new_model=word2vec.Word2Vec.load('temp/word2vec_model')
new_model
# 计算某个词的相关词列表
y2 = new_model.wv.most_similar(positive=['段誉', '慕容复'], topn=10) # 10个最相关的
for item in y2:
print(item[0], item[1])
#使用一些词语来限定,分为正向和负向的
result = model.wv.most_similar(positive=['段誉', '王语嫣'], negative=['虚竹'], topn=20)
print('同"段誉"与"王语嫣"二词接近,但是与"虚竹"不接近的词有:')
for item in result:
print(' "'+item[0]+'" 相似度:'+str(item[1]))
#从一堆词里面找到不匹配的
model.wv.doesnt_match(np.array(['王语嫣 ', '阿紫', '阿朱', '虚竹']))