基于RNN---LSTM+CTC的注册码识别实践

**

基于RNN—LSTM+CTC的注册码识别实践

**

**一、	实验原理及知识储备**

RNN(Recurrent Neural Networks)循环神经网络是时间递归网络和结构递归神经网络的总称。RNN目前已经在众多自然语言处理中取得了很大成就。在传统的神经网络模型中,是从输入层到隐含层再到输出层,层与层之间是全连接的,每层之间的节点是无连接的。但这种普通的神经网络对于很多问题却是无能为力。例如,要预测句子的下一个单词是什么,通常需要联系上下文才可做出准确判断。RNN基于这种问题对神经网络加以改造,把隐状态视作“记忆体”,捕捉了之前时间点上的信息,其输出Ooutput,由当前记忆(结合之前所有学习经验)共同计算得到。不同于CNN,RNN整个神经网络共享一组参数,极大减少了需要训练和预估的参数量。下图为RNN结构图:
图一 RNN结构图
上图X_t为输入,h_t为输出,循环神经网络可以看作是多个神经网络间传递信息,将上图展开会是如下所示

图2 -展开的RNN
上图中为按时间轴展开后的RNN,每次输入两个信息,输出两个信息,每轮处理hidden state 由于t状态的t由t-1时候决定,因而具有记忆功能,隐状态(当前时刻t的状态),可由如下表示:
在这里插入图片描述
LSTM(long short-term memory)长短期记忆网络是对RNN进行改造,也属于特殊的RNN,不过由于它规避了标准的RNN中梯度爆炸以及梯度消失的问题,所以会显得好用些,学习速度更快,现在在工业上,如果考虑使用RNN作为模型来训练的时候通常也是直接使用LSTM网络。LSTM与传统的RNN相比,多了一个“忘记门”,是现在所有LSTM算法介绍资料中都喜欢引用的最经典的例子。LSTM是可以像上面这样成为一个很大的方阵的,其中除了输入层和输出层分别对应着X_t和h_t的值以外,中间的部分都是一个一个的LSTM单元。我们来解剖一下这个单元,看看有什么特别的地方。
在这里插入图片描述
其中,各个模块代表的含义如下图所示,分别为神经网络层、逐点操作、向量传输、连接合并、拷贝
在这里插入图片描述

LSTM的关键之处在于当前“细胞状态”,LSTM如何控制“细胞状态”可分为以下步骤:
Step One:通过“忘记门”让信息选择性通过,来去除或者增加信息到细胞状态中,这其中包含一个sigmoid神经网络层,和一个pointwise乘法操作,输出为0-1的概率值,描述每部分信息有多少概率可以通过。公式为:
在这里插入图片描述
Step Two:通过两个小的神经网络层,即我们熟悉的σ标识的部分,和tanh标识的神经网络层来决定放什么新的消息到“细胞状态”中,sigmoid层决定什么层需要更新,而tanh层创建一个新的候选值向量 ,tanh函数可以把值映射到-1和1之间,在这之后,由前一次传递过来的C_(t-1)向量会和此刻状态进行线性叠加。这一步也决定了本次输出的C_t究竟有多少采纳本次输入,有多少采纳上一层遗留下来的信息。公式如下图所示
在这里插入图片描述
图五 -更新细胞
Step Three:更新“细胞状态”,更新C_(t-1)为C_t。
Step Four:基于“细胞状态”得到输出。最后的输出有两个部分,运行一个sigmoid来确认细胞状态的哪一部分将输出,接着用tanh处理细胞状态(得到一个介于-1到1之间的值),再与sigmoid门的输出相乘,输出我们要输出的那部分,公式与结构图如下所示:
在这里插入图片描述
CTC(Connectionist Temporal Classifier)一般译为联结主义时间分类器,适合用于输入特征和输出标签之间对齐关系不确定的时间序列问题,CTC可以自动端到端的同时优化模型参数和对齐切分的边界。
二、 实验内容
环境依赖:Python3.6+TensorFlow+freetype-py 代码参考:https://github.com/jimmyleaf/ocr_tensorf low_cnn
第一部分:图片预处理,对应实验要求1-生成彩色图像加噪声的数据集,本实验图像数据是由freetype生成,代码如下:

genObj = gen_id_card()
image_data, label, vec = genObj.gen_image()
# image_data = np.where(image_data==0, 255, random.randint(1,128))
print('image_data', image_data)
img = Image.fromarray(image_data, mode='RGBA')
color_ = random_color(0, 128)#, random.randint(220, 250)
create_noise_dots(img, color_)
create_noise_curve(img, color_)

