# 1.7 对新序列采样（Sampling novel sequences）

## 基于词汇的**RNN**模型

序列模型模拟了任意特定单词序列的概率，要做的是对这些概率分布进行采样来生成一个新的单词序列。编号1所示的网络已经被上方所展示的结构训练过，编号2是进行采样

[![](https://github.com/fengdu78/deeplearning_ai_books/raw/master/images/8b901fc8fcab9e16b1fe26b92f4ec546.png)](https://github.com/fengdu78/deeplearning_ai_books/blob/master/images/8b901fc8fcab9e16b1fe26b92f4ec546.png)

第一步要做的是对想要模型生成的第一个词进行采样，输入$$x^{<1>} =0$$，$$a^{<0>} =0$$，第一个时间步得到的是所有可能的输出，是经过**softmax**层后得到的概率，然后根据这个**softmax**的分布进行随机采样。对这个向量使用`np.random.choice`，来根据向量中这些概率的分布进行采样，就能对第一个词进行采样

然后继续下一个时间步，$$\hat y^{<1>}$$作为输入（编号4），然后**softmax**层就会预测$$\hat y^{<2>}$$是什么。假如第一个词进行抽样后得到的是**The**，现在要计算出在第一词是**The**的情况下，第二个词应该是什么（编号5），然后再用采样函数来对$$\hat y^{<2>}$$进行采样

即无论得到什么样的用**one-hot**码表示的选择结果，都把它传递到下一个时间步，然后进行采样，直到最后一个时间步

怎样知道一个句子结束：

* 如果代表句子结尾的标识在字典中，可以一直进行采样直到得到**EOS**标识（编号6），代表着已经抵达结尾，可以停止采样
* 如果字典中没有这个词，可以决定从20个或100个或其他个单词进行采样，然后一直将采样进行下去直到达到所设定的时间步。不过这种过程有时候会产生一些未知标识（编号7），如果要确保算法不会输出这种标识，要做的是拒绝采样过程中产生任何未知的标识，一旦出现就继续在剩下的词中进行重采样，直到得到一个不是未知标识的词

这就是如何从**RNN**语言模型中生成一个随机选择的句子。以上所建立的是基于词汇的**RNN**模型，意思就是字典中的词都是英语单词（下图编号1）

[![](https://github.com/fengdu78/deeplearning_ai_books/raw/master/images/1d31771da8ced333968541fbbf67e6f1.png)](https://github.com/fengdu78/deeplearning_ai_books/blob/master/images/1d31771da8ced333968541fbbf67e6f1.png)

## 基于字符的**RNN**结构

用以上字符组成字典（上图编号2所示）

序列$$\hat y^{<1>}$$，$$\hat y^{<2>}$$，$$\hat y^{<3>}$$在训练数据中是单独的字符，对于“**Cats average 15 hours of sleep a day.**”，**C**是$$\hat y^{<1>}$$，**a**就是$$\hat y^{<2>}$$，**t**就是$$\hat y^{<3>}$$等等

优点：

不必担心会出现未知的标识，基于字符的语言模型会将**Mau**这样的序列也视为可能性非零的序列。而基于词汇的语言模型，如果**Mau**不在字典中，只能当作未知标识**UNK**

缺点：

最后会得到太多太长的序列，基于字符的语言模型在捕捉句子中的依赖关系也就是句子较前部分如何影响较后部分不如基于词汇的语言模型那样可以捕捉长范围的关系，并且基于字符的语言模型训练起来计算成本比较高
