python深度学习tensorflow和fme结合,实现档案扫描件数据自动分类



前言

之前我发过一遍用fme调用谷歌的汉字识别库来实现扫描件分类的文章,虽然能减少大量的人力物力,但是缺点依旧有很多,比如很多扫描件资料文字不清晰,房屋照片图像资料无法识别,文字识别率低,环境配置复杂,同时分类效率低下,大概需要花费1秒才能完成一张照片的分类。于是悟空我开始从深度学习上探索如何实现扫描件的0误差分类。学习了接近一个月的机器学习基础,深度学习算法,终于是实现了这个案例的接近于99的正确率分类。



一、深度学习基础知识简介

1、什么是深度学习

深度学习是机器学习的一个分支,主要通过学习样本数据的内在规律和表示层次,这些学习过程中获得的信息对诸如文字,图像和声音等数据的解释有很大的帮助。它的最终目标是让机器能够像人一样具有分析学习能力,能够识别文字、图像和声音等数据。 深度学习是一个复杂的机器学习算法,在语音和图像识别方面取得的效果,远远超过先前相关技术。

2、深度学习的原理

深度学习为什么叫深度学习,故名思义其实就是通过庞大复杂的卷积层、池化层、隐藏层、全连接层、输出层来对目标进行特征提取,特征降维,通过线性回归的方式,求出能预测输出结果的最合适的权重。深度学习不同于机器学习,其最大的特点就是模拟了人脑的神经网络结构,通过激活函数,来实现快速,高效对目标的计算。

3、深度学习应用场景

深度学习不局限于图像语音识别,深度学习其实就是模拟人脑的一种算法,为什么人和计算机相比计算能力如此低下,却能在大部分时候,分辨物体,神经反射等时候,拥有比计算机更强大的性能,其实就是得益于神经元的和神经元的全连接的结构,平时不做功,但是一旦传入信号,相应的神经元便立刻激活,通过庞大的神经网络,快速做出反应。所以深度学习是一种非常有潜力的技术,可以部署到系统,完成各种复杂的数据计算。


二、深度学习环境搭建


1.深度学习库的安装

我这里选取了谷歌开发的tensorflow2,当然也可以选择pytorch,这个看个人喜好,两者功能几乎没什么区别,只是如果考虑后期部署到服务器给平台后台计算使用,一般我会推荐使用tensorflow,如果是做学术研究,都推荐使用pytorch。安装很简单,只需要pip install tensorflow  就可以了。这里由于我的开发环境是fme,所以我选择fme.exe python -m pip install tensorflow --target "C:Program FilesFMEpython" 进行安装。


2.CUDA和对应版本的cudnn下载

这里我不做赘述,只需要进入官网下载,但是需要注意一点就是,必须要注意版本的对应,我这里用的是11.2CUDA,8.1的CUDNN,2.7的tensorflow,以及python3.7的编译环境。

三、实战教学

1.基础数据集的准备

因为图像分类是监督学习,所以我们需要事先准备好数据集,数据集需要图片本身以及图片对应的目标值。我这里直接截图数据集格式。

 其中每个数字都包含了一种类型的文档扫描件。我一共准备了2300张图片,其实为了满足精度,一般来说图片数量是越多越好,这里的准备我使用了我以前博客提过的调用谷歌的文字识别库的fme模板来处理的基础数据。

2、图片数据集转换为可训练数据集

首先我们需要了解最终我们要输出给神经网络进行训练的数据格式什么样子的,因为神经网络模型不能直接识别图像,所以我们要先将图像转换为一个np.array格式的4维数组如下图所示。

 这里我首先使用了fme的路径读模块,然后筛选出图像,将结果打入字段,同时对要素进行了打乱,因为最终我们需要将数据划分为训练集和测试集,所以这里提前打乱排序,切割样本的时候就会达到均匀的分割。

 这里是我需要导入的模块

import fme
import fmeobjects
import pandas as pd
import tensorflow.keras as keras
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.keras import layers

通过init方法实例化列表对象

    def __init__(self):
        self.all_image=[]  
        self.label=[]
        pass

在input方法中将要素迭代,添加进列表

    def input(self,feature):
        self.all_image.append(feature.getAttribute('path_windows'))
        self.label.append(int(feature.getAttribute('label')))
        self.pyoutput(feature)

将数据划分为训练集和测试集

        split=int(len(self.all_image)*0.8)
        train_dir=self.all_image[ :split]
        test_dir=self.all_image[split: ]
        train_label=np.array(self.label[:split])
        test_label=np.array(self.label[split:])

将训练集列表数据转换为4维数组

        train_image=[]
        for path in train_dir:
            image=keras.preprocessing.image.load_img(path,target_size=(224,224))
            image_array=keras.preprocessing.image.img_to_array(image)
            image_array=image_array/255#数据归一化
            train_image.append(image_array)
        train_image_array=np.stack(train_image)

将测试集列表数据转换为4维数组

        test_image=[]
        for path1 in test_dir:
            image1=keras.preprocessing.image.load_img(path1,target_size=(224,224))
            image1_array=keras.preprocessing.image.img_to_array(image1)
            image1_array=image1_array/255#数据归一化
            test_image.append(image1_array)#生成图片测试集
        test_image_array=np.stack(test_image)

以上基础数据就准备好了,(1867, 224, 224, 3)我在这解释一下这4个维度的数据分辨代表什么,第一个是图片张数,第二个是x轴像素,第三个是y轴像素,最后一个是颜色的rgb通道,如果是黑白就是1,彩色就是3,当然处理过的图片也会出现2的情况,这个结合实际情况而定。

3、模型搭建

这里我的卷积层直接采用了预训练模型 MobileNetV2,当然我们也可以自己搭建神经网络结构。这里我主要讲解一下卷积和池化的概念:卷积按我的理解其实就是对图片特征值提取的一个过程,通过定义的卷积核(在卷积核上定义好权重)然后把图片从左到右从上到下全部摸一遍,最终得到一个卷积核认识过后的初始图像数据,池化层就是在卷积后将图像数据进一步缩小,把厚度进一步加深。这里激活函数我选择的relu,使用的是函数api格式搭建的模型,用了一次Droput防止过拟合

        mobile_net=keras.applications.MobileNetV2(input_shape= 
        (224,224,3),include_top=False)#使用预训练模型,不包括头部
        inputs=keras.Input(shape=(224,224,3))
        x=mobile_net(inputs)

        x=keras.layers.GlobalAveragePooling2D()(x)#将卷积后的数据 展平
        x1=keras.layers.Dense(1024,activation='relu')(x)#构建全链接层
        x2=keras.layers.Dropout(0.5)(x1)
        out_type=keras.layers.Dense(17,activation='softmax')(x2)#构建输出层
        model=keras.Model(inputs=inputs,outputs=out_type)
        model.summary()

4、模型初始化和模型训练以及模型保存

这里没什么好说的,注意的是因为我用了自定义函数,所以只把模型的权重保存。

 可以看到准确率已经到 了百分之98 而且拟合度非常之好。

        model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.0001),loss='sparse_categorical_crossentropy',metrics=['acc'])

model.fit(train_image_array,train_label,epochs=5,batch_size=4,validation_data=(test_image_array,test_label))
        model.save_weights('23333.h5')

5、模型再优化

 首先我要说明,模型的优化最好的方法就是增大数据集,但是很多时候我们并没有这个条件,所以这里就引入了图像增强的方法,由于扫描件数据格式都比较接近,而且训练的结果已经非常理想,我并没有做图像增强,但是我还是简单介绍一下图像增强的原理。过拟合通常发生在训练样本较少时。数据增强采用的方法是从现有示例中生成额外的训练数据,方法是使用随机变换来增强它们,从而产生看起来可信的图像。这有助于将模型暴露于数据的更多方面并更好地概括。 您将使用以下Keras预处理层实现数据增强:tf.keras.layers.RandomFlip,tf.keras.layers.RandomRotation,和tf.keras.layers.RandomZoom。这些可以像其他层一样包含在您的模型中,并在 GPU 上运行。

data_augmentation = keras.Sequential(  [ layers.RandomFlip("horizontal",                                                            input_shape=(img_height,  img_width,  3)),     
                                         layers.RandomRotation(0.1),    
                                         layers.RandomZoom(0.1),  ] )

6、使用模型进行预测

这里我直接调用模型进行预测,并将预测结果保留到字段

       
        pass
    def input(self,feature):
       
        
        
        image=keras.preprocessing.image.load_img(feature.getAttribute('path_windows'),target_size=(224,224))
        image_array=keras.preprocessing.image.img_to_array(image)
        image_array=image_array/255#数据归一化
         
        train_image_array=np.expand_dims(image_array,0)#拓展维度
        #模型结构
        mobile_net=keras.applications.MobileNetV2(input_shape=(224,224,3),include_top=False)#使用预训练模型,不包括头部
        inputs=keras.Input(shape=(224,224,3))
        x=mobile_net(inputs)

        x=keras.layers.GlobalAveragePooling2D()(x)#将卷积后的数据 展平
        x1=keras.layers.Dense(1024,activation='relu')(x)#构建全链接层
        x2=keras.layers.Dropout(0.5)(x1)
        out_type=keras.layers.Dense(17,activation='softmax')(x2)#构建输出层
        model=keras.Model(inputs=inputs,outputs=out_type)
        
        #模型数据初始化(优化函数和loss函数)
       # model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.0001),loss='sparse_categorical_crossentropy',metrics=['acc'])
        #
        model.load_weights('23333.h5')
        
       
        a=model(train_image_array)
        #print(a)
        b=np.argmax(a[0])
      #  print(b)
        feature.setAttribute("分类结果",int(b))
        self.pyoutput(feature)

然后使用filecopy将预测结果整理好转换为文本,并输出为成果 

 可以看到分类效果是非常之好,而且几乎0误差。



总结

通过一个多月的学习,我大概看了接近30个g的各种教程,4本书,从机器学习算法到深度学习实战,也走过很多弯路,自学的过程是痛苦而快乐的,痛苦就痛苦在出错时候你不知道问题出在哪儿,记得当时因为一个显卡的vs编译器版本低导致一直无法训练,我排查了一整天,就用控制变量法,一步一步的试错。快乐就是代码成功运行的时候,那种充实感,成就感可能是任何东西都无法比拟的。还有一点就是关于深度学习,现在网上的教程鱼龙混杂,最终我得出结论,真要学东西,就得去翻官网 翻源码,只要达到这一步,你才能对代码有自己的认识,而不仅仅是一个码代码抄代码的工具。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>