利用神经网络识别12306验证码——(五)训练模型

需要训练的有两个模型,一个是文本识别模型,一个是图像识别模型。在训练的时候,尝试了ResNet50、ResNet101、MobileNetV2,三种模型,前两个残差神经网络模型的参数比较大,训练比较耗时,精度上也逊色于第三个模型。尝试了RTX 2080、RTX 2070、Tesla K80三种GPU,三者的训练速度依次递减,但差距不是很大。训练平台在篇尾再进行介绍。
两个模型的训练基本上可以共用一套代码,只有一些细微的差异。
首先介绍共用的代码部分,其中加载数据的函数,数据的根目录根据自己的情况,需要自行修改。

#导入必要的包
from tensorflow.compat.v1 import ConfigProto
from tensorflow.compat.v1 import InteractiveSession

config = ConfigProto()
config.gpu_options.allow_growth = True
session = InteractiveSession(config=config)
import tensorflow as tf
from tensorflow import keras
#from tensorflow.keras.applications import ResNet101
from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2
from keras.callbacks import EarlyStopping
import numpy as np
import os
import shutil
import collections
import math
import random
import pathlib

#加载数据
def dataloader():
    data_root = '/mnt/Train_Valid_text'  #根目录自行更改
    train_data_root = pathlib.Path(data_root + "/Train")
    valid_data_root = pathlib.Path(data_root + "/Valid")
    #train_valid_data_root = pathlib.Path(data_root + "/Train_valid")
    # test_data_root = pathlib.Path(data_root+"/test")
    label_names = sorted(item.name for item in train_data_root.glob('*/') if item.is_dir())
    print(label_names)
    label_to_index = dict((name, index) for index, name in enumerate(label_names))
    print(label_to_index)
    
    train_all_image_paths = [str(path) for path in list(train_data_root.glob('*/*'))]
    valid_all_image_paths = [str(path) for path in list(valid_data_root.glob('*/*'))]
    #train_valid_all_image_paths = [str(path) for path in list(train_valid_data_root.glob('*/*'))]
    # test_all_image_paths = [str(path) for path in list(test_data_root.glob('*/*'))]

    train_all_image_labels = [label_to_index[pathlib.Path(path).parent.name] for path in train_all_image_paths]
    valid_all_image_labels = [label_to_index[pathlib.Path(path).parent.name] for path in valid_all_image_paths]
    #train_valid_all_image_labels = [label_to_index[pathlib.Path(path).parent.name] for path in
                                    #train_valid_all_image_paths]
    # test_all_image_labels = [-1 for i in range(len(test_all_image_paths))]
    print("First 10 images indices: ", train_all_image_labels[:10])
    print("First 10 labels indices: ", train_all_image_labels[:10])

    batch_size = 64   #批量大小
    train_ds = tf.data.Dataset.from_tensor_slices((train_all_image_paths, train_all_image_labels)).map(
        transform_train).shuffle(len(train_all_image_paths)).batch(batch_size)
    valid_ds = tf.data.Dataset.from_tensor_slices((valid_all_image_paths, valid_all_image_labels)).map(
        transform_train).shuffle(len(valid_all_image_paths)).batch(batch_size)
    #train_valid_ds = tf.data.Dataset.from_tensor_slices(
        #(train_valid_all_image_paths, train_valid_all_image_labels)).map(transform_train).shuffle(
        #len(train_valid_all_image_paths)).batch(batch_size)

    print(train_ds)
    return train_ds, valid_ds, label_names

#模型创建函数
def creat_model(label_names):
    net = MobileNetV2(
        input_shape=(64, 64, 3),    #输入图片大小为64x64
        weights=None,               #不需要它自带的模型权重
        include_top=False)
    model = tf.keras.Sequential([
        net,
        tf.keras.layers.GlobalAveragePooling2D(),
        tf.keras.layers.Dense(len(label_names), activation='softmax', dtype=tf.float32)
    ])
    model.summary()
    return model

接下来是略微有些差异的地方,主要是数据增强和callback部分,代码如下。下面的transform_train函数中,包含了一些常用的数据增强操作,根据训练的数据集情况,选择需要的部分,并不是都需要用到。

