word2vec 学习笔记和中文语料实战

前言

计算机处理图像的时候,本质上利用了图像的像素数值信息。对自然语言来说,并没有包含计算机擅长处理的数值信息,因此,需要通过一定的手段将“自然语言”量化,进而利用已有的机器学习方法对自然语言进行处理、分析和预测。

独热编码

也称One-hot编码 (一位有效码),其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。比如现在有下面的状态表:

indicator-1indicator-2
sample-111
sample-222
sample-323

转化为独热编码为(注意这里容易和数字电路中的真值表编号相混淆,请务必区分开来)

indicator-1indicator-2
sample-10 10 0 1
sample-21 00 1 0
sample-31 01 0 0

如果上面的indicator不是数值量,而是文本,则可以表示为:

indicator-1indicator-2
sample-1“male”“from Europe”
sample-2“female”“from US”
sample-3“female”“from Russia”

对应的独热编码可以编号为:

indicator-1indicator-2
sample-10 10 0 1
sample-21 00 1 0
sample-31 01 0 0

这样处理的优缺点在哪?

首先是优点,很显然,将一个word映射为一个数学向量,这便与我们后续进行各种机器学习算法的输入处理。

缺点也很明显:

  • 它是一个词袋模型,不考虑词与词之间的顺序(文本中词的顺序信息也是很重要的)
  • 它假设词与词相互独立(在大多数情况下,词与词是相互影响的)
  • 它得到的特征是离散稀疏的

在数据结构或离散数学中,有稀疏矩阵的概念,也就是说这个矩阵蕴含的有效信息很少,大部分矩阵元素都为0. 上面的独热编码正是特殊的1 x n维的稀疏矩阵,这样就非常浪费空间,容易造成维度灾难。因此,我们急切需要一种可以降低维度的方法。

Dristributed representation

Dristributed representation 的思路是通过训练,将每个词都映射到一个较短的词向量上来。所有的这些词向量就构成了向量空间,用普通的统计学的方法来研究词与词之间的关系。词向量维度一般在训练时指定。下图说明了一个简单示例:
在这里插入图片描述
词汇表里的词用"Royalty",“Masculinity”, "Femininity"和"Age"4个维度来表示,King这个词对应的词向量可能是(0.99,0.99,0.05,0.7)(0.99,0.99,0.05,0.7)。如果参加过数学建模,你可能对此有些熟悉,因为其表示方式与因子分析法相似。

上面,我们将king这个词从一个可能非常稀疏的向量坐在的空间,映射到现在这个四维向量所在的空间,这个过程就是词嵌入(word embedding).
在这里插入图片描述
假如我们将词的维度降低到2D,有研究表明:
在这里插入图片描述
国王 - 男性 + 是女性 = 女王,挺有道理的
在这里插入图片描述
出现这种现象的原因是,我们得到最后的词向量的训练过程中引入了词的上下文。

Word2Vec (一个神经网络模型)

输入是One-Hot Vector,Hidden Layer没有激活函数,也就是线性的单元。Output Layer维度跟Input Layer的维度一样,用的是Softmax回归。当这个模型训练好以后,我们并不会用这个训练好的模型处理新的任务,我们真正需要的是这个模型通过训练数据所学得的参数,例如隐藏层的权重矩阵。

