自然语言处理——词的表示

摘要:
我们需要将单词逐个编码成向量。向量表示单词空间中的一个点。最简单的单词向量是一个pot向量:每个单词都表示为$mathbb{R}^{left|Vight|imes1}$的向量。修改后的单词在单词列表中的索引位置为1,其他位置为0$左|右|$是单词列表的大小。这个方案显然不理想。对角线$sigma_I$上的元素称为奇异值。

1、词向量(Word Vectors)

英语中大约有13亿个符号,从Feline(猫科动物)到cat(猫),hotel(旅馆)到motel(汽车旅馆),很明显它们之间是有关联的。我们需要将单词一一编码到向量中,一个向量表示了词空间中的一个点。

最简单的一种词向量就是one-hot向量:将每个词都表示为一个$mathbb{R}^{left | V ight | imes 1}$的向量,改词在词表中索引的位置是1,其他位置都是0。$left | V ight |$是词表的大小。one-hot词向量形式如下:

egin{align*}
w^{aardvark} = egin{bmatrix}1\ 0\ 0\ vdots \ 0 end{bmatrix},
w^{a} = egin{bmatrix}0\ 1\ 0\ vdots \ 0 end{bmatrix},
w^{at} = egin{bmatrix}0\ 0\ 1\ vdots \ 0 end{bmatrix},
cdots ,
w^{zebra} = egin{bmatrix}0\ 0\ 0\ vdots \ 1 end{bmatrix}
end{align*}

虽然我们成功地将每个词都表示为了不同的实体,但这一表示方式并不能提供词之间相似性的概念,例如:

egin{align*}
(w^{hotel})^Tw^{motel} = (w^{hotel})^Tw^{cat} = 0
end{align*}

我们需要找到一个空间,该空间维度远小于$mathbb{R}^{left | V ight | imes 1}$,并且该空间中的词向量,可以体现出词之间的相似度。

2、基于SVD(奇异值分解)的方法

为了找到词嵌入(word embeddings,可以简单的理解为与词向量等价),可以首先遍历巨大的语料库,统计两个词之间某种形式的共现次数,并将统计值保存在一个矩阵$X$中。然后应用奇异值分解:$X = USV^T$。我们使用$U$中的每一行作为每个词的词嵌入。下面将讨论$X$的一些选择方式。

2.1 词-文档矩阵(Word-Document Matrix)

作为第一次尝试,我们首先大胆地猜想,经常出现在同一文档中的词是有关联的。比如,"banks"、"bonds"、"stocks"、"money"等等,很可能会共同出现。但是"banks"、"octopus"、"banana"、"hockey"并不能经常共现。基于这一事实创建一个词-文档矩阵$X$,方法如下:遍历数以亿计的文档,每当第$i$个词出现在第$j$个文档中,就对矩阵中元素$X_{i,j}$加一。最终得到的是一个庞大的$mathbb{R}^{left | V ight | imes M}$矩阵,并且还会随着文档数量($M$)缩放比例。该方案显然很不理想。

2.2 基于窗口的共现矩阵(Window based Co-occurrence Matrix)

这个方法不再考虑文档的数量,统计两个词在给定窗口中的共现次数。例如,语料是下面的三句话,窗口大小是1:

1. I enjoy flying.
2. I like NLP.
3. I like deep learning.

共现矩阵为:

自然语言处理——词的表示第1张

2.3 对共现矩阵应用SVD

对$X$应用SVD:

自然语言处理——词的表示第2张

中间的矩阵除了对角线,其他位置都是0。对角线上的元素$sigma_i$称为奇异值。我们可以从矩阵U中选取前$k$列,作为词向量。而这前$k$列所能保存的原数据的方差(variance)比例为:

egin{align*}
frac{sum_{i=1}^{k} left | sigma_i ight |}{sum_{i=1}^{left | v ight |} left | sigma_i ight |}
end{align*}

通过选取前$k$列奇异向量进行降维:

