TensorFlow2.0深度学习(三)分类问题

1. 手写数字图片数据集

        机器学习需要从数据中间学习,首先需要采集大量的真实样本数据。以手写的数字图片识别为例,如下图所示,需要收集大量的由真人书写的0~9的数字图片,为了便于存储和计算,一般把收集的原始图片缩放到某个固定的大小,比如224个像素的行和224个像素的列(224×224),这张图片将作为输入数据x。同时,需要给每一张图片标注一个标签,它将作为图片的真实值y,这个标签表明这张图片属于哪一个具体的类别,一般通过映射方式将类别名一一对应到从0开始编号的数字,对于手写数字图片识别问题,用数字的0~9来表示类别名字为0~9的图片。

        然后来看一下图片的表示方法。一张图片包含了h行,w列,每个位置保存了像素值,像素值一般使用0~255的整形数值来表达颜色强度信息,例如0表示强度最低,255表示强度最高。如果是彩色图片,则每个像素点包含了R, G, B三个通道的强度信息,分别代表红色通道、绿色通道、蓝色通道的颜色强度,所以与灰度图片不同,它的每个像素点使用一个1维、长度为3的向量来表示,向量的3个元素依次代表了当前像素值上面的R, G, B颜色强值,因此彩色图片需要保存为形状是[h, w, 3]的张量。如果是灰度图片,则使用一个数值来表示灰度强度,因此它只需要一个形状为[h, w]的二维矩阵来表示一张图片信息。

        这里利用TensorFlow自动在线下载MNIST数据集,并转换为Numpy数组格式:

load_data()函数返回两个元祖(tuple)对象,第一个是训练集,第二个是测试集,每个tuple的第一个元素是多个训练图片数据X,第二个元素是训练图片对应的类别数字Y。其中训练集X的大小为(60000,28,28),代表了60000个样本,每个样本由28行、28列构成,由于是灰度图片,故没有RGB通道;训练集Y的大小为(60000,),代表了这60000个样本的标签数字,每个样本标签用一个0~9的数字表示。测试集X的大小为(10000,28,28),代表了10000章测试图片,Y的大小为(10000,)。

        从TensorFlow中加载MNIST数据图片,数值的范围在[0,255]之间。在机器学习中间,一般希望数据的范围在0周围小范围分布。通过预处理步骤,把[0,255]像素范围归一化到[0,1.]区间,再缩放到[-1,1]区间,从而有利于模型的训练。

        每一张图片的计算流程是通用的,在计算的过程中可以一次进行多张图片的计算,充分利用CPU或GPU的并行计算能力。一张图片用shape为[h,w]的矩阵来表示,对于多张图片来说,在前面添加一个数量维度(Dimension),使用shape为[b,h,w]的张量来表示,其中的b代表了batch size(批量);多张彩色图片可以使用shape为[b,h,w,c]的张量来表示,其中的c表示通道数量(Channel),彩色图片c=3。通过TensorFlow的Dataset对象可以方便完成模型的批量训练,只需要调用batch()函数即可构建带batch功能的数据集对象。

2. 模型构建

        在回归问题讨论的生物神经元结构。把一组长度为d_{in}的输入向量x=[x_1,x_2,...,x_{d_{in}}]^T简化为单输入标量x,模型可以表达成y=x*w+b。如果是多输入、单输出的模型结构的话,需要借助于向量形式:

y=\boldsymbol{w}^T\boldsymbol{x}+b=[w_1,w_2,w_3,...,w_{d_{in}}]\cdot\begin{bmatrix}x_1\\x_2\\x_3\\...\\x_{d_{in}}\end{bmatrix}+b

        更一般地,通过组合多个多输入、单输出的神经元模型,可以拼成一个多输入、多输出的模型:

y=Wx+b

其中,x\in R^{d_{in}},\boldsymbol{b}\in R^{d_{out}},\boldsymbol{y}\in R^{d_{out}},W\in R^{d_{out}\times d_{in}}

        对于多输出节点、批量训练方式,将模型写成张量形式:

Y=X@W+b

其中,X\in R^{b\times d_{in}},\boldsymbol{b}\in R^{d_{out}}\text{,Y}\in R^{b\times d_{out}},W\in R^{d_{in}\times d_{out}}d_{in}表示输入节点数,d_{out}表示输出节点数;@符号表示矩阵相乘。

        考虑2个样本,输入特征长度d_{in}=3,输出特征长度d_{out}=2的模型:

\begin{bmatrix}o_1^1&o_2^1\\o_1^2&o_2^2\end{bmatrix}=\begin{bmatrix}x_1^1&x_2^1&x_3^1\\x_1^2&x_2^2&x_3^2\end{bmatrix}\begin{bmatrix}w_{11}&w_{12}\\w_{21}&w_{22}\\w_{31}&w_{32}\end{bmatrix}+\begin{bmatrix}b_1\\b_2\end{bmatrix}

其中上标表示样本索引号,下标表示样本向量的元素。对应模型结构图为