#数据增强操作
def transform_train(imgpath,label):
    feature=tf.io.read_file(imgpath)
    feature = tf.image.decode_jpeg(feature,channels=3)
    
    feature = tf.image.resize(feature, size=[64, 64])
    #下面两行代码只在训练图像识别模型时需要用
    #训练文本识别模型时,把这两行代码注释掉,因为没有颠倒的文字
    feature = tf.image.random_flip_left_right(feature)  #左右翻转
    feature = tf.image.random_flip_up_down(feature)    #上下翻转
    # 标准化
    feature = tf.divide(feature, 255.)
    # 正则化
    mean = tf.convert_to_tensor([0.485, 0.456, 0.406])
    std = tf.convert_to_tensor([0.229, 0.224, 0.225])
    feature = tf.divide(tf.subtract(feature, mean), std)
    feature = tf.image.per_image_standardization(feature)	#仅在文本训练时进行标准化处理,图像训练时将本行代码注释掉
    #print(feature,label)
    return tf.image.convert_image_dtype(feature, tf.float32),label

#学习率控制函数,超过一定的训练迭代轮次后,开始逐渐减小学习率,使模型稳定
#两种模型的训练样本量差异比较大,因此所需要训练的轮次数量也不太一样,
#那么学习率开始减小的门槛也有不同
#训练文本识别模型时,总的迭代次数建议不超过70轮,门槛设置在30轮左右比较合适
#训练图形识别模型时,总的迭代次数建议不超过110轮,基本上100轮即可,门槛可设置在80轮
def scheduler(epoch):
    if epoch < 30:
        return lr
    else:
        return lr * math.exp(lr_decay * (30 - epoch))

下面就是调用以上函数,开始训练的代码,损失函数为交叉熵损失函数。

if __name__ == '__main__':
    lr = 0.1  #学习率
    lr_decay = 0.01   #学习率衰减系数
    train_ds, valid_ds, label_names = dataloader()
    model = creat_model(label_names)
    model_checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(
    filepath='/mnt/text_model.h5',  #模型存储路径以及名字
    save_weights_only=False,
    monitor='val_accuracy',    #监控指标为验证集的准确率
    mode='max',
    save_best_only=True)  #这个回调函数用以自动保存验证准确率最高的模型
    callback = [tf.keras.callbacks.LearningRateScheduler(scheduler), model_checkpoint_callback]
    model.compile(optimizer=keras.optimizers.SGD(learning_rate=lr, momentum=0.9),
                  loss='sparse_categorical_crossentropy', metrics=['accuracy'])
    history = model.fit(train_ds, epochs=85, validation_data=valid_ds, callbacks=callback)

文本识别模型的训练很快,总体样本量接近9000,利用RTX2070 GPU,7、8分钟左右就可以训练完,Tesla K80 GPU大概需要20分钟;图像识别模型的训练,我训练的数据样本大概在4万张左右,大概需要七八个小时才能训练完。
训练完之后,可以将训练损失以及准确率可视化一下看看,训练损失可视化代码如下。

import matplotlib.pyplot as plt

plt.plot(history.history['loss'], label='Train loss')
plt.plot(history.history['val_loss'], label='Valid loss')
plt.xlabel('epochs')
plt.ylabel('Loss')
plt.legend(loc='upper right')
plt.grid()
#plt.savefig('/mnt/文本训练损失.jpg')
plt.show()

准确率可视化代码如下

import matplotlib.pyplot as plt

plt.plot(history.history['accuracy'], label='Train accuracy')
plt.plot(history.history['val_accuracy'], label='Valid accuracy')
plt.xlabel('epochs')
plt.ylabel('Accuracy')
plt.legend(loc='lower right')
plt.grid()
#plt.savefig('/mnt/文本训练准确率.jpg')
plt.show()

文本识别模型的训练损失和准确率图像如下。文本模型最终的验证准确率可以稳定在99.8%,无限逼近100%。
在这里插入图片描述在这里插入图片描述

图像识别模型的训练损失和准确率图像如下。图像模型最终的验证准确率可以稳定在96.5%左右。
在这里插入图片描述
在这里插入图片描述
以上就是所有的训练以及可视化代码。
调参:然后再调一调学习率、批量大小等超参数,可以把图像训练的验证准确率提高并稳定在98%。见下图。在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值