基于神经网络的图像识别

 

一、目的

1. 了解深度学习的基本原理;

2. 能够使用 PaddleHub 深度学习开源工具进行图像识别;

3. 能够使用 PaddlePaddle 训练神经网络模型;

4. 能够使用 Paddle 完成手写实验.

5. 能够使用 keras 训练神经网络模型。

二、环境配置:

Anaconda

PaddlePaddle PaddlePaddle-gpu

PaddleHub

Tensorflow2.0.0

Keras2.3.1

Pycharm

4.1 Tensorflow 简介

TensorFlow Google 开发的一款神经网络的 Python 外部的结构包,也是一个

采用数据流图来进行数值计算的开源软件库.TensorFlow 让我们可以先绘制计算

结构图,也可以称是一系列可人机交互的计算操作,然后把编辑好的Python文件转

换成更高效的 C++,并在后端进行计算。TensorFlow 无可厚非地能被认定为神经

网络中最好用的库之一。它擅长的任务就是训练深度神经网络.通过使用

 

TensorFlow 我们就可以快速的入门神经网络,大大降低了深度学习(也就是深度

神经网络)的开发成本和开发难度。TensorFlow 的开源性,让所有人都能使用

并且维护,巩固它。使它能迅速更新,提升。

因为 TensorFlow 是采用数据流图(data flow graphs)来计算,所以首先我们

得创建一个数据流流图,然后再将我们的数据(数据以张量(tensor)的形式存在)

放在数据流图中计算。节点(Nodes)在图中表示数学操作,图中的线(edges)则

表示在节点间相互联系的多维数据数组,即张量(tensor)。训练模型时 tensor 会不

断的从数据流图中的一个节点 flow 到另一节点,这就是 TensorFlow 名字的由来。

Tensor 张量意义:张量有很多种,零阶张量为纯量或者标量,一阶张量为向

量,二阶张量为矩阵,以此类推。

 

4.2 Keras 简介

4.2.1 Keras 简单介绍

Keras 是一个开放源码的高级深度学习程序库,是一个用 Python 编写的高级

神经网络 API,能够运行在 TensorFlow Theano 之上。其主要作者和维护者是

Google 公司的工程师,以 MIT 开放源码方式授权。Keras 使用最少的程序代码、

花费最少的时间就可以建立深度学习模型,进行训练、评估准确率,并进行预测。

相对来说,使用 TensorFlow 这样低级的链接库虽然可以完全控制各种深度学习

模型的细节,但是需要编写更多的程序代码,花费更多时间进行开发。

 

Keras 的开发重点是支持快速的实验,能够把你的 idea 迅速转换为结果

 

4.2.2 为什么选择 Keras

1.Keras 被工业界和学术界广泛采用;

2.Keras 模型可以轻松部署在更广泛的平台;

3.Keras 支持多个后端引擎;

4.Keras 拥有强大的多 GPU 和分布式训练支持;

5.Keras 的发展得到深度学习生态系统中的关键公司的支持。

4.3 Tensorflow Keras 的安装

在配置好 anaconda 环境,可以直接使用 pip 的情况下,这里注意激活了虚拟

环境。使用 pip 下载 TensorFlow2.0.0 库和 Keras2.3.1 库。

4.3.1 Tensorflow 的安装

 

 

 

4.3.2 Keras 的安装

 

 

 

 

4.3.3 Tensorflow keras 的安装测试

点击 开始,选择 运行 (也可以快捷键 win+R),进入 cmd

 

 

 

或者进入 anaconda prompt,开始菜单进入,选择。

 

 

 

激活虚拟环境 paddle37

 

输入命令:activate paddle37

进入 python 环境

 

导入 keras 命令:import keras

 

出现如图所示,表示 keras 安装运行成功。

 

利用 Keras 进行一个程序的测试

使用 Keras 运行一个简单例子,用来对 IMDB 的正负电影评论进行分类。

import keras

from keras import models

from keras import layers

from keras.datasets import imdb

import numpy as np

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

def vectorize_sequences(sequences, dimension=10000):

# Create an all-zero matrix of shape (len(sequences), dimension)