可以看到,通过张量形式表达网络结构,更加简洁清晰,同时也可充分利用张量计算的并行加速能力。

        对于输出标签,前面已经介绍了数字编码,它可以用一个数字来表示便签消息,例如数字1表示猫,数字3表示鱼等。但是数字编码一个最大的问题是,数字之间存在天然的大小关系。如果1,2,3分别对应的标签是猫、狗、鱼,它们之间并没有大小关系,所以采用数字编码的时候会迫使模型区学习这种不要的约束。

        可以将输出设置为d_{out}个输出节点的向量,d_{out}与类别数相同,让第i\in[1,d_{out}]个输出值表示当前样本属于类别i的概率P。如果物体属于第i类的话,那么索引为i的位置上设置为1,其他位置设置为0,把这种编码方式叫做one-hot编码(独热编码)。

        手写数字图片的总类别有10种,即输出节点数为10,那么对于某个样本,假设它属于类别i,即图片的中数字为i,只需要一个长度为10的向量y,向量y的索引号为i的元素设置为1,其他位为0。比如图片0的One-hot编码为[1,0,0,...,0]。One-hot编码是非常稀疏的,相对于数字编码来说,占用较多的存储空间,所以一般在存储时还是采用数字编码,在计算时,根据需要来把数字编码转换成One-hot编码:

        现在回到手写数字图片识别任务,输入是一张打平后的图片向量x\in R^{28\times 28},输出是一个长度为10的向量o\in R^{10},图片的真实标签y经过one-hot编码后变成长度为10的非0即1的稀疏向量。预测模型采用多输入,多输出的线性模型o=W^Tx+b,其中模型的输出记为输入的预测值o,希望o越接近真实标签y越好。把输入经过一次(线性)变换叫做一层网络。

3. 误差计算

        对于分类问题来说,目标是最大化某个性能指标,比如准确率acc,但是把准确率当做损失函数去优化时,会发现\frac{\partial acc.}{\partial \theta}是不可导的,无法利用梯度下降算法优化网络参数。一般的做法是,设立一个平滑可导的代理目标函数,比如优化模型的输出o与One-hot编码后的真实标签y之间的距离,通过优化代理目标函数得到的模型,一般在测试性能上也能有良好的表现。因此,相对回归问题而言,分类问题的优化目标函数和评价目标函数是不一致的。模型的训练目标是通过优化损失函数\mathcal{L}来找到最优数值解W*, b*:

\mathrm{W}^*,\boldsymbol{b}^*=\underbrace{argmin}_{W,\boldsymbol{b}}\mathcal{L}(\boldsymbol{o},\boldsymbol{y})

        对于分类问题的误差计算来说,更常见的是采用交叉熵损失函数,而不是采用回归问题中介绍的均方差损失函数。

4. 真的解决了吗

  • 线性模型
  • 表达能力

        目前所采用的多神经元模型仍是线性模型,表达能力偏弱。

5. 非线性模型

        可以给线性模型嵌套一个非线性函数,即可将其转换为非线性函数。把这个非线性函数称为激活函数(Activation function),用σ表示:

o=σ(Wx+b)

        这里的σ代表了某个具体的非线性激活函数,比如Sigmoid函数,ReLU函数。

6. 表达能力

        针对于模型的表达能力偏弱的问题,可以通过重复堆叠多次变换来增加其表达能力:

h_1=ReLU(W_1x+b_1)

h_2=ReLU(W_2h_1+b_2)

o=W_3h_2+b_3

把第一层神经元的输出值作为第二层神经元模型的输入,把第二层神经元的输出作为第三层神经元的输入,最后一层神经元的输出作为模型的输出o。

        网络结构如下图所示。

7. 优化方法

        对于仅一层的网络模型,如线性回归的模型,可以直接推导出\frac{\partial \mathcal{L}}{\partial w}\frac{\partial \mathcal{L}}{\partial b}的表达式,然后直接计算每一步的梯度,根据梯度更新法则循环更新w,b参数即可。但是,当网络层数增加、数据特征长度增大、添加复杂的非线性函数之后,模型的表达式将变得非常复杂,很难手动推导出梯度的计算公式;而且一旦网络结构发生变动,网络的函数模型也随之发生改变,依赖手工去计算梯度的方式显然不可行。

        这个时候,就可以借助于自动求导(Autograd)技术,深度学习框架在计算函数的损失函数的过程中,会记录模型的计算图模型,并自动完成任意参数\theta的偏导分\frac{\partial \mathcal{L}}{\partial \theta}的计算,用户只需要构建出网络结构,梯度将自动完成计算和更新。

8. 手写数字图片识别体验

        网络搭建

        对于第一层模型来说,接受的输入x\in R^{784},输出h_1\in R^{256}设计为长度为256的向量。使用TensorFlow的Sequential容器可以非常方面地搭建多层的网络。对于3层网络:

快速完成3层网络的搭建,第1层的输出节点数设计为256,第2层设计为128,输出层节点数设计为10。直接调用这个模型对象model(x)就可以返回模型最后一层的输出o。

        模型训练 

        得到模型输出o后,通过MSE损失函数计算当前的误差\mathcal{L}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值