Jupyter Notebook使用Gensim库做中文Word2Vec模型计算

2021-9-16 11:39| 发布者: Fuller| 查看: 4291| 评论: 5

摘要: 本notebook想尝试一下使用实际场景的数据,探索一下能计算出来什么结果。演练完这个notebook,我的感受是word2vec主要还是为下一步运算准备数据,自身生成的结果不要过多解读,不像我们在前面几个notebook中介绍的te ...

1,本Notebook背景介绍

本notebook想尝试一下使用实际场景的数据,探索一下能计算出来什么结果。演练完这个notebook,我的感受是word2vec主要还是为下一步运算准备数据,自身生成的结果不要过多解读,不像我们在前面几个notebook中介绍的textRank、LDA、k-means等算法,其结果是用来解读的,相反,word2vec主要还是为了弥补one-hot编码的缺点,利用上下文隐含的语义信息产生稠密的矩阵,而且生成的词向量是不可解读的。至少从我这种悲观主义者眼中看是这样的。所以从我们推荐的研究论文范文中也可以看到,word2vec是作为一个中间步骤。

在昨天发布的《Jupyter Notebook使用gensim做Word2Vec模型实验》一文中,我们按照Gensim官网教程,基于安装gensim库时自带的英文语料库“Lee评估语料库”,进行了针对英文文本的Word2Vec模型实验,主要步骤有:

1. 加载语料库

2. 训练模型

3. 查看和输出模型

4. 保存模型

5. 加载已经保存的模型并进行更新训练

今天我们进行针对中文文本的Word2Vec模型计算:先使用GooSeeker文本分词和情感分析软件进行分词,分词得到的“分词效果表”作为中文语料库,进行word2vec计算。

那么,使用gensim的Word2Vec算法的关键一步是:把实际场景的数据变成sentences数据结构,剩下的步骤就是gensim的word2vec各种函数调用了。本Jupyter Notebook将做详细讲解。

什么是word2vec以及相关的学习材料等不再赘述,有兴趣的同学可以看《Jupyter Notebook使用gensim做Word2Vec模型实验

2,第三方库

本notebook使用了gensim库,gensim库用于做Word2vec实验。

如果未安装,请先使用下面的命令安装gensim库,再运行实验本notebook:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple gensim #国内安装使用清华的源,速度快

3,本notebook的主要步骤

参考Gensim官网的教程,使用实际场景中的中文内容进行word2vec计算,要做以下步骤:

1. 使用GooSeeker文本分词和情感分析软件进行分词,分词得到的“分词效果表”作为中文语料库

2. 从分词工具导出的分词效果表文件“分词效果_20xxxxxxxxxxxxxxxxx.xlsx”放入本notebook的data/raw/目录下

3. 运行本Jupyter Notebook,使用Pandas把分词结果数据读出来,转成csv文件

4. 利用gensim库中的读取csv文件的函数生成sentences数据结构

5. 将sentences数据结构交给word2vec模型

第5步相对来说比较简单,只要熟练掌握gensim的相关函数调用就行了。而1-4步是在实际分析场景下必须完成的步骤。

4,准备运算环境

4.1 开启日志输出

把实验过程中的日志信息直接在Jupyter Notebook中输出,对于初学者来说,有助于掌握word2vec的算法和gensim的计算原理。熟练以后,可以把这一段删除。

import logging

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)

4.2 引入gensim库

引入gensim库下的models,datapath,utils。其中datapath是便于操作磁盘文件的程序库,而uitils中一个使用csv文件的函数可以方便我们生成word2vec需要的sentences数据结构。

from gensim.test.utils import datapath

from gensim import utils

import gensim.models

5,生成word2vec需要的数据结构

按照gensim的官方文件,sentences是一个iteratable的数据结构即可,而且要求可以rewind的,不能是iterator生成器生成的只能迭代一次的结构。我们使用utils里面的一个函数,可以把csv文件直接读进来生成sentences数据结构表示的语料库。所以,首先要将GooSeeker分词软件生成的excel文件中的分词结果数据转换成csv文件。

