> For the complete documentation index, see [llms.txt](https://anxiang1836.gitbook.io/nlp-keypoints/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://anxiang1836.gitbook.io/nlp-keypoints/mldl-ji-chu-ban-kuai/09-lstm.md).

# LSTM

> PS：不看不知道，原来RNNs和LSTM都是上个世纪诞生的产物，惊人啊！

## 问题1：传统RNNs的问题？

传统RNNs模型一定程度上可以建立时间序列上的数据关系；但是，其面对较长的依赖关系，就很难处理了，因为会有梯度消失问题呀！

> [Hochreiter (1991) \[German\]](http://people.idsia.ch/~juergen/SeppHochreiter1991ThesisAdvisorSchmidhuber.pdf) 和 [Bengio, et al. (1994)](http://www-dsi.ing.unifi.it/~paolo/ps/tnn-94-gradient.pdf) 曾经对这个问题进行过深入的研究，发现 RNNs 的确很难解决这个问题。
>
> 我嘞个亲娘啊，30年前\~\~惊叹了。

![](https://raw.githubusercontent.com/anxiang1836/FigureBed/master/img/20200303221040.png)

## 问题2：LSTM的模型结构？

> LSTM由[Hochreiter & Schmidhuber (1997)](http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf)提出，许多研究者进行了一系列的工作对其改进并使之发扬光大。

LSTM的关键是元胞状态(Cell State)，下图中横穿整个元胞顶部的水平线。

Cell State有点像是传送带，它直接穿过整个链，同时只有一些较小的线性交互。上面承载的信息可以很容易地流过而不改变。

![](https://raw.githubusercontent.com/anxiang1836/FigureBed/master/img/20200303222001.png)

然后，在整个Cell的内部，通过门的结构来控制Cell对Cell State的信息添加或删除：

* Forget Gate（遗忘门）

  $$
  f\_t = \sigma(W\_f\cdot\[h\_{t-1};x\_t]+b\_f)
  $$

  > 理解：选择性的对上一状态的信息进行遗忘。
  >
  > 例如：元胞状态可能包含当前主语的性别信息，以用来选择正确的物主代词。当我们遇到一个新的主语时，我们就需要把旧的性别信息遗忘掉。
* Input Gate（传入门）

  $$
  \begin{align}
  i\_t &= \sigma(W\_i\cdot\[h\_{t-1},x\_t]+b\_i)\\
  \\
  \tilde{C\_t} &= tanh(W\_C\cdot\[h\_{t-1},x\_t]+b\_C)
  \end{align}
  $$

  > 理解：决定让多少新的信息加入到Cell状态中来。实现这个需要包括两个步骤：首先，Input Gate决定哪些信息需要更新；然后tanh生成一个向量，也就是备选的用来更新的内容。
* Update Cell State

  $$
  C\_t=f\_t*C\_{t-1}+i\_t*\tilde{C\_t}
  $$

  > 理解：就是融上一步的部分记忆，并更新这一步的新信息进来
* Output Gate（输出门）

  $$
  \begin{align}
  o\_t &= \sigma(W\_o\[h\_{t-1},x\_t]+b\_o)\\
  \\
  h\_t &= o\_t\*tanh(C\_t)
  \end{align}
  $$

  > 理解：根据当前的输入xt和前step的输出ht-1，来计算得到当前要输出多少内容（可理解为权重）；然后，将得到的权重作用于激活后的当前Cell State，得到当前Cell的输出。

## 问题3：为什么LSTM可以轻松处理长时依赖？

主要是LSTM的Cell State的的核心思路起的作用。

在LSTM中，有两个通道在保持记忆：

* 短期记忆h，保持非线性操作，通过门结构实现；
* 长期记忆C，保持线性操作，通过Cell State实现。

因为线性操作是比较稳定的，那么C的变化也就是相对稳定，因此，LSTM可以很好保持长期记忆。

## 问题4：LSTM该不该使用Relu激活？

**答：可以，但需要付出额外考虑梯度爆炸时的梯度裁剪。**

激活函数的作用其实是在为神经网络增加非线性，tanh是LSTM的默认激活函数。

在RNN的层数较深的时候，这时为了避免产生梯度消失的风险，可以考虑使用Relu替换LSTM的激活函数，但是ReLUs在RNNs中，可能会出现另外一个问题：

> 因为RNNs的Cell在时间序列上是参数共享的，且ReLUs的导数要么为0要么为1，那么在BP过程，从某种程度上，可以近似看成权重矩阵的连乘（当然有的会被抑制掉），这就会很大风险出现可怕的梯度爆炸的问题。
>
> 也就是当替换tanh为ReLUs时候要考虑的问题：gradient clip（梯度裁剪）。

### 补充问题4.+：如何在Keras下做梯度裁剪呢？

在keras所有的优化器中，直接设置`clipvalue`参数或者是`clipnorm`参数，如下图：

![](https://raw.githubusercontent.com/anxiang1836/FigureBed/master/img/20200304012351.png)

## 问题5：LSTM的门可否用Relu激活？

**答：显然不能！！！**

首先我们要明白LSTM中的门的在实际工作中的意义是在做选择（可以类比考虑一下逻辑电路的思想）：例如选择遗忘多少，选择记忆多少，选择更新多少。

根据这种实际的数学意义，显然是：

我们是必须要使用值域为\[0,1]的饱和激活函数来实现门的选择功能，同时，又可以很好的兼顾满足非线性的激活需要。

## 参考资料

\[1].[Understanding LSTM Networks](http://colah.github.io/posts/2015-08-Understanding-LSTMs/)

\[2].[（译）理解 LSTM 网络](https://blog.csdn.net/Jerr__y/article/details/58598296)

\[3].[Keras中文文档](https://keras.io/zh/optimizers/)

\[4].[RNN 中为什么要采用 tanh，而不是 ReLU 作为激活函数？](https://www.zhihu.com/question/61265076)

\[5]. [LSTM question](https://www.reddit.com/r/MachineLearning/comments/2t1rsp/lstm_question/)

\[6].[LSTM该不该使用RELU？](https://blog.csdn.net/xygl2009/article/details/78855795)

\[7].[在训练LSTM的时候使用除了Tanh/Sigmoid以外的激活函数效果都很差，是为什么？](https://www.zhihu.com/question/49272008?from=profile_question_card)

\[8].[Keras中的LSTM](https://www.jianshu.com/p/3edff278f021)(主要用于参考Coding用)

\[9].[理解LSTM在keras API中参数return\_sequences和return\_state](https://blog.csdn.net/u011327333/article/details/78501054)(主要用于参考Coding用)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://anxiang1836.gitbook.io/nlp-keypoints/mldl-ji-chu-ban-kuai/09-lstm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
