Python文本分析:将词转换为向量-Word2Vec

发布时间:2022-12-27 阅读 1092

Stata连享会   主页 || 视频 || 推文 || 知乎 || Bilibili 站

温馨提示: 定期 清理浏览器缓存,可以获得最佳浏览体验。

New! lianxh 命令发布了:
随时搜索推文、Stata 资源。安装:
. ssc install lianxh
详情参见帮助文件 (有惊喜):
. help lianxh
连享会新命令:cnssc, ihelp, rdbalance, gitee, installpkg

课程详情 https://gitee.com/lianxh/Course

课程主页 https://gitee.com/lianxh/Course

⛳ Stata 系列推文:

PDF下载 - 推文合集

作者:王卓 (合肥工业大学)
邮箱2020171526@mail.hfut.edu.cn


目录


1. 简介

文本分析目前是经济金融领域炙手可热的研究工具,这种非结构化数据 (unstructured data) 能够为金融学领域提供更丰富的研究内容和研究视角。已有大量文献通过文本挖掘的方式,将非标准数据转化为可量化的指标,对非传统领域的经济现象展开研究。但是直接的文本不属于计算机可读语言,必须将文本转化为特征数值输入才可以对文本进行进一步分析。这篇文章针对文本“数值化”的方法之一 Word2Vec 进行简要介绍和简单的案例操作。

  • 本文案例实现过程均使用 Python 语言,适用于习惯使用 Python 的读者进行阅读。
  • 本文尽量使用通俗的语言解释 Word2Vec,不免出现表达不规范的地方。
  • 本文对 Word2Vec 的介绍不涉及对底层算法的讨论,数理基础薄弱的读者可以放心食用。
  • 本文对 Word2Vec 的操作较为简单,该方法的适用性还需考虑个人的具体要求。

2. Word2Vec 介绍

Word2Vec 模型由谷歌于 2013 年创建,是一种无监督的,基于预测性深度学习的模型 (其实并不深度),主要用于计算和生成高质量、分布式和连续稠密向量表示的词汇,以捕获上下文和语义的相似度。该模型可以吸收大量文本语料库,创建可能的词汇表,并为代表该词汇表的向量空间中的每个单词生成稠密的词嵌入 (Embedding)。

为了更好的理解 Word2Vec 的特点和优势,这部分主要从词向量,Word2Vec 模型两大方面进行简单介绍。

2.1 词向量介绍

词向量,简单的说就是将文字这种人类语言转化为计算机可理解的语言。这个过程就是把语言这种符号信息转化为向量形式的数字信息,即将自然语言问题转换为机器学习的问题。主流的词向量主要有独热编码 (one-hot Representation) 模型和分布式表征 (distributed representation) 模型。

独热编码:是用一个很长的向量来表示一个词,向量长度为词典的大小 N。每个向量中数值为 1,表示该词语在词典的位置,向量其余维度全部为 0。

例如,我们需要分析的文本有两句话:“你今天学习了吗”和“你论文写完了吗”。在去除停用词 (即一些没有实际含义的虚词) 后,第一句话里有“你”、“今天”、“学习”三个词,第二句话里有“你”、“论文”、“写”三个词,此时我们的词典里共有 5 个词,即词典大小为 5。

独热编码后,“你”可以表示为 [1,0,0,0,0],“学习”可以表示为 [0,0,1,0,0]。不难理解,第一句话词向量可以表示为 [1,1,1,0,0],第二句可以表示为 [1,0,0,1,1]。两个向量均出现 1 的位置即代表“你”。

虽然这种编码方式简洁、易理解,但当词点大小 N 太大时,在文本语言模型构建时会出现“维度灾难”,而且每个词都是独立的,考虑不到上下文词汇的相关性。

分布式表征:其核心思想是词语的语义是通过上下文信息来确定的,即相同语境出现的词,其语义也相近。也就是说该模型最大的贡献就是让相关或者相似的词,在距离上更接近了。

具体来说,不同于独热编码的稀疏表示,分布式表征是一种固定长度的稠密词向量。一般形式如 [0.618, −0.401, −0.401, 0.419, …]。分布式表征词向量编码一定程度上解决了独热编码忽略词汇上下文的问题,而且词典的长度是固定的,也避免了词向量维度过大导致的计算问题。