results = np.zeros((len(sequences), dimension))

for i, sequence in enumerate(sequences):

results[i, sequence] = 1. # set specific indices of results[i] to 1s

return results

# Our vectorized training data

x_train = vectorize_sequences(train_data)

# Our vectorized test data

x_test = vectorize_sequences(test_data)

# Our vectorized labels

y_train = np.asarray(train_labels).astype('float32')

y_test = np.asarray(test_labels).astype('float32')

model = models.Sequential()

model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))

model.add(layers.Dense(16, activation='relu'))

 

model.add(layers.Dense(1, activation='sigmoid'))

model.compile(optimizer='rmsprop',

loss='binary_crossentropy',

metrics=['acc'])

model.fit(x_train, y_train, epochs=4, batch_size=512)

result = model.evaluate(x_test, y_test)

print(result)

结果如下:

 

本文介绍的 Keras CPU 版本的安装,推荐大家以后尽可能使用 GPU 版本,提高运算速度。

 跑完本代码发现,CPU 版本下某些模型的训练时间还是比较长的。例如使

VGG 预训练模型,对 Kaggle 猫狗分类问题进行训练,并微调 VGG 顶层

参数,整个训练时间达到了 5 个小时左右。

 如果安装 GPU 版本,需要额外安装 CUDA Toolkit + cuDNN。需要特别注

意的是 CUDA+cuDNN 的版本。因为每个人的 GPU 显卡型号和安装版本不尽

相同,所以本文不再赘述。

没有 GPU,本代码基本也能跑得通,就是大型模型的训练速度比较慢。

 

2利用 Keras 实现 CNN 实现手写数字识别

4.5.1 加载 keras 手写数字识别实验相关的类库。

 

4.5.2 加载数据集

 

 

本实验使用的 mnist 数据集可以使用 Keras 直接加载。文件内容包括:训练数

据、测试数据两部分,分别包含 6000010000 条手写数字数据,每个样本都是

28*28 像素的。

4.5.3 数据预处理

 

 

使用 keras 必须声明输入图像深度的尺寸,例如,具有所有 3 RGB 通道

的全色图像的深度为 3。本实验中,我们将深度定为 1,将数据集从形状

n,rows,cols)转换为(n,rows,cols,channels)。并将数据的大小除以 255 进行归

一化。进行归一化的原因:在不同的评价指标中,量纲单位往往不同,变化区间

 

处于不同的数量级,若不进行归一化,会导致某些指标被忽视,从而影响到数据

分析的结果。归一化本身就是把需要的数据经过一定的处理限制在一定的范围

内。np_utils.to_categorical 是将标签转换为热值码,我们需要将 0-9 共十个数字

标签转化成 onehot 标签,例如:数字标签“6”转化为 onehot 标签就是[000

0001000]

4.5.4 构建网络

 

 

 

卷积神经网络由多个卷积层和池化层组成,如下所示。卷积层负责对输入进

行扫描以生成更抽象的特征表示,池化层对这些特征表示进行过滤,保留最关键

的特征信息。

 

2. 编译、训练、评估、保存模型

 

编译模型时,声明损失函数采用交叉熵和优化器(SGD,Adam 等),接着,

传入训练集数据进行训练,batch 大小设置为 32,训练周期设为 3,接下来,传

入测试集数据对模型进行评估,最后将训练好的模型保存为 h5 格式的模型文件。

3. 训练结果 模型训练结果:

 

模型评估结果:

 

 

 3 利用 Paddle 实现手写识别

 

4.6.1 神经网络

神经网络(Neural Network) 是一种计算机模型或者数学模型,是存在于计算

机的神经系统,由大量的神经元相连接并进行计算,在外界信息的基础上,改变

内部的结构,常用来对输入和输出之间复杂的关系进行建模。

下图就是一个神经网络系统,它有很多层组成。输入层(Input Layer)负责

接受信息。输出层(Output Layer)是计算机对这个输入信息的判断结果。中间

的隐藏层(Hidden Layer)是对输入信息的传递和加工处理。

 

4.6.2 如何训练神经网络

