学习[#深度学习继卷积之后—RNN-CSDN博客]之后看会更加理解
循环神经网络前向公式
zt:t-1时刻的隐层状态(ht-1)乘上对应的隐藏状态权重矩阵(U) 再加上t时刻输入的X和权重参数矩阵W相乘 就是隐藏层的净输入
ht:对计算的zt添加一个激活函数tanh激活函数
这里有个问题
为什么CNN的激活函数使用relu,RNN的激活函数使用tanh?
CNN使用ReLU激活函数的原因是ReLU能够更好地处理卷积层输出中的非线性特征,他的导数是0或1,避免和Sigmoid函数出现一样的问题:当输入值非常大或非常小的时候容易出现梯度消失的问题。
RNN不使用ReLU的原因是ReLU的输出范围在 [0, +∞) 上,会导致输出值非常的大,而使用tanh,他的输出范围在[-1, 1] 上,相当于对输出进行了标准化使得网络更容易训练,此外,tanh 激活函数具有平滑的导数,有助于梯度传播和避免梯度消失问题。但是由于tanh导数的取值范围为 (0,1],因此长时间依赖关系仍然可能导致梯度消失或爆炸问题。因此,一般需要采用梯度裁剪等技术来进一步避免这些问题。
yt(输出):因为要输出结果查看概率所以要加一个softmax激活函数进行归一化
(Sigmoid函数的输出范围是0到1。由于输出值限定在0到1,因此它对每个神经元的输出进行了归一化)
ht(隐层):加了一个tanh激活函数
python代码
(注意下图的隐藏状态权重矩阵是W不是U)
import numpy as np
def forward_propagation(self,x):
#样本个数 也就是时间长度
T = len(x)
#初始化0时刻的h0
h = np.zeros(T + 1,self.hidden_dim)
h[-1] = np.zeros(self.hidden_dim)
#预测值的个数和形状输出输入时保持一致
y_hat = np.zeros((T,self.in_shape))
for t in np.arange(T):
#reshape(-1,1)变成多行1列
x_t = np.array(x[t]).reshape(-1,1)
#reshape(-1)变成向量
z = (self.U.dot(x_t) + self.W.dot(h[t-1].reshape(-1,1))).reshape(-1)
h[t] = self.tanh(z)
o_t = self.V.dot(h[t])
y_hat[t] = self.softmax(o_t)
return y_hat,h
循环神经网络前向传播计算流程
假设在t时刻:
zt:
Uxt:xt(K * 1大小的矩阵) 与U(H * K大小的矩阵)相乘 顺序为U * x ->(H * K) * (K * 1) 因为两个矩阵要是想相乘需要满足,第一个矩阵的列数等于第二个矩阵的行数 详细内容请看[矩阵相乘的要求-CSDN博客]得到一个H*1大小的矩阵
Wht:W隐藏状态权重矩阵(H * H大小的矩阵)与t-1时刻的隐藏层的净输入ht-1(H * 1大小的矩阵)相乘 顺序为W * ht-1 -> (H * H)*(H * 1) 得到一个 H * 1大小的矩阵
这样Uxt与Wht的矩阵大小就相同了 然后可以进行相加得到zt
ht:
上一个隐藏层的净输入经过激活函数tanh之后的值 矩阵大小还是H * 1
ot:
ot就是没有经过归一化处理之前的值
V权重矩阵( K* H大小的矩阵)与ht(H * 1大小的矩阵)相乘得到一个K * 1大小的矩阵
yt:
输出值 ot经过softmax激活函数归一化处理之后输出的值
Lt:
t时刻的交叉熵损失函数值
标签:输出,RNN,tanh,self,矩阵,ht,传播,函数 From: https://blog.csdn.net/disciplining/article/details/142767529