本文介绍的 Word2Vec 模型是生成分布式表征词向量模型的方式之一 (其他生成方式还有 LSA 矩阵分解模型、PLSA 潜在语义分析概率模型、LDA 文档生成模型等)。看不懂,没关系。总的来说就是分布式表征可以做到算的又快又好,而 Word2Vec 正好可以产生分布式表征的词向量。

2.2 Word2Vec 模型

Word2Vec 的含义就如他的名字所示:将词转化为向量。其过程大致是将 word 映射到一个新的空间中,并以多维的连续实数向量进行表示,这叫做词嵌入 (Word Represention 或 Word Embedding)。

一般的机器学习或深度学习模型中,我们训练的样本一般都有输入值 x 和目标值 y,训练模型时主要构建 f(x) 对 y 的映射。但语言模型 (language model) 的输入值和目标值不同于传统模型,语言模型把 x 看做一个句子里的一个词语,y 是这个词语的上下文词语,构建模型 f(x),进而判断判断 (x,y) 这个样本是否符合自然语言的法则,例如 x 和 y 连在一起读是不是合理。

Word2vec 作为语言模型的一种,虽然他最终目的不是训练一个完美的 f,但他关心模型训练完后的参数 (这里特指神经网络的权重),并将这些参数作为输入 x 的某种向量化的表示,这也就是我们上文提到的词向量。

2.2.1 Skip-gram 模型

Skip-gram 即跳词模型,训练时词汇 x 为独热编码形式的输入 (这里为什么是 one-hot 形式而不是 distributed,请读者思考,答案就在上文中),y 是在词库中所有词汇上输出的概率。最终,我们希望真实的 y 和独热编码形式的 x 相同。模型的神经网络图如下:

从 x 输入到模型输出过程有一个无任何表现形式的“隐含层”,该隐含层对输入进行了一系列的“加工”,产生了一个权重向量,在到输出层的过程中也产生了一个权重向量,我们可以把这个两个权重向量看作输入词语的另外一种表达方式,也就是 Word2Vec 的词向量。这两个词向量分别是输入向量和输出向量,一般情况下使用输入向量。

需要提到一点的是,这个词向量的维度 (与隐含层节点数一致) 一般情况下要远远小于词语总数的大小,所以 Word2vec 本质上是一种降维操作,即把词语从 one-hot encoder 形式的表示降维到 Word2vec 形式的表示。

例如,小明不小心打翻墨水,遮住了书中的部分文字。其中有一段文字变成了:

深蓝的___中挂着一轮金黄的___,下面是海边的___,都种着一望无际的碧绿的___,其间有一个十一二岁的少年,项带银圈,手捏一柄钢叉,向一匹猹尽力的刺去,那猹却将身一扭,反从他的胯下逃走了。这少年便是闰土。

小明想用本文分析的方法来填空。他用一个通过鲁迅全部作品训练好的 Word2Vec 模型,分别将“深蓝”、“金黄”、“海边”、“碧绿”输入进去,对于“深蓝”,模型会分别输出“天空”和一系列模型预测可能相关的词汇,以及这些词汇的相似度数值。如下图:

2.2.2 CBOW 模型

CBOW (continuous bag-of-words) 的目标是根据上下文来预测当前词语的概率,且上下文所有的词对当前词出现概率的影响的权重是一样的,因此叫 continuous bag-of-words 模型。与 Skip-gram 模型不同,CBOW 输入变成了多个单词,所以要对输入进行处理,一般是求和然后平均。

总之,Word2Vec 本质上是一个语言模型,训练模型时考虑了单个词的上下文,且对词汇向量进行了降维处理。多次迭代后训练得到模型的权重向量即为 Word2Vec 的词向量。

3. Word2Vec 的 Python 应用

3.1 gensim 库安装

上面的理论内容略显复杂,但其实 Word2Vec 真正应用的时候只需要调用 Python 的 gensim 库即可,安装过程如下:

  • 首先,我们需要在 CMD 中输入以下命令:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple gensim
  • 然后在 Python 中输入:
import gensim

3.2 数据与模型

为了保证代码的可复现性,本案例利用《红楼梦》展示 Word2Vec 的基础应用。红楼梦 TXT 下载地址为 地址1地址2