自然语言处理——词的表示第3张

用这种方式生成的词向量保留了足够多的语法和语义信息,但也还是存在一些问题:

  • 矩阵维度经常变动,比如新词频繁加入。
  • 由于绝大部分词并不会共现,造成矩阵过于稀疏。
  • 矩阵维度一般很高,大约$10^6 imes 10^6$。
  • 并且难以合并新词或新的文档。对于一个$m imes n$矩阵,训练时的计算复杂度是$O(mn^2)$
  • 由于词频的极度不平衡,需要对矩阵$X$应用一些黑科技。

上述问题的一些解决方案:

  • 忽略the、he、has等虚词。
  • 应用一个斜坡窗口(ramp window,也就是说,不再对窗口内的所有词一视同仁)——比如,根据距离当前词的距离,对共现次数赋予相应的权重。
  • 使用皮尔逊相关系数(Pearson correlation coefficient),取代直接计数。

看了下一小节我们就会发现,基于迭代的方法可以使用更优雅的方式解决上述问题。

3 基于迭代的方法——Word2vec

与之前计算和存储巨大数据集的全局信息不同,现在我们用反向传播训练一个模型,预测一个词在给定上下文存在的概率,该模型的参数就是词向量。下面介绍一个简单的、较新的、基于概率的模型——word2vec:

  • 两个算法:continuous bag-of-words (CBOW)和skip-gram。CBOW是给定上下文环境时,预测该环境中间的那个中心词。Skip-gram正好相反,预测一个中心词上下文环境的分布。
  • 两个训练方法:负采样(negative sampling)和分层softmax。

word2vec概况:https://myndbook.com/view/4900

3.1 语法模型(一元、二元)

首先我们来定义一个模型,该模型可以给一个符号序列分配概率。以下面的句子为例:

"The cat jumped over the puddle."

一个好的语言模型,会给上面的句子分配一个较高的概率。因为这个句子在语法和语义上都是正确的。数学上,这$n$个词的概率可表示为:

egin{align*}
p(w_1, w_2, cdots, w_n)
end{align*}

一元语法模型就是假设每个词都是独立的,这会大大降低联合概率的复杂性:

egin{align*}
p(w_1, w_2, cdots, w_n) = prod_{i=1}^{n}P(w_i)
end{align*}

但这一模型是很荒唐的。因为我们知道,后词对它前面序列的依赖性是很高的。这也可能会使得错误的句子得到一个较高的概率。所有这就有了二元语法模型,当前词只依赖于它前面的一个词:

egin{align*}
p(w_1, w_2, cdots, w_n) = prod_{i=2}^{n}P(w_i|w_{i-1})
end{align*}

虽然这一模型也很幼稚,但它的效果还可以。

现在我们已经知道,一个符号序列是可以有概率的。下面将介绍可以学习这些概率的模型。

3.2 连续词袋模型(Continuous Bag of Words Model,CBOW)

把{"The", "cat", ’over", "the’, "puddle"}看作是上下文环境,来预测中间的单词"jumped",这就是CBOW模型。这是一个简单的神经网络,如下所示:

自然语言处理——词的表示第4张

图1 CBOW工作原理

