全球名校课程作业分享系列--斯坦福CS231n之RNN与计算机看图说话
Posted 寒小阳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全球名校课程作业分享系列--斯坦福CS231n之RNN与计算机看图说话相关的知识,希望对你有一定的参考价值。
课程作业原地址:CS231n Assignment 3
作业及整理:@张礼俊 && @Molly && @寒小阳
时间:2018年2月。
出处:http://blog.csdn.net/han_xiaoyang/article/details/79316411
1. 问题背景
在问题1里,我们要训练一个循环神经网络(Recurrent neural networks)来生成一个图片的文字注释(captions)。问题2中,用以长短时记忆单元(Long-short term memory,LSTM)为基础的循环神经网络来完成同样的任务。
我们将用到的数据集是微软的COCO数据集,该数据集是测试为图片加文字注释算法的标准数据集。在该数据集中有大概80000张训练图片和40000张测试图片,每张图片在Amazon Mechanical Turk上征集了五个志愿者来手动写文字说明。
我们可以运行问题1的前几个单元来对我们将要应用的数据有个直观的概念,要注意一点的是之后的处理中我们不会再碰到原始图像,该问题已经为我们提取了图像特征。
2. 循环神经网络
问题1要求我们实现一个循环神经网络。这一部分讲述了问题1的前半部分代码。
循环神经网络是一类处理序列数据的神经网络。在本题用到的循环神经网络的架构如下图所示:
1)单步前向传播(RNN step forward)
我们要实现的第一段代码是单步前向传播。对于每一层神经网络,或每一个时刻,我们输入一个隐藏状态
h
t
−
1
h_t-1
ht−1(上一层神经网络的输出),一个外部输入
x
t
x_t
xt;之后得到下一个隐藏状态
h
t
h_t
ht,以及该时刻的输出
y
t
y_t
yt。对应的数学表达式为
KaTeX parse error: No such environment: equation at position 8: \\begin̲e̲q̲u̲a̲t̲i̲o̲n̲̲ \\beginaligned…
b
b
b为偏差值。
作业中,我们要在rnn_layers.py文件下实现如下函数:
def rnn_step_forward(x, prev_h, Wx, Wh, b):
"""
输入:
- x: 外部输入数据, 维度 (N, D).
- prev_h: 上一个时刻的隐藏状态, 维度 (N, H)
- Wx: x对应的权值矩阵, 维度 (D, H)
- Wh: 隐藏状态h对应的权值矩阵, 维度 (H, H)
- b: 偏差值 shape (H,)
输出:
- next_h: 下一个时态的隐藏状态, 维度 (N, H)
- cache: 计算梯度反向传播时需要用到的变量.
"""
temp1 = np.dot(x,Wx)
temp2 = np.dot(prev_h,Wh)
cache=(x,prev_h,Wx,Wh,temp1+temp2+b)
next_h = np.tanh(temp1+temp2+b)
return next_h, cache
单层的前向传播并不难,实现的时候只要熟练使用numpy底下的矩阵运算即可。一个要注意的点是这里的激活函数是作用于向量中的每一个元素(element wise)。
2)梯度单步反向传播(RNN step backward)
可以说几乎所有训练神经网络的算法都是基于梯度下降(gradient descent)的,所以如何获得每个节点,以及相应的参数对应的梯度至关重要。正如之前的作业中训练神经网络时做的,求梯度反向传播其实只是在不断的应用求导的链式法则。假设最终的损失函数为
E
E
E,在进行反向传播时,我们得到了上一层传来的梯度
d
E
d
h
t
\\fracdEdh_t
dhtdE,我们需要计算
d
E
d
h
t
−
1
\\fracdEdh_t-1
dht−1dE,
d
E
d
x
t
\\fracdEdx_t
dxtdE,
d
E
d
W
x
h
\\fracdEdW_xh
dWxhdE,
d
E
d
W
h
h
\\fracdEdW_hh
dWhhdE和
d
E
d
b
\\fracdEdb
dbdE。还记得前向传播的公式为
$$
\\beginequation*
\\beginaligned
h &=f_w(h_t-1,x_t)\\\\
&=\\tanh(W_hhh_t-1+W_xhx_t+b)
\\endaligned
\\endequation*
KaTeX parse error: Can't use function '$' in math mode at position 4: 假设$̲a=W_hhh_t-1…
\\beginequation*
\\beginaligned
\\fracdEdh_t-1&=\\fracdEdh_t\\fracdh_tdh_t-1 \\\\
&=\\fracdEdh_t\\fracdh_tda\\fracdadh_t-1
\\endaligned
\\endequation*
$$
而
d
h
t
d
a
\\fracdh_tda
dadht就是在对激活函数求导。
d
a
d
h
t
−
1
\\fracdadh_t-1
dht−1da就是权值矩阵
W
h
h
W_hh
Whh。
要注意一点的是,为了更易于阐明概念,上式做了一些简化,
d
E
d
h
t
\\fracdEdh_t
dhtdE和
d
E
d
h
t
\\fracdEdh_t
dhtdE都是向量,他们的相乘是逐项(element wise)相乘。之后与
d
a
d
h
t
−
1
\\fracdadh_t-1
dht−1da相乘,则是一般的向量乘矩阵,编程时注意对应的维度就好。
我们可以用相似的思路获得
d
E
d
x
t
\\fracdEdx_t
dxtdE,
d
E
d
W
x
h
\\fracdEdW_xh
dWxhdE,
d
E
d
W
h
h
\\fracdEdW_hh
dWhhdE和
d
E
d
b
\\fracdEdb
dbdE的计算方式。
作业中,我们要实现如下函数:
def rnn_step_backward(dnext_h, cache):
"""
输入:
- dnext_h: 下一层传来的梯度
- cache: 前向传播存下来的值
输出
- dx: 输入x的梯度, 维度(N, D)
- dprev_h: 上一层隐藏状态的梯度, 维度(N, H)
- dWx: 权值矩阵Wxh的梯度, 维度(D, H)
- dWh: 权值矩阵Whh的梯度, 维度(H, H)
- db: 偏差值b的梯度,维度(H,)
"""
x=cache[0]
h=cache[1]
Wx=cache[2]
Wh=cache[3]
# cache[4]对应着公式中的a
cacheD=cache[4]
N,H=h.shape
# 计算激活函数的导数
temp = np.ones((N,H))-np.square(np.tanh(cacheD))
delta = np.multiply(temp,dnext_h)
# 计算x的梯度
tempx = np.dot(Wx,delta.T)
dx=tempx.T
# h的提督
temph = np.dot(Wh,delta.T)
dprev_h=temph.T
# Wxh的梯度
dWx = np.dot(x.T,delta)
# Whh
dWh = np.dot(h.T,delta)
# b的梯度
tempb = np.sum(delta,axis=0)
db=tempb.T
return dx, dprev_h, dWx, dWh, db
3)前向传播(RNN forward)
我们完成了单步前向传播之后,对于整个循环神经网络的前向传播过程就是单步前向传播的循环,而且在本题中,每一层神经网络都共享了参数 W x h W_xh Wxh, W h h W_hh Whh, b b b。对应的代码如下:
def rnn_forward(x, h0, Wx, Wh, b):
"""
输入:
- x: 整个序列的输入数据, 维度 (N, T, D).
- h0: 初始隐藏层, 维度 (N, H)
- Wx: 权值矩阵Wxh, 维度 (D, H)
- Wh: 权值矩阵Whh, 维度 (H, H)
- b: 偏差值,维度 (H,)
输出:
- h: 整个序列的隐藏状态, 维度 (N, T, H).
- cache: 反向传播时需要的变量
"""
N,T,D=x.shape
N,H=h0.shape
prev_h=h0
# 之前公式中对应的a
h1=np.empty([N,T,H])
# 隐藏状态h的序列
h2=np.empty([N,T,H])
# 滞后h一个时间点
h3=np.empty([N,T,H])
for i in range(0, T):
#单步前向传播
temp_h, cache_temp = rnn_step_forward(x[:,i,:], prev_h, Wx, Wh, b)
#记录下需要的变量
h3[:,i,:]=prev_h
prev_h=temp_h
h2[:,i,:]=temp_h
h1[:,i,:]=cache_temp[4]
cache=(x,h3,Wx,Wh,h1)
return h2, cache
4)梯度反向传播(RNN backward)
和前向传播一样,我们已经有了单步反向传播,编程时反向传播就是单步反向传播的循环。另外因为每一层神经网络都共享了参数 W x h W_xh Wxh, W h h W_hh Whh, b b b,最终的 d E d W x h \\fracdEdW_xh dWxhdE是每一层计算得到的 d E d W x h \\fracdEdW_xh dWxh以上是关于全球名校课程作业分享系列--斯坦福CS231n之RNN与计算机看图说话的主要内容,如果未能解决你的问题,请参考以下文章
全球名校课程作业分享系列(10)--斯坦福CS231n之Network visualization
全球名校课程作业分享系列(10)--斯坦福CS231n之Network visualization
全球名校课程作业分享系列--斯坦福计算机视觉与深度学习CS231n之KNN
全球名校课程作业分享系列--斯坦福计算机视觉与深度学习CS231n之tensorflow实践