# -*- coding: utf-8 -*-
"""
Created on May 01 2022
@author: ZoeWang
"""
# 导入第三方库
import jieba
import re
import numpy as np
from sklearn.decomposition import PCA
import gensim
from gensim.models import Word2Vec
import matplotlib.pyplot as plt
import matplotlib

# 数据预处理
f = open(r"hongloumeng.txt",encoding='utf-8')
lines = []
for line in f:
    temp = jieba.lcut(line)
    words = []
    for i in temp:
        # 去除不必要字符
        i = re.sub("[\s+\.\!\/_.$%^*(++\"\'“”《》]+|[+——!,。?、\
                            ~·@#¥%……&* ( ) '------------';:‘]+","",i)
        if len(i) > 0:
            words.append(i)
    if len(words) > 0:
        lines.append(words)
print(lines[:3]) # 展示前三段的分词结果
[['第一回', '甄士隐', '梦幻', '识通灵', '贾雨村', '风尘', '怀', '闺秀'], 
['此', '开卷', '第一回', '也', '作者', '自云', '因曾', '历过', '一番', 
'梦幻', '之后', '故', '将', '真事', '隐去', '而', '借', '通灵', '之', 
'说', '撰此', '石头记', '一书', '也', '故曰', '甄士隐', '云云', '但书', 
'所记', '何事', '何人', '自又云', '今', '风尘碌碌', '一事无成', '忽', 
'念及', '当日', '所有', '之', '女子', '一一', '细考', '较', '去', '觉其', 
'行止', '见识', '皆', '出于', '我', '之上', '何', '我', '堂堂', '须眉', 
'诚不若', '彼', '裙钗', '哉', '实愧', '则', '有余', '悔', '又', '无益', 
'之大', '无可如何', '之日', '也', '当', '此', '则', '自欲', '将', '已往', 
'所赖', '天恩祖', '德', '锦衣', '纨绔', '之', '时', '饫甘餍肥', '之', '日', 
'背', '父兄', '教育', '之恩', '负', '师友', '规谈', '之德', '以至', '今日', 
'一技无成', '半生', '潦倒', '之罪', '编述', '一集', '以告', '天下人', '我', 
'之', '罪固', '不免', '然', '闺阁', '本自', '历历', '有人', '万', '不可', 
'因', '我', '之', '不肖', '自护己', '短', '一并', '使', '其', '泯灭', 
'也', '虽', '今日', '之茅', '椽蓬', '牖', '瓦灶', '绳床', '其', '晨夕', 
'风露', '阶柳庭花', '亦', '未有', '妨', '我', '之', '襟怀', '笔墨', 
'者', '虽', '我', '未学', '下笔', '无', '又', '何妨', '用', '假语', 
'村言', '敷', '演出', '一段', '故事', '来', '亦可', '使', '闺阁', '昭传', 
'复可悦', '世之目', '破人', '愁闷', '不', '亦', '宜乎', '故曰', '贾雨村', '云云'], 
['此回', '凡用', '梦', '用', '幻', '等', '字', '是', '提醒', '阅者', '眼目', 
'亦', '是', '此书', '立意', '本旨']]
# 调用 Word2Vec 建立模型
# 常用参数 
# vector_size: 词向量的维度;  
# window: 上下文窗口长度;  
# min_count: 少于该字段的次数的单词会被丢弃
model = Word2Vec(lines, vector_size = 20, window=3, min_count=3, \
                 epochs=7,negative=10) # 这里为了训练速度,对参数值设置较低

# 输入一个路径,保存训练好的模型,其中./data/model目录事先要存在
model.save("./data/model/word2vec_gensim")

# 查看 “林黛玉” 的词向量
print(model.wv.get_vector("林黛玉"))

# 查看与“林黛玉”最相近的前10个词
print(model.wv.most_similar('林黛玉',topn=10))

# 查看“林黛玉”与“贾宝玉”的相似度
print(model.wv.similarity('林黛玉', '贾宝玉'))

以下结果展示了经过训练后“林黛玉”词向量表示,“林黛玉”相似度前 10 的词语,以及“林黛玉”与“贾宝玉”的相似度。

[-1.9263046   1.2421334  -1.0091485  -0.13790976  0.11818279 -2.8261106
  0.6490951  -0.40219253  0.26743338 -0.75846136  0.3968666  -0.6893399
 -0.39468396  0.38637197  1.9181769  -0.25307047 -0.17784327  0.5558692
  0.5961813  -0.10329818]