【注意】生成了中间文件不是唯一选择,只是一种编程便利方式,可能运行时会稍微慢一点,因为要从pandas转成csv。但是,这个csv并没有实际存盘,是内存中的,所以,也不会慢很多。

5.1 准备好pandas

导入必要的Python程序包,并且设定文件目录变量。原始数据放在raw文件夹,而处理好的数据放在processed文件夹。这里的原始数据就是从GooSeeker分词软件导出的分词效果表;而处理好的数据就是生成的csv文件。

import pandas as pd

import os

import time

%xmode Verbose

import warnings

warnings.filterwarnings("ignore", category=DeprecationWarning)

# 存原始数据的目录

raw_data_dir = os.path.join(os.getcwd(), '..\\..\\data\\raw')

# 存处理后的数据的目录

processed_data_dir = os.path.join(os.getcwd(), '..\\..\\data\\processed')

filename_temp = pd.Series(['分词效果'])

file_seg_effect = ''

输出结果:

Exception reporting mode: Verbose

5.2 检测data\raw目录下是否有分词效果表

在我们发布的一系列Jupyter Notebook中,凡是处理GooSeeker分词软件导出的结果文件的,都给各种导出文件起了固定的名字。为了方便大家使用,只要把导出文件放在data/raw文件夹,notebook就会找到导出文件,赋值给对应的文件名变量。下面罗列了可能用到的文件名变量:

file_word_freq:词频表

file_seg_effect: 分词效果表

file_word_choice_matrix: 选词矩阵表

file_word_choice_match: 选词匹配表

file_word_choice_result: 选词结果表

file_co_word_matrix: 共词矩阵表

【注意】本notebook只使用分词效果表,下面的代码将检查data/raw中有没有分词效果表,如果没有会报错,后面的程序就没法执行了。

# 0:'词频', 1:'分词效果', 2:'选词矩阵', 3:'选词匹配', 4:'选词结果', 5:'共词矩阵'

print(raw_data_dir + '\r\n')

for item_filename in os.listdir(raw_data_dir):

    if filename_temp[0] in item_filename:

        file_seg_effect = item_filename

        continue

if file_seg_effect:

    print("分词效果excel表:", "data\\raw\\", file_seg_effect)

else:

    print("分词效果excel表:不存在")


5.3 读取分词效果表

df = pd.read_excel(os.path.join(raw_data_dir, file_seg_effect))


5.4 查看excel表前10行数据

我们使用“分词数据”这一列,作为模型实验的语料库。可以看到“分词数据”这列的数据是分词后的效果,每个分开的词之间用空格间隔。

df.head(10)

5.5 把“分词数据”列保存到csv文件

corpus_path = os.path.join('../../data/processed', 'corpus.csv')

df["分词数据"].to_csv(corpus_path,index=False, header=False ,encoding="utf-8")


6,构建语料库

6.1 定义SegEffectCorpus语料库类

定义一个python类,为了今后方便使用。这个类就是把前面生成的csv文件的每一行读进来,一行是一个文档,所有行构建成word2vec需要的语料库数据结构。

class SegEffectCorpus:

    """An iterator that yields sentences (lists of str)."""

    def __iter__(self):

        corpus_path = "corpus.csv"

        for line in open(corpus_path, encoding='UTF-8'):

            # 每行一篇文档,每个文档由空格分隔的多个词组成

            # there's one document per line, tokens separated by whitespace

            yield utils.simple_preprocess(line)


6.2 生成语料库

一行一个文档,这里面有所有行,命名为sentences。

sentences = SegEffectCorpus()


7,基于句子训练word2vec模型

训练时,句子(sentences)参数必须指定,除此之外,还有其它几个可选参数:

