前向传播
根据公式
st = tanh (Uxt + Wst-1 + ba)
ot = softmax(Vst + by )
m = 3 词的个数 n = 5
import numpy as np
import tensorflow as tf
# 单个cell 的前向传播过程
# 两个输入,x_t,s_prev,parameters
def rnn_cell_forward(x_t,s_prev,parameters):"""单个cell 的前向传播过程:param x_t: 当前T时刻的序列输入:param s_prev: 上一个cell的隐藏层状态输入:param parameters: cell中参数,字典:return: 隐层输出 s_next,out_pred,cache"""# 取出参数U = parameters["U"]W = parameters["W"]V = parameters["V"]ba = parameters["ba"]by = parameters["by"]# 根据公式计算# 隐层输出计算s_next = np.tanh(np.dot(U,x_t) + np.dot(W,s_prev) + ba)# 计算cell的输出out_pred = tf.nn.softmax(np.dot(V,s_next) + by)# 记录每层的值,用于反向传播计算使用cache = (s_next,s_prev,x_t,parameters)return s_next,out_pred,cache
if __name__ == '__main__':# forwardnp.random.seed(1)# 定义该cell的输入x_t = np.random.randn(3, 1,)s_prev = np.random.randn(5, 1)# 定义参数W = np.random.randn(5, 5)U = np.random.randn(5, 3)V = np.random.randn(3, 5)ba = np.random.randn(5, 1)by = np.random.randn(3, 1)parameters = {"U": U, "W": W, "V": V, "ba": ba, "by": by}s_next, out_pred, caches = rnn_cell_forward(x_t, s_prev, parameters)print("s_next = ", s_next)print("s_next.shapr = ", s_next.shape)print("out_pred =", out_pred)print("out_pred.shape = ",out_pred.shape)
单个cell反向传播
根据图我们能够知道需要计算的梯度变量有哪些
ds_next:表示当前cell的损失对输出s的导数
dtanh:表示当前cel的损失对激活函数的导数
dx_t:表示当前cell的损失对输入xt的导数。
dU:表示当前cell的损失对U的导数
ds_prev:表示当前cell的损失对上一个cell的输入的导数
dW:表示当前cell的损失对W的导数
dba:表示当前cell的损失对dba的导数
表示公式:
def rnn_cell_forward(x_t,s_prev,parameters):"""单个cell 的前向传播过程:param x_t: 当前T时刻的序列输入:param s_prev: 上一个cell的隐藏层状态输入:param parameters: cell中参数,字典:return: 隐层输出 s_next,out_pred,cache"""# 取出参数U = parameters["U"]W = parameters["W"]V = parameters["V"]ba = parameters["ba"]by = parameters["by"]# 根据公式计算# 隐层输出计算s_next = np.tanh(np.dot(U,x_t) + np.dot(W,s_prev) + ba)# 计算cell的输出out_pred = tf.nn.softmax(np.dot(V,s_next) + by)# 记录每层的值,用于反向传播计算使用cache = (s_next,s_prev,x_t,parameters)return s_next,out_pred,cache
def rnn_cell_backward(ds_next, cache):"""对单个cell进行反向传播:param ds_next: 当前隐层输出结果相对于损失的导数:param cache: 每个cell的缓存:return:gradients"""# 获取缓存值(s_next, s_prev, x_t, parameters) = cacheprint(type(parameters))# 获取参数U = parameters["U"]W = parameters["W"]# V = parameters["V"]# ba = parameters["ba"]# by = parameters["by"]# 计算tanh的梯度通过对s_nextdtanh = (1 - s_next ** 2) * ds_next# 计算U的梯度值dx_t = np.dot(U.T, dtanh)dU = np.dot(dtanh, x_t.T)# 计算W的梯度值ds_prev = np.dot(W.T, dtanh)dW = np.dot(dtanh, s_prev.T)# 计算b的梯度dba = np.sum(dtanh,axis=1,keepdims= 1)# 梯度字典gradients = {"dtanh" : dtanh,"dx_t": dx_t, "ds_prev": ds_prev, "dU": dU, "dW": dW, "dba": dba}return gradients