zoukankan      html  css  js  c++  java
  • 自然语言处理——词的表示

    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.

    共现矩阵为:

    2.3 对共现矩阵应用SVD

    对$X$应用SVD:

    中间的矩阵除了对角线,其他位置都是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$列奇异向量进行降维:

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

    • 矩阵维度经常变动,比如新词频繁加入。
    • 由于绝大部分词并不会共现,造成矩阵过于稀疏。
    • 矩阵维度一般很高,大约$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模型。这是一个简单的神经网络,如下所示:

    图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的位置的索引,损失函数:

    3.3 Skip-Gram模型

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

    图2 Skip-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*}

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

    此外,

    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)$建模:

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

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

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

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

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

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

    "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)$(这是在模型训练开始之前就选好的。每个中间节点都有两个子节点,可以任意选择。在本文中,每次都选左侧子节点)。

    图3 分层Softmax的二叉树

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

    其中,

    此外,$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节。

  • 相关阅读:
    Stereo Matching文献笔记之(一):《Cross-Scale Cost Aggregation for Stereo Matching》读后感~
    机器视觉之 ICP算法和RANSAC算法
    基于语义约束与 Graph Cuts 的稠密三维场景 重建
    RANSAC算法详解
    三维重建技术在无人机方面的应用如何?三维重建未来的学术前景如何?
    尺度空间(Scale space)理论
    网速调控、带宽限制原理探究
    Cisco交换机IOS升级
    Nmap
    vi实用命令集
  • 原文地址:https://www.cnblogs.com/royhoo/p/How-to-represent-words.html
Copyright © 2011-2022 走看看