在以上代码中将freetype生成图像转换成彩色图片,以下代码则是对齐进行加噪处理,其中create_noise_dots()为加上随机颜色的点噪声,create_noise_curve()则是加上随机线噪声,效果图如下2-1所示

# 增加噪音
def create_noise_dots(image, color, width=2, number=50):
    draw = ImageDraw.Draw(image)
    w, h = image.size
    while number:
        x1 = random.randint(0, w)
        y1 = random.randint(0, h)
        # draw.line(((x1, y1), (x1 - 1, y1 - 1)), fill=color, width=width)
        draw.point((x1, y1), fill=color)
        number -= 1
    return image
def create_noise_curve(image, color):
    w, h = image.size
    x1 = random.randint(0, int(w / 5))
    x2 = random.randint(w - int(w / 5), w)
    y1 = random.randint(int(h / 5), h - int(h / 5))
    y2 = random.randint(y1, h - int(h / 5))
    points = [x1, y1, x2, y2]
    end = random.randint(160, 200)
    start = random.randint(0, 20)
    ImageDraw.Draw(image).arc(points, start, end, fill=color)
    return image

在这里插入图片描述
将生成的图片数据集改为0-9,且改成不定长的数字序列,长度上限设置为4,再将生成的图片分别进行灰度转换、二值化处理、降噪处理,代码如下:

def random_text(self):
    text = ''
    vecs = np.zeros((self.max_size * self.len))
    size = random.randint(1, self.max_size) #长度随机在1-maxlengt
    for i in range(size):
        c = random.choice(self.char_set)
        vec = self.char2vec(c)
        text = text + c
        vecs[i*self.len:(i+1)*self.len] = np.copy(vec)
    return text,vecs
img = img.convert('L') #灰度化
img = img.convert(‘1’)#二值化
clearNoise(img)#降噪
灰度化、二值化、降噪后的效果图如下所示:

在这里插入图片描述
在这里插入图片描述
第二部分:模型训练。LSTM网络的定义,第一部分:图片预处理,对应实验要求1-生成彩色图像加噪声的数据集,本实验图像数据是由freetype生成,代码如下:
在这里插入图片描述
这里LSTM的网络层只有一层,原因是生成的图片为32X256,经过转置(np.transpose)后变成256X32,转置的原因是图片读取时是沿着纵向读取(若横向读取,每一个单元内则包含多个对象),所以lstm定义一层网络就已经可以达到效果。Cell=tf.contrib.rnn.LSTMCell(num_hidden,state_is_tuple=True)则是定义单个网络,num_hidden就是hidden_size
我们需要最小化的目标函数为ctc_loss,官方自带的定义如下:
ctc_loss(
labels,
inputs,
sequence_length,
preprocess_collapse_repeated=False,
ctc_merge_repeated=True,
time_major=True
)
Input:输入(训练)数据,是一个三维float型的数据结构[max_time_step , batch_size , num_classes],当修改time_major = False时,为[batch_size,max_time_step,num_classes]。输入图片shape:[322563],灰度化后则为322561,转置后为25632,将其一列作为feature,那么共有256个feature,32个time_step,batch_size设置为128,我们则获得[128256*32]的训练数据,然后将训练数据送入lstm网络中。Lstm中不同time_size之间共享权值,所以只需定义W的结构为[num_hidden,num_classes],b的结构为[num_classes]。
三、 实验结果
训练到7100个step的时候训练结束,保存模型,测试模型的预测结果,将代码中训练模型代码修改为crack_image(),调用保存的模型,输出预测结果,代码部分如下所示:
saver = tf.train.Saver()
with tf.Session() as session:
saver.restore(session, “./ocr.model-7000”)
#test_inputs,test_targets,test_seq_len = get_next_batch(1)
test_inputs,test_targets,test_seq_len,image = get_a_image()
test_feed = {inputs: test_inputs,
targets: test_targets,
seq_len: test_seq_len}
dd, log_probs, accuracy = session.run([decoded[0], log_prob, acc], test_feed)
report_accuracy(dd, test_targets)
plt.imshow(image)
plt.show()
模型训练的正确率达到
在这里插入图片描述
实验结果如预期一样,输出理想的预期结果,实验结果如下图3-2所示:
在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值