
* Refactor js submodule * Remove change-log * Update ocr module * Update ocr-detection module * Update ocr-detection module * Remove change-log
3.4 KiB
RNN算子计算过程
一、RNN理解
RNN 是循环神经网络,由输入层、隐藏层和输出层组成,擅长对序列数据进行处理。
paddle官网文档:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/nn/RNN_cn.html#rnn
paddle源码实现:https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/operators/rnn_op.h#L812
##二、RNN计算方式
t 时刻,输入层为 ,隐藏层为
,输出层为
。由上图可知,
的值不仅仅取决于
,还取决于
。计算公式如下:
三、pdjs中RNN算子实现
因为 RNN 有梯度消失问题,不能获取更多上下文信息,所以 CRNN 中使用的是 LSTM(Long Short Term Memory),LSTM 是一种特殊的 RNN,能够保存长期的依赖关系。
基于图像的序列,两个方向的上下文是相互有用且互补的。由于 LSTM 是单向的,所以将两个 LSTM,一个向前和一个向后组合到一个双向 LSTM 中。此外,可以堆叠多层双向 LSTM。ch_PP-OCRv2_rec_infer 识别模型就是使用的双层双向 LSTM 结构。计算过程如下图所示:
以ch_ppocr_mobile_v2.0_rec_infer 模型 rnn算子为例:
{
Attr: {
mode: 'LSTM'
// 是否双向,为true则正向反向都需要遍历
is_bidirec: true
// 隐藏层层数,代表循环次数
num_layers: 2
}
Input: [
transpose_1.tmp_0[25, 1, 288]
]
PreState: [
fill_constant_batch_size_like_0.tmp_0[4, 1, 48],
fill_constant_batch_size_like_1.tmp_0[4, 1, 48]
]
WeightList: [
lstm_cell_0.w_0[192, 288], lstm_cell_0.w_1[192, 48],
lstm_cell_1.w_0[192, 288], lstm_cell_1.w_1[192, 48],
lstm_cell_2.w_0[192, 96], lstm_cell_2.w_1[192, 48],
lstm_cell_3.w_0[192, 96], lstm_cell_3.w_1[192, 48],
lstm_cell_0.b_0[192], lstm_cell_0.b_1[192],
lstm_cell_1.b_0[192], lstm_cell_1.b_1[192],
lstm_cell_2.b_0[192], lstm_cell_2.b_1[192],
lstm_cell_3.b_0[192], lstm_cell_3.b_1[192]
]
Output: [
lstm_0.tmp_0[25, 1, 96]
]
}
整体计算过程
rnn 计算中新增op:
1)rnn_origin
计算公式: blas.MatMul(Input, WeightList_ih, blas_ih) + blas.MatMul(PreState, WeightList_hh, blas_hh)
2)rnn_matmul
计算公式:rnn_matmul = rnn_origin + Matmul( S_{t-1}
, WeightList_hh)
3)rnn_cell
计算方式:将rnn_matmul op输出结果分割成4份,每份执行不同激活函数计算,最后输出lstm_x_y.tmp_c[1, 1, 48]。x∈[0, 3],y∈[0, 24]。 详见算子实现:rnn_cell )
4)rnn_hidden 计算方式:将rnn_matmul op输出结果分割成4份,每份执行不同激活函数计算,最后输出lstm_x_y.tmp_h[1, 1, 48]。x∈[0, 3],y∈[0, 24]。 详见算子实现:rnn_hidden