min_count:缺省值是5, 表示在预料库里不少于5次的词才会被保留

vector_size: Gensim Word2vec 映射单词的 N 维空间的维度 (N) 数。

下面我们将训练多个模型做对比,每个模型的vector_size不一样

model_v20 = gensim.models.Word2Vec(sentences=sentences, vector_size = 20)

model_v50 = gensim.models.Word2Vec(sentences=sentences, vector_size = 50)

model_v100 = gensim.models.Word2Vec(sentences=sentences, vector_size = 100)

model_v1000 = gensim.models.Word2Vec(sentences=sentences, vector_size = 1000)

model_v5000 = gensim.models.Word2Vec(sentences=sentences, vector_size = 5000)

7.1 看看模型有哪些维度

先看一下模型所在的向量空间是多少维,原始维度是一样的,都是5513个词

print(len(model_v20.wv.index_to_key));

print(len(model_v50.wv.index_to_key));

print(len(model_v100.wv.index_to_key));

print(len(model_v1000.wv.index_to_key));

print(len(model_v5000.wv.index_to_key));

输出结果:

5513

5513

5513

5513

5513

7.2 查看模型的前10个词

for index, word in enumerate(model_v20.wv.index_to_key):

    if index == 20:

        break

    print(f"word #{index}/{len(model_v20.wv.index_to_key)} is {word}")

输出结果:

word #0/5513 is 下岗

word #1/5513 is 一个

word #2/5513 is 没有

word #3/5513 is 国企

word #4/5513 is 现在

word #5/5513 is 企业

word #6/5513 is quot

word #7/5513 is 他们

word #8/5513 is 时候

word #9/5513 is 自己

word #10/5513 is 工人

word #11/5513 is 国家

word #12/5513 is 这个

word #13/5513 is 我们

word #14/5513 is 当时

word #15/5513 is 工作

word #16/5513 is 因为

word #17/5513 is 什么

word #18/5513 is 但是

word #19/5513 is 很多

7.3 不同模型的维度构成

上面看到所有模型中查到的原始维度都是由5513个词构成的,而用下面的语句可以看到计算完成后每个词的向量维度数等于vector_size,但是这些维度是什么?看不出来,不是原先的词,不要以为从原先5513个词选出了20个、50个...构成了新的向量空间。

vec_king = model_v20.wv['企业']

print(vec_king)

输出结果:

[-0.3846502  -0.35217553  0.78828686  0.8946948  -0.205592   -0.8147616

 -0.2380229   0.6689105   0.12241378  2.2435844   1.9278524  -0.21242936

  0.06304763 -0.84816504  0.917462    1.5474753   0.31649536  0.30643114

  0.03492499 -1.0469717 ]

7.4 对比不同模型相近的词

查看词语“企业”最相近的10个词

print("20维:企业最相近的10个词")

for item in model_v20.wv.most_similar(positive=['企业'], topn=10):

    print(item)

print("50维:企业最相近的10个词")

for item in model_v50.wv.most_similar(positive=['企业'], topn=10):

    print(item)

print("100维:企业最相近的10个词")

for item in model_v100.wv.most_similar(positive=['企业'], topn=10):

    print(item)

print("1000维:企业最相近的10个词")

for item in model_v1000.wv.most_similar(positive=['企业'], topn=10):

    print(item)

print("5000维:企业最相近的10个词")

for item in model_v5000.wv.most_similar(positive=['企业'], topn=10):

    print(item)

输出结果:

20维:企业最相近的10个词

('政府', 0.9701895117759705)

('国有企业', 0.9596976637840271)

('效率', 0.955802857875824)

('大量', 0.9421055316925049)

('中小型', 0.9379032254219055)

('低下', 0.9362995624542236)

('亏损', 0.9339385032653809)

('垄断', 0.9311338663101196)

('生产', 0.9291993379592896)

('盈利', 0.9277654886245728)

50维:企业最相近的10个词