我们定义输入层到隐层的权重矩阵为$mathcal{V} in mathbb{R}^{n imes left | V ight |}$(也就是上图中的$W_{V imes N}$),隐层到输出层的权重矩阵为$mathcal{U} in mathbb{R}^{left | V ight | imes n}$(也就是上图中的$W'_{N imes V}$)。其中,$n$是隐层神经元个数,也是词嵌入空间的维度。$mathcal{V}$是输入词矩阵,当一个词$w_i$作为输入进入模型时,$mathcal{V}$的第$i$列就是该词的嵌入向量。这一$n imes1$向量记为$v_i$。类似的,$mathcal{U}$是输出词矩阵,当一个词$w_j$是该模型的输出时,$mathcal{U}$的第$j$行就是该词的嵌入向量。这一$1 imes n$矩阵记为$u_j$。所以,在模型中,一个词是对应两个词向量的。

用反向传播训练这一神经网络:

  1. 假设窗口为$m$,输入数据就是上下文环境中$2m$个词的one-hot向量:$x^{(c-m)},cdots ,x^{(c-1)},x^{(c+1)},cdots x^{(c+m)} in mathbb{R}^{left | V ight |}$
  2. 获取上下文环境的嵌入词向量:$v_{c-m} = mathcal{V}x^{(c-m)},cdots ,v_{c+m} = mathcal{V}x^{(c+m)} in mathbb{R}^n$
  3. 计算这次嵌入词向量的均值:$hat{v} = frac{v_{c-m} + cdots + v_{c+m}}{2m}$
  4. 生成一个分值向量$z = mathcal{U}hat{v} in mathbb{R}^{left | V ight |}$。由于相似向量的内积较大,这会使得相似词的向量越来越相似,以便得到较高的分值
  5. 应用softmax激活函数,将分值转换为概率$hat{y} = mbox{softmax}(z) in mathbb{R}^{left | V ight |}$
  6. 神经网络的目标值就是中心词"jumped"的one-hot向量,记为$y$。定义损失函数为交叉熵损失,反向传播进行训练。

假设$c$是目标值one-hot向量为1的位置的索引,损失函数:

自然语言处理——词的表示第5张

3.3Skip-Gram模型

这次给定中心词"jumped",然后预测它周围的词"The", "cat", "over", "the", "puddle"。这也是一个神经网络,如下所示:

自然语言处理——词的表示第6张

图2Skip-Gram工作原理

定义同样的$mathcal{V} in mathbb{R}^{n imes left | V ight |}$和$mathcal{U} in mathbb{R}^{left | V ight | imes n}$,训练这一神经网络

  1. 输入向量$x in mathbb{R}^{left | V ight |}$是中心词的one-hot向量。
  2. 计算中心词的嵌入词向量$v_c = mathcal{V}x in mathbb{R}^n$
  3. 计算分值向量$z = mathcal{U}v_c$
  4. 使用softmax激活函数,将分值转换为概率$hat{y} = mbox{softmax}(z) in mathbb{R}^{left | V ight |}$
  5. 目标值是中心词周围那些词的one-hot向量,记为$y^{(c-m)},cdots ,y^{(c-1)},y^{(c+1)},cdots ,y^{(c+m)}$。

定义损失函数:

egin{align*}
J = -logP(w_{c-m},cdots ,w_{c-1},w_{c+1},cdots ,c_{c+m}|w_c)
end{align*}

为了简化模型,我们假设这些条件概率相互独立(朴素贝叶斯假设),从而有:

自然语言处理——词的表示第7张

此外,

egin{align*}
J &= -logprod_{j=0,j eq m}^{2m}P(w_{c-m+j}|w_c) \
&= -logprod_{j=0,j eq m}^{2m}P(u_{c-m+j}|v_c) \
&= -sum_{j=0,j eq m}^{2m}logP(u_{c-m+j}|v_c) \
&= sum_{j=0,j eq m}^{2m}H(hat{y},y_{c-m+j})
end{align*}

其中,$H(hat{y},y_{c-m+j})$是交叉熵。

3.4 Negative Sampling

我们再回头观察一下损失函数,对整个$left | V ight |$求和,计算量巨大。每一次更新或者评估损失函数,都会有$O(left | V ight |)$的时间复杂度。我们必须减少这一计算量。
在训练时的每一步,与遍历整个词汇表不同,这次只需要抽样部分反面例子(negative examples)。我们从一个噪声分布($P_n(w)$,noise distribution)抽样,其概率分布与词汇表的词频相对应。

虽然negative sampling基于Skip-Gram模型,事实上前者是在优化一个不同的目标函数。考虑一个词(word)和上下文环境(context)的组合$(w,c)$。将$(w,c)$在语料中存在的概率记为$P(D=1|w,c)$,在语料中不存在的概率记为$P(D=0|w,c)$。首先使用sigmoid函数对$P(D=1|w,c)$建模:

自然语言处理——词的表示第8张

然后,应用极大似然估计,创建新的目标函数,使得$P(D=1|w,c)$最大,$P(D=0|w,c)$最小(此时模型的参数是$ heta$,在外面之前的例子中是$mathcal{V}$和$mathcal{U}$):

自然语言处理——词的表示第9张

最大似然和最小负log似然是等价的:

自然语言处理——词的表示第10张

其中,$widetilde{D}$是错误的、反面的语料。也就是说,类似"stock boil fish is toy"不通顺的句子。可以从词库中随机抽样,生成这种错误的句子。

对于skip-gram模型,给出中心词$c$并观察它窗口内的单词$c-m+j$时的损失函数更新为:

自然语言处理——词的表示第11张

对于CBOW模型,给出上下文环境$hat{v} = frac{v_{c-m} + cdots + v_{c+m}}{2m}$并观察到中心词$u_c$时的损失函数更新为:

自然语言处理——词的表示第12张

在上面的公式中,${ widetilde{u_k}|k=1,cdots ,K }$是从$P_n(w)$抽样而来的。为了达到最佳逼近效果,采用了一元语法模型,并对词频取3/4次幂。下面一个例子,说明了为什么是3/4:

自然语言处理——词的表示第13张

"Bombastic"被抽样的概率,增加到原来的三倍,而"is"几乎不变。

3.5 分层Softmax

Mikolov等人表明,分层softmax的效率要远高于普通的softmax。在实践中,分层softmax更擅长于处理不常见的词汇,而negative sampling更擅长处理常见词汇以及生产更低维度的向量。

分层softmax使用一棵二叉树来表示词表中的所有词汇。每个叶节点都是一个词,并且从根节点到叶节点的路径是唯一的。该模型并不会输出词汇的向量表示,不过图中的每一个节点(除了根节点和叶子节点)都对应一个向量,这些向量是模型需要学习的参数。

在模型中,给定一个向量$w_i$,该向量表示词$w$的概率$P(w|w_i)$,与从根节点到达叶子节点的概率相同。这种方式带来的好处是,时间复杂度从常规softmax(3.1和3.2所使用的,计算概率的激活函数)的$O(left | V ight |)$下降到了$O(log(left | V ight |))$(其实就是将3.1、3.2使用的softmax激活函数替换成了一棵二叉树,同时也引入了一堆需要训练的参数)。

现在需要引入一些概念。用$L(w)$表示从根节点到叶节点$w$的节点数。例如,在图3中,$L(w_2) = 3$。记$n(w,i)$是路径上的第$i$个节点,相应的向量为$v_{n(w,i)}$。因此$n(w,1)$是根节点,$n(w,L(w))$是$w$的父节点。对于每个中间节点$n$,我们任意选择它的一个子节点并称之为$ch(n)$(这是在模型训练开始之前就选好的。每个中间节点都有两个子节点,可以任意选择。在本文中,每次都选左侧子节点)。

自然语言处理——词的表示第14张

图3 分层Softmax的二叉树

然后计算如下形式的概率:

自然语言处理——词的表示第15张

其中,

自然语言处理——词的表示第16张

此外,$sigma(cdot)$是sigmoid函数。

上面的公式信息量比较大,我们来详细地解释一下:

公式的最右侧是在计算向量内积。$v_{n(w,j)}$的长度是在变动的,所以每次$v_{w_i}$都截取相应的位数。我们假设$ch(n)$每次都是左侧的子节点。所以单词$w$真实的路径是向左时,$[ n(w,j+1) = ch(n(w,j))]$返回1,否则返回-1。

此外,$[ n(w,j+1) = ch(n(w,j))]$可以起到标准化(normalization)的作用。对于任一节点,走向左节点的概率和走向右节点的概率之和都应该为1(因为就两个子节点,不是向左就是向右)。对于任意的$v_n^Tv_{w_i}$,下面等式始终都是成立的:

egin{align*}
sigma(v_n^Tv_{w_i}) + sigma(-v_n^Tv_{w_i}) = 1
end{align*}

这其实也很好证明。sigmoid函数的定义:

egin{align*}
sigma(x) = frac{1}{1 + e^{-x}}
end{align*}

从而可得:

egin{align*}
sigma(x) + sigma(-x) &= frac{1}{1 + e^{-x}} + frac{1}{1 + e^{x}} \
&= frac{1 cdot e^x}{(1 + e^{-x}) cdot e^x} + frac{1}{1 + e^{x}} \
&= frac{e^x}{e^x + 1} + frac{1}{1 + e^{x}} \
&= 1
end{align*}

这也保证了$sum_{w=1}^{left | V ight |} P(w|w_i) = 1$是成立的。

为了训练这一模型,我们的损失函数依然是负log loss(与交叉熵一样):$-logP(w|w_i)$。

本文翻译自CS224n课程的官方笔记1,对应该课程的第1、2节。

免责声明:文章转载自《自然语言处理——词的表示》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇odoo开发笔记:Server+Action服务器动作自动触发执行Dbutils下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

汉语词性对照表[北大标准/中科院标准]

汉语词性对照表[北大标准/中科院标准] 词性编码 词性名称 注 解 Ag 形语素 形容词性语素。形容词代码为 a,语素代码g前面置以A。 a 形容词 取英语形容词 adjective的第1个字母。 ad 副形词 直接作状语的形容词。形容词代码a和副词代码d并在一起。 an 名形词 具有名词功能的形容词。形容词代码 a和名词代码n并在一起...

中英文对照 —— 标点符号(punctuation)

有限的几个; What Are the Fourteen Punctuation Marks in English Grammar? period:句号;comma:逗号;冒号:colon;分号:semicolon; prime:上撇号,如数学分析中的一阶导数 f′(x) underscore:下划线;省略号:ellipsis; exclamatio...

SQL判断某列中是否包含中文字符、英文字符、纯数字

一、包含中文字符 select * from 表名 where 列名 like '%[吖-座]%' 二、包含英文字符 select * from 表名 where 列名 like '%[a-z]%'  三、包含纯数字 select * from 表名 where 列名 like '%[0-9]%'...

CSS字体无法设置成功的问题

在 CSS 中设置字体名称,直接写中文是可以的。但是在文件编码(GB2312、UTF-8 等)不匹配时会产生乱码的错误。xp 系统不支持类似微软雅黑的中文。 方案一:你可以使用英文来替代。比如 font-family:"Microsoft Yahei"。 方案二:在 CSS 直接使用 Unicode 编码来写字体名称可以避免这些错误。使用 Unicode...

Codevs_1040_[NOIP2001]_统计单词个数_(划分型动态规划)

描述 http://codevs.cn/problem/1040/ 与Codevs_1017_乘积最大很像,都是划分型dp. 给出一个字符串和几个单词,要求将字符串划分成k段,在每一段中求共有多少单词(两个单词不能共享第一个字母),将每一段中的单词个数相加,求最大值. 1040 统计单词个数 2001年NOIP全国联赛提高组 时间限制: 1 s...

关于英语作文AI批改的思考(含定向高分方案)

在科技高速发展的今天,借助于AI,我们的老师终于能摆脱繁重的作业批改任务,从而把时间投入到更高效的教学工作中去。然而,我在多次的体验中,越来越发现AI批改英语作文的弊病。 有时候自己认真敲出来的作文,甚至还没有别人随便一篇中文翻译出来的分数高。 自己的语法明明正确,但是却一直报错。 自己不甘80分的命运,疯狂输入大量优美句子,然而分数仍然不涨。 在看到别...