跟王小美与三岁一起学paddle — 图像分类!


简单有趣带你图像分类

跟王小美与三岁一起学paddle 第三讲

致读者

在看这个notebook的你,对没错就是你

关注王小美喵,点个star⭐谢谢喵

注:本项目部分图片为自制,非授权请勿私自使用

下图是我做的一个小应用,后面有时间会出一期教大家如何从零到完成一个AI应用

王小美:
三岁老师,我打csgo又被打死了,您能不能教我AI自瞄啊!!ε(┬┬﹏┬┬)3、

三岁:
哎呀,怎么能开挂呢?不过AI自瞄倒是一个不错的技术,我们将他应用到生活中能给大家带来许多便利哦!(★ᴗ★)

要自瞄首先就要知道物体的位置,这时候就需要目标检测技术,在学习目标检测之前我们先从图像分类开始吧!!!

图像分类

根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法

我们从一个图像分类问题开始。 假设每次输入是一个2x2的灰度图像。 我们可以用一个标量表示每个像素值。每个图像有四个特征x1,x2,x3,x4

假设每个图像属于类别“猫”“鸡”和“狗”中的一个。接下来,我们要选择如何表示标签?ヾ(=・ω・=)o

独热编码(one-hot encoding)

独热编码是一个向量,它的分量和类别一样多。 类别对应的分量设置为1,其他所有分量设置为0。

在我们的例子中,标签将是一个三维向量(1,0,0)代表“猫” ,(0,1,0)代表“鸡”,(0,0,1)代表“狗”

三岁:
上节课我们将的线性回归是一个回归任务,而这节课的图像分类是个分类任务,让我们来看看他们的网络结构有什么不同吧!

三岁:
像上图这样,每个输出都是由所有输入影响的网络层,我们称之为全连接层(Full connection layer)╮( ̄▽ ̄)╭

上图中的O我们称之为 未规范化的预测(logit)

三岁:
接下来就是本节课的重点了(敲黑板,哦不敲notebook)

相信你已经能知道我们是如何通过神经网络来预测分类结果了

我们希望模型的输出Yj可以视为属于类j的概率, 然后选择具有最大输出值的类别作为我们的预测。
例如,如果Y1、Y2、Y3分别为0.1、0.8和0.1, 那么我们预测的类别是2,在我们的例子中代表“鸡”。

但是我们通过上面的网络输出的Oj并不是像Yj这样和为1的正数,我们要如何对Oj进行处理呢?接下来就要用到softmax函数了

SoftMax函数

softmax函数能够将未规范化的预测变换为非负数并且总和为1,同时让模型保持 可导的性质。

为了完成这一目标,我们首先对每个未规范化的预测求幂,这样可以确保输出非负。

为了确保最终输出的概率值总和为1,我们再让每个求幂后的结果除以它们的总和

softmax运算不会改变未规范化的预测之间的大小次序,只会确定分配给每个类别的概率

尽管softmax是一个非线性函数,但softmax回归的输出仍然由输入特征决定。 因此,softmax回归是一个线性模型

王小美:
那为什么不直接让 Oj/sum(Oj) 呢?
三岁:
其实这里面就涉及到许多数学上的内容了

其实我们使用softmax函数处理的话可以让我们输出的大部分值处在一个范围区间

在我们生活中,热水器的控温是不是没有在0到100度之间,而是在一个人体感受良好的范围内,这是不是就利于我们调节了

softmax函数其中就具有这个思想

三岁:
得到预测值之后我们就需要设计损失函数来计算与真实值的损失从而调整权重了

交叉熵(cross-entropy loss)

交叉熵(Cross Entropy)是Shannon信息论中一个重要概念

它是分类问题最常用的损失之一

这边借用李沐大佬的图

王小美:
那么交叉熵是怎么来的呢?
三岁:

竟然你诚心诚意的发问了,那我就大发慈悲的告诉你把!

要明白交叉熵首先要知道什么是熵

信息熵

信息熵也被称为熵,用来表示所有信息量的期望。

期望是试验中每次可能结果的概率乘以其结果的总和。

所以信息量的熵可表示为:

例如

三岁:

明白了熵的概念后,我们再来看一下什么是KL散度

KL散度

如果对于同一个随机变量X有两个单独的概率分布P(x)和Q(x),则我们可以使用KL散度来衡量这两个概率分布之间的差异。

在我们的例子中,标签将是一个三维向量(1,0,0)代表“猫” ,(0,1,0)代表“鸡”,(0,0,1)代表“狗”

如果我们预测一张图像是猫的真实分布P(X)是(1,0,0) softmax函数输出是预测分布Q(X) = (0.7,0.2,0.1)

三岁:
将KL散度拆开,就能看到交叉熵了 ̄▽ ̄

王小美:

原来是这样啊,我懂了!(p≧w≦q)

小结

softmax运算可以把网络输出结果转换成概率