('国有企业', 0.9838334321975708)

('社会', 0.9760490655899048)

('开放', 0.9752578139305115)

('政府', 0.9712843298912048)

('改革', 0.969390869140625)

('大量', 0.9637796878814697)

('效率', 0.9617377519607544)

('市场', 0.9595521688461304)

('国家', 0.9594038128852844)

('垄断', 0.9583749175071716)

100维:企业最相近的10个词

('国有企业', 0.9907254576683044)

('社会', 0.9851162433624268)

('开放', 0.9797177910804749)

('改革', 0.9780121445655823)

('政府', 0.9771029949188232)

('大量', 0.9718190431594849)

('效率', 0.9714088439941406)

('垄断', 0.9705336689949036)

('国家', 0.9695110321044922)

('市场', 0.9664446711540222)

1000维:企业最相近的10个词

('国有企业', 0.9982540607452393)

('社会', 0.9979686737060547)

('开放', 0.9975664615631104)

('效率', 0.9960200190544128)

('大量', 0.9959481358528137)

('垄断', 0.9956788420677185)

('低下', 0.99522864818573)

('政府', 0.9952222108840942)

('三产', 0.9947063326835632)

('盈利', 0.9945940971374512)

5000维:企业最相近的10个词

('劳动力', 0.9991272687911987)

('市场', 0.9990919828414917)

('发展', 0.9990687370300293)

('工业', 0.9990560412406921)

('僵化', 0.9990420937538147)

('抓大放小', 0.9989959001541138)

('现代化', 0.9989417195320129)

('放权', 0.9989097118377686)

('产业', 0.998893141746521)

('需求', 0.9988720417022705)

vector_size不同的时候,结果差别还是很大的。怎么解释?怎么选择?还需要进一步探索。

8,其他探索

8.1 对于模型中没有的词,是查不到的

try:

    vec_cameroon = model_v20.wv['给力']

except KeyError:

    print("The word '给力' does not appear in this model")

输出结果:

The word '给力' does not appear in this model

8.2 看看哪个词距离最远

print("20维的时候:" + model_v20.wv.doesnt_match([ '私企', '外资企业','企业', '集体企业', '国企', '集体企业', '外企']))

print("50维的时候:" + model_v50.wv.doesnt_match([ '私企', '外资企业','企业', '集体企业', '国企', '集体企业', '外企']))

print("100维的时候:" + model_v100.wv.doesnt_match([ '私企', '外资企业','企业', '集体企业', '国企', '集体企业', '外企']))

print("1000维的时候:" + model_v1000.wv.doesnt_match([ '私企', '外资企业','企业', '集体企业', '国企', '集体企业', '外企']))

print("5000维的时候:" + model_v5000.wv.doesnt_match([ '私企', '外资企业','企业', '集体企业', '国企', '集体企业', '外企']))

输出结果:

20维的时候:企业

50维的时候:企业

100维的时候:企业

1000维的时候:国企

5000维的时候:企业

这里也不太好解读,而且我发现把这个notebook运行多次,看到的结果会有变化,“国企”从1000维变到5000维,再变到1000维

9,保存模型

把训练得到的模型保存到磁盘,按照我们这套notebook的目录规划,把训练好的模型存在model目录中。下面将存两个文件,一个是原生结构的模型文件,另一个是字符格式的模型文件,便于观察。

#import tempfile

#model_path = ''

#with tempfile.NamedTemporaryFile(prefix='gensim-model-', delete=False) as tmp:

#    temporary_filepath = tmp.name

    #model_v20.save(temporary_filepath)

#    model_v20.wv.save_word2vec_format(temporary_filepath)

#    model_path = temporary_filepath

model_file = 'gensim-model-' + str(time.strftime("%Y%m%d%H%M%S", time.localtime()))

format_file = model_file + '-fmt'

model_path = os.path.join('../../model/', model_file)