每个神经元都有属于它的激活函数(activation function),用这些函数给计

首先需要很多数据。比如它要判断一张图片是不是猫,就要输入上千万张带

有标签的猫猫狗狗的图片,然后再训练上千万次。其次,错误的结果也可以帮助

神经网络进行训练,经网络将会对比正确答案和错误答案之间的区别,然后把这

个区别反向的传递回去,对每个相应的神经元向争取的方向进行一点点的改变。

那么在下一次训练的时候就可以用已经改进过的神经元去得到稍微准确的结构。

每个神经元都有属于它的激活函数(activation function),用这些函数给计算

机一个刺激行为。在第一次给计算机看猫的图片时,只有部分的神经元被激活,

被激活的神经元所传递的信息是对输出结果最有价值的信息。如果输出的结果被

判定为是狗,也就是说是错误的,那么就会修改神经元,一些容易被激活的神经

元会变得迟钝,另外一些神经元会变得敏感,这样一次次的训练下去,所有神经

元的参数都在被改变,它们变得对重要的信息越来越敏感。

 

 

4.6.3 梯度下降(Gradient Descent

 

 

运用神经网络的时候,必然会用到误差方程(Cost Function):

Cost=(predicted-real)^2=(Wx-y)^2,

用来计算预测出来的值和我们实际的值的差别.梯度是当前 Cost 的斜率,

Cost 误差最小的地方就是 cost 曲线最低的地方,而当前所知道的是自己所在位

置的一个下降方向,则朝向当前方向继续下降,直至梯度线躺平,此时就得到

Wx-y 参数的最理想值。

4.6.4 卷积神经网络 CNN

卷积神经网络(Convolutional Neural Networks,CNN)是一类包含卷积计算

且具有深度结构的前馈神经网络,是深度学习的代表算法之一。卷积神经网络仿

造生物的视知觉(( visual perception)机制构建,能够进行平移不变分类。对卷

积神经网络的研究始于二十世纪 80 90 年代,LeNet-5 是较早出现的卷积神经

网络。

加入采用全连接网络进行图像分类:

 

CNN 特点之一:局部卷积

可以把卷积想象成作用于矩阵的一个滑动窗口函数。滑动窗口又称作卷积

核、滤波器或是特征检测器。

对于给定的输入图像,输出特征图中每个像素实际上是输入图像中局部区域

中像素的加权平均,其权值由卷积核定义。

卷积具体实例:

 

 

CNN 特点之二:多卷积核

为了充分提取特征,可以使用多个卷积核

每个卷积核都会对输入图像进行卷积处理,生成另一幅图像。不同卷积核生

成的不同图像可以理解为是该输入图像的不同通道。

CNN 特点之三:池化处理

池化处理也叫作降采样处理(down-pooling),是对不同位置的特征进行聚合

统计。通常是取对应位置的最大值(最大池化)、平均值平均池化)等。

池化的优点:1.降维 2.克服过拟合 3.在图像识别领域,池化还能提供平移和

旋转不变性。

CNN 特点之四:多层处理

 

 

一般而言,在图像处理中,一层卷积及降采样往往只学到了局部的特征。层

数越多,学到的特征越全局化。因此通过这样的多层处理,低级的特征组合形成

更高级的特征表示。

4.6.5 MNIST 数据集

Mnist 数据集分为两部分,分别含有 50000 张训练图片和 10000 张测试图片。

每一张图片包含 28*28 个像素。Mnist 数据集把代表一张图片的二维数据转

开成一个向量,长度为 28*28=784。因此在 Mnist 的训练数据集中训练图片是一

个形状为[50000, 784]的张量,第一个维度数字用来索引图片,第二个维度数字

用来索引每张图片中的像素点,图片里的某个像素的强度值介于-1-1 之间。

4.6.6 步骤

在配置好 anaconda 环境,可以直接使用 pip 的情况下,使用 pip 下载

paddlepaddle 库和paddlepaddle-hub 库。

加载飞浆平台与手写数字识别实验相关的类库。

数据读取与数据集划分

本实验使用的mnist 数据集以json 格式存储在本地。

'./"目录下读取文件名称为'mnist.json.gz' MINST 手写数字识别数据,文

件格式是压缩后的 json 文件。文件内容包括:训练数据、验证数据、测试数据三

 

部分,分别包含 500001000010000 条手写数字数据和两个元素列表。以训练

集数据为例,它为两个元素的列表为[traim_imgs, train_labels]

train_imgs:一个维度为[50000,784]的二维列表,包含 50000 张图片。每张图

片用一个长度为 784 的向量表示,内容是 28*28 尺寸的像素灰度值(黑白图片)

train_labels:一个维度为[50000,]的列表,表示这些图片对应的分类标签,即

0-9 之间的一个数字。

接下来将数据读取出来:

 

 

定义数据读取函数

飞桨提供分批次读取数据函数 paddle.batch,该接口是一个 reader 的装饰器,

返回的 reader 将输入的 reader 的数据打包,成指定的 batch_size 大小的批处理数据

(batched.data)

在定义数据读取函数中,我们需要做很多事情,包括但不限于:

打乱数据,保证每轮训练读取的数据顺序不同。

数据类型转换。

 

 

 

 

上面代码中 mode 参数可以取三个值中的一个,分别是 trainvalideval

选择的模式不同,读取的数据集也不同,为了兼容后面的代码,读取后的变量都

 

相同,都是 imgslabels;

在数据生成器中,只有在 mode train 的情况下我们才考虑把读取的数据打

;接下来是数据格式处理,目标类型是 shape[1,28,28],1 表示灰度图,数据类型

float32;通过 yield 关键字返回一个 batch 的数据;在最后一个 index_list 中,如

imgs_list 长度不满足一个 batch,这时 imgs_list 长度不为零,会直接跳出 for

循环,被后面的 len(imgs_list)拦截,形成一个小的 mini-batch

为机器校验代码,如果数据集中的图片数量和标签数量不等,说明数据逻辑

存在问题。可以使用 assert 语句校验图像数量和标签数据是否一致。

人工校验方法:首先打印数据输出结果,观察是否是设置的格式。再从训练

的结果验证数据处理和读取的有效性。实现数据处理和加载函数后,我们可以调

用它读取一次数据,观察数据的 shape 和类型是否与函数中设置的一致。

定义模型结构

 

 

 

 

卷积神经网络由多个卷积层和池化层组成,如下所示。卷积层负责对输入进

行扫描以生成更抽象的特征表示,池化层对这些特征表示进行过滤,保留最关键

的特征信息。

线性模型的局限性:只通过线性变换,任意层的全连接神经网络和单层神经

网络的表达能力并没有任何区别,线性模型能解决的问题是有限的。激活函数的

目的是去线性化,如果将每一个神经元的输出通过一个非线性函数,那么整个神

经网络的模型也就不再是线性的了,这个非线性函数就是激活函数。

评价某个激活函数是否有用时,需要考虑的因素有:

1)该函数应是单调的, 这样输出便会随着输入的增长而增长,从而使利用梯度

