<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>LSTM on bitJoy</title><link>https://bitjoy.net/tags/lstm/</link><description>Recent content in LSTM on bitJoy</description><generator>Hugo -- 0.148.2</generator><language>en</language><lastBuildDate>Fri, 30 Aug 2019 17:45:12 +0800</lastBuildDate><atom:link href="https://bitjoy.net/tags/lstm/index.xml" rel="self" type="application/rss+xml"/><item><title>【论文速读】End-to-End Differentiable Learning of Protein Structure</title><link>https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/</link><pubDate>Fri, 30 Aug 2019 17:45:12 +0800</pubDate><guid>https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/</guid><description>&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/ProteinStructurePrediction.png">&lt;/p>
&lt;p>首先放出本文的Hightlights：&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Highlights.png">&lt;/p>
&lt;p>蛋白质三级结构预测一般分为两种方法，一种是基于模板的预测方法（Template-Based Modeling, TBM），另一种是从头测序方法（Free Modeling, FM）。TBM方法目前已经能达到比较好的预测精度，但并不是所有蛋白都有同源模板，当模板蛋白和目标蛋白的相似性低于某个阈值时，TBM方法的性能就会比较差。而传统的FM方法，需要过多的人工特征，使得整个流程非常复杂。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Figure1.png">
&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Rosetta.png">&lt;/p>
&lt;p>作者在一次报告中，将传统的蛋白质结构预测算法（上图）比作10年前的图像识别算法（下图），虽然10年前的图像识别算法也能达到比较好的性能，但需要很多人工设计的特征，比如SIFT特征等，不够简洁漂亮。随着深度学习的兴起，现在图像识别不再需要人工设计特征，只要搭建好神经网络，输入原始图片即可完成识别和分类，性能比之前的人工方法还要好。所以，作者也希望能提出一个简洁、纯深度学习的模型来预测蛋白质的三级结构。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Pascal-voc-2009.png">&lt;/p>
&lt;p>本文的模型（Recurrent Geometric Networks, RGN）从宏观上来说就如博客开篇的图片所示，非常的简洁漂亮，输入是蛋白质的一维序列，经过神经网络，输出是每个氨基酸残基的三个扭转角，然后再通过三维重构，得到蛋白质的笛卡尔坐标。&lt;/p>
&lt;p>更具体来说，RGN包括三个部分，分别是模型预测、三维重构和误差反向传播，下面分别介绍这三个部分。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Figure2.png">&lt;/p>
&lt;p>模型预测是上图的左下角部分，即输入是蛋白质序列，输出是每个氨基酸残基的三个扭转角。因为每个氨基酸对应三个扭转角输出，每个氨基酸和其上下文的氨基酸有关联，所以使用双向LSTM最合适不过了。Bi-LSTM没什么好讲的，关键讲讲其模型的输入和输出。输入部分，作者把每个氨基酸编码成一个41维的向量，如上图所示，其中包括20维氨基酸的one-hot向量（因为只有20种氨基酸）、20维PSSM位置向量和1维具体的位置信息。其中的PSSM位置向量可以理解为这个位置上的不同氨基酸的概率分布，由于有20种氨基酸，所以PSSM向量维度也是20。网上没有找到氨基酸的PSSM向量示例，找到一个DNA的，如下图，每个位置上，字母越大表示出现该核苷酸的概率越大，换成氨基酸是类似的道理。所以整个网络的输入，除了PSSM矩阵，没有任何人工设计的特征，已经很优雅了。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/mef2_seq_logo.png">
&lt;a href="https://davetang.org/muse/2013/10/01/position-weight-matrix/">https://davetang.org/muse/2013/10/01/position-weight-matrix/&lt;/a>&lt;/p>
&lt;p>Bi-LSTM的输出是三个扭转角，但并不是三个实数这么简单。作者首先把整个拉氏图平面聚类，比如聚类成m=60个点，然后就把输出离散化成60类的分类问题。分类输出采用Softmax归一化，这样就会得到60类的概率分布，如RGN网络图最右边的子图所示。60类的概率分布再通过加权平均的方式得到最终的三个扭转角的实数值。我很好奇为什么需要经过一个离散再加权平均的方法，Bi-LSTM直接回归输出三个扭转角的实数不是更省事吗？&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Cluster2Alphabet.png">&lt;/p>
&lt;p>预测得到三个扭转角之后，进入RGN的第二个阶段，就是三维重构，在RGN网络图的左上角。三维重构说起来也简单，就是根据每个氨基酸残基的三个扭转角，重构出蛋白质的三维结构。由于常规的蛋白质三维结构坐标系是笛卡尔坐标系（直角坐标系），所以需要把扭转角坐标转换为笛卡尔坐标，以便于求解误差。这个部分作者没有细说，因为是另一篇论文：&lt;a href="https://onlinelibrary.wiley.com/doi/full/10.1002/jcc.25772">Parallelized Natural Extension Reference Frame: Parallelized Conversion from Internal to Cartesian Coordinates&lt;/a>。&lt;/p>
&lt;p>最后就是怎样求解误差以及误差反向传播了。这个也比较有意思，想想看，对于一条长为L的蛋白质序列，给定预测的三维结构和真实的三维结构，怎样计算它们之间的误差。不能直接对应坐标相减，因为有可能两个坐标系的坐标原点不一样。作者的方法是这样的：对于预测结构，求每两个氨基酸的距离差，就是\(\tilde{d}_{j,k}\)；对于真实结构，也做类似的操作。这样做的好处是抹掉了坐标原点的影响，用两点之间的相对距离来表示三维结构。然后，对真实的\(\tilde{d}_{j,k}^{(exp)}\)和预测的\(\tilde{d}_{j,k}^{(pred)}\)再求二范数\(||D||_2\)，最后除以长度进行归一化，就得到了误差dRMSD。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/dRMSD.png">&lt;/p>
&lt;p>上述dRMSD误差相比于之前领域内常用的TMscore，好处就是可微分，可自动求导，可梯度下降了；另外，如上所述，dRMSD不要求预测结构和真实结构进行对齐；但是有一点是dRMSD对size敏感，而且不能识别镜面对称这种错误结构，比如左手和右手的结构是镜面对称的，如果真实结构是左手，但模型预测成了右手，dRMSD是检测不到这种错误的。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/dRMSD.vs.TMscore.png">&lt;/p>
&lt;p>模型介绍完毕，训练和测试数据集来自CASP竞赛。作者把每一届CASP比赛的数据集作为测试集，从CASP7~CASP12；每一届比赛之前公布的所有PDB数据集（seq, structure）作为对应测试集的训练集。其中，CASP11分出一部分作为验证集，用来优化网络超参数。&lt;/p>
&lt;p>测试结果如Table 1所示，可以看到，在没有模板的FM类别中，本文的RGN预测误差是最小的；在有模板的TBM类别中，RGN的性能几乎垫底，当然这里参与评测的都是当届比赛中Top-5的模型，所以RGN和这5个模型比是垫底，但差距是很小的。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Table1.png">&lt;/p>
&lt;p>另外，作者提到，在TBM类别的数据集中，CASP的参赛模型比较依赖模板的质量。具体来说，对于真实的结构，如果模板结构和真实结构误差很小（y轴），则模型的预测结构和真实结构的误差也很小（x轴），这两个变量成一定的线性相关关系（第一行）。而对于本文的RGN，则没有这种相关关系，说明RGN一视同仁，不会受模板质量的影响，因为RGN是纯深度学习的模型，根本就没有用到模板。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Figure4.png">&lt;/p>
&lt;p>在预测速度上，RGN虽然需要训练几周甚至上月的时间，但预测速度是毫秒级别的，是评测的几个模型中最快的。快速的RGN能使一些新的应用成为可能，比如药物发现、蛋白质设计等。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-30-paper-reading-end-to-end-differentiable-learning-of-protein-structure/Table2.png">&lt;/p>
&lt;p>最后，总结一下本文的主要工作、创新点和局限性：&lt;/p>
&lt;p>三个特点：&lt;/p>
&lt;ul>
&lt;li>torsional angles，局部信息&lt;/li>
&lt;li>geometric units ，全局信息&lt;/li>
&lt;li>dRMSD，局部+全局&lt;/li>
&lt;/ul>
&lt;p>创新点：&lt;/p>
&lt;ul>
&lt;li>简洁，Model replaces structure prediction pipelines with one mathematical function&lt;/li>
&lt;li>另辟蹊径，纯deeplearning，不依赖structural templates、co-evolutionary information、energy model等，本文预测融合了本文方法和领域知识的新模型有望解决蛋白质结构预测问题&lt;/li>
&lt;/ul>
&lt;p>局限性：&lt;/p>
&lt;ul>
&lt;li>依赖PSSM矩阵&lt;/li>
&lt;/ul>
&lt;p>本文作者来自哈佛医学院系统药理学实验室，文章只有作者一个人，很了不起了。哈佛医学院的另一个教授评价作者：“AlQuraishi 研究的特点在于，一名埋头在哈佛医学院和波士顿生物医学社区丰富研究生态系统中的研究人员，居然能够在计算机科学最热门的领域里抗衡谷歌等巨头。——Peter Sorger”，太棒了，我也想做这样的研究。&lt;/p></description></item><item><title>CS224N（2.7）Question Answering</title><link>https://bitjoy.net/posts/2019-08-04-cs224n-0207-question-answering/</link><pubDate>Sun, 04 Aug 2019 15:45:07 +0800</pubDate><guid>https://bitjoy.net/posts/2019-08-04-cs224n-0207-question-answering/</guid><description>&lt;p>这节课的内容比较简单，是问答系统（Question Answering, QA）的入门介绍。&lt;/p>
&lt;h1 id="qa简介">QA简介&lt;/h1>
&lt;p>首先，为什么需要QA？目前各大搜索引擎对于一个查询，给出的都是一个结果列表。但是很多查询是一个问题，答案也往往比较确定，比如“现任美国总统是谁？”，此时，返回一堆结果列表就显得太过啰嗦了，尤其是在手机等移动设备上搜索时，简单的给出回答也许会更好一些。另一方面，智能手机上的助手如Siri、Google Now之类的，用户期望的也是简洁的答案，而不是一堆网页列表。&lt;/p>
&lt;p>QA系统的组成主要有两个部分，一部分是根据问题检索到相关的文档，这部分是传统的信息检索的内容；另一部分是对检索到的文档进行阅读理解，抽取出能回答问题的答案，这部分就是本文要介绍的QA系统。&lt;/p>
&lt;p>QA的历史可追溯到上世纪七十年代，但真正取得突破性进展也就是最近几年。2015/2016年，几个大规模QA标注数据集的发表，极大的推动了这个领域的发展。这其中比较有名的数据集是斯坦福大学发布的Stanford Question Answering Dataset (SQuAD)。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-04-cs224n-0207-question-answering/p16.png">&lt;/p>
&lt;p>SQuAD数据集的每一个样例包含一段描述P，一个问题Q，以及对Q的人工标注答案A。为了使数据集更加鲁棒，对于每个问题，都给出了三个人工标注答案。每个答案都是描述P中的一小段文字，称为一个span。所以，问题相对来说比较简单，答案可以直接从描述中提取sub-sequence得到。&lt;/p>
&lt;p>QA系统的评价指标有两个，一个是确定性匹配Exact match，即对于每个问题，模型给出的回答如果和3个答案中的任意一个完全匹配，则加1分，否则不加分。另一个是F1指标，使用词袋模型（不考虑词的顺序），对于每个问题，模型给出的回答和3个答案中的每一个计算F1，这个问题的F1是3个F1的最大值，最终得分是所有问题的F1打分的均值。Exact match和F1都不考虑标点符号和冠词。相对来说，F1比Exact match更可靠和鲁棒一些。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-04-cs224n-0207-question-answering/p17.png">&lt;/p>
&lt;p>经过两年的两三年的刷榜，SQuAD数据集的最好性能已经超越了人类的性能，为了增加数据集的难度，斯坦福后续推出升级版本SQuAD 2.0。&lt;/p>
&lt;p>由于1.1版本的问题都有答案，所以QA系统变成了一个排序系统，只需要把Answer列表中排名第一的结果输出就好了。2.0在1.1的基础上，增加了没有答案的问题，可以理解为假问题，对系统造成干扰。此时就要求系统判断这个问题能否从描述P中获得答案，如果没有答案的话，就不输出任何回答&amp;lt;No Answer&amp;gt;。对于没有答案的问题，如果系统没有输出答案，得1分，否则输出任何答案都得0分。&lt;/p>
&lt;p>SQuAD数据集的局限性：&lt;/p>
&lt;ol>
&lt;li>回答都是span-based类型的，没有yes/no、计数、why等的问答。&lt;/li>
&lt;li>由于构造问题q的时候，已知了描述P，那么q和P的描述会很像，无论是用词还是语法。而搜索引擎面临的真实情况往往是，q根本不知道P是什么，有可能q和P的描述在行文及用词上有很大差别。&lt;/li>
&lt;li>描述P比较简单，因为答案是一个span，所以模型把q和P匹配，找到可能的答案位置就行。实际的复杂场景有可能要综合好几个句子的信息，还要理解不同的指代关系等才能得出最终答案。&lt;/li>
&lt;/ol>
&lt;p>虽然SQuAD数据集还有不少局限性，但由于其是一个well-targeted、well-structured、clean dataset，在QA发展初期，还是为促进QA发展立下了汗马功劳。&lt;/p>
&lt;h1 id="stanford-attentive-reader">Stanford Attentive Reader&lt;/h1>
&lt;p>下面介绍一下Chris Manning组针对SQuAD数据集开发的QA系统——Stanford Attentive Reader。该系统目前虽然不是最好性能，但它包含QA的基本模块，可以作为QA的一个baseline模型。&lt;/p>
&lt;p>首先模型对问题q进行表征的方法如下，输入是q中每个词的词向量，然后使用一个Bi-LSTM提取句子特征，由于是双向的LSTM，所以模型把正向和反向的LSTM的最后一个隐状态拼接起来，作为对整个句子的表征。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-04-cs224n-0207-question-answering/p28.png">&lt;/p>
&lt;p>由于SQuAD数据集的回答都是描述P中的一个span，那么，模型只需要预测出这个span在P中的起始位置和终止位置即可，具体方法如下图所示。其实也很简单，上一步我们得到的句子的表征向量q，下一步，我们对描述P也使用Bi-LSTM，得到描述P中每个词的表征向量\(\tilde p_i\)。然后，使用两次Attention，用q查询集合\(P=[\tilde p_1,…,\tilde p_n]\)，得到答案span的起始位置\(\alpha_i\)和终止位置\(\alpha’_i\)。另外，由于\(q\)和\(\tilde p_i\)的维度可能不一样，又或者为了提升模型性能，在计算Attention score的时候，不是简单的向量点积，而是采用了线性变换的方法，增加了参数\(W\)。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-04-cs224n-0207-question-answering/p30.png">&lt;/p>
&lt;p>后来，Chris Manning组又推出了升级版本Stanford Attentive Reader++，主要包括两个方面。首先，对表征问题的网络进行了改进，\(q\)不仅包含Bi-LSTM的两个尾结点的隐状态，而是包含整个问题所有隐状态的加权平均，而且网络层数增加到了3层。其次，对描述P的表征方面，原来的输入只包含词向量，现在还包含语言特征（如POS、NER的标签）、词频、以及近义词的相似度等。改进版模型性能提升了不少。&lt;/p>
&lt;p>另一个比较流行的QA系统是BiDAF，如下图所示，这里不再详细介绍。它的特点一方面输入不仅包含词向量，还包含字符级别的特征。另一大创新是在Attention Flow Layer，相对于Stanford Attentive Reader，BiDAF的Attention是双向的，不但包含q对P的Attention，还包含P对q的Attention。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-04-cs224n-0207-question-answering/p37.png">&lt;/p></description></item><item><title>CS224N（1.29）Vanishing Gradients, Fancy RNNs</title><link>https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/</link><pubDate>Thu, 01 Aug 2019 11:03:17 +0800</pubDate><guid>https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/</guid><description>&lt;h1 id="梯度消失">梯度消失&lt;/h1>
&lt;p>今天介绍RNN的梯度消失问题以及为了解决这个问题引出的RNN变种，如LSTM何GRU。&lt;/p>
&lt;p>在&lt;a href="https://bitjoy.net/posts/2019-07-31-cs224n-0124-language-models-and-rnns/">上一篇博客&lt;/a>中，通过公式推导，我们已经解释了RNN为什么容易产生梯度消失或梯度爆炸的问题，核心问题就是RNN在不同时间步使用共享参数\(W\)，导致\(t+n\)时刻的损失对\(t\)时刻的参数的偏导数存在\(W\)的指数形式，一旦\(W\)很小或很大就会导致梯度消失或梯度爆炸的问题。下图形象的显示了梯度消失的问题，即梯度不断反传，梯度不断变小（箭头不断变小）。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p11.png">&lt;/p>
&lt;p>梯度消失会带来哪些问题呢？一个很明显的问题就是参数更新更多的受到临近词的影响，那些和当前时刻\(t\)较远的词对当前的参数更新影响很小。如下图所示，\(h^{(1)}\)对\(J^{(2)}(\theta)\)的影响就比对\(J^{(4)}(\theta)\)的影响大。久而久之，因为梯度消失，我们就不知道\(t\)时刻是真的对\(t+n\)时刻没影响还是因为梯度消失导致我们没学习到这种影响。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p14.png">&lt;/p>
&lt;p>下图是一个更形象的例子，假设我们需要预测句子The writer of the books下一个单词，由于梯度消失，books对下一个词的影响比writer对下一个词的影响更大，导致模型错误的预测成了are，但这显然是不对的。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p17.png">&lt;/p>
&lt;p>类似的，如果梯度爆炸，则根据梯度下降的更新公式，参数会一瞬间更新非常大，导致网络震荡，甚至出现Inf或NaN的情况。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p18.png">&lt;/p>
&lt;p>梯度爆炸一个比较好的解决方法是梯度裁剪，即如果发现梯度的范数大于某个阈值，则以一定的比例缩小梯度的范数，但不改变其方向。如下下图所示，左子图是没有梯度裁剪的情况，由于RNN的梯度爆炸问题，导致快接近局部极小值时，梯度很大，参数突然爬上悬崖，然后又飞到右边一个随机的区域，miss掉了中间的局部极小值。右子图是增加了梯度裁剪之后，更新步伐变小，参数稳定在局部极小值附近。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p19.png">&lt;/th>
&lt;th style="text-align: center">&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p20.png">&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;/tbody>
&lt;/table>
&lt;p>总的来说，梯度爆炸相对好解决，但梯度消失就没那么简单了。在RNN中，每个时刻\(t\)，都改写了前一个时刻的隐状态，而由于梯度消失问题，长距离以前的状态对当前时刻的影响又很小，所以导致无法建模长距离依赖关系。那么，如果把每个时刻的状态单独保存起来，是否能解决长距离依赖问题呢？&lt;/p>
&lt;h1 id="lstm">LSTM&lt;/h1>
&lt;p>LSTM就是这样一个思路，请大家结合如下两幅图来理解：&lt;/p>
&lt;ul>
&lt;li>（下图）首先，从宏观上来说，LSTM的隐层神经元不仅包含隐状态\(h_t\)，还专门开辟了一个cell来保存过去的“记忆”\(c_t\)，LSTM希望用\(c_t\)来传递很久以前的信息，以达到长距离依赖的目的。所以LSTM隐层神经元的输入是上一时刻的隐状态\(h_{t-1}\)和记忆\(c_{t-1}\)，输出是当前时刻的隐状态\(h_t\)和希望传递给下一个时刻的记忆\(c_t\)。&lt;/li>
&lt;li>（上图）每个时刻\(t\)，为了调控遗忘哪些记忆，写入哪些新记忆，LSTM设置了两个门，分别是遗忘门\(f^{(t)}\)和写入门\(i^{(t)}\)。它们都是上一时刻的隐状态\(h^{(t-1)}\)和当前时刻的输入\(x^{(t)}\)的函数。\(f^{(t)}\)控制遗忘哪些记忆，即\(f^{(t)}\circ c^{(t-1)}\)；\(i^{(t)}\)控制写入哪些新记忆，即\(i^{(t)}\circ \tilde c^{(t)}\)，其中\(\tilde c^{(t)}\)即为期望写入的新记忆，它也是\(h^{(t-1)}\)和\(x^{(t)}\)的函数。最终，新时刻\(t\)的记忆就是这两部分的组合，请看上图\(c^{(t)}\)表达式。&lt;/li>
&lt;li>（上图）输出门\(o^{(t)}\)控制哪些记忆需要输出到下一个隐状态\(h^{(t)}\)，\(o^{(t)}\)自己又是\(h^{(t-1)}\)和\(x^{(t)}\)的函数。&lt;/li>
&lt;/ul>
&lt;p>大家结合上图的公式和下图的示意图就不难理解了。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p23.png">&lt;/th>
&lt;th style="text-align: center">&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p25.png">&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;/tbody>
&lt;/table>
&lt;p>LSTM解决梯度消失最直接的方法就是，遗忘门选择不遗忘，每一时刻的\(f^{(t)}\)都选择记住前一时刻的记忆\(c^{(t-1)}\)，然后直接传递给下一时刻。那么，所有前\(t-1\)时刻的记忆都会被完整的传递给第\(t\)时刻，从而对\(t\)时刻的输出产生影响。&lt;/p>
&lt;p>而朴素RNN无法保存前期状态的原因就是因为朴素RNN把之前时间步的信息都一股脑存储在隐状态\(h^{(t)}\)中了，隐状态\(h^{(t)}\)成为了整个网络的瓶颈，一旦出现梯度消失，则很久以前的信息对当前时刻的影响就微乎其微了。LSTM的关键就是开辟了一个新的cell来存储记忆，这个新的cell相当于记忆的一条捷径，时刻\(t\)除了可以像常规RNN一样通过\(h^{(t-1)}\)来获取很久以前的信息，还可以通过cell存储的记忆\(c^{(t-1)}\)来便捷地获取到很久以前的信息，所以隐状态\(h^{(t)}\)不再成为整个网络的瓶颈，有新的cell来分担。&lt;/p>
&lt;p>需要提醒的是，虽然LSTM开辟新的cell来存储记忆，但这个记忆也会受到连续梯度相乘的影响，所以依然存在梯度消失或梯度爆炸的问题，但从实际效果来看，LSTM性能很不错，也很鲁棒。&lt;/p>
&lt;h1 id="gru">GRU&lt;/h1>
&lt;p>另一种能缓解RNN梯度消失的网络——GRU。为了简化LSTM，GRU又没有cell了，但依然保留了门来控制信息的传递。首先看下图最后一个公式，当前时刻的隐状态\(h^{(t)}\)等于上一时刻的隐状态\(h^{(t-1)}\)和新写入的隐状态\(\tilde h^{(t)}\)的加权平均，通过更新门\(u^{(t)}\)来控制它们之间的比例，\(u^{(t)}\)是上一时刻的隐状态\(h^{(t-1)}\)和当前时刻的输入\(x^{(t)}\)的函数。新写入的隐状态\(\tilde h^{(t)}\)又通过一个重置门\(r^{(t)}\)来控制，类似的，\(r^{(t)}\)也是\(h^{(t-1)}\)和\(x^{(t)}\)的函数。&lt;/p>
&lt;p>个人觉得，GRU中的更新门\(u^{(t)}\)类似于LSTM中的输出门\(o^{(t)}\)；GRU中的重置门\(r^{(t)}\)类似于LSTM中的遗忘门\(f^{(t)}\)和写入门\(i^{(t)}\)的组合；GRU中新写入的隐状态\(\tilde h^{(t)}\)类似于LSTM中的细胞记忆\(c^{(t)}\)。所以，可以把GRU看作LSTM的简化版本。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p28.png">&lt;/p>
&lt;p>直观来说，GRU和LSTM类似，解决梯度消失的策略就是新增\(u^{(t)}\)来控制\(h^{(t-1)}\)和\(\tilde h^{(t)}\)的比例，如果\(u^{(t)}=0\)，则\(h^{(t)}=h^{(t-1)}\)，即\(t\)时刻的隐状态和上一时刻的隐状态相同，虽然这肯定效果不好，但至少说明GRU是有能力保留之前的隐状态的。&lt;/p>
&lt;p>GRU和LSTM的性能差不多，但GRU参数更少，更简单，所以训练效率更高。但是，如果数据的依赖特别长且数据量很大的话，LSTM的效果可能会稍微好一点，毕竟参数量更多。所以默认推荐使用LSTM。&lt;/p>
&lt;h1 id="其他缓解梯度消失的策略">其他缓解梯度消失的策略&lt;/h1>
&lt;p>由于链式法则，或者所选非线性激活函数的原因，不仅仅RNN，所有神经网络都存在梯度消失或者梯度爆炸的问题，比如&lt;a href="https://bitjoy.net/posts/2019-03-18-neural-networks-and-deep-learning-3-1-gradient-vanishing/">全连接网络&lt;/a>和CNN。一些通用解决方法如下：&lt;/p>
&lt;p>ResNet。因为梯度是在传递的过程中逐渐减小并消失的，如果跨越好几层直接进行连接，天然能保持远距离信息。个人理解，这就相当于买家和卖家直接相连，没有中间商赚差价\(\mathcal F(x)\)，买到的价格最接近卖出的价格\(x\)。能一定程度上减弱梯度消失的问题。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p30.png">&lt;/p>
&lt;p>更激进的是DenseNet，把跨越多层之间的很多神经元都连起来，也就是说有更多的线路没有中间商赚差价，进一步减弱梯度消失问题。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p31.png">&lt;/p>
&lt;p>HighwayNet。借鉴了LSTM和GRU的思路，不是像ResNet一样直接新增一条直连线路\(x\)，而是搞一个平衡因子\(u\)，卖家到买家的价格由\(u\)进行调和平均：\(u*\mathcal F(x)+(1-u)*x\)，用\(u\)来控制多少走中间商，多少走直连线路。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p32.png">&lt;/p>
&lt;p>虽然所有神经网络都存在梯度消失的问题，但RNN的这个问题更严重，因为它连乘的是相同的权重矩阵W，而且RNN针对的是序列问题，往往更深。&lt;/p>
&lt;h1 id="双向rnn">双向RNN&lt;/h1>
&lt;p>假设我们在对句子进行情感分类，如下图所示。对于terribly这个词，常规RNN，terribly的梯度只能看到左边的信息，看不到右边的信息，因为网络是从左到右的。单独看terribly或者从左往右看，在没有看到exciting时，可能认为terribly是贬义词，但是如果跟右边的exciting结合的话，则意思变为强烈的褒义词，所以有必要同时考虑左边和右边的信息。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p36.png">&lt;/p>
&lt;p>双向RNN包含两个RNN，一个从左往右，一个从右往左，两个RNN的参数是独立的。最后把两个RNN的输出拼接起来作为整体输出。那么，对于terribly这个词，它的梯度能同时看到左边和右边的信息。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p37.png">&lt;/p>
&lt;p>由于双向RNN对于某个时刻\(t\)，既需要知道\(t\)时刻前的信息（Forward RNN），又需要知道\(t\)时刻之后的信息（Backward RNN），所以双向RNN无法用于学习语言模型，因为语言模型只知道时刻\(t\)之前的信息，下一时刻的词需要模型来预测。对于包含完整序列的NLP问题，双向RNN应该是默认选择，它通常比单向RNN效果更好。&lt;/p>
&lt;h1 id="多层rnn">多层RNN&lt;/h1>
&lt;p>前面展示的RNN从时间\(t\)的维度上来说可以认为是多层的，但是RNN还可以从另一个维度来增加层数。如下图所示，将上一层（RNN layer 1）的输出作为下一层（RNN layer 2）的输入，不断堆叠下去，变成一个多层RNN。通常来说，深度越大，性能越好，如果梯度下降能训练好的话。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://bitjoy.net/posts/2019-08-01-cs224n-0129-vanishing-gradients-fancy-rnns/p42.png">&lt;/p>
&lt;p>RNN的层数通常不会很深，不会像CNN一样，达到上百层，RNN通常2层，最多也就8层。一方面是RNN的梯度消失问题比较严重，另一方面是RNN训练的时候是串行的，不易并行化，导致网络太深的话训练很花时间。&lt;/p></description></item></channel></rss>