在这里插入图片描述
这个模型是如何定义数据的输入和输出呢?一般分为CBOW(Continuous Bag-of-Words 与Skip-Gram两种模型。CBOW模型的训练输入是某一个特征词的上下文相关的词对应的词向量,而输出就是这特定的一个词的词向量。 Skip-Gram模型和CBOW的思路是反着来的,即输入是特定的一个词的词向量,而输出是特定词对应的上下文词向量。CBOW对小型数据库比较合适,而Skip-Gram在大型语料中表现更好。通俗一点来说,CBOW解决的是这样的问题:
在这里插入图片描述
而Skip-gram解决的是这样的问题:
在这里插入图片描述
在这里插入图片描述

CBOW的训练模型

在这里插入图片描述
处理步骤;

  • 输入:上下文单词的onehot编码,每个onehot编码是1 x V的向量
  • 每个onehot向量乘以V x N的权重矩阵
  • 全部向量相加求平均得到隐藏层的特征向量,这个向量是1 x N维的
  • 隐藏层的特征向量乘以N x V维的输出权重矩阵,得到1 x V维的输出向量
  • 输出向量通过激活函数处理,得到概率分布
  • 概率最大的index所指示的单词为预测出的中间词

训练完毕后,输入层的每个单词与矩阵W相乘得到的向量的就是我们想要的词向量 (word embedding).

下面是一个简单例子:
在这里插入图片描述
在这里插入图片描述

Skip-Gram的训练模型

在这里插入图片描述
假如我们有一个句子 “The dog barked at the mailman”。首先我们选句子中间的一个词作为我们的输入词,例如我们选取 “dog” 作为input word.

有了input word以后,我们再定义一个叫做skip_window的参数,它代表着我们从当前input word的一侧(左边或右边)选取词的数量。如果我们设置skip_window=2,那么我们最终获得窗口中的词(包括input word在内)就是[‘The’, ‘dog’, ‘barked’, ‘at’]。skip_window=2代表着选取左input word左侧2个词和右侧2个词进入我们的窗口,所以整个窗口大小span=2x2=4。另一个参数叫num_skips,它代表着我们从整个窗口中选取多少个不同的词作为output word,当skip_window=2,num_skips=2时,我们将会得到两组 (input word, output word) 形式的训练数据,即 (‘dog’, ‘barked’),(‘dog’, ‘the’)。

神经网络基于这些训练数据将会输出一个概率分布,这个概率代表着我们的词典中的每个词是output word的可能性。这句话有点绕,我们来看个栗子。第二步中我们在设置skip_windownum_skips=2的情况下获得了两组训练数据。假如我们先拿一组数据 (‘dog’, ‘barked’) 来训练神经网络,那么模型通过学习这个训练样本,会告诉我们词汇表中每个单词是“barked”的概率大小。模型的输出概率代表着到我们词典中每个词有多大可能性跟input word同时出现。

Word2Vec的优缺点

优点
  • 由于 Word2vec 会考虑上下文,跟之前的 Embedding 方法相比,效果要更好
  • 比之前的 Embedding方法维度更少,所以速度更快
  • 通用性很强,可以用在各种 NLP 任务中
缺点
  • 由于词和向量是一对一的关系,所以多义词的问题无法解决。
  • Word2vec 是一种静态的方式,虽然通用性强,但是无法针对特定任务做动态优化

Word2Vec中文语料实战

环境

win10 + python3
依赖包:gensim与jieba (通过pip install 安装)

语料库

诛仙小说 (部分)
在这里插入图片描述

文本预处理

去除文本中可能存在的空白等,防止对训练造成干扰。

# 文本预处理
file = open('text.txt', 'w', encoding='utf-8')
with open('诛仙.txt', 'r', encoding='utf-8') as origin_file:
    for line in origin_file:
        line = line.strip()
        file.write(line + '\n')

file.close()
中文分词

将停顿词放在一个stop.txt文件中,这里选取了部分停顿词如下:
在这里插入图片描述
调用jieba库进行词语划分.

# 分词
import jieba
stop_words_file = 'stop.txt'
stop_words = []
with open(stop_words_file, 'r', encoding='utf-8') as origin_stop_words_file:
    text = origin_stop_words_file.readlines()
    for line in text:
        line = line.strip()
        stop_words.append(line)
        
origin_txt_file = 'text.txt'
target_file = open('text_cut.txt', 'w', encoding='utf-8')
with open(origin_txt_file, 'r', encoding='utf-8') as origin_file:
    text = origin_file.readlines()
    for line in text:
        line =line.strip()
        out_str = ''
        word_list = jieba.cut(line, cut_all=False)
        for word in word_list:
            if word not in stop_words:
                if word != '\t':
                    out_str += word
                    out_str += ' '
        target_file.write(out_str.rstrip() + '\n')

target_file.close()

分词结果:
在这里插入图片描述

训练word2vec模型
#coding:utf8
import gensim.models.word2vec as w2v

model_file_name = 'model'
#模型训练,生成词向量
sentences = w2v.LineSentence('text_cut.txt')
# 训练参数:输出词的向量维数为20,训练窗口为5,截断频次在5次以下的词,4个并行任务
model = w2v.Word2Vec(sentences, size=1000, window=5, min_count=5, workers=4) 
model.save(model_file_name)
模型测试
import gensim
import warnings

warnings.filterwarnings(action='ignore', category=UserWarning,module='gensim')
model = gensim.models.Word2Vec.load("model")

word = '金瓶儿'
result = model.similar_by_word(word)

print("跟 "+word+" 最相近的词:")
for i in result:
    print(i)
模型结果

在这里插入图片描述

参考文献

[1] Muwen. (2021). [NLP] Understanding the essence of Word2vec. Retrieved from https://zhuanlan.zhihu.com/p/26306795

[2] Wuyiji. (2017). Use python-gensim to train word2vec model and understanding of gensim API. Retrieved from https://blog.csdn.net/sinat_26917383/article/details/69803018

[3] Gensim. (2021). models.word2vec – Word2vec embeddings. Retrieved from https://radimrehurek.com/gensim/models/word2vec.html

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值