文中提到的部分文件在这里

项目已发布到py.he-cheng.space

实验报告

实验名称综合实验
课程名称人工智能技术与应用
姓名王**陈*
学院********
专业********
手机176********185********
邮件269189****@qq.com249071****@qq.com

东华大学 计算机科学与技术学院

2020年 6月 4日

一、选题说明

1.数据集的领域背景、采集方法、标注方法。

本课题采用了中科院自动化所发布的中文手写数据。包括187个人通过Walcom笔在线输入的手写文本,分为3755个类别(即汉字)。

下载链接:

http://www.nlpr.ia.ac.cn/databases/download/feature_data/HWDB1.1trn_gnt.zip

http://www.nlpr.ia.ac.cn/databases/download/feature_data/HWDB1.1tst_gnt.zip

其中HWDB1.1trn_gnt是训练集,HWDB1.1tst_gnt是测试集

解压后得到若干个.gnt格式的文件,这里不再赘述图片的解码方式(可以参考tool.py,代码搬运自知乎)我们已经将数据集解码为.png格式的图片并保存至百度网盘中。

链接:https://pan.baidu.com/s/1EonVXu-3VSEGdFt3keh5rA

提取码:mxtj

2.数据属性及含义说明,各类样本数据量,并给出5个数据样本

下图展示了解码完成后的数据文件结构:

数据集分为两大目录:train和test(分别代表训练集和测试集),两个目录下各有3755个子目录,每个子目录下存放着若干张(训练集为240张,测试集为60张)所对应汉字的图片,如图:

由此可见,这里的每个子目录对应着多分类任务的一个类别。同时,通过子目录的名称可以在dict.csv(如图)中查询到该类别对应汉字的Unicode码,从而完成最终的汉字识别任务。

  • 任务目标

(数据集的应用目标,指实际业务应用目标)

本课题只完成简单的单个手写汉字识别。后续优化之后或许可以与其他的图像分割工具以及GUI整合,从而完成大规模的手写文档录入工作,减轻相关从业人员的负担

二、编程建模实现过程及结果分析

1.建模任务
(说明具体的回归分析、分类任务或聚类任务目标)
读取一张带有单个手写汉字的图片,输出分类结果(识别出其中的汉字)

2.数据预处理
首先,由于数据集非常大(如图),如果同时将所有图片读入内存并转换为多维数组,占用的内存空间将非常”可观”,并且根据预先的测试,模型训练过程中随着内存占用的增加,程序随时可能崩溃抱错(训练用的计算机内存只有16GB)

在查询了有关资料之后,我们了解到tensorflow本身有能解决这个问题的API,可以将数据事先打包在硬盘中,随着训练的进行逐步读取。但是,官方文档晦涩难懂,我们作为初学者,学习有关的方法需要大量的时间。为了尽快完成任务(毕竟还得准备其他很多科目的期末任务和考试),我们采用了一个取巧的办法:
把整个训练分为数个小的回合。在读取每个回合的数据时,遍历3755个类别对应的目录,从每个目录下随机抽取若干张图片,把这些图片转化为相同大小的灰度图像,再将它们整合为训练模型所需的X_train变量。(我们训练时采用了8个回合,每个回合抽取了3755*30张训练集中的图像。)
实际训练时,使用这种方法读取数据,python的内存占用最高没有超过7GB,效果十分理想。但该方法对模型的训练效果影响未知。
下面结合代码进行解释。这是负责进行数据加载的函数:
(该函数接收总回合数all_round和当前回合数now用于显示进度提示,并返回可以直接用于模型训练的X_train和y_train变量。)

def read_data(all_round,now):
    print('正在读取第 %d 组数据,共 %d 组... 进度:%.2f'%(now, all_round, now/all_round))   输出进度提示
    start_time = time.time()
    X_train, y_train = [], []
    for path in dic['path']:   开始遍历数据。这里的dic即为之前提到的dic.csv文件
        path_root = os.path.join(train_root,'%05d'%int(path))   获取当前要抽取图片的目录的相对路径。train_root为训练集根目录。
        for root, dirs, files in os.walk(path_root):
            images = files   获取目录下的全部文件名
        for a in range(imgs_each_round):
            b = random.randint(0, len(images)-1)   随机选择一张要抽取的图片
            dest_image = os.path.join(path_root, images[b])   获取图片的相对路径
            images.pop(b)
            img = image.load_img(dest_image, target_size=(img_size,img_size))   以固定大小读取图片
            img = img.convert('L')   转化为灰度图像
            X = image.img_to_array(img)   把图片转化为数组
            X_train.append(X)   整合图片
            y_train.append(path)   将当前目录的名称作为分类标签保存到y_train变量
    X_train = np.array(X_train, dtype="float32") / 255.0   标准化
    y_train = np.array(y_train)
y_train = to_categorical(y_train, num_classes=dic.shape[0]   转化为onehot标签
    print ('读取完成,耗时', time.time() - start_time)   输出提示
    return X_train, y_train   返回数据
    • 这里没有做数据增强。我们观察了图像,发现这些字有的写得歪,有的写得正;有的写得粗,有的写得细。这个数据集已经足够大,覆盖的情况已经足够丰富。再说也没有人会写翻转的字,把文字翻转过来加入训练集,只会引入噪声,例如”人”字和”入”字,翻转就会出现严重的混淆问题,减弱训练结果。
    • 建模过程(所使用的1种或多种模型及训练过程)
      因为时间有限,而单次训练模型所需的时间就要数个小时,我们没有对网络进行反复的调整优化。为了快速达到较好的效果,我们找到了github上类似的项目
      项目地址https://github.com/orange90/HandWrittenChineseRecogntion 该项目已被多次commit,可以认为,这个模型是人家经过反复调试找到的较优解。下面是模型的结构:
      这个模型使用了四个卷积层,两个maxpooling层,以及若干个全连接层、dropout层等。
      经过四个小时共8个回合的训练(每个回合训练了12个Epoch,batch_size为128),模型最终在训练集上的准确率达到了99%(如下图,最后一个回合训练返回的信息)

  • 性能分析(评估指标、模型对比实验结果、可视化分析)
    经过测试,模型在测试集上的准确率达到了86%。模型出现了一定程度的过拟合。

三、结果分析

模型训练完成之后,我们实现了一个利用该模型进行简单的文字的应用(参见 手写汉字识别_应用.ipynb)该应用能读取指定的图片并识别其中的汉字并输出识别概率。我们利用它对测试集上的一些图片进行了识别,效果良好。

部分识别出错的图片,也只能怪字本身有鬼神之势…(下图原字是”延”)

    有的字连人都不容易看出来,而机器却能硬生生地打回原形…

此外我们也从百度上找到了一篇手写文章,将其中的汉字单独裁切下来(如下图),识别效果不错。不过我们发现要识别的图片背景必须是纯白,否则准确率会大幅降低。猜测是因为这些图像在转化为灰度图像时会引入大量的噪声,干扰识别结果。后续改进时或许可以通过滤镜改变训练集的背景颜色,来解决这一问题。

  • 总结、感想及课程建议
    最近很多课程临近结课,任务越来越多,所以我们组的前期准备工作做得很不到位。周一上课汇报进度之前我们俩连大致方向都没商量好。我(王俊程)甚至直到汇报前一个小时才想起这事… 说到底还是我没有引起足够的重视。到了课上,我本以为这个三分钟的报告只是简单概括一下就行,没想到其它小组个个带着精心准备的PPT来了… 我本来也不喜欢打无准备之仗:这样上去讲不是丢脸吗?于是我让陈思同学干脆还是别讲了,大不了实验内容认真做好就行。这使得我们组的课题缺乏老师的专业指导,浪费了老师的一片好心。这一点还请老师原谅。
    不过总的来说这次的实验完成还是比较顺利的。前天下载好了数据集,想了想大致的思路;昨天下午抽空写好了代码,晚上稍微调试了一下,今天早上起来模型就训练好了;现在这篇实验报告也差不多写完了。要我说最难的还是这最后一步:要把自己做的工作跟人讲明白,不容易。
    最开始想要做这个东西,完全就是用手机打字的时候灵机一动:手写输入的原理,是不是和计算机课上讲的神经网络有关系?(不过后来我了解到输入法识别的不是整字,而是一个一个的笔画。完了再用识别出来的笔顺到数据库里去匹配,找到候选的字。不信你可以用倒着的笔顺写一个”中”字试试。我们做的这个课题,更合适的叫法是’OCR’,目前市面上比较常见的图片转文本技术就是基于这个。)于是就着手查找有关的资料。这期间我又不禁开始感慨时代的便利。学校里的老师教会了我们跑,搜索引擎就能带我们飞。比如我们读取数据时用到的随机文件抓取,就是从CSDN上的某篇博客里学到的。Github上各种开源的库,更是随时都能下载下来学习。霎时间我仿佛有种成为了后浪的自豪感。如今,不管问题多复杂,只要敢于动手、善于动手,你就能干成。
    同时在实验过程中我也感受到,神经网络不仅仅是在学习。它具有一定的想象力!!比如它眼中一些看着很像的字:拜-佯, 扮-捞,笨-苯…. 这些字如果手写出来,连人都比较难以辨认!!但是,要知道这些字在类别上并不是相邻的。也就是说,模型具有一定的联想能力!至此,我不禁感慨计算机科学家和数学家的伟大。俩字:牛逼!!!

参考文献

《用Keras实现手写汉字识别》https://zhuanlan.zhihu.com/p/33071173

分类: 学习

0 条评论

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注