softmax回归适用于分类问题,它使用了softmax运算中输出类别的概率分布。

交叉熵是一个衡量两个概率分布之间差异的很好的度量,它测量给定模型编码数据所需的比特数。

三岁:

让我们来通过paddle的api快速对Mnist数据集实现softmax回归吧!ヾ(=・ω・=)o

Mnist数据集是一个手写数字数据集哦!

SoftMax回归的代码实现(基于paddle2.0)

三岁:

还记得我说的步骤吗?

1.数据处理

2.网络搭建

3.模型训练和调参

4.模型推理

5.模型部署

1.数据处理

paddle数据集函数介绍


paddle.vision.datasets.MNIST

MNIST 数据集的实现。

参数

image_path (str,可选) - 图像文件路径,如果 download 参数设置为 True,image_path 参数可以设置为 None。默认值为 None,默认存放在:~/.cache/paddle/dataset/mnist。

label_path (str,可选) - 标签文件路径,如果 download 参数设置为 True,label_path 参数可以设置为 None。默认值为 None,默认存放在:~/.cache/paddle/dataset/mnist。

mode (str,可选) - ‘train’ 或 ‘test’ 模式两者之一,默认值为 ‘train’。

transform (Callable,可选) - 图片数据的预处理,若为 None 即为不做预处理。默认值为 None。

download (bool,可选) - 当 data_file 是 None 时,该参数决定是否自动下载数据集文件。默认值为 True。

backend (str,可选) - 指定要返回的图像类型:PIL.Image 或 numpy.ndarray。必须是 {‘pil’,’cv2’} 中的值。如果未设置此选项,将从 paddle.vision.get_image_backend 获得这个值。默认值为 None。

1
2
3
4
5
6
import paddle
from paddle import nn # 组网函数api
# 通过paddle2.0的数据集读取api读取数据
from paddle.vision.transforms import ToTensor
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=ToTensor())
val_dataset = paddle.vision.datasets.MNIST(mode='test', transform=ToTensor())
item   26/2421 [..............................] - ETA: 5s - 2ms/item

Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-images-idx3-ubyte.gz 
Begin to download


item 8/8 [============================>.] - ETA: 0s - 3ms/item


Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-labels-idx1-ubyte.gz 
Begin to download

Download finished


item  67/403 [===>..........................] - ETA: 0s - 2ms/item

Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-images-idx3-ubyte.gz 
Begin to download


item 2/2 [===========================>..] - ETA: 0s - 2ms/item


Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-labels-idx1-ubyte.gz 
Begin to download

Download finished

2.网络搭建

组网函数介绍


paddle.nn.Sequential

顺序容器。子 Layer 将按构造函数参数的顺序添加到此容器中。传递给构造函数的参数可以 Layers 或可迭代的 name Layer 元组。

softmax回归的输出层是一个全连接层。因此,为了实现我们的模型,我们只需在Sequential中添加一个带有10个输出的全连接层


paddle.nn.Flatten

构造一个 Flatten 类的可调用对象。它实现将一个连续维度的 Tensor 展平成一维 Tensor。

参数

start_axis (int,可选) - 展开的起始维度,默认值为 1。

stop_axis (int,可选) - 展开的结束维度,默认值为-1。


paddle.nn.ReLU

ReLU 激活层(Rectified Linear Unit)。计算公式如下:

ReLU(x)=max(0,x)

paddle.nn.Dropout

Dropout 是一种正则化手段,该算子根据给定的丢弃概率 p,在训练过程中随机将一些神经元输出设置为 0,通过阻止神经元节点间的相关性来减少过拟合。

1
2
3
4
5
6
7
Net = paddle.nn.Sequential(
paddle.nn.Flatten(), # 展平
paddle.nn.Linear(784, 512), # 输入线性变换层数目为784个,输出为512个
paddle.nn.ReLU(),
paddle.nn.Dropout(0.2), # 丢弃概率为0.2
paddle.nn.Linear(512, 10) # 输入线性变换层数目为512个,输出为10个
)

3.模型训练

关于使用paddle api进行模型训练的详细介绍


使用 paddle.Model 封装模型

Model 对象是一个具备训练、测试、推理的神经网络。该对象同时支持静态图和动态图模式,通过 paddle.disable_static() 来切换。需要注意的是,该开关需要在实例化 Model 对象之前使用。输入需要使用 paddle.static.InputSpec 来定义。

使用高层 API 训练模型前,可使用 paddle.Model 将模型封装为一个实例,方便后续进行训练、评估与推理。


使用 Model.prepare 配置训练准备参数

用 paddle.Model 完成模型的封装后,需通过 Model.prepare 进行训练前的配置准备工作,包括设置优化算法、Loss 计算方法、评价指标计算方法:

优化器(optimizer):即寻找最优解的方法,可计算和更新梯度,并根据梯度更新模型参数。飞桨框架在 paddle.optimizer 下提供了优化器相关 API。并且需要为优化器设置合适的学习率,或者指定合适的学习率策略,飞桨框架在 paddle.optimizer.lr 下提供了学习率策略相关的 API。

损失函数(loss):用于评估模型的预测值和真实值的差距,模型训练过程即取得尽可能小的 loss 的过程。飞桨框架在 paddle.nn Loss层 提供了适用不同深度学习任务的损失函数相关 API。

评价指标(metrics):用于评估模型的好坏,不同的任务通常有不同的评价指标。飞桨框架在 paddle.metric 下提供了评价指标相关 API。


使用 Model.fit 训练模型

做好模型训练的前期准备工作后,调用 Model.fit 接口来启动训练。 训练过程采用二层循环嵌套方式:内层循环完成整个数据集的一次遍历,采用分批次方式;外层循环根据设置的训练轮次完成数据集的多次遍历。因此需要指定至少三个关键参数:训练数据集,训练轮次和每批次大小:

训练数据集:传入之前定义好的训练数据集。

训练轮次(epoch):训练时遍历数据集的次数,即外循环轮次。

批次大小(batch_size):内循环中每个批次的训练样本数。

除此之外,还可以设置样本乱序(shuffle)、丢弃不完整的批次样本(drop_last)、同步/异步读取数据(num_workers) 等参数,另外可通过 Callback 参数传入
回调函数,在模型训练的各个阶段进行一些自定义操作,比如收集训练过程中的一些数据和参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 预计模型结构生成模型实例,便于进行后续的配置、训练和验证
model = paddle.Model(Net)

# 模型训练相关配置,准备损失计算方法,优化器和精度计算方法
model.prepare(paddle.optimizer.Adam(parameters=Net.parameters()),
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy())

# Adam 优化器出自 Adam 论文 的第二节,能够利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。
#CrossEntropyLoss 计算输入 input 和标签 label 间的交叉熵损失,它结合了 LogSoftmax 和 NLLLoss 的 OP 计算

# 开始模型训练
model.fit(train_dataset,
epochs=5,
batch_size=64,
verbose=1)
The loss value printed in the log is the current step, and the metric is the average value of previous steps.
Epoch 1/5
step 938/938 [==============================] - loss: 0.1564 - acc: 0.9289 - 15ms/step          
Epoch 2/5
step 938/938 [==============================] - loss: 0.1323 - acc: 0.9687 - 16ms/step          
Epoch 3/5
step 938/938 [==============================] - loss: 0.0240 - acc: 0.9779 - 15ms/step          
Epoch 4/5
step 938/938 [==============================] - loss: 0.0049 - acc: 0.9826 - 16ms/step          
Epoch 5/5
step 938/938 [==============================] - loss: 0.0314 - acc: 0.9862 - 15ms/step          

模型验证

通过loss和acc的结果来评断模型训练的质量和效率

1
2
3
4
model.evaluate(val_dataset, verbose=1)

# verbose (int,可选) - 可视化的模型,必须为 0,1,2。当设定为 0 时,
# 不打印日志,设定为 1 时,使用进度条的方式打印日志,设定为 2 时,一行一行地打印日志。默认值:2。
Eval begin...
step 10000/10000 [==============================] - loss: 3.5763e-07 - acc: 0.9807 - 2ms/step          
Eval samples: 10000





{'loss': [3.5762793e-07], 'acc': 0.9807}

模型保存与加载

模型训练后,训练好的模型参数保存在内存中,通常需要使用模型保存(save)功能将其持久化保存到磁盘文件中,并在后续需要训练调优或推理部署时,再加载(load)到内存中运行。

1
model.save('/home/aistudio/model/model')  # 保存训练完的模型
1
2
3
4
5
# 加载动态图模型参数和优化器参数
model.load('/home/aistudio/model/model')
model.fit(train_dataset, epochs=2, batch_size=64, save_freq=1, verbose=1)

# 通过它的参数 save_freq可以设置保存动态图模型的频率,即多少个 epoch 保存一次模型,默认值是 1。
The loss value printed in the log is the current step, and the metric is the average value of previous steps.
Epoch 1/2
step 938/938 [==============================] - loss: 0.0352 - acc: 0.9883 - 15ms/step          
Epoch 2/2
step 938/938 [==============================] - loss: 0.0105 - acc: 0.9905 - 15ms/step          
三岁:

本次图像分类是介绍softmax回归的一个小任务,下次讲卷积神经网络的时候我会再和你一起完成一次哦!

今天就讲到这了,竟然没看睡着,不错嘛(o°ω°o)

王小美:

我懂了,原来图像分类是这样做的ヾ(≧?≦)〃
太棒了!!!

作者简介

ID:Flose

School:浙大宁波理工学院

专业:自动化

宁理炼丹师协会-飞桨领航团QQ群:699816720

深度学习菜狗,正在不断努力,咱们一起加油