循环神经网络
循环神经网络介绍摘抄自莫凡博士的教程
序列数据
我们想象现在有一组序列数据 data 0,1,2,3. 在当预测 result0 的时候,我们基于的是 data0, 同样在预测其他数据的时候, 我们也都只单单基于单个的数据. 每次使用的神经网络都是同一个 NN. 不过这些数据是有关联 顺序的 , 就像在厨房做菜, 酱料 A要比酱料 B 早放, 不然就串味了. 所以普通的神经网络结构并不能让 NN 了解这些数据之间的关联.
处理序列数据的神经网络
那我们如何让数据间的关联也被 NN 加以分析呢? 想想我们人类是怎么分析各种事物的关联吧, 最基本的方式,就是记住之前发生的事情. 那我们让神经网络也具备这种记住之前发生的事的能力. 再分析 Data0 的时候, 我们把分析结果存入记忆. 然后当分析 data1的时候, NN会产生新的记忆, 但是新记忆和老记忆是没有联系的. 我们就简单的把老记忆调用过来, 一起分析. 如果继续分析更多的有序数据 , RNN就会把之前的记忆都累积起来, 一起分析.
我们再重复一遍刚才的流程, 不过这次是以加入一些数学方面的东西. 每次 RNN 运算完之后都会产生一个对于当前状态的描述 , state. 我们用简写 S( t) 代替, 然后这个 RNN开始分析 x(t+1) , 他会根据 x(t+1)产生s(t+1), 不过此时 y(t+1) 是由 s(t) 和 s(t+1) 共同创造的. 所以我们通常看到的 RNN 也可以表达成这种样子.
RNN 的运用
RNN 的形式不单单这有这样一种, 他的结构形式很*. 如果用于分类问题, 比如说一个人说了一句话, 这句话带的感情色彩是积极的还是消极的. 那我们就可以用只有最后一个时间点输出判断结果的RNN.
又或者这是图片描述 RNN, 我们只需要一个 X 来代替输入的图片, 然后生成对图片描述的一段话.
或者是语言翻译的 RNN, 给出一段英文, 然后再翻译成中文.
有了这些不同形式的 RNN, RNN 就变得强大了. 有很多有趣的 RNN 应用. 比如之前提到的, 让 RNN 描述照片. 让 RNN 写学术论文, 让 RNN 写程序脚本, 让 RNN 作曲. 我们一般人甚至都不能分辨这到底是不是机器写出来的.
字符级循环神经网络实例
数据IO:
读文件
建立独有字符列表(利用set的特性后转换为list)
记录数据长度&字典长度
建立字典到向量映射(dict)
建立向量到字典映射(dict)
初始化:
隐藏层向量输入(非节点数)
输入层节点个数(每次传入网络的数据块大小)
学习率
输入层->隐藏层权重参数
隐藏层->隐藏层权重参数
隐藏层->输出层权重参数
输入层->隐藏层偏置参数(共享参数)
隐藏层->输出层偏置参数(共享参数)
主循环(跳过loss部分):
p相当于文件指针,每次文件结束时清除隐藏层激活数据(记忆),并从头开始
设定输入数据的25个字符串(p到p+25,每次p增加25)设定目标(相当于标签)字符串,是输出的顺次加1(p+1到p+25),也就是说每次预测多一位字母
每100轮训练,从测试中读取数据使用RNN预测,并打印结果
损失函数以及梯度计算
更新参数,使用的是adagrad法
损失函数:
向前传播过程:
xs {..., i:array([0...1...]), ...} 使用dict和onehot编码来表示输入字符的向量空间表示向前传播以及softmax分类
反向传播过程:
[注]:本部分涉及了反向传播的具体代码实现,值得参考。
-
reversed
(seq)
Return a reverse iterator. seq must be an object which has a
__reversed__()
method or supports the sequence protocol (the__len__()
method and the__getitem__()
method with integer arguments starting at0
).说明:
1. 函数功能是反转一个序列对象,将其元素从后向前颠倒构建成一个新的迭代器。
ps {..., i:class, ...} 记录softmax分类,onehot编码dy [0,0,..., 1, ...] 理论值,实际上是个概率分布,dy[i]-1意思是正确类只要不到1就需要增加(减去负梯度),由于是概率分布错误分类恒正,所以不需额外处理就会被下降掉。
反向通过softmax层
反向通过线性层
反向通过tanh层