深度学习:识别图片中的电话号码(2)
背景介绍见:深度学习:识别图片中的电话号码(1)
识别电话号码最终采用的是:循环卷积网络。先看下网络的结构,有几处比较trick的地方,后面会讲到。
注意的地方
1. 上图中的网络是训练网络的结构,训练的输入有三个:image图片;seq是时序的标识,如果时序长度为5则为[0,1,1,1,1],0表示序列的开始,1表示序列继续(当前时刻有信号输入),上一时刻的细胞状态会传递给当前时刻。label表示序列的真实结果,如“123”应该表示为[1,2,3,-1,-1],长度和seq一致。
在batchsize中,多个样本的seq大小如果不同,短序列的seq=[0,1,1,…1,0,0..0],表示短序列提前结束了。当然电话识别中,把图片特征按列等分了n份,大家的序列长度是一致的。
2. 序列的分割
输入image的大小是:batch_size*3*h*w
输入seq的大小是:batch_size*n ,n表示序列的长度=图片特征要切割的份数
输入label的大小是:batch_size*n
经过ZF特征提取网络,relu5的输出为:batch_size*num_output*height*width,num_output表示featureMap的数据,width/height特征层的宽高。
trans1转置层,参数为:
transpose_param {
dim: 0
dim: 3
dim: 2
dim: 1
}
输出的维度为:batch_size*width*num_output*height。trick的做法是:n的大小可以设置为width,即把特征层的每一列作为一个时刻的输入。
conv5_trans为全连接层,当然它的全连接只针对某一列在num_output个featureMap上的节点进行,参数为:
inner_product_param {
num_output: 4096
weight_filler {
type: "gaussian"
std: 0.01
}
bias_filler {
type: "constant"
value: 0
}
axis: 2
}
输出为:batch_size*width(n)*4096。
3. 构建序列,主要是构建LSTM的输入格式,注意LSTM的输入是:T*batch_size*C,T就是时序长度n,C是特征的维度即4096。
4. LSTM的输出为:T*batch_size*lstm_c,lstm_c表示LSTM中特征维度的大小,这里取256。
经过fc-final,全连接为字符的种类数目+1(背景)。比如数字,输出为T*batch_size*11。
5. 最终输入CTC网络,CTC网络会对T时刻的数据做后处理计算与真实label的差异,返回loss。正如上节说的,T的大小应该大于label的长度,因为CTC的后处理会把结果中的空格(背景)和连续相同字符去除(重复识别)去除,如果T<len(label),后处理后得到的字符一定和label不同了,这样就没意义了。
比如T=20,序列为:“1_88_8_1_1_66_10_16_8”,处理后得到“18811610168”。
检测网络
检测网络和训练类似,只是CTCLoss层替换为CTCDecoder即可。
由于新加了一些层的依赖,基于的caffe为:https://github.com/houkai/caffe