Keras深度学习实战——使用GloVe模型构建单词向量

时间:2022-09-26 12:22:26

0. 前言

《使用fastText模型构建单词向量》一节中,我们学习了如何构建 fastText 模型以生成单词向量,GloVe (Global Vectors for Word Representation) 是另一种生成单词向量的方式。在本节中,我们将介绍 GloVe 的算法原理,然后介绍如何实现 GloVe 模型生成单词向量。

1. GloVe 算法模型

1.1 模型目标

GloVe 的提出旨在实现以下两个目标:

  • 创建在向量空间中能够捕获其含义的单词向量
  • 利用全局计数统计信息,而不仅仅是局部信息

1.2 GloVe 算法计算细节

GloVe 主要通过利用单词的共现矩阵并针对损失函数进行优化来学习单词向量。我们首先使用以下示例,以此来了解 GloVe 算法的计算细节。
假设我们存在以下两个句子:

This is apple
This is also an

接下来,我们首先构建一个单词共现矩阵。在以上的示例句子*有五个不重复单词,单词共现矩阵如下所示:

this is apple also an
this 0 2 1 1 1
is 0 0 1 1 1
apple 0 0 0 0 0
also 0 0 0 0 1
an 0 0 0 0 0

在上表中,单词 thisis 在两个句子中都同时存在,因此共现值为 2。而单词 thisapple 在只在一个句子中同时出现过,因此共现值为 1,需要注意的是,共现值的计算需要考虑单词的先后顺序,例如没有 apple 出现在 this 之前,因此 (apple, this) 的共现值为 0
但是,在以上矩阵中,我们没有考虑两个单词之间的距离。如果需要考虑两个单词之间的距离,那么如果同现单词彼此之间的距离越远,它们与同现值的相关性就越小。
因此,我们引入一个新的量度——偏移量 (offset),偏移量会因为给定单词与共现单词之间的距离过长而对共现值进行惩罚。 例如,apple 在第一句中与 this 的距离为 2,因此我们需要将它们同时出现的次数除以 2 得到最终共现值。转换后的同现矩阵如下所示:

this is apple also an
this 0 2 0.5 0.5 0.33
is 0 0 1 1 0.5
apple 0 0 0 0 0
also 0 0 0 0 1
an 0 0 0 0 0

接下来,我们再引入一个附加参数:要考虑的单词的上下文窗口。例如,如果上下文窗口大小为2,则与单词 thisa 对应的同现值将为0,因为两个单词之间的距离大于 2。当上下文窗口大小为 2 时,转换后的同现矩阵如下:

this is apple also an
this 0 2 0.5 0.5 0
is 0 0 1 1 0.5
apple 0 0 0 0 0
also 0 0 0 0 1
an 0 0 0 0 0

我们已经得出了修改后的同现矩阵,接下来,为每个单词的随机初始化权重和偏差值,其中每个单词的向量大小为 3,如下所示:

weights1 weights2 weights3 bias
this -0.64 0.82 -0.08 0.16
is -0.89 -0.31 0.79 -0.34
apple -0.01 0.14 0.82 -0.35
also -0.1 -0.67 0.89 0.26
an -0.1 -0.84 0.35 0.36

由于最初的权重和偏置是随机初始化的,因此需要修改权重以优化损失函数。为了完成此目的,我们定义损失函数,如下所示:

J = ∑ i , j = 1 V f ( X x j ) ( w i T w ‾ j + b j + b ‾ j − l o g X i j ) 2 J=\sum _{i,j=1}^Vf(X_{xj})(w_i^T \overline w_j+b_j+\overline b_j-logX_{ij})^2 J=i,j=1Vf(Xxj)(wiTwj+bj+bjlogXij)2

其中, w i w_i wi 表示第 i i i 个单词的单词向量, w ‾ j \overline w_j wj 表示第 j j j 个单词的单词向量; b i b_i bi b ‾ j \overline b_j bj 分别是与第 i i i 个单词和第 j j j 个单词对应的偏置。 X i j X_{ij} Xij 表示我们先前定义的最终共现值中的值。例如, i i i 是单词 this j j j 是单词 also,则 X i j X_{ij} Xij 的值是 0.5

X i j X_{ij} Xij 的值为 0 时, f ( X i j ) f(X_{ij}) f(Xij) 的值为 0。否则, f ( X ) f(X) f(X) 计算公式如下:

f ( X ) = { ( X X m a x ) α i f     X < X m a x 1 o t h e r w i s e f(X)= \begin{cases} (\frac X {X_{max}})^\alpha & & if\ \ \ X<X_{max} \\ 1 & & otherwise \end{cases} f(X)={(XmaxX)α1if   X<Xmaxotherwise

在以上等式中,我们设定 α \alpha α0.75 X m a x X_{max} Xmax100 X X X X i j X_{ij} Xij 的值。在定义了 f ( X ) f(X) f(X) 方程之后,我们将其应用于共现矩阵,如下所示:

A B C D E F G H I J
1 this is apple also an weights1 weights2 weights3 bias
2 this 0 2 0.5 0.5 0 -0.64 0.82 -0.08 0.16
3 is 0 0 1 1 0.5 -0.89 -0.31 0.79 -0.34
4 apple 0 0 0 0 0 -0.01 0.14 0.82 -0.35
5 also 0 0 0 0 1 -0.1 -0.67 0.89 0.26
6 an 0 0 0 0 0 -0.1 -0.84 0.35 0.36
A B C
7 损失值 加权损失值
8 (C2/100)^0.75 ((G2*G3+H2*H3+I2*I3)+J2+J3-log(C2))^2 (B8^2)*A8
9 (D2/100)^0.75 ((G2*G4+H2*H4+I2*I4)+J2+J4-log(D2))^2 (B9^2)*A9
10 (E2/100)^0.75 ((G2*G5+H2*H5+I2*I5)+J2+J5-log(E2))^2 (B10^2)*A10
11 (D3/100)^0.75 ((G3*G4+H3*H4+I3*I4)+J3+J4-log(D3))^2 (B11^2)*A11
12 (E3/100)^0.75 ((G3*G5+H3*H5+I3*I5)+J3+J5-log(E3))^2 (B12^2)*A12
13 (F3/100)^0.75 ((G3*G6+H3*H6+I3*I6)+J3+J6-log(F3))^2 (B13^2)*A13
14 (F5/100)^0.75 ((G5*G6+H5*H6+I5*I6)+J5+J6-log(F5))^2 (B14^2)*A14
15 总损失值 C8+C9+C10+...+C14

第一个表表示单词共现矩阵以及随机初始化的权重和偏置。第二张表代表损失值计算,计算了总的加权损失值。训练神经网络优化权重和偏置,直到总加权损失值最小。

3. 实现 GloVe 模型构建单词向量

了解了如何使用 GloVe 生成单词向量后,我们使用 Keras 实现此模型。

3.1 数据集

接下来,我们实现 GloVe 模型生成单词向量,所用的数据集与在《从零开始构建单词向量》一节中使用的数据集相同,即航空公司 Twitter 数据集。

3.2 模型实现

为了快速构建 GloVe 模型,我们需要使用 GloVe 库,如果并未安装 GloVe 库,首先安装 GloVe

$ pip install glove_python_binary

(1) 导入相关库,并加载所需数据集:

from glove import Corpus, Glove
import pandas as pd

data = pd.read_csv('archive/Tweets.csv')
print(data.head())

(2) 按照在 word2vecskip-gram 和 CBOW 算法中使用的预处理方式对数据集进行预处理:

import re
import nltk
from nltk.corpus import stopwords

stop = set(stopwords.words('english'))
def preprocess(text):
    text=text.lower()
    text=re.sub('[^0-9a-zA-Z]+',' ',text)
    words = text.split()
    words2 = [i for i in words if i not in stop]
    words3=' '.join(words2)
    return(words3)
    
data['text'] = data['text'].apply(preprocess)
list_words=[]
for i in range(len(data)):
     list_words.append(data['text'][i].split())

(3) 创建一个语料库,并使用 list_words 进行训练:

corpus = Corpus()
corpus.fit(list_words, window=5)

输出语料库的字典:

print(corpus.dictionary)

得到的不重复单词及其对应的单词 ID 的输出如下:

{'occasion': 9536, 'janna': 9538, 'transportation': 9545, 'deplorable': 9546, 'blushing': 9584, 'container': 9585, ...}

在以上输出的词汇表字典中可以看到单词的键值及其相应的索引 ID。我们可以使用以下代码获取共现矩阵:

print(corpus.matrix.todense())

共现矩阵输出结果如下:

[[0.  1.  0.5 ... 0.  0.  0. ]
 [0.  0.  1.  ... 0.  0.  0. ]
 [0.  0.  0.  ... 0.  0.  0. ]
 ...
 [0.  0.  0.  ... 0.  0.  0. ]
 [0.  0.  0.  ... 0.  0.  0. ]
 [0.  0.  0.  ... 0.  0.  0. ]]

(4) 根据模型参数构建 GloVe 模型,模型参数包括单词向量维数,学习率和要训练的 epoch 数:

glove = Glove(no_components=50, learning_rate=0.025)
glove.fit(corpus.matrix, epochs=100, no_threads=4, verbose=True)

glove.add_dictionary(corpus.dictionary)

(5) 拟合模型后,可以使用以下方式得到单词向量的权重和偏差:

glove.word_biases.tolist()
glove.word_vectors.tolist()

给定单词的单词向量可以使用以下方式获取,例如,获取 united 的单词向量:

glove.word_vectors[glove.dictionary['united']]

输出 united 的单词向量结果如下

[ 0.28914408  0.26329115  0.3667015  -0.40723394  0.73858237 -0.13237962
 -0.26181053 -0.48674251  0.31886485 -0.37118261  0.15298666 -0.50613528
  0.05106491  0.34530569  0.23514142  0.65529507 -0.60675551  0.31481698
 -0.40108001 -0.15245143 -0.71323699  0.19949217  0.12902499  0.04324692
 -0.26129482  0.32892659 -0.22194619 -0.61558947  0.49860624  0.62138189
 -0.42737696 -0.81103652 -0.53062233  0.49564949 -0.02642339 -0.41012973
 -0.25496882 -0.48373637  0.42132076 -0.39728154  0.1378011   0.50213151
 -0.01935292  0.51946005 -0.39898713  0.2305064   0.6597054  -0.20041417
  0.2480132  -0.45826004]

(6) 与给定单词的最相似单词可以使用 most_similar 方法获取:

glove.most_similar('united')

与 “united” 最相似的词的输出如下:

[('staralliance', 0.9714900524160623), ('danahajek', 0.9604158805663079), ('perfectomobile', 0.9368125153546437), ('annricord', 0.9249781977575551)]

相关链接

Keras深度学习实战(1)——神经网络基础与模型训练过程详解
Keras深度学习实战(2)——使用Keras构建神经网络
Keras深度学习实战(7)——卷积神经网络详解与实现
Keras深度学习实战(24)——从零开始构建单词向量
Keras深度学习实战(25)——使用skip-gram和CBOW模型构建单词向量
Keras深度学习实战(26)——文档向量详解
Keras深度学习实战——使用fastText模型构建单词向量