自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧

自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧

NLP中进行词义消歧的一个非常方便且简单的方法就是训练词向量,通过词向量计算余弦值,来推断某个词在句子中的含义。python中的gensim提供了一个非常方便的方法,一句话就可以训练词向量。不过嘛,正如我们想的那样,肯定是语料库越大越好,但越大呢就训练的时间越长,这也是没办法的事情。
我建议大家用GPU来训练,当当当,强烈推荐AIstudio,非常好用,免费GPU10小时,不用白不用。
自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧_第1张图片哇塞,我刚刚发现百度AIstudio新推出了至尊GPU,赶紧来体验一下,这名字听起来太霸气了!

完整项目的aistudio链接:http://www.sogou.com/labs/resource/cs.php.
可以直接fork哦,有问题的话及时联系我哦。

训练词向量

首先我们来训练词向量,我使用的是搜狗实验室提供的新闻语料,链接如下:
http://www.sogou.com/labs/resource/list_yuliao.php.
自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧_第2张图片我下载的是这个完整版的,648MB,对我来说应该够用了,不过搜狗实验室还提供了一些更大的语料,还有1GB以上的,大家有兴趣的话,可以尝试一下,语料越大,效果越好哦。
下载好语料之后,对语料进行解压

!cd data/data83697 && unzip -q news_sohusite_xml.full.zip

因为语料是新闻的格式,我们这里的话只需要文本部分也就是content部分,所以提取content部分,保存到content.txt文件里面。
自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧_第3张图片

cat data/data83697/news_sohusite_xml.dat | iconv -f gbk -t utf-8 -c | grep ""  > corpus.txt

接下来,对文本进行一个分词处理,因为是中文,不像英文那样可以直接以空格隔开,所以使用jieba来进行分词。

import jieba
import numpy as np
filePath='corpus.txt'
fileSegWordDonePath ='corpusSegDone_1.txt'
# 打印中文列表
def PrintListChinese(list):
    for i in range(len(list)):
        print (list[i]) 
                
# 读取文件内容到列表
fileTrainRead = []
with open(filePath,'r') as fileTrainRaw:
    for line in fileTrainRaw:  # 按行读取文件
        fileTrainRead.append(line)

# jieba分词后保存在列表中
fileTrainSeg=[]
for i in range(len(fileTrainRead)):
    fileTrainSeg.append([' '.join(list(jieba.cut(fileTrainRead[i][9:-11],cut_all=False)))])
    if i % 100 == 0:
        print(i)
                
# 保存分词结果到文件中
with open(fileSegWordDonePath,'w',encoding='utf-8') as fW:
    for i in range(len(fileTrainSeg)):
        fW.write(fileTrainSeg[i][0])
        fW.write('\n')

分好词之后,我们就可以快乐训练啦,有种要炼丹的感觉。
我是在AIStudio里面做的实验,要先安装gensim库,一句话就好,告诉它,把gensim库给我安装上。

!pip install gensim

接下来,我们导入一下各种会用到的包,这一步我基本上都是导入许许多多。

import warnings
import logging
import os.path
import sys
import multiprocessing

import gensim
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
# 忽略警告
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')

正式开始训练词向量

program = os.path.basename(sys.argv[0]) # 读取当前文件的文件名
logger = logging.getLogger(program)
logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s',level=logging.INFO)
logger.info("running %s" % ' '.join(sys.argv))

# inp为输入语料, outp1为输出模型, outp2为vector格式的模型
inp = 'corpusSegDone_1.txt'
out_model = 'corpusSegDone_1.model'
out_vector = 'corpusSegDone_1.vector'
 
# 训练模型
model = Word2Vec(LineSentence(inp), vector_size=50, window=5, min_count=5,workers=multiprocessing.cpu_count())

# 保存模型
model.save(out_model)
# 保存词向量
model.wv.save_word2vec_format(out_vector, binary=False)

这一步真的还挺漫长的,GPU大概半个多小时左右,如果使用至尊GPU(我还没试过)应该可能会更快一点。

开始词义消歧

首先我们用“苹果”来做一个示范:
先引入刚刚训练好的模型

from gensim.models import Word2Vec
import numpy as np
model = Word2Vec.load('corpusSegDone_1.model')

