代码见 https://github.com/cs123951/machine_learning_practice
RNN.ipynb和RNN_add.py
实现的难点主要在于backward层。
首先定义Tanh和sigmoid两个**层,以及最后的softmax层。
- Tanh的导数为:(1-tanh(x)*tanh(x))
- simoid的导数为:(1-sigmoid(x))*sigmoid(x)
- softmax计算式为:,也就是输出类别的概率,是softmax层前一层的输出。
类别的输出形式为[1,0,0,…0]的one-hot向量的形式,采用交叉熵 (p为真实样本分布,q为预测样本分布)作为损失函数,则只有当p为1时,log q才有意义,所以损失 Loss=.
当预测正确,j=i,
当预测不正确,j != i,
然后定义乘法矩阵和加法矩阵的求导过程:
对于矩阵x*w=z, dw = x’*dz, dx = dz*x’
对于矩阵加法:x1+x2=z, dx1=dx2=dz
有了上面的基础运算,就可以构建RNN层,
而一个RNN就是由若干个RNN层堆叠在一起的,其中的U,W,V参数是共享的。
RNN的反向传播用到了bptt(BackPropagation Through Time),也就是在更新一个节点的时候,往前统计t-1个节点的梯度,称为向前看。
而优化算法用了最简单的随机梯度下降法,因此loss下降特别慢,训练时间特别长。
构建了网络之后,通过两个案例来测试效果,其中对网络都有稍加修改:
- 输入一个句子,然后输出预测的下一个句子。RNN.ipynb
句子的每个词用一个8000维的向量表示,因此输入x的长度是8000,
输入输出如下:
x:[1, 51, 27, 16, 10, 853, 53, 25, 34, 69]
y:[51, 27, 16, 10, 853, 53, 25, 34, 69, 0]
结果:我不知道为啥预测的都是333333. - 输入两个二进制数字,预测相加后的数字。RNN_add.py
x:[0 1 1 1 1 0 1 1] [0 0 1 0 1 1 1 1]
y:[1 0 1 0 1 0 1 0]