[('宝玉', 0.9402182698249817), ('尤二姐', 0.9391377568244934), ('赵姨娘', 0.9354947209358215), 
('香菱', 0.9352374076843262), ('探春', 0.9203108549118042), ('紫鹃', 0.9188699722290039), 
('凤姐', 0.9174630641937256), ('湘云', 0.9170628786087036), ('雨村', 0.9147610068321228), 
('拍', 0.9131830930709839)]

0.6685995

3.3 可视化操作

接下来,我们以更直观的画图形式展现 Word2Vec 模型结果。这里我们用到了 PCA 降维,主要是为了将多维词向量投影在二维平面上。

rawWorVec = []
word2ind = {}
for i,w in enumerate(model.wv.index_to_key): #生成序号,词语
    rawWorVec.append(model.wv[w]) #词向量
    word2ind[w] = i
rawWorVec = np.array(rawWorVec) #降维之前的20维数组
X_reduced = PCA(n_components=2).fit_transform(rawWorVec) #降维之后的2维数组

fig = plt.figure(figsize = (16,16))
ax = fig.gca()
ax.set_facecolor('white')
ax.plot(X_reduced[:,0],X_reduced[:,1],'.',markersize=1,alpha=0.3,color='black')

words = ['紫鹃','香菱','王熙凤','林黛玉','贾宝玉'] # 绘制单个词汇的向量

zhfont1 = matplotlib.font_manager.FontProperties(fname='C:\\Windows\\Fonts\\simhei.ttf',size=10)
for w in words:
    if w in word2ind:
        ind = word2ind[w]
        xy = X_reduced[ind]
        plt.plot(xy[0],xy[1],'.',alpha=1,color='green',markersize=10)
        plt.text(xy[0],xy[1],w,alpha=1,color='blue',fontproperties=zhfont1)

下图展示了词向量可视化的结果,不难发现相似度高的词语距离比较近

3.4 实操总结

  • 上述操作是基础的 Word2Vec 代码实现过程,当然还有其他功能可以探索,建议各位读者去 Word2Vec官网 挖掘宝藏。
  • 当然 Word2Vec 也有很多缺点,例如没有考虑多义词 (不知道大家在上文中有没有发现“林黛玉”和“宝玉”高度相关,但和“贾宝玉”相关度却低了很多)、没有考虑全局文本信息、不是严格意义上的语序。
  • 分词也是决定模型优度的重要因素之一,建议大家对于特殊领域,可以在分词时加入特殊词典。

4. 参考资料

5. 相关推文

Note:产生如下推文列表的 Stata 命令为:
lianxh 文本 机器, m
安装最新版 lianxh 命令:
ssc install lianxh, replace

相关课程

免费公开课

最新课程-直播课

专题 嘉宾 直播/回看视频
最新专题 文本分析、机器学习、效率专题、生存分析等
研究设计 连玉君 我的特斯拉-实证研究设计-幻灯片-
面板模型 连玉君 动态面板模型-幻灯片-
面板模型 连玉君 直击面板数据模型 [免费公开课,2小时]
  • Note: 部分课程的资料,PPT 等可以前往 连享会-直播课 主页查看,下载。

课程主页

课程主页

关于我们

  • Stata连享会 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 连享会-主页知乎专栏,700+ 推文,实证分析不再抓狂。直播间 有很多视频课程,可以随时观看。
  • 公众号关键词搜索/回复 功能已经上线。大家可以在公众号左下角点击键盘图标,输入简要关键词,以便快速呈现历史推文,获取工具软件和数据下载。常见关键词:课程, 直播, 视频, 客服, 模型设定, 研究设计, stata, plus, 绘图, 编程, 面板, 论文重现, 可视化, RDD, DID, PSM, 合成控制法

连享会小程序:扫一扫,看推文,看视频……

扫码加入连享会微信群,提问交流更方便

✏ 连享会-常见问题解答:
https://gitee.com/lianxh/Course/wikis

New! lianxhsongbl 命令发布了:
随时搜索连享会推文、Stata 资源,安装命令如下:
. ssc install lianxh
使用详情参见帮助文件 (有惊喜):
. help lianxh