format_path = os.path.join('../../model/', format_file)

model_v20.save(model_path)

model_v20.wv.save_word2vec_format(format_path)

输出结果:

2021-09-16 10:33:18,106 : INFO : Word2Vec lifecycle event {'fname_or_handle': '../../model/gensim-model-20210916103318', 'separately': 'None', 'sep_limit': 10485760, 'ignore': frozenset(), 'datetime': '2021-09-16T10:33:18.106494', 'gensim': '4.0.1', 'python': '3.8.5 (default, Sep  3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)]', 'platform': 'Windows-10-10.0.19041-SP0', 'event': 'saving'}

2021-09-16 10:33:18,107 : INFO : not storing attribute cum_table

2021-09-16 10:33:18,112 : INFO : saved ../../model/gensim-model-20210916103318

2021-09-16 10:33:18,118 : INFO : storing 5513x20 projection weights into ../../model/gensim-model-20210916103318-fmt

10,加载模型

从已保存的文件里加载模型

new_model = gensim.models.Word2Vec.load(model_path)

输出结果:

2021-09-16 10:33:23,673 : INFO : loading Word2Vec object from ../../model/gensim-model-20210916103318

2021-09-16 10:33:23,781 : INFO : loading wv recursively from ../../model/gensim-model-20210916103318.wv.* with mmap=None

2021-09-16 10:33:23,784 : INFO : setting ignored attribute cum_table to None

2021-09-16 10:33:23,889 : INFO : Word2Vec lifecycle event {'fname': '../../model/gensim-model-20210916103318', 'datetime': '2021-09-16T10:33:23.889030', 'gensim': '4.0.1', 'python': '3.8.5 (default, Sep  3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)]', 'platform': 'Windows-10-10.0.19041-SP0', 'event': 'loaded'}

11,继续训练

基于加载的模型,我们可以使用新的预料进行进一步的训练

more_sentences = [

    ['我国','GDP','最高','的','四座','省份', '分别', '是', '广东', '江苏', '山东', '浙江']

]

new_model.build_vocab(more_sentences, update=True)

new_model.train(more_sentences, total_examples=model_v20.corpus_count, epochs=model_v20.epochs)

12,下载本Notebook

下载源代码请进:在实际数据场景下使用Gensim库做中文Word2Vec计算


鲜花

握手

雷人

路过

鸡蛋
发表评论

最新评论

评论 15964002091 2021-10-23 14:50
《基于多源数据的物流服务水平地区差异性分析》(周雪)、《基于在线评论的进口跨境电商物流服务顾客满意度研究》(
魏蕊)这是我看的两篇硕士论文里面都用到了这个聚类,将特征词聚类
评论 Fuller 2021-10-23 11:04
15964002091: 能否在这个实验基础上,使用K-means对Word2vec输出的词向量做聚类,我看有的论文里是这样用的,可否出一个notebook。 ...
把那个论文题目发出来我看看。你是想对词进行聚类吗?
评论 15964002091 2021-10-23 10:36
能否在这个实验基础上,使用K-means对Word2vec输出的词向量做聚类,我看有的论文里是这样用的,可否出一个notebook。
评论 Fuller 2021-9-16 15:38
15964002091: 我看的一篇论文,他先获取了高频词汇,然后对高频词汇使用Word2Vec进行相似词的拓展,来拓展高频词库,这个能实现吗 ...
你是说当时建立word2vec模型的时候用了更大一个语料库,里面有一些值得提取出来的词? 用相似函数可以做拓展词的任务。这里讨论的这个论文好像就是这么做的:https://www.gooseeker.com/doc/thread-19066-1-1.html
评论 15964002091 2021-9-16 15:17
我看的一篇论文,他先获取了高频词汇,然后对高频词汇使用Word2Vec进行相似词的拓展,来拓展高频词库,这个能实现吗

查看全部评论(5)

GMT+8, 2024-11-24 20:18