来查看一下和苹果相似的词

model.wv.most_similar(u"苹果")

哦豁,有点意思哦,和“苹果”最相关的是“微软”、“谷歌”和“苹果公司”。可能有人要疑惑了,奇怪哦,为什么和苹果相似的不是“香蕉”、“葡萄”、“水蜜桃”之类的呢?没错,你发现了我们模型的问题!这个其实是因为我们的新闻语料库的原因,看来我们的新闻语料更偏向于科技方面。
后来,试了一下搜狗实验室的其他语料,惊讶的发现和苹果最相关的竟然是“月饼”还有“水果”!所以这个语料的选择真的非常重要!
自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧_第4张图片接下来我们就来测验一下,看看“用苹果性能好,分辨率高”中的“苹果”究竟是手机还是水果还是其他物品。
我给苹果的含义分了三种语义,“水果”、“手机”、“电影”,它们的使用场景分别是“这个()真好吃,营养价值高”、“()手机配置不高,但整体性能优化的很好”、“()上映了,听说非常精彩”。把这三句话jieba分词一下,来看一看我们的目标句子和这三句话哪个更接近。

content=['用','苹果','性能','好','分辨率','高']
des1=['这个','真','好吃','营养价值','高']
des2=['手机','配置','不高','但','整体','性能','优化','的','很','好']
des3=['上映','了','听说','非常','精彩']
def w2v_mean(essay,model):
    ls=np.zeros(50)
    for unit in essay:
        try:
            ls+=np.array(model.wv[unit])
        except:
            pass
    return ls/len(essay)

通过余弦值大小来判断,目标句子与三种语境的相似程度,余弦值越大,代表越接近。

content=w2v_mean(content,model)
d1=w2v_mean(des1,model)
d2=w2v_mean(des2,model)
d3=w2v_mean(des3,model)
print(np.dot(d1,content)/(np.linalg.norm(d1)*(np.linalg.norm(content))))
print(np.dot(d2,content)/(np.linalg.norm(d2)*(np.linalg.norm(content))))
print(np.dot(d3,content)/(np.linalg.norm(d3)*(np.linalg.norm(content))))

来看一看结果吧!
在这里插入图片描述很明显看到,第二种语境下的余弦值大于另外两个,所以我们可以说我们目标句子中的“苹果”就是手机的意思。
是不是非常有趣!
那我们再来试一下“算账”,算账有两种意思,一种是计算账目。如,“你别打扰他,他正在算账呢。” 还有一种是吃亏或失败后与人较量.如,“好了,这回算你赢,下回我再跟你算账!”

首先来看看我们的语料中和“算账”相似的词,效果还可以。

model.wv.most_similar(u"算账")

自然语言处理之使用gensim.Word2Vec训练词向量进行词义消歧_第5张图片我相看一看“我正要找你算账”中的“算账”应该是什么意思。(在自我推敲之后,自己也有点不确定,这句话中的“算账”该怎么解释)

content=['我','正要','找你','算账']
des1=['你别','打扰','他','他','正在','呢']
des2=['好','了','这回','算','你','赢','下回','我','再','跟','你']
def w2v_mean(essay,model):
    ls=np.zeros(50)
    for unit in essay:
        try:
            ls+=np.array(model.wv[unit])
        except:
            pass
    return ls/len(essay)
content=w2v_mean(content,model)
d1=w2v_mean(des1,model)
d2=w2v_mean(des2,model)
print(np.dot(d1,content)/(np.linalg.norm(d1)*(np.linalg.norm(content))))
print(np.dot(d2,content)/(np.linalg.norm(d2)*(np.linalg.norm(content))))

来看看结果,非常相近,不过第二种对应的余弦值更大一些,那这里的“算账”就解释为“吃亏或失败后与人较量”吧。
在这里插入图片描述语义消歧就是这样啦,大家可以直接点击连接去运行一下代码,非常方便哦!
哦对啦,我开始把讲解更新B站和抖音啦,名字都叫猫猫头丁,欢迎大家来关注啊!!!
B站:https://space.bilibili.com/410893912.

你可能感兴趣的:(自然语言处理,自然语言处理,nlp,词向量,gensim,aistudio)