下降法寻找局部极值点成为可能.

2)该函数应是可微分的,以保证该函数定义域内的任意一点上导数都存在,

而使得梯度下降法能够正常使用来自这类激活函数的输出。

 

relu 函数

 

relu 函数是个非常常用的激活函数,其公式为:f(x) = max(0, x),即,大于 0

的为其本身,否则为 0

.

Tanh 函数

其公式为:y =(exp(x)-exp(-x))/(exp(x)+exp(-x)) = (1 - exp(-2x)) / (1 +

exp(-2x)),导数:df(x)/dx=1-f(x)^2

在具体的例子中,如卷积神经网络 Convolutional neural networks 的卷积层

中,一般使用的激励函数是 relu.在循环神经网络中 recurrent neural networks,一般

使用的是 tanh 或者是 relu

Softmax 函数

Softmax 函数,又称归一指数函数,多用于分类过程,它将多个神经元的输出,

映射到(0.1)区间内。F.softmax 的作用是,输出每一个预测标签(0-9)的的概

率,并且十个预测标签的概率之和为 1

 

训练模型

 

 

 

通过 paddle.set_device API,设置在 GPU 上训练还是 CPU 上训练。参数

device (str):此参数确定特定的运行设备,可以是 cpu gpu:x 或者是 xpu:x。其

