RNN神经网络


RNN背后的想法是利用顺序信息。在传统的神经网络中,我们假设所有输入(和输出)彼此独立。但是对于许多任务来说,这是一个非常糟糕的主意。如果要预测句子中的下一个单词,则最好知道哪个单词在它之前。RNN之所以称为递归, 是因为它们对序列的每个元素执行相同的任务,其输出取决于先前的计算。思考RNN的另一种方法是,它们具有“内存”,可以捕获有关到目前为止已计算出的内容的信息。从理论上讲,RNN可以任意长的顺序使用信息,但实际上,它们仅限于回顾一些步骤(稍后再介绍)。

通过展开,我们仅表示我们为整个序列写出了网络。例如,如果我们关心的序列是5个单词的句子,则该网络将展开为5层神经网络,每个单词一层。控制RNN中发生的计算的公式如下:

是时间步的输入。例如, 可以是与句子的第二个单词相对应的“一字通”向量。
是时间步的隐藏状态。这是网络的“内存”。根据先前的隐藏状态和当前步骤的输入来计算。该函数通常是诸如tanh或ReLU之类的非线性函数。 计算第一个隐藏状态所需的,通常初始化为全零。

下面的内容是如何实现RNN网络:
https://blog.csdn.net/rtygbwwwerr/article/details/51012699
http://www.wildml.com/2015/09/recurrent-neural-networks-tutorial-part-2-implementing-a-language-model-rnn-with-python-numpy-and-theano/
语言模型:
某一句话s是由n个词语(w)组成的集合,那么这句话生成的概率为:
P(s) = P(w_1,w_2,…,w_n)=P(w_1)P(w_2|w_1)P(w_3|w_1,w_2)…P(w_n|w_1,…,w_n-1)

公式中,需要n个联合条件分布率,通常我们做一些假设,每一个词语都依赖它的前一个词语,那么就可以化简为:
P(s) = P(w_1)P(w_2|w_1)P(w_3|w_2)…P(w_n|w_n-1)
当依赖两个单词的时候同样类似。

上面就被称为2-Gram和3-Gram,关联的词语越多,模型就越精确,训练成本也很大。

这里使用RNN训练一个2-Gram模型。也就是通过RNN来估计每对单词的条件概率P(w_i|w_j)

训练样本数为Ns,目标词典的word数量为Nw,每个单词使用one-hot表示。
输入/出层节点数为 Ni=No=Nw
隐藏层节点数为Nh(通常为Ni的十分之一)
隐藏层的激活函数为tanh,
输出层激活函数为softmax
隐藏层存在一个递归边,每个时刻的输出乘以权值矩阵W后,将作为下一个时刻输入的一部分。

权值矩阵:
U :Input Layer -> Hidden Layer NhNi
V :Hidden(t) Layer -> Output Layer No
Nh
W :Hidden(t-1) Layer-> Hidden(t) Layer Nh*Nh
f_h:隐藏层激活函数
f_o:输出层激活函数

s_k(t):t时刻第k个隐藏层节点的输出值
o_k(t):t时刻第k个输出层节点的输出值

y_k:第k个输出层就诶点的目标输出值

程序的组成:

1.标记文本:
我们有原始的文本,但是,我们希望在词语的基础上进行预测,这就表示,我们需要在句子中对文本进行标识,我们可以通过空格将每个评论分割开,但是这样就无法正确处理符号,
句子‘He left!’应该是三个词语令牌:’He’,’left’,’!’我们将会使用NLTK中的word_tokenize和sent_tokenize方法,这将会替我们完成最复杂的工作。

2.删除低频词语
文本中的大多数词语仅仅出现1到2次,将低频的词语删除是一个好方法。
大量的词汇表将会使得训练的速度降低。而且,由于我们没有很多低频词语的上下文实例,因此我们也无法学习如何正确使用低频词语。为了能够理解如何使用一个单词,你需要在不同的上下文中看到它。

代码中,我们将最常用的词汇表限制为vocabulary_size,默认为8000,但是可以随意修改。我们将不包含在词汇表中的词语用UNKNOWN_TOKEN来代替。

我们将会把UNKNOWN——TOKEN作为我们词汇的一部分,当我们生成新的文本的时候,我们可以再次替换UNKNOWN——TOKEN,例如通过在词汇表中抽取一个随机采样的单词,或者我们可以通过生成句子,直到得到一个不包含未知标记的句子。

3.添加开始和结束标记:
我们同样希望学习哪些词语在开头或者结尾,为此,我们准备了SENTENCE——START和SENTENCE-END令牌,考虑到第一个token是SENTENCE-START,那么什么词语跟在后面呢,也就是句子的第一个单词。

4.建立训练数据矩阵
CNN的输入是向量,我们需要建立一个单词到序列的映射,index_to_word和word_to_index