CS224n: Natural Language Processing with Deep Learning课程笔记



  • 所有课件及Assignments可见我的Github:hunto/CS224n
    论坛排版有点难看,可见我的博客: hunto.github.io

    Lecture 1 - 课程介绍

    本讲主要内容

    1. 什么是自然语言处理?人类语言的本质
    2. 什么是深度学习?
    3. 课程架构
    4. 为什么理解语言是困难的?
    5. 深度学习在自然语言处理中的应用

    1. 什么是自然语言处理

    • 自然语言处理是以下领域的交叉:
      • 计算机科学
      • 人工智能
      • 语言学
    • 目的:使计算机能够处理或“理解”自然语言以用于需要的任务中,例如:
      • 执行任务,例如建立日程表、购物
      • 语言翻译
      • 智能问答
    • 完全理解和表示语言的意义(甚至是定义它)是一个困难的目标
    • Perfect language understanding is AI-complete.出色的自然语言理解是一个AI完全问题。
      [注:在人工智能领域,最困难的问题被非正式地称为AI-complete或AI-hard,这意味着这些计算问题的难度等同于解决中心人工智能问题 - 使计算机像人一样聪明。为了解决问题,AI-complete反映了一种态度,即它不能通过简单的特定算法来解决。 AI-完全问题包括计算机视觉,自然语言理解,以及在解决任何现实世界问题时处理意外情况。 目前,AI完全问题不能单靠现代计算机技术解决,但也需要人工计算。]

    2. 什么是深度学习

    • 深度学习是机器学习的一个分支
    • 所有有很好的效果的机器学习方法均是因为对数据人为设计的表示输入特征
    • 机器学习通过调整权重来得到最好的最终预测结果

    第一讲为简介,剩余内容可以自己看课件



  • Lecture2 - 词向量


    1. 如何表示一个词语?

    一个新词语的意思是通过已知词语来表示的

    0_1530785759492_0f4b67cd-2371-471f-8de3-91f4bd6b220d-image.png

    WordNet这样解释词语的问题

    • 缺少对词语见细微差别的表示
    • 缺少词语新的意思 -- 词的意思不是一成不变的,但是保证对词语的解释永远是最新的是不可能
    • 主观的
    • 需要人为构建和适配
    • 难以计算细微的词语相似度

    因此,我们可以将词使用离散的数学标记来表示。
    词语可以使用one-hot向量 [one-hot意思为向量中有1个1,其余为0] 的方式来表示,例如:

    辣鸡 = [1, 0, 0, 0]
    优秀 = [0, 1, 0, 0]
    

    这样得到的向量的维度 = 词库中的词语数

    但是,这样的表示方法也存在很多问题:
    例如:

    辣鸡 = [1, 0, 0, 0]
    垃圾 = [0, 0, 1, 0]
    

    但在具体语境中,辣鸡zzy垃圾zzy是相近或者说等价的,可他们放到one-hot中的表示却是不同的两个向量,因此,这样的表示方法无法表示出词语间的相似度(one-hot向量间的距离与他们的词语相似度无关)。

    解决方案:

    • 可否依靠WordNet的词库来得到词语相似度?
    • 或者使机器自己学会在向量中编码表示相似度

    我们想到用词语所处的语境来表示词语。

    • 核心思路一个词的意思由频繁出现在它附近的词决定
    • 使用大量含有目标单词的语句来建立目标单词的词向量表示
      0_1530787172058_2b1f014f-f0b4-4e8d-b41d-0ec686fe89ed-image.png

    2. Word2Vec概览

    Word2Vec(Mikolov et al. 2013)是一个训练词向量的框架。

    • 有大量的语料
    • 适配的词典中的每一个词都由一个向量表示
    • 遍历文本中出现单词c的每一个位置,我们假设c周围的若干单词为o,使用oc的词向量相似度来计算通过o推出c的概率。不断调整词向量以使概率最大化。
      0_1530788239279_c2592089-9346-4638-8f0d-6a0059153cdc-image.png

    目标函数(损失函数)

    J(θ)=1TlogL(θ)=1Tt=1Tmjm,j0logP(wt+jwt;θ)J(\theta)=-\frac1{T}logL(\theta)=-\frac1{T}\sum_{t=1}^T\sum_{-m\le j\le m, j\neq0}logP(w_{t+j}|w_t;\theta)
    其中,t=1,...,T为语句中的位置,m为周围词的范围,中心词为wjw_j

    调整权重将损失函数值降到最低<=>使预测概率最大化

    如何计算P?

    对于每个词,我们将使用两个向量:

    • vwv_w, 当w为目标单词(中心词)
    • uwu_w, 当w为周围单词

    那么,对于一个中心词c和周围词o,我们可以得到概率公式为:
    P(oc)=exp(uoTvc)wvexp(uoTvc)P(o|c)=\frac{exp(u_o^Tv_c)}{\sum_{w\in v}exp(u_o^Tv_c)}
    0_1530789375609_dd47722d-d6be-48af-b200-629395d416d9-image.png
    0_1530789414068_b1512cf4-aa55-443a-93aa-facc71bcce42-image.png

    • 为什么要使用两个向量?
      更容易优化。在最后求两者平均值。

    两种类型的模型

    1. Skip-grams(SG)
      使用目标单词作为输入,预测目标单词周围的词,取概率最高的[8](窗口大小)个词

    2. Continuous Bag of Words(CBOW)
      使用目标单词周围的[8]个词作为输入,预测目标单词,取概率最高的


    我们现在已经有一个需要最小化的损失函数了,但是如何使损失函数最小化呢?

    Gradient Descent(梯度下降)

    梯度下降是一个最小化损失函数的算法。
    梯度下降法,当前θ值,计算其在损失函数中的梯度,再向梯度下降方向变化当前值,直到找到局部最小值。
    0_1530790038690_47ed27fe-967a-46e5-8b2c-3b900304b211-image.png

    Stochastic Gradient Descent(随机梯度下降)

    我们一次对语料库中的所有词语使用梯度下降算法是不现实的,因此我们使用随机梯度下降算法来解决梯度下降的计算资源问题。在随机梯度下降法中,每次我们只取一段sample window,进行梯度下降。



  • Assignment1

    q1_softmax

    softmax函数很简单,每一个元素的e次幂除以所有元素的e次幂之和,即:
    softmax(x)=exijexjsoftmax(x)=\frac{e^{x_i}}{\sum_j e^{x_j}}

    但是直接把公式放到计算机中使用numpy计算肯定是不行的。e的1000次方肯定爆,且计算量太大,于是我们根据定理:
    softmax(x+c)=softmax(x)softmax(x+c)=softmax(x)
    可以令c=max(x),这样就不会产生计算错误出现无穷数infty的情况了。

    实现的代码如下:

    if len(x.shape) > 1:
        # Matrix
        ### YOUR CODE HERE
        cal_softmax = lambda x: np.exp(x) / np.repeat(np.sum(np.exp(x), axis=1, keepdims=True), x.shape[1], axis=1)
        x = cal_softmax(x - np.reshape(np.max(x, axis=1), [x.shape[0], 1]))
        ### END YOUR CODE
    else:
        # Vector
        ### YOUR CODE HERE
        cal_softmax = lambda x: np.exp(x) / np.sum(np.exp(x), axis=0)
        x = cal_softmax(x - np.max(x))
        ### END YOUR CODE
    

    q2

    q2_sigmoid

    首先需要实现sigmoid函数,sigmoid function定义如下:
    σ(x)=11+ex\sigma(x)=\frac{1}{1+e^{-x}}

    q2_sigmoid.py实现代码如下:

    • sigmoid(x)
      s = 1 / (1 + np.exp(-x))
      
    • sigmoid_grad(s)
      ds = s * (1 - s)
      

    q2_gradcheck

    接着实现grad_check用于之后的测试。

    x[ix] += h
    
    random.setstate(rndstate)
    new_f1 = f(x)[0]
    
    x[ix] -= 2 * h
    
    random.setstate(rndstate)
    new_f2 = f(x)[0]
    
    x[ix] += h
    

    q2_neural

    最关键的地方,这里定义了一个简单的网络:
    0_1530862803490_9d8b0efe-88e4-4f7a-8ade-c370d54338bd-image.png
    其中,
    h=sigmoid(xW1+b1),y^=softmax(hW2+b2)h=sigmoid(xW_1+b_1), \hat{y}=softmax(hW_2+b_2)
    这些即为网络的前端部分。

    h = sigmoid(np.dot(X, W1) + b1) # hidding layer
    y_hat = softmax(np.dot(h, W2) + b2) # output y
    

    网络后端部分为loss与梯度。

    cost = np.sum(-np.log(y_hat[labels == 1])) / X.shape[0]
    d3 = (y_hat - labels) / X.shape[0]
    gradW2 = np.dot(h.T, d3)
    gradb2 = np.sum(d3, axis=0, keepdims=True)
    
    dh = np.dot(d3, W2.T)
    grad_h = sigmoid_grad(h) * dh
    
    gradW1 = np.dot(X.T, grad_h)
    gradb1 = np.sum(grad_h, axis=0)
    

    到这里,一个简单的网络就定义完了

    q3_word2vec

    normalizeRows

    首先需要实现一个normalizeRows函数用于将向量单位化(ljht这个名称我还给老师了),也就是向量元素平方和为1。

    x = x / np.sqrt(np.sum(np.square(x), axis=1, keepdims=True))
    

    softmaxCostAndGradient

    该函数与q2中实现的大致相同

    y_hat = softmax(np.dot(predicted, outputVectors))
    cost = np.log(np.sum(np.exp(np.dot(predicted, outputVectors)),
                            axis=0)) - outputVectors[target].dot(predicted)
    
    gradPred = np.sum(y_hat.reshape(-1, 1) * outputVectors,
                        axis=0) - outputVectors[target]
    
    grad = y_hat.reshape(-1, 1) * np.tile(predicted, (outputVectors.shape[0], 1))
    
    grad[target] -= predicted
    

    后面的内容见github吧



  • Lecture3 - More Word Vectors

    对Word2Vec实现的总结

    • 遍历语料库中的所有单词
    • 预测每个词周围的词
    • 每一个相邻词语组合(如I likeIlink为相邻词语)只会被捕获一次

    那么,为什么不直接获取词语组合的个数?

    例如:
    0_1530928752784_f8045c95-f7f0-48a0-a95b-99d96f992a99-image.png

    朴素共素向量的问题:

    • 出现新的词时,旧向量的维度都需要改变
    • 维度由词典大小决定 -- 高维度
    • 高稀疏性

    解决办法:将高维向量转为低维向量
    例如SVD
    0_1530931665593_a76cf556-ef18-4a08-943e-42b36f5019f5-image.png

    但SVD也有问题:

    • 计算复杂度高:MxN矩阵复杂度为O(M x N)
    • 增加词后还是需要更新整个矩阵
    • 与其他的DeepLearning模型训练方式不同

    两种方法的比较:

    0_1530930181553_5a54073a-fcdb-412a-9bce-2c2e92d9df09-image.png

    当然,也有两者结合的:GloVe

    0_1530930223789_d4b1ff60-29dd-4a29-829a-327fffc92f21-image.png

    如何评价一组词向量

    • 内部:在一个特定的子任务中评估
      • 快速评估
      • 帮助理解系统
      • 不确定词向量对真实任务的效果
    • 外部:在一个真实任务中评估
      • 计算准确率可能需要花费很长时间
      • 不确定结果是否为子系统的问题或者是词向量与子系统共同作用的问题


  • -------- 多公式预警 --------

    Lecture4 - Word Window Classification and Neural Networks

    传统机器学习分类一般使用Logistic Regression或SVM等模型来划分决策边界,即只改变分类间的分界线,而不改变输入的特征向量。

    0_1530932176555_c8acff4d-ddc4-452d-8cef-3fb682cd52b0-image.png

    softmax分类函数

    p(yj=1x)=exp(Wyx)c=1Cexp(Wcx)p(y_j=1|x)=\frac{exp(W_y\cdot x)}{\sum_{c=1}^Cexp(W_c\cdot x)}

    softmax分类函数取权值矩阵W的一行W_j乘上输入向量,归一化得到概率。

    softmax与cross-entropy error(交叉熵误差)

    我们的目标是最大化正确的y的概率。因此,最小化正确分类的概率的负对数。

    logp(yx)=log(exp(fy)c=1Cexp(fc))-logp(y|x)=-log(\frac{exp(f_y)}{\sum_{c=1}^Cexp(f_c)})

    因为分类y为one-hot向量,所以loss函数等价于交叉熵函数:
    H(y^,y)=j=1Cyjlog(y^j)=yilog(y^i)H(\hat{y}, y)=-\sum_{j=1}^{C}y_jlog(\hat{y}_j)=-y_ilog(\hat{y}_i)

    对N个点来说,总loss为:
    i=1Nlog(exp(fyi)c=1Cexp(fc))\sum_{i=1}^N-log(\frac{exp(f_{y_i})}{\sum_{c=1}^Cexp(f_c)})

    平均后加上正则化项,为:
    1Ni=1Nlog(exp(fyi)c=1Cexp(fc))+λkθk2\frac1N\sum_{i=1}^N-log(\frac{exp(f_{y_i})}{\sum_{c=1}^Cexp(f_c)}) + \lambda \sum_k \theta_k^2

    因此,我们可以得到真正的损失函数为:
    J(θ)=1Ni=1Nlog(exp(fyi)c=1Cexp(fc))+λkθk2J(\theta) = \frac1N\sum_{i=1}^N-log(\frac{exp(f_{y_i})}{\sum_{c=1}^Cexp(f_c)}) + \lambda \sum_k \theta_k^2

    当我们有很多特征时,正则化可以减轻过拟合
    0_1530933944164_2628551e-960c-4623-82e3-fe393f7d3f08-image.png

    一般机器学习在词向量分类中的问题

    对于一般的机器学习,没有很多特征向量,权值矩阵维度低,只需要更新决策边界。但是在深度学习或词向量中,需要同时学习权值矩阵和词向量,特征维度很高,极其容易过拟合。
    0_1530934302014_68c28408-ae03-4810-a1e4-d221542b3ede-image.png

    重新训练词向量中的陷阱

    我们有一个预训练的词向量,结果较泛化。
    0_1530934454404_e42dc7af-dcf0-4d60-aac7-cd538868011d-image.png

    而当我们想用特定语料重新训练词向量时,极易产生分类错误的情况。
    0_1530934523042_f0b68709-c301-473b-a6e5-5f7fb01d564b-image.png

    那么,我们该不该训练我们自己的词向量呢?

    • 如果语料库很小==》不要重新训练词向量
    • 如果有非常大的数据集==》训练词向量可能会得到更好的结果

    side note:

    • 词向量矩阵L常被称作lookup table
      0_1530934831888_f91e32c3-0788-48b7-a400-9043ab1772ae-image.png
    • Word vectors = word embeddings = word representations (mostly)

    Window Classification

    通过之前的介绍,我们对单个单词的分类已经几乎完成了。我们可以通过上下文给单个单词分类,以消除歧异。
    所谓window classification,我们可以将特征向量X想象成一个固定大小窗口,内容为文本的一部分,我们直接将窗口内的词语的向量拼接可得到X。
    0_1530935336226_04a6b1e8-254e-4180-8e9e-a016e4421fd3-image.png

    由于我们的特征向量X只是原有X的拓展,损失函数与之前相同。

    Oh! Neural Network

    Softmax (等价于logistic regression)效果有限,只有线性决策边界,当问题变得复杂时,效果不好。但是神经网络可以学到复杂的多的特性和非线性决策边界。Neural Network, YES!
    0_1530935881445_ff2d6a30-d87c-4d73-9cc9-b1c214548dbb-image.png

    From logistic regression to neural nets

    神经网络的每一个神经元都是一个二分类逻辑回归单元。
    0_1530944741189_e223c4df-4a17-4979-8abd-80e72b4b58f8-image.png
    0_1530944804636_1b7f3492-aef5-4a5b-a062-1c4c33f6e8cd-image.png

    神经网络同时运行多个逻辑回归,但我们并不需要知道他们预测什么,只需要丢给下一层网络,由最终损失函数自动决定他们预测什么。多层并行逻辑回归网络就构成了多层神经网络。
    0_1530944955931_0db53667-0c83-4087-88ac-f18559c0fd6c-image.png
    0_1530944968740_545abe04-cf19-479b-97b0-1d2a5cba1976-image.png
    0_1530944982029_bc52b130-3615-4081-81fa-902153cee05d-image.png

    为什么要是非线性系统
    因为多层线性系统叠加还是线性系统。
    W1W2...Wnx=WxW_1W_2...W_nx=Wx

    0_1530945207552_da0c29f5-0ad9-4dac-a911-1fac6bee49ba-image.png

    Feed-forward Computation 前向传播网络

    课件中给了一个简单的网络作为例子:
    0_1530945365404_8c1fb10a-76f9-4529-a404-6f77fc630b6b-image.png

    这种红点图经常在论文里看到,大致代表单元数;中间的空格分隔开一组神经元,比如隐藏层单元数为2×4。U是隐藏层到class层的权值矩阵:
    0_1530945474416_c42b3315-ed99-4068-8f2d-62a03919a864-image.png

    其中a是激活函数:
    a=11+exp((WTx+b))a=\frac{1}{1+exp(-(W^Tx+b))}

    The max-margin loss 间隔最大化损失

    怎么设计目标函数呢,记scs_c代表误分类样本的得分,ss表示正确分类样本的得分。则朴素的思路是最大化$(s−s_c)$ 或最小化 $(s_c−s)$。但有种方法只计算$s_c>s⇒(s_c−s)>0$时的错误,也就是说我们只要求正确分类的得分高于错误分类的得分即可,并不要求错误分类的得分多么多么小。这得到间隔最大化目标函数:
    J=max(scs,0)J=max(s_c-s,0)

    但上述目标函数要求太低,风险太大了,没有留出足够的“缓冲区域”。可以指定该间隔的宽度$(s−s_c<\varDelta)$ ,得到:
    J=max(Δ+scs,0)J=max(\Delta +s_c-s,0)

    可以调整其他参数使得该间隔为1:
    J=max(1+scs,0)J=max(1+s_c-s,0)

    在这个分类问题中,这两个得分的计算方式为:
    sc=UTf(Wxc+b)s_c=U^Tf(Wx_c+b)
    s=UTf(Wx+b)s=U^Tf(Wx+b)
    通常通过负采样算法得到负例。

    另外,这个目标函数的好处是,随着训练的进行,可以忽略越来越多的实例,而只专注于那些难分类的实例。

    反向传播训练

    U的梯度:
    0_1530946339265_59a29cc4-6d5b-4875-923d-5ba3bcb0f767-image.png

    对于偏置的偏导数δi(k)\delta_i^{(k)}:
    0_1530946508230_52bd82c2-794b-49d5-adfd-0f02484e0812-image.png

    最后一片拼图是对词向量的偏导数,由于连接时每个输入单元连到了多个隐藏单元,所以对某个输入单元的偏导数是求和的形式(残差来自相连的隐藏单元):
    0_1530946544351_e1c3de57-9515-44ad-ada1-af3dd54d60d4-image.png

    其中,WTjW^T \cdot j是第jj列,转置后得到行向量;红色部分是误差,相乘后得到一个标量,代表词向量第jj维的导数。那么对整个词向量的偏导数就是:
    sx=WTδ\frac{\partial s}{\partial x} = W^T\delta



  • Python Review



  • Lecture5 - backpropagation (反向传播)

    单层神经网络
    0_1530956249043_781bf661-4a85-41ba-9c58-262e4a3850db-image.png

    多层神经网络
    0_1530956303304_65c79f5d-d8bb-4f4c-b924-6eff9a077c26-image.png

    为什么需要更多层网络?
    层数越多,可以表达的问题越复杂

    0_1530956403558_7a2057de-cb9b-40dc-a847-807ee2ec4d63-image.png

    Stochastic Gradient Descent 随机梯度下降

    θnew=θoldαθJ(θ)\theta^{new} = \theta^{old} - \alpha \nabla_\theta J(\theta)

    前向传播与反向传播
    0_1530956819974_f6caaaa7-e4d3-453c-88d8-927dcc21f193-image.png

    0_1530956883896_16b2e385-014a-44e5-ab6d-fdac43e34d23-image.png



  • Lecture6 - Introduction to TensorFlow

    YX TensorFlow.




  • 核心层

    此回复已被删除!


  • Lecture7 - Dependency parsing (句法分析)



  • Lecture8 - Recurrent Neural Networks (循环神经网络)

    Language Modeling (语言模型)

    语言模型是一个预测一段文字的下一个词是什么的任务。
    0_1531030485353_b2c16532-829b-4665-8900-283749b33a08-image.png

    正式地说,Language Model就是,通过已给的词的序列{X_1, X_2, ..., X_t},计算出下一个词X_{t+1}的概率:

    P(x(t+1)=wjx(t),...,x(1))P(x^{(t+1)}=w_j|x^{(t)}, ..., x^{(1)})

    其中,W_j是词库中的一个词。


    我们每天都在使用Language Model:

    0_1531030877346_0c0b0750-d273-4744-9c0c-c3e43a09f395-image.png
    0_1531030891358_03811854-4db8-4898-b1e8-d03b0a859a66-image.png

    n-gram Language Models

    我们该如何学习一个语言模型呢?
    使用n-gram Language Model

    一个 n-gram 是一个由连续的词组成的序列:

    • unigrams: "the", "students", "opened", "their"
    • bigrams: "the students", "students opened", "opened their"
    • trigrams: "the students opened", "students opened their"
    • 4 - grams: "the students opened their"

    n-gram的思路是统计每个gram出现的次数,用这些来预测下一个词。

    具体实现

    我们首先做一个简单的假设: 第t+1个词只由它之前的(n-1)个词决定,即:

    P(x(t+1)x(t),...,x(1))=P(x(t+1)x(t),...,x(tn+2))=P(x(t+1),x(t),...,x(tn+2))P(x(t),...,x(tn+2))P(x^{(t+1)}|x^{(t)}, ..., x^{(1)})=P(x^{(t+1)}|x^{(t)}, ..., x^{(t-n+2)}) = \frac{P(x^{(t+1)}, x^{(t)}, ..., x^{(t-n+2)})}{P(x^{(t)}, ..., x^{(t-n+2)})}

    但是,我们怎么得到这n个gram和n-1个gram的概率呢?
    通过在大语料库中计算它们的个数

    P(x(t+1)x(t),...,x(1))count(x(+1),x(t),...,x(tn+2))count(x(t),...,x(tn+2))P(x^{(t+1)}|x^{(t)}, ..., x^{(1)}) \approx \frac {count(x^{(+1)}, x^{(t)}, ..., x^{(t-n+2)})} {count(x^{(t)}, ..., x^{(t-n+2)})}

    n-gram Language Model Example

    假设我们正在学习一个4-gram语言模型。
    0_1531032283628_30064fc6-9ac3-4ff9-bce2-53d3527279ba-image.png
    若在语料库中:

    • students opened their出现了1000次
    • students opened their books出现了400次 => P(books|students opened their) = 0.4
    • students opened their exams出现了100次 => P(exams|students opened their) = 0.1

    n-gram模型的问题

    1. 如果语料库中一个词从没有出现在某个词序列(students opened their)后,那个词的概率就是0
      解决方案:给每个词的count值加一个很小的量 —— smoothing(平滑处理)

    2. 如果语料库中压根就没有这个词序列(students opened their),所有词的概率都是0!
      解决方案:使用更小的gram(opened their)来替代 —— backoff

    3. n-gram模型是巨大的,它需要给每个词都与预测序列计算一次概率,空间以及时间复杂度均很高。

    那么,我们能不能用神经语言模型(neural Language Model)来实现呢?
    当然可以。

    可以用一个固定大小的CNN来实现。

    A fixed-window neural Language Model

    0_1531033171764_3f5eb738-4161-422b-96ce-78ee7578d4da-image.png

    这样的模型相较于n-gram的提升:

    • 没有稀疏的问题
    • 模型大小为O(n),相较于n-gram的O(exp(n))提升巨大

    但是也存在问题:

    • 固定的window太小
    • 增加window大小的同时也会增加W的大小
    • window永远不可能足够大
    • 输入的4个x都有不同的W,当挪动window时,它们并不共享权值。例如the students opened theirstudents opened their books虽然都有students,但是不是同一个位置,并不能共享权值。

    因此,我们需要一个可以处理任何长度输入的神经模型。

    OH! Recurrent Neural Networks (RNN)

    0_1531033583135_097a4c2a-7f99-4812-b7ef-e20bd343ea5f-image.png

    0_1531033696665_a3742532-810a-4c9a-aca7-4f0abcf13d92-image.png

    Loss Function损失函数
    我们一般使用Cross-Entropy交叉熵作为损失函数。对于时间点t中预测得到的下一个词y(t)^\hat{y^{(t)}},以及真实的下一个词y(t)=x(t+1)y^{(t)} = x^{(t+1)},有该节点的损失函数:

    J(t)(θ)=CE(y(t),y^(t))=j=1Vyj(t)logy^j(t)J^{(t)}(\theta) = CE(y^{(t)}, \hat{y}^{(t)}) = - \sum_{j=1}^{|V|}y_j^{(t)}log\hat{y}_j^{(t)}

    总损失函数为:

    J(θ)=1Tt=1TJ(t)(θ)J(\theta)=\frac1T\sum_{t=1}^TJ^{(t)}(\theta)

    0_1531034914539_f9a5333c-510c-4d60-8d6e-dad056937bb4-image.png

    反向传播
    这里可以参考CS224n笔记8 RNN和语言模型,写的很好
    0_1531036282246_2c2e756a-37c6-4516-8c3b-b9e82210c090-image.png
    0_1531036331820_9f65ad3c-ca44-49c6-912c-9c7a503d02ea-image.png

    循环神经网络的优点

    • 可以处理任意长度的输入
    • 对于更长的输入,模型大小并不会增加
    • 循环神经网络中某一步的计算可以使用之前计算结果。(受之前计算影响,与之前的有关)

    循环神经网络的缺点

    • 递归计算很慢,无法并行计算。
    • 很难从中间的步骤中获取到有用的信息。
    • 之后还会介绍更多的缺点


  • Lecture9 - Vanishing Gradients and Fancy RNNs(LSTMs and GRUs)

    课件前半部分讲了梯度消失问题,我已在机器学习梯度消失与梯度爆炸问题详解中说明,不再赘述。


    Gated Recurrent Units

    为了改善梯度消失问题,引入了更复杂的隐藏单元,例如GRU。主要思想是

    • 保留记忆以捕捉更长的关系,可以决定何时遗忘
    • 误差可以根据输入的不同而不同

    在标准的RNN中,隐藏层的计算直接基于前一层的输出以及输入x:

    ht=f(W(hh)h(t1)+W(hx)xt)h_t=f(W^{(hh)}h_{(t-1)}+W^{(hx)}x_t)

    而GRU首先会基于当前输入和隐藏状态计算一个更新门(另一层):

    zt=σ(W(z)xt+U(z)ht1)z_t=\sigma (W^{(z)}x_t+U^{(z)}h_{t-1})

    再利用相同的方法不同的权值计算一个reset gate:

    rt=σ(W(r)xt+U(r)ht1)r_t=\sigma (W^{(r)}x_t+U^{(r)}h_{t-1})

    然后就可以得到与一般RNN之前不同的记忆内容:

    h~t=tanh(Wxt+rtUht1)\tilde h_t = tanh(Wx_t + r_t\circ Uh_{t-1})

    如果reset gate的元素为0,则会遗忘之前的记忆,只会存储新输入的信息。

    最后得到的隐藏层h_t为:

    ht=ztht1+(1zt)h~th_t = z_t \circ h_{t-1} + (1-z_t)\circ \tilde h_t

    从这里我们可以看出,update gate决定的是当前输入是否改变隐藏层状态。如果z_t为1,则h_t仅会复制前一层的状态,与当前输入无关。而reset gate则是控制记忆是否被遗忘或遗忘的多少,如果r_t为0,则之前层的记忆会被遗忘。

    用图示的方法更为直观:
    0_1531897658037_ca5b979d-bda7-480e-a4a8-39aa0512f0db-image.png


    GRU是如何改善梯度消失问题的?

    0_1531898121096_57aa0564-906b-448c-a5db-61b3e0999871-image.png

    GRU可以让网络剪掉不必要的连接,减少反向传播的深度。

    0_1531898257043_4e443e42-496d-460d-beab-0ca6caa64a27-image.png

    0_1531898303936_7729d00a-962d-4580-9dd8-3b4f9f81e1a2-image.png


    Long-short-term-memories (LSTMs)

    LSTM是一个比GRU更复杂的RNN模型,它允许修改每一个时间节点。

    • Input gate

      it=σ(W(i)xt+U(i)ht1)i_t = \sigma (W^{(i)}x_t+U^{(i)}h_{t-1})

    • Forget

      ft=σ(W(f)xt+U(f)ht1)f_t=\sigma(W^{(f)}x_t+U^{(f)}h_{t-1})

    • Output

      ot=σ(W(o)xt+U(o)ht1)o_t = \sigma (W^{(o)}x_t+U^{(o)}h_{t-1})

    • New memory cell

      c~t=tanh(W(c)xt+U(c)ht1)\tilde c_t = tanh(W^{(c)}x_t+U^{(c)}h_{t-1})

    由此得到的最终memory cell为:

    ct=ftct1+itc~tc_t = f_t \circ c_{t-1} + i_t \circ \tilde c_t

    最终的隐藏层状态为:

    ht=ottanh(ct)h_t = o_t \circ tanh(c_t)

    LSTM模型的可视化如下

    0_1531899702873_fcadea37-8490-4960-a8c2-52e4b6363ee9-image.png
    0_1531899727583_8a5596bb-3d69-4a4e-9e5f-e7a83d023117-image.png

    图片来自Understanding LSTMs,推荐阅读。


    LSTM可以作为所有序列问题的优秀模型

    • 非常powerful,特别是网络更深时。
    • 对于大量数据很有用

    Bidirectional RNNs (双向RNN)

    文本分类时,我们同时需要前后文,因此使用双向RNN可以同时存储前后文信息。
    0_1531900511334_b5777b87-f6d1-40f0-b832-21f6b8cee247-image.png

    更深层的双向RNN如下:

    0_1531900574873_1b1a2736-2ca0-410c-8f72-c481ae530eb4-image.png


    0_1531900643367_196f9718-db1e-4c4a-8edc-18f69f4e93e8-image.png



  • Midterm Review





  • Lecture10 - Machine Translation, Sequence-to-sequence and Attention

    机器翻译、seq2seq模型和注意力机制

    到这里,课程已经过半了,剩余的课程几乎都是由项目驱动,我们将会学到NLP+DL的研究前沿。课程也会变得更高层:不再有梯度计算、有时我们只会对一些知识做概述。
    这次的课程包含NLP深度学习的两项核心技术——seq2seq & Attention


    Machine Translation

    机器翻译是将一个语言的句子翻译成另一语言的任务。
    例如将I love machine learning.翻译成我爱机器学习。

    早期机器翻译

    早期的机器翻译更多的是基于语言规则、使用词典来构建。


    1990s-2010s: Statistical Machine Translation

    90年代到2010年左右,机器学习多基于统计。
    传统统计机器翻译的核心思路是:从数据中学习一个概率模型,使用贝叶斯找到概率最大的句子:

    y^=argmaxyP(yx)=argmaxyP(xy)P(y)\hat y = argmax_yP(y|x)=argmax_yP(x|y)P(y)

    其中P(x|y)为翻译模型,指导词和短语翻译,训练数据为双语数据。P(y)为语言模型,指导如何写出好的翻译句子,训练数据为目标翻译语言。

    那么,我们如何学习一个P(x|y)模型呢?
    首先,我们需要大量的双语模型。
    接着,我们需要的翻译模型其实是

    P(x,ay)P(x,a|y)

    其中a用于对齐,因为中英文中语言的顺序是不一样的,例如Chinese eat with chopsticks.的中文为中国人用筷子吃饭,这两句话的词语并不是按顺序对应的。


    对齐

    • 有一些词在另一语言中并没有与它对应的单词
      0_1531902906795_63dc734a-6477-429e-aa24-1593559016f0-image.png

    • 有一些词可以翻译为多个词
      0_1531902949831_3465d240-c405-44cc-954a-48822b3b3170-image.png

    • 也有一些词可以由多个词翻译成
      0_1531903000888_a072845d-99fd-491a-8c45-0dda387435e1-image.png

    • 甚至有多对多的情况出现
      0_1531903033268_b7889433-863d-487f-abbc-c86afcdc51a6-image.png


    对齐如此复杂,怎么训练一个翻译模型呢?

    • 可以举出所有y与x的配对组合然后计算概率吗? -- 当然不行,计算代价太高

    我们可以使用一个启发式搜索算法来逐渐构造翻译模型,忽略概率低的假设。
    0_1531903392517_b11dd4f1-9b2c-4ec9-a39e-2952555e9c50-image.png

    就算这样也会有非常多的组合。
    0_1531903432405_84ac7323-0373-4ba0-8d6d-9e3dc9b4c256-image.png


    之前的课程中,我们说到用传统机器学习做文本分类很困难,于是出现了深度神经网络。现在在机器翻译中,我们也要喊出同样的一句话:

    Oh! Neural Network!

    0_1531903694239_e175447c-6548-4485-9fbc-052f78cd47b0-image.png

    Neural Machine Translation

    NMT是一种只使用一个神经网络进行机器翻译的方法。它的神经网络模型叫做sequence-to-sequence(简写为seq2seq),包括两个RNN。

    0_1531903873760_5abb931b-a2d4-4767-b40c-604d80e021c5-image.png

    网络由两个RNN组成,Encoder RNN产生一个对原句子的编码,Decoder RNN通过Encoder RNN的输出编码来产生目标句子。

    seq2seq是一种条件语言模型(Conditional Language Model):

    • decoder用于预测翻译句子的下一个词,因此它属于Language Model
    • 由于预测仍然由输入的原句子决定,因此它是有条件的Conditional

    0_1531904424331_36693ff3-15fd-4092-9dca-a46079b253d0-image.png


    训练一个seq2seq模型

    0_1531904501538_6abb98a6-a3ec-4a33-bde5-7cbf0e230038-image.png

    Greedy Decoding
    下图所示的就是greedy decoding(将每一部中输出的词都放入翻译结果):
    0_1531904832213_6f009516-b3a2-4370-ae3d-269f2e4467d2-image.png

    但是这样做是有问题的:

    • 不能撤销决定。例如有一句法语les pauvres sont démunis (the poor don’t have any money),翻译过程如下:
      • the ___
      • the poor___
      • the poor are___

    那是否有更好的方式?
    => 使用beam search来寻找几个可能的假设并选出最合适的一个。


    Beam search decoding

    我们的目的是寻找到可能性最大的y:
    0_1531905226147_3cd130ec-3942-401b-bc94-c48fa3e1c651-image.png

    我们可以尝试所有的可能,但是这样开销太大了。

    Beam search: 在decoder的每一个时间节点,保持跟踪前k个最可能的翻译部分

    • k叫做beam size(通常在5-10)
    • 不保证能找到最佳结果
    • 但是要高效得多

    0_1531905480428_a598266f-274c-4058-b20e-5d986ceb0135-image.png


    Neural Machine Translation的优点

    • 有更好的效果:得到的结果更流畅,对上下文的理解更好,对近义短语的理解更好。
    • 只需要一个单一神经网络就可以完成端到端翻译。
    • 需要更少的人类工程:不需要特征工程,对所有语言翻译可以使用同样的方法。

    NMT的缺点

    • 可解释性差:难以debug
    • 很难控制NMT的结果:
      • 不能轻易地指定翻译规则
      • 安全问题

    NMT是NLP深度学习中最大的成功

    • 2014:第一篇seq2seq论文发表
    • 2016:Google翻译从SMT切换到NMT

    这样的变化,将每年成百上千工程师构建的SMT切换成了屈指可数的工程师在几个月内即可构建完成的NMT。

    那么,机器翻译问题解决了吗?
    显然没有!

    机器翻译仍然有许多问题需要解决:

    • 在词典外的词
    • 训练和测试数据的领域不同
    • 长文本语境的保留
    • 数据量少的翻译语料

    0_1531906312173_224be2f4-9c76-4643-b04e-0154a584d92f-image.png
    0_1531906341250_d1c6be99-bce2-4896-907d-97d2a3d719fe-image.png
    0_1531906351852_ab5c41bb-54a7-49d3-a75d-329d1e091406-image.png


    2017年,在机器翻译领域有一篇重磅论文,Attention Is All You Need
    下面介绍机器翻译邻域新的改进方法:注意力机制

    ATTENTION

    seq2seq的瓶颈

    0_1531906589720_f4528885-1b80-41ec-8543-431bb17408b8-image.png

    Encoder需要捕捉原句子中的所有信息 - 信息瓶颈。


    Attention

    注意力机制提供了对于信息瓶颈的解决方案。它的核心思想是:在decoder的每一个时间节点,只专注于原序列的一个特定部分。

    我们先使用图表的形式了解attention:

    Attention首先对encoder输出的每一个节点计算一个attention score,再使用softmax得到每个点的概率(Attention distribution),由概率得到注意力输出,与decoder的hidden state结合得到当前输出。以下为decoder每一时间节点的状态图。

    0_1531906945204_00db08c3-263f-48fd-b2b4-83847d10b261-image.png
    0_1531907117174_6683661e-0398-4d76-9edd-cef8406ce3be-image.png
    0_1531907128483_e51448fd-04f2-420b-8d0b-77e5d99a7013-image.png
    0_1531907143847_35eaeb4a-eee0-470d-928c-c2de051f9a13-image.png
    0_1531907157485_11d1feae-0e7a-4cac-b47d-b3b0a26a932c-image.png
    0_1531907172171_f251b75d-b383-4811-849e-abad125899d0-image.png


    下面为公式:

    • 隐藏状态

    h1,h2,...,hnRhh_1,h_2,...,h_n \in R^h

    • 在时间节点t,有decoder隐藏状态

    stRNs_t \in R^N

    • 在这一节点,有attention scores:

    et=[stTh1,stTh2,...,stThN]RNe^t = [s_t^Th_1,s_t^Th_2,...,s_t^Th_N] \in R^N

    • 给attention score套一层softmax得到attention distribution

    αt=softmax(et)RN\alpha^t=softmax(e^t)\in R^N

    • αt\alpha^t乘以对应的encoder的hidden states来计算输出的a_t

    at=i=1NaithiRha_t = \sum^N_{i=1}a_i^th_i\in R^h

    • 最后将a_t与s_t concat到一起

    [at;st]R2h[a_t;s_t]\in R^{2h}


    Attention 的优点

    • Attention对NMT的效果有重大提升
      允许decoder专注于确定的部分很有用
    • Attention解决了NMT的瓶颈
      Attention允许decoder直接观察到原句子,解决了瓶颈
    • Attention对缓解梯度消失有帮助
      提供了到达很远的状态的捷径
    • Attention有一定的可解释性
      • 我们可以通过attention distribution看到decoder正在关注什么
      • 我们通过attention直接得到了对齐信息
      • 这一点很酷,因为我们从没有明确地训练一个对齐系统
      • 网络自己学到了对齐
        0_1531911099361_ed2f8f93-e779-4603-af7e-4fd47535d9be-image.png

    seq2seq用途广泛

    seq2seq不只是适用于机器翻译,在很多领域也有很好的效果:

    • Summarization (long text -> short text)
    • Dialogue (previous utterances -> next utterance)
    • Parsing (input text -> output parse as sequence)
    • Code generation (natural language -> Python code)


  • Lecture11 - Paying attention to attention and Tips and Tricks for large MT

    Attention是一项通用的深度学习技术,它不仅应用于seq2seq中,今天我们还将介绍attention的更多应用。

    Attention

    Attention是一个根据输入向量序列计算元素的权值的技术。

    几种Attention的变体

    • 上一课中提到的attention,我们有encoder 隐藏状态

      h1,...,hnRd1h_1,...,h_n\in R^{d_1}

      有decoder 隐藏状态query

      sRd2s\in R^{d_2}

    • Attention总是从attention scores(e)中计算得到attention output a,例如:

      α=softmax(e)RN\alpha = softmax(e) \in R^N

      a=i=1NαihiRd1a = \sum^N_{i=1}\alpha_ih_i \in R^{d_1}

    • 但其实,我们有很多种方式计算attention scores(e)

    计算e的几种方式

    通过encoder与encoder的hidden states(hRd1h \in R^{d_1}, sRd2s \in R^{d_2}),我们有以下几种方式计算attention scores:

    • 基本的点乘attention(Basic dot-product attention)

      ei=sThiRe_i = s^Th_i\in R

      • 注意这里e和s的向量大小要是相同的
      • 我们上节课说的attention就是这种计算方式
    • 中间乘上权值矩阵(Multiplicative attention)

      ei=sTWhiRe_i = s^TWh_i \in R

      • WRd2×Rd1W \in R^{d_2 \times R^{d_1}}为权重矩阵
    • h和s分别乘不同的矩阵后相加(Addictive attention)

      ei=vTtanh(W1hi+W2s)e_i = v^Ttanh(W_1h_i+W_2s)

      • 其中,W1Rd3×d1W_1 \in R^{d_3 \times d_1}, W2Rd3×d2W_2 \in R^{d_3 \times d_2}为权重矩阵,vRd3v \in R^{d_3}为权重向量

    更多信息,可以查看Deep Learning for NLP Best Practices


    Attention的应用:Pointing to words for language modeling

    思路:softmax与pointer混合

    Pointer Sentinel Mixture Models
    0_1531969078357_ed374125-8743-439b-847e-4116f2d92987-image.png

    Pointer-Sentinel Model

    0_1531969480755_579e91ae-52a0-449f-8b7b-7d3948651f49-image.png
    0_1531969598076_9333d84e-15a7-4491-b058-3897a7021de1-image.png


    Attention应用:Intra-Decoder attention for Summarization

    A Deep Reinforced Model for Abstractive Summarization
    0_1531969822013_97f8f7a1-cc2c-4e16-b872-29038f055e0e-image.png


    Attention应用:Similar Seq2Seq Idea as in Translation

    0_1531969984139_64e699bd-f0a7-4e54-ab82-b53f41c3407d-image.png


    还有很多attention的应用,这里不一一列举了。现在,我们先介绍一些能够提升机器翻译效果的tips & tricks。

    将NMT拓展到更多语言

    • 光是复制原理还不够

      • Transliteration: Christopher ↦ Kryštof
      • Multi-word alignment: Solar system ↦ Sonnensystem
    • 需要准备一个大词库

      • 丰富的语法
        • nejneobhospodařovávatelnějšímu - Czech = “to the worst farmable one”
        • Donaudampfschiffahrtsgesellschaftskapitän – German = Danube steamship company captain
      • 非正式的拼写: goooooood morning !!!!!

    解决大词表问题

    大词表加大了softmax的计算难度
    0_1531970591328_5769e591-9084-4a96-9ac0-ac5b17a292a0-image.png

    在早期的MT中,会使用较小的词表,但这样并不能说解决了问题:
    0_1531970719921_d193bdad-dcc9-48df-8cc5-6d87051c95c3-image.png

    另一种想法是缩小softmax大小,但这样对gpu不友好
    0_1531970814765_cfe20eb7-fbdf-4eff-9eae-27c776e90b33-image.png


    Large-vocab NMT

    这个方法的思路是,首先在大词表训练集的子集下训练模型,再在测试时添加一些技巧处理那些出现很少的词。

    Training
    每次都训练一个比原词库小很多的子集,训练多个子集
    0_1531971098389_5829a8dc-34e8-4a22-ba16-a692ff34a0fa-image.png

    例如,每次选取子集大小为5:
    0_1531971191735_0a09c625-b721-4704-80ad-692f2be8e642-image.png
    0_1531971217240_da92c5e5-7488-4495-9840-f4dcb47141cb-image.png
    0_1531971225528_6a0bf7c8-51a9-4f29-afc0-7189520b3018-image.png

    Test

    • 取k个出现频率最高的词 - unigram prob
      de, , la . et des les …
    • 每个词取k'个翻译候选单词
      0_1531971395512_2392f140-ab51-47b9-80a4-f135fe9ca049-image.png

    0_1531971502392_14d48027-e71e-47ca-99cf-b92ac9327078-image.png


    之后还说到了很多解决大词库的思路

    Byte Pair Encoding

    这种方法试图用分词的思想去找出所有有意义的“词素”,其统计方法说来也简单,就是在词频词表里统计所有的ngram组合作为新的更长的ngram:
    0_1531971726609_852ea8ad-544b-4c2d-8a8a-716651065d17-image.png


    字符级别的LSTM(character-based LSTM)

    0_1531971812894_084f1303-8c0d-479c-b73b-995c01f7c6eb-image.png


    Hybrid NMT

    另有一些混合动力的NMT,大部分情况下在词语级别做翻译,只在需要的时候从字符级去翻译。这个系统的主体是词语级别的LSTM,先在词语级别上做常规的柱搜索,当出现unknown词时,切换到char级别做柱搜索:
    0_1531971894974_b398431f-c24f-4d03-942e-0210a5760f84-image.png

    BLEU得分
    0_1531972018666_e8ff3495-c04e-4fb4-b41d-a2a7187330c4-image.png



  • Lecture12 - Transformer Networks and Convolutional Neural Networks

    Problems with RNNs = Motivation for Transformers

    • 连续计算阻止了平行化
      0_1531978477143_6cc314db-c754-45bc-8d33-29d728231ad1-image.png
    • 尽管有GRU和LSTM,RNN仍然需要attention机制来处理长距离的关系 - 状态间需要关系计算的长度随序列的增加而增加
    • 但,如果attention能使我们得到任意状态,那么其实我们并不需要RNN?

    Transformer概述

    • Sequence-to-sequence
    • Encoder-Decoder
    • Task: machine translation with parallel corpus(平行语料)
    • Predict each translated word
    • Final cost function is standard cross-entropy loss on top of a softmax classifier

    0_1531978728127_05dd8915-607d-476b-b0a5-20fa417c1cfb-image.png


    在这里不得不说这篇非常有名的论文,Attention Is All You Need,Transformer也是出自这篇论文。

    Transformer Basics

    我们首先定义一个transformer的基础部分:attention layers

    Dot-Product Attention

    这里我们使用的是Dot-Product Attention。

    • 输入:query q和指向输出output的key-value对的集合
    • query, keys, values, output都是向量
    • output是values的权重计算结果,其中
      • 每一个value的权重都由一个内部产生的query以及相应的key计算出
      • queries和keys都有相同的维度d_k, value的维度为d_v

    A(q,K,V)=ieqkijeqkjviA(q, K, V) = \sum_i\frac {e^{q\cdot k_i}}{\sum_je^{q\cdot k_j}}v_i

    当我们有query的集合Q,Q就是一个矩阵,上式变成:

    A(Q,K,V)=softmax(QKT)VA(Q,K,V) = softmax(QK^T)V

    0_1531981013480_49e52467-686b-47d2-9bcf-c0086b922f50-image.png


    Scaled Dot-Product Attention

    这里出现了一个问题,当d_k特别大时,q^Tk的变化就会很大,softmax中的一些值就会变得很大,softmax也就会变得很大,因此它的梯度会变小。

    解决方法
    里面除以query/key向量的长度的平方根来缩小softmax内值的大小。

    A(Q,K,V)=softmax(QKTdk)VA(Q,K,V) = softmax(\frac{QK^T}{\sqrt{d_k}})V

    0_1531981353252_360e50ee-4e0e-4ae0-a765-c9922b780b8f-image.png


    Self-attention and Multi-head attention

    • 输入的词向量可以是queries,keys,values
    • 换言之,词向量间互相选择
    • Word vector stack = Q = K = V

    问题:只有一种方式能使词之间互相影响
    解决方式:Multi-head attention

    • 首先将Q, K, V放入h个W矩阵的空间中
    • 再应用attention,将attention的输出concat到一起,然后经过一个线性层。

    0_1531982281168_8eb71577-ccb9-4ada-a5d0-f2aa5e7afaeb-image.png

    0_1531982335988_7f1f920d-d427-4317-be59-3047b27a1338-image.png


    Complete transformer block

    • 每一个block有两个"sublayers"
      1. Multihead attention
      2. 2 layer feed-forward Nnet (with relu)

    0_1531982703822_1140e30f-f126-4fe2-8c3a-38aca3441988-image.png

    这两层之间还包括:

    • Residual(short-circuit) connection and LayerNorm
      • LayerNorm(x + Sublayer(x))
      • Layernorm改变输入,将输出的方差为1,均值为0

    0_1531983029908_91da9883-4131-4021-a265-e93ec44dc1d3-image.png
    这部分Layer Normalization可见这篇论文:
    Layer Normalization by Ba, Kiros and Hinton


    Encoder Input

    • 词的表示使用的是byte-pair encodings(见上一篇lecture)
      0_1531983249082_c4c62feb-9b45-4731-be99-d2742a8cb6f2-image.png
    • 同时也加入了positional encoding,这样同样的词在不同的位置会有不同的表示。
      0_1531983357748_ede1e158-248a-4702-8c75-b22c6d26ff2e-image.png

    Complete Encoder

    • 在Encoder的每一块中,我们使用了与前一层相同的Q,K,V
    • blocks重复6次
      0_1531983562579_22cb5672-4ea3-4aad-9798-5ea5c832f795-image.png

    layer5的attention可视化

    0_1531984015977_8bc1274f-9225-46f0-a94c-f15a5a84f97a-image.png
    可以看到,词开始注意到了其它词。

    attention可视化: 隐藏的指代分辨

    0_1531984119578_27cd9bea-a7f4-4fbf-8eb6-ff170aff6f03-image.png
    在layer5中,it's对它所指代的词law的attention已经很大了。


    Transformer Decoder

    0_1531978728127_05dd8915-607d-476b-b0a5-20fa417c1cfb-image.png

    • decoder中不再是2个sublayer
    • masked decoder self-attention on previously generated outputs:
      0_1531984978584_b9ba5342-b561-4bb7-b470-445a7000e484-image.png
    • Encoder-Decoder的attention,query来自前一层decoder layer,keys和values来自encoder的输出
      0_1531985086237_0e126a9d-ed4e-452c-8a53-69b7c18df43c-image.png
    • blocks也会重复6次

    Tips and tricks of the Transformer

    在All Attention论文中提到的一些特性:

    • Byte-pair encodings
    • Checkpoint averaging
    • ADAM optimizer with learning rate changes
    • Dropout during training at every layer just before adding residual
    • Label smoothing
    • Auto-regressive decoding with beam search and length penalties
    • 总之,模型很难部署,同时不像LSTM一样,all attention很难在其他block结构中表现好

    CNN

    • CNN的主要思想:如果我们为语料中的每种可能的短语计算多种向量会怎样?
    • 不管怎样,短语是符合语法规则的,CNN得到的短语也是符合的
    • 示例:the country of my birth可以计算的向量有:
      the country, country of, of my, my birth, the country of, country of my, of my birth, the country of my, country of my birth
    • 然后把这些向量分组
    • 这样做从语言学上来说不是很可信,但是计算非常快

    什么是卷积

    这里就不做介绍了
    0_1531986015212_475231f2-25ca-40d6-8e2a-5c12b4264a04-image.png

    单层CNN - 卷积层

    • 使用了一层卷积层和池化层的简单结构

    • 基于"Convolutional Neural Networks for Sentence Classification" (TextCNN)

    • Word vectors

      xiRkx_i \in R^k

    • Sentence(就是直接把词向量concat到一起)

      x1:n=x1x2...xnx_{1:n}=x_1\oplus x_2 \oplus ... \oplus x_n

    • Concatenation of words in range:

      xi:i+jx_{i:i+j}

      就是把j个词的向量加在一起做卷积

    • Convolutional filter:

      wRhkw \in R^{hk}

      这里用一个大小为h的window来扫过句子

    • 卷积核可以是2或者更高,比如3:
      0_1531986605446_628e9077-83f4-4f96-a06e-cdd0395fe1c2-image.png

    • 计算得到卷积层的值

      ci=f(WTxi:i+h1+b)c_i = f(W^Tx_{i:i+h-1}+b)

    • 把多个c放到一个数组中,构成一个feature map

      c=[c1,c2,...,cnh+1]Rnh+1c = [c_1, c_2,...,c_{n-h+1}] \in R^{n-h+1}

      0_1531987240258_cfed3270-b0a4-4ca4-bdf6-3a30abe9227c-image.png


    池化层

    • max-over-time pooling layer

    • 思想:从feature map

      c=[c1,c2,...,cnh+1]Rnh+1c=[c_1,c_2,...,c_{n-h+1}]\in R^{n-h+1}

    捕捉最重要的特性

    • 池化单个数:

      c^=max{c}\hat c = max\lbrace c\rbrace

    这样就可以得到卷积层提取出的特征了,但我们希望得到更多的特征,怎么办?


    Multiple filters

    • 使用多个filter size来构建多个大小的窗口
    • 因为用的是max-pooling,c的长度不受限制,因此我们可以使用多个不同的size,就像n-gram一样。

    Multi-channel(多通道) 思想

    TextCNN有几种:

    • CNN-rand: 句子中的的word vector都是随机初始化的,同时当做CNN训练过程中需要优化的参数;
    • CNN-static: 句子中的word vector是使用word2vec预先对语料库进行训练好的词向量表中的词向量。且在CNN训练过程中作为固定的输入,不作为优化的参数;
    • CNN-non-static: 句子中的word vector是使用word2vec预先对语料库进行训练好的词向量表中的词向量。在CNN训练过程中作为固定的输入,做为CNN训练过程中需要优化的参数;

    这里说的是用word2vec训练的static TextCNN

    • 使用预训练的词向量进行初始化(Word2Vec或Glove)
    • 使用两个CNN copies
    • 只反向传播一个CNN,保持另外一个为'static'
    • 两个通道的结果都加到c_i中,再进行max-pooling

    CNN层之后进行分类

    多个filter得到的max-pooling结果构成一个向量:

    z=[c^1,...,c^m]z = [\hat c_1,...,\hat c_m]

    最后再加上softmax层得到归一化概率:

    y=softmax(W(s)z+b)y = softmax(W^{(s)}z+b)


    TextCNN

    0_1531988312389_127b1e94-6c76-4208-a373-1adb3024183c-image.png

    这是Kim在2014年论文中提到的TextCNN结构。


    让模型效果更好的tricks - Dropout

    • 思想:随机将隐藏层中的部分特征移除

    • 随机构建一个伯努利矩阵r。r可以控制哪些特征要被drop

    • 在训练的时候删除部分特征

      y=softmax(W(s)(rz)+b)y = softmax(W^{(s)}(r\circ z)+b)

    • 因此在训练的时候,只会通过r中等于1的部分影响梯度进行反向传播

    • 为什么要Dropout?
      可以防止过拟合
    • 来源:Paper: Hinton et al. 2012: Improving neural networks by preventing co-adaptation of feature detectors

    另一个trick - regularization

    • 使用l2正则来正则化每个分类的权重向量,使其适配一个超参数s
    • 如果 $$||W_c^{(s)}|| > s$$, 将其缩小至s
      Wc(s)=s||W_c^{(s)}|| = s
    • 这种方法不是很常见

    kim的TextCNN中的一些超参数

    • 非线性激活函数: Relu
    • Window Filter sizes h = 3, 4, 5
    • 每个filter size有100个feature map
    • Dropout p = 0.5
    • L2正则的softmax约束超参数s = 3
    • SGD training的batch size为50
    • 词向量:预训练的word2vec,维度为300

    0_1531990389588_8f1e53c6-2d95-45ee-84a8-e46c9c46c9a7-image.png


    0_1531990412321_94050c5d-b0b6-4b9c-b36f-6c877f3c26a9-image.png



  • Lecture13 - Coreference Resolution

    What is Coreference Resolution

    分辨语言中代词所指的实体。

    0_1532587105840_329f86f1-c25f-4fa5-8362-e63fcfbe4bb5-image.png

    0_1532587193511_ea6b3604-82e3-49e6-8663-ba5b3b5dc1b3-image.png

    0_1532587285920_16929b79-e0ef-4399-9726-c36af57976ce-image.png

    Applications

    • Full text understanding
      • information extraction, question answering, summarization, ...
    • Machine trainslation
      • 语言中有很多隐藏的信息如性别代词数字等
        0_1532587512944_34d6868f-5828-4366-b77f-98f555f39ba0-image.png
    • Dialogue Systems
      • "Book tickets yo see James Bond"
      • "Two tickets for the showing at three"

    Coreference Resolution非常难

    • “She poured water from the pitcher into the cup until it was full”
    • “She poured water from the pitcher into the cup until it was empty”
    • The trophy would not fit in the suitcase because it was too big.
    • The trophy would not fit in the suitcase because it was too small

    以上的这些例子叫做 Winograd Schema

    • WS最近被提议作为图灵测试中的一项
      • Turing test: 人类无法分辨出聊天的人是人类还是机器,则说明我们建立了AI系统
    • 如果我们完全解决了coreference问题,可能我们就解决了AI问题

    Coreference Resolution的两步

    1. 检测出代词 (easy)
      “[I] voted for [Nader] because [he] was most aligned with [[my] values],” [she] said

      • 代词是可以嵌套的
    2. 给代词聚类 (hard)

      • I, my, she
      • Nader he
      • my values

    Mention Detection

    Three kind of mentions:

    1. Pronouns
      • I, your, it, she, him, etc.
    2. Named entities
      • People, places, etc.
    3. Noun phrases
      • "a dog", "the big fluffy cat stuck in the tree"

    Use other NLP systems for detection

    1. Pronouns
      • Use a part-of-speech tagger
    2. Named entities
      • Use a NER system (like hw3)
    3. Noun phrases
      • Use a constituency parser (next lecture)

    后面有点无聊,都不写了



  • Lecture14


 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

与 Dian 的连接断开,我们正在尝试重连,请耐心等待