中,x GPU XPU 的编号。当 device cpu 时,程序在 CPU 上运行;当 device

gpu:x 时,程序在 GPU 上运行。

opt = paddle.optimizer.SGD(learning_rate=0.01,

weight_decay=paddle.regularizer.L2Decay(coeff=0.1),

parameters=model.parameters())

在深度学习神经网络模型中,通常使用标准的随机梯度下降算法 SGD 更新

参数,学习率 learning_rate 代表参数更新幅度的大小,即步长。当学习率最优

时,模型的有效容量最大,最终能达到的效果最好。学习率和深度学习任务类型

有关,合适的学习率往往需要大量的实验和调参经验。探索学习率最优值时需要

注意如下两点:

学习率不是越小越好。学习率越小,损失函数的变化速度越慢,意味着需要

花费更长的时间进行收敛。

学习率不是越大越好。只根据总样本集中的一个批次计算梯度,抽样误差会

导致计算出的梯度不是全局最优的方向,且存在波动。在接近最优解时,过大的

学习率会导致参数在最优解附近震荡,损失难以收敛。

加入正则化项,避免模型过拟合。

过拟合现象:对于样本量有限、但需要使用强大模型的复杂任务,模型很容

易出现过拟合的表现,即在训练集上的损失小,在验证集或测试集上的损失较大。

过拟合原因:模型过于敏感,而训练数据量太少或其中的噪音太多。

正则化项:为了防止模型过拟合,在没有扩充样本量的可能下,只能降低模

型的复杂度,可以通过限制参数的数量或可能取值(参数值尽量小)实现。在模

型的优化目标(损失)中人为加入对参数规模的惩罚项。当参数越多或取值越大

 

时,该惩罚项就越大。通过调整惩罚项的权重系数,可以使模型在尽量减少训

练损失保持模型的泛化能力之间取得平衡。

正则化项的存在,增加了模型在训练集上的损失。飞桨支持为所有参数加上

统一的正则化项,也支持为特定的参数添加正则化项。前者的实现如下代码所示,

仅在优化器中设置weight_decay 参数即可实现。使用参数coeff 调节正则化项的

权重,权重越大时,对模型复杂度的惩罚越高。

cross_entropy()为计算交差熵函数,常用于分类问题,神经网络的输出层为

输出十个标签的概率模式,因此,正确解标签对应的输出越大,交叉熵的值越

接近0;当输出为1 时,交叉熵误差为0。反之,如果正确解标签对应的输出越

小,则交叉熵的值越大。

paddle.save(model.state_dict(), 'mnist_regul12.pdparams')为输出参数模型函 数,可以用于后续加载继续训练。

结果可视化

 

可视化分析:

训练模型时,经常需要观察模型的评价指标,分析模型的优化过程,以确保

训练是有效的。可选用这两种工具:Matplotlib 库和VisualDL。在此处,仅展示

Matplotlib 的画法。

Matplotlib 库:Matplotlib 库是 Python 中使用的最多的 2D 图形绘图库,

它有一套完全仿照 MATLAB 的函数形式的绘图接口,使用轻量级的 PLT

(Matplotlib)作图是非常简单的。

VisualDL:如果期望使用更加专业的作图工具,可以尝试VisualDL,飞桨

可视化分析工具。VisualDL 能够有效地展示飞桨在运行过程中的计算图、各种

指标变化趋势和数据信息。

 

使用 Matplotlib 库绘制损失随训练下降的曲线图。将训练的批次编号作为 X

轴坐标,该批次的训练损失作为 Y 轴坐标。训练开始前,声明两个列表变量存

储对应的批次编号(iters=[])和训练损失(losses=[]),随着训练的进行,将 iter

losses 两个列表填满。训练结束后,将两份数据以参数形式导入 PLT 的横纵坐标。

最后,调用 plt.plot()函数即可完成作图。

 

结果如下所示:

 

 

  • 6
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaofeimax

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值