zoukankan      html  css  js  c++  java
  • CS224n学习笔记(一)

    How do we have usable meaning in a computer?

    Represents the words as discrete symbols, (离散型变量)

    Use the one-hot vector to represent the word in sentence, (Traditional way, we can use Distributional semantics)

    Distributional semantics: A word's meaning is giving by words that frequently appear close-by.

    when a word w appear in a text, its context words is the set of words that appears nearby. We can use many contexts of w to build up a representation of w.

    Word Vector:We build a dense(稠密的) vector for each word, chosen so that it's similar to vector of words that appear in similar contexts, it's a probability vector .

    所有的句子都表示 banking的意思。

    [bank =left( egin{array}{r}{0.286} \ {0.792} \ {-0.177} \ {-0.107} \ {0.109} \ {-0.549} \ {0.371}end{array} ight) ]

    单词向量有时候又叫做word embedding 或者 word representation。上面是分布式 distributed representation。不仅仅是一个简单的位置向量,每一个单词都有一个 distributed representation,就构成了向量空间

    Word2vec是一个框架用于学习单词向量。

    主要思想:

    • 有一大簇的文本
    • 每一个单词在一个确定的词典中可以用向量表示
    • Go through文本中的每一个位置,这个文本有一个中心单词 C 以及 context(“outside 单词”) O。我们要观察这个单词周围的单词。
    • 使用单词 C与单词 O的单词向量的相似性来计算给定的 O,是C的概率
    • 调整这个单词向量,直到最大化这个概率

    使用中间的单词可以预测出周围的单词

    例如对于下面这个例子来说:

    我们需要计算的是 (Pleft(w_{t+j} | w_{t} ight))

    我们希望的是通过周围的单词预测出中间的单词 ‘into’ 。所以我们可以改变这些预测,如果我们从贝叶斯的角度看的话,那么就是我们先计算出当遇到 'into' 的时候,周围每个单词的概率作为先验,然后当遇到周围的单词的时候,用后验就可以算出单词是 ‘into’的概率。

    对于 Word2vec的目标函数函数

    对于文本中的每一个位置,(t=1, dots, T)来说预测用一个确定大小为 m的窗口预测 context words, 对于中心单词 (w_{j})。目标函数就是

    [LikeLihhod =L( heta)=prod_{t=1}^{T} prod_{-m leq j leq m atop j eq 0} Pleft(w_{t+j} | w_{t} ; heta ight) ]

    m 表示窗口的大小,(L( heta)) 是关于最优化 ( heta)的函数,那么 (J( heta))就是 negative log 似然函数。( heta) 恰恰就是单词向量

    [J( heta)=-frac{1}{T} log L( heta)=-frac{1}{T} sum_{t=1}^{T} sum_{-m leq j leq m atop j eq 0} log Pleft(w_{t+j} | w_{t} ; heta ight) ]

    上面的 (J( heta)) 是损失函数,也就是目标函数。最小化目标函数等价于最大化预测的准确率。

    这个 ( heta) is actually going to be the vector representation. Use that word to predict what the other words occur

    那么问题来了,怎么计算 P函数。

    对于每个word,我们有两种表现方法,分别是:

    • (v_{w}) when (w) is a center word
    • (u_{w}) when (w) is a context word

    那么对于中心单词 c 于 context word o来说:

    [P(o | c)=frac{exp left(u_{o}^{T} v_{c} ight)}{sum_{w in V} exp left(u_{w}^{T} v_{c} ight)} ]

    对于前面的例子来说就是:(Pleft(u_{ ext {problems}} | v_{i n t o} ight)) short for (mathrm{P}left(problems|into; u_{ ext {problems}}, v_{i n t o}, heta ight))

    上面公式的解释,我们使用的是 (u_{o}^{T} v_{c})来表示权重的大小。也就是两个单词间的关联程度,(u_{o}^{T} v_{c})越大越相关,(从向量的角度解释)。分母是所有的情况。然后是一个 (Softmax)函数:

    [operatorname{softmax}left(x_{i} ight)=frac{exp left(x_{i} ight)}{sum_{j=1}^{n} exp left(x_{j} ight)}=p_{i} ]

    这个比较容易理解。这个公式也用于后面的CBOW 以及 skip-gram计算损失函数时候。

    梯度下降解最小化损失函数

    我们的参数只有一个 ( heta),但是请记住 ( heta) 包含中心向量与 context word向量,所以是两截长。这里我们只是用 ( heta) 来模糊的表示位置参数,那么 ( heta) 到底是一个什么样的参数呢?在 CBOW 与 skip-gram中可以理解为两个矩阵。这个后面再说。所以用梯度下降求解损失函数也放在后面。

    [ heta=left[ egin{array}{l}{v_{ ext {aardvark}}} \ {v_{a}} \ {vdots} \ {v_{z e b r a}} \ {u_{ ext {aardvark}}} \ {u_{a}} \ {vdots} \ {u_{z e b r a}}end{array} ight] in mathbb{R}^{2 d V} ]

    基于 SVD的方法获得单词向量

    在具体使用word2vec之前,我们先讲一下使用 SVD(奇异值分解)的方法,这个比较简单,但是这个方法十分有用,潜在语义索引(LSI) 就可以使用这种方法。we first loop over(遍历) a massive dataset and accumulate word co-occurrence counts in some form of a matrix X。 然后对 X矩阵使用 SVD(奇异值分解),获得 (US V^{T})。我们使用 U的行向量作为词典中所有单词的单词向量。

    Word-Document Matrixs

    构造 X的矩阵的方法如下,遍历所有的文件(billions of),word i 每出现在 文档 j 中一次 , 那么 (X_{i j})就+ 1. 可以看出 (left(mathbb{R}^{|V| imes M} ight))这个矩阵超级大。

    Window based Co-occurrence Matrix

    这种方法记录的不是单词与文本之间的联系,而是单词于单词之间,共同出现的情况下的联系:

    比如说图中的例子:

    Applying SVD to the cooccurrence matrix

    对上面的关系矩阵使用 SVD变换,我们的做法就是提取了前 k个特征向量,用来表示单词向量。

    [frac{sum_{i=1}^{k} sigma_{i}}{sum_{i=1}^{|V|} sigma_{i}} ]

    下面的图可以看到具体的方法,奇异值分解后得到三个矩阵,对中间的 S矩阵取前 k个对角线的数值。

    所以前面的 U矩阵的列向量只有 k个,这样就降低了单词向量的维度。这个方法还面临这许多问题。

    基于迭代的方法 - Word2vec

    两个算法:CBOW 和 skip-gram

    两种训练方法:negative sampling and hierarchical softmax

    Language Models

    首先需要理解,我们是将一个概率赋给一个序列的单词。从数学上表示,(Pleft(w_{1}, w_{2}, cdots, w_{n} ight))。如果我们假设每个单词的出现是完全独立的,那么:

    [Pleft(w_{1}, w_{2}, cdots, w_{n} ight)=prod_{i=1}^{n} Pleft(w_{i} ight) ]

    这个假设显然不合理,因为大多数情况下,句子中,单词间有一定的关系,比如说,‘read’ 后面 往往是 ‘book’ 或者是 ‘maganize’ 等。所以我们将这个句子的概率表示成,句子中出现的成对的单词,表示成这个单词与他下一个单词为一对,可以写成这样:

    [Pleft(w_{1}, w_{2}, cdots, w_{n} ight)=prod_{i=2}^{n} Pleft(w_{i} | w_{i-1} ight) ]

    以上就是我们表示一个序列的概率的例子。

    Continuous Bag of Words Model (CBOW)

    通过上下文预测中间单词。

    对于词袋模型,我们输入,(上下文的one-hot表示的单词向量)用 (x^{(c)})来表示。输出用 (y^{(c)})来表示,我们训练的时候,输出只有一个 (y) 表示中心词。下面定义未知数:

    首先定义两个矩阵:

    [mathcal{V} in mathbb{R}^{n imes|V|} ext { and } mathcal{U} in mathbb{R}^{|V| imes n} ]

    这里面 n 定义了单词向量空间的大小, (mathcal{V})是输入矩阵,(mathcal{V}) 的第 i 列是 对于输入单词 (w_{i}) 所表示的 n 维向量。我们表示成 (n imes 1) 向量 (v_{i})。同理对于输出,(mathcal{U}) 是输出矩阵,输出矩阵 (mathcal{U}) 的第 j 行是一个 n 维的单词向量作为单词 (w_{i}) 的输出向量。我们表示成 (u_{j})。 为什么可以这么说呢?从线性代数的角度来说,我们最开始的输入是 one-hot编码的 (x^{(c)}),我们可以理解为矩阵 (mathcal{V}) 对向量 (x^{(c)}) 的线性变换。 (v_{i}) 完全由参数 (i) 与矩阵 (mathcal{V}) 决定,所以我们可以直接当成是输入,这里巧妙的就是,我们最后优化的,也是这个 (v_{i})

    下面是具体的步骤,

    1. 对于输入大小为 m 的上下文, 我们产生一个one-hot 编码为

      [left(x^{(c-m)}, ldots, x^{(c-1)}, x^{(c+1)}, ldots, x^{(c+m)} in mathbb{R}^{|V|} ight) ]

    2. 这个上下文的单词向量就是((v_{c-m}=mathcal{V} x^{(c-m)}, v_{c-m+1}=mathcal{V} x^{(c-m+1)}, ldots, v_{c+m}=mathcal{V} x^{(c+m)} in mathbb{R}^{n} ))

    3. 将这些向量求平均值得到:

      [hat{v}=frac{v_{c-m}+v_{c-m+1}+ldots+v_{c+m}}{2 m} in mathbb{R}^{n} ]

    4. 产生一个用来表示分数的向量 (z=mathcal{U} hat{v} in mathbb{R}^{|V|}),而实际上打分的是矩阵 (mathcal{U}) 。由于相似矢量的点积更高,那么我们最大化点积的话,相似的单词就会靠的越近。

    5. 将分数通过 softmax函数:(hat{y}=operatorname{softmax}(z) in mathbb{R}^{|V|})

    6. 我们希望得分最高的是中心词,训练的中心词我们用 (y in mathbb{R}|V|)表示,而我们预测的结果用 (hat{y} in mathbb{R}|V|)来表示。

    现在我们要得到矩阵 (mathcal{V})(mathcal{U}) ,那么我们就要一个目标函数,然后最小化损失函数就可以了。我们使用信息学中的cross-entropy(交叉熵)损失函数,(H(hat{y}, y))。从离散的角度,我们可以写成下面的公式,(y) 向量的每一个位置都要最为离散的偏差算进来。

    [H(hat{y}, y)=-sum_{j=1}^{|V|} y_{j} log left(hat{y}_{j} ight) ]

    但是 (y) 是一个one-hot编码,所以 (H(hat{y}, y)=-y_{i} log left(hat{y}_{i} ight))。 最理想的情况下 (hat{y}_{i}) = 1,与 (y_{i}) 是相同的。但是预测的会有偏差。如果 $hat{y}_{i} < 1 $那么 (H(hat{y}, y)) > 0。因此最优化,我们写成下式:

    [最小化 J = ]

    [egin{array}{l}{=-log Pleft(w_{c} | w_{c-m}, ldots, w_{c-1}, w_{c+1}, ldots, w_{c+m} ight)} \ {=-log Pleft(u_{c} | hat{v} ight)} \ {=-log frac{exp left(u_{c}^{T} hat{v} ight)}{sum_{j=1}^{|V|} exp left(u_{j}^{T} hat{v} ight)}} \ {=-u_{c}^{T} hat{v}+log sum_{j=1}^{|V|} exp left(u_{j}^{T} hat{v} ight)}end{array} ]

    然后使用随机梯度下降更新 (u_{c}) and (v_{j})。上述式子在理解的过程中,关键的地方是要知道还未经过 (softmax) 函数的时候,我们用 (u_{c})来表示 (w_{c})。而输入使用的是 (mathcal{V}) 的列向量表示的,处理之后,用 (hat{v})来表示。

    Skip-Gram Model

    该算法与 CBOW的思路相反。是通过中心词预测上下文的单词向量:我们输入用 (x) 表示 ,输出用 (y^{(j)}) 来表示,我们定义相同的矩阵 (mathcal{V})(mathcal{U}) 。该算法也分成六部完成:

    1. 中心单词的 one-hot编码,用 (x in mathbb{R}^{|V|})来表示。
    2. 我们产生单词向量 (v_{c}=V x inmathbb{R}^{n})。这一步使用了矩阵 (mathcal{V})
    3. 然后使用 (z=mathcal{U} v_{c}) 得到,(z) 是一个矩阵,用来表示每个预测的 (y)
    4. 然后使用 softmax函数,(hat{y}=operatorname{softmax}(z))。 然后假设 (hat{y}_{c-m}, dots, hat{y}_{c-1}, hat{y}_{c+1}, dots, hat{y}_{c+m}) 是观察到每一个文本向量的概率。
    5. 我们希望的是我们产生的概率 (hat{y}_{c-m}, dots, hat{y}_{c-1}, hat{y}_{c+1}, dots, hat{y}_{c+m}) 与实际的概率 (y^{(c-m)}, ldots, y^{(c-1)}, y^{(c+1)}, ldots, y^{(c+m)})相等。实际的概率就是每一个单词的 one-hot编码。

    接下来就是定义目标函数以及最小化损失函数:(J) =

    [egin{aligned} J &=-sum_{j=0, j eq m}^{2 m} log Pleft(u_{c-m+j} | v_{c} ight) \ &=sum_{j=0, j eq m}^{2 m} Hleft(hat{y}, y_{c-m+j} ight) end{aligned} ]

    [egin{array}{l}{=-log Pleft(w_{c-m}, ldots, w_{c-1}, w_{c+1}, ldots, w_{c+m} | w_{c} ight)} \ {=-log prod_{j=0, j eq m}^{2 m} Pleft(w_{c-m+j} | w_{c} ight)} \ {=-log prod_{j=0, j eq m}^{2 m} Pleft(u_{c-m+j} | v_{c} ight)} \ {=-log prod_{j=0, j eq m}^{2 m} frac{exp left(u_{c-m+j}^{T} v_{c} ight)}{sum_{k=1}^{|V|} exp left(u_{k}^{T} v_{c} ight)}} \ {=-log prod_{j=0, j eq m}^{2 m} u_{c-m+j}^{T} v_{c}+2 m log sum_{k=1}^{|V|} exp left(u_{k}^{T} v_{c} ight)}end{array} ]

    上面的损失函数就比较好理解了。

    Negative Sampling

    前面计算面临的问题,在 (softmax) 阶段,计算量与单词向量的长度成 (O(|V|))关系,而 (softmax) 计算公式也很复杂

    [sigma(mathbf{z})_{j}=frac{e^{z_{j}}}{sum_{k=1}^{K} e^{z_{k}}} quad ext { for } j=1, ldots, K ]

    所以计算太复杂了,为了简化计算,我们能否不遍历语料库呢?

    什么是Negative Sampling(负采样)

    对于一个样本,在之前的样本中,我们都是将与正确的结果作为训练结果拿去训练的。对于负采样,在语言模型中,假设中心词为 (w), 他周围的上下文共有 (2m) 个单词,记为 (context(w)) ,那个 (w)(context(w)) 的对应就是一个正例,而负例(可以理解为错误的例子)就是我们取 (n) 个与 (w) 不同的单词 (w_{i}, i=1,2, ldots n), 这些 (w_{i})(context(w)) 就构成了负样本,然后利用分类的思想,这就相当于一个二元分类问题,通过最优化这个分类问题求解模型的参数。

    对于一个样本是正样本,我们用逻辑回归的模型计算是正样本的概率,这里我们用 (v_{c}^{T} v_{w}) 表示的是 单词向量 (v_{c}) 与 文本向量 (v_{w}) 的点积,点积越大,越相关,那么 (P = 1) 的概率就越大:

    [P(D=1 | w, c, heta)=sigmaleft(v_{c}^{T} v_{w} ight)=frac{1}{1+e^{left(-v_{c}^{T} v_{w} ight)}} ]

    Negative Sampling下的损失函数

    假设我们的参数还用 ( heta) 来表示的话, 分别用 (D)(D') 表示正负样本集合

    [ heta=underset{ heta}{operatorname{argmax}} prod_{(w, c) in D} P(D=1 | w, c, heta) prod_{(w, c) in D'} P(D=0 | w, c, heta) ]

    [=underset{ heta}{operatorname{argmax}} prod_{(w, c) in D} P(D=1 | w, c, heta) prod_{(w, c) in D'}(1-P(D=1 | w, c, heta)) ]

    [egin{array}{l}{=underset{ heta}{operatorname{argmax}} sum_{(w, c) in D} log P(D=1 | w, c, heta)+sum_{(w, c) in D'} log (1-P(D=1 | w, c, heta))} \ {=underset{ heta}{operatorname{argmax}} sum_{(w, c) in D} log frac{1}{1+exp left(-u_{w}^{T} v_{c} ight)}+sum_{(w, c) in ilde{D}} log left(1-frac{1}{1+exp left(-u_{w}^{T} v_{c} ight)} ight)}end{array} \ =underset{ heta}{operatorname{argmax}} sum_{(w, c) in D} log frac{1}{1+exp left(-u_{w}^{T} v_{c} ight)}+sum_{(w, c) in D'} log left(frac{1}{1+exp left(u_{w}^{T} v_{c} ight)} ight) ]

    在上面的式子中,我们又将参数 ( heta) 替换成了 矩阵 (mathcal{V})(mathcal{U}) 列向量与行向量,分别表示输入与输出。

    最大化似然函数,等价于最小化下面的目标函数:

    [J=-sum_{(w, c) in D} log frac{1}{1+exp left(-u_{w}^{T} v_{c} ight)}-sum_{(w, c) in D'} log left(frac{1}{1+exp left(u_{w}^{T} v_{c} ight)} ight) ]

    那么对于 skip-gram算法来说

    对于每一个中心词 C 来说:(这里没有遍历每一个中心词)

    [J = -log sigmaleft(u_{c-m+j}^{T} cdot v_{c} ight)-sum_{k=1}^{K} log sigmaleft(- ilde{u}_{k}^{T} cdot v_{c} ight) ]

    对于CBOW算法,(hat{v}=frac{v_{c-m}+v_{c-m+1}+ldots+v_{c+m}}{2 m}) 还是用这个公式,所以损失函数就可以写成:

    [J = -log sigmaleft(u_{c}^{T} cdot hat{v} ight)-sum_{k=1}^{K} log sigmaleft(- ilde{u}_{k}^{T} cdot hat{v} ight) ]

    Hierarchical Softmax​

    分层 (Softmax) 在用于非连续的单词向量的时候,表现比较好。而负采样用于连续的单词向量的时候表现比较好。分层 (Softmax) 使用的是哈夫曼树。

    $nleft(w_{2}, 1 ight)$
    $nleft(w_{2}, 1 ight)$
    $nleft(w_{2}, 2 ight)$
    $nleft(w_{2}, 2 ight)$
    $nleft(w_{2}, 3 ight)$
    $nleft(w_{2}, 3 ight)$
    $w_{1}$
    $w_{1}$
    $w_{2}$
    $w_{2}$
    $w_{3}$
    $w_{3}$
    $w_{4}$
    $w_{4}$
    $w_{V-1}$
    $w_{V-1}$
    $w_{V-2}$
    $w_{V-2}$
    ……
    [Not supported by viewer]

    我们使用叶子结点代表每一个单词,单词的概率定位为从根节点随机走到该节点的概率。由于是二叉树,我们结算复杂度为 (O(log (|V|)))。这样就降低了模型的复杂度,而我们要学习的参数,就是除了叶节点之外的权重。我们用 (L(w)) 表示从根结点到叶结点的长度,比如图中的 (L(w2)) = 3. 而我们用 (n(w, i)) 表示路径上的第 (i) 个结点,对应于向量中的参数就是 (v_{n(w, i)})。对于结点 (n) 我们用 (operatorname{ch}(n)) 表示 (n) 的孩子结点,那么叶结点是 (w)的概率就是:

    [Pleft(w | w_{i} ight)=prod_{j=1}^{L(w)-1} sigmaleft([n(w, j+1)=operatorname{ch}(n(w, j))] cdot v_{n(w, j)}^{T} v_{w_{i}} ight) ]

    其中

    [[x]=left{egin{array}{l}{1 ext { if } x ext { is true }} \ {-1 ext { otherwise }}end{array} ight. ]

    上面的式子,对于某个结点 (i) ,如果 (n(w, i+1)) 就是 (n(w, i)) 的孩子的节点的的话,那么 ([x] = 1),否则 ([x] = -1) ,这里的 +1 或者 -1 仅仅是用来表示叶结点的方向。对于上图中的例子来说就是:

    [egin{aligned} Pleft(w_{2} | w_{i} ight) &=pleft(nleft(w_{2}, 1 ight), ext { left } ight) cdot pleft(nleft(w_{2}, 2 ight), ext { left } ight) cdot pleft(nleft(w_{2}, 3 ight), ext { right) } ight.\ &=sigmaleft(v_{nleft(w_{2}, 1 ight)}^{T} v_{w_{i}} ight) cdot sigmaleft(v_{nleft(w_{2}, 2 ight)}^{T} v_{w_{i}} ight) cdot sigmaleft(-v_{nleft(w_{2}, 3 ight)}^{T} v_{w_{i}} ight) end{aligned} ]

    而且我们可以保证:

    [sum_{w=1}^{|V|} Pleft(w | w_{i} ight)=1 ]

    可以看出,对于每一次更新语料库,不需要重新计算全部,而是计算,新的 word 对应的 Path 中的参数就可以了。

  • 相关阅读:
    冲刺一阶段———个人总结06
    典型用户分析
    冲刺一阶段———个人总结05
    冲刺一阶段———个人总结04
    冲刺一阶段———个人总结03
    冲刺一阶段———个人总结02
    冲刺一阶段———个人总结01
    软件需求分析
    课堂作业——寻找发帖水王
    四则运算网页版
  • 原文地址:https://www.cnblogs.com/wevolf/p/10781636.html
Copyright © 2011-2022 走看看