机器学习与数据挖掘人工智能/模式识别/机器学习精华专题呆鸟的Python数据分析

TensorFlow深度学习-第三章

2019-11-27  本文已影响0人  皮皮大

Char3-分类问题

在人工智能上花一年时间,这足以让人相信上帝的存————艾伦​佩利

分类问题典型的应用就是教会机器如何去自动识别图片中物体的种类。本章中主要是介绍了MNIST数据集。

手写数字数据集介绍

数据集是手写数字0-9,具有的特征为:

  1. 真人书写的0-9数字图片

  2. 为了便于存储和计算,将图片缩放到固定的大小size,比如224*224,或者96*96:作为输入x

  3. 每张图片加上标签label,作为图片的真实值y

  4. 一般是通过映射方式进行类别命名;通过0-1表示正反面的方式,叫做数字编码

MNIST数据集具体信息

特征
QpNC1x.png
每张图片信息
  1. 每张图片包含h行(height、row)和w(width、column)列

  2. 每个位置保存了pixel像素值,像素值使用的是0-255来表示强度值,0表示最低,`255表示最高

  3. 如果是彩色图片,每个图片包含RGB三通道,分别是红色、绿色、黄色的颜色强度。保存的形状是[h,w,3]的张量Tensor,即3维数组

  4. 如果是灰色照片,像素点就是一个1维、长度为3的向量;使用形状为[h,w]的二维数组来表示一张图片信息,也可以表示成[h,w,1]形状的张量

QpNm4A.png

利用TF下载MNIST数据

 import os
 import tensorflow as 
 from tensorflow import kreas   # 导入子库
 from tensorflow.kreas import layers, optimizers, datasets
 ​
 (x,y), (x_val, y_val) = datasets.mnist.load_data()   # 加载数据集
 x = 2 * tf.convert_to_tensor(x, dtype=tf.float32) / 255.-1  # 转成张量,并且缩放到-1到1之间
 y = tf.convert_to_tensor(y, dtype=tf.int32)  # 转成张量
 y = tf.one_hot(y, depth=10)   # 热编码形式
 ​
 print(x.shape, y_shape)
 train_dataset = tf.data.Dataset.from_tensor_slices(x,y)  # 构建数据集对象
 train_dataset = train_data.batch(512)  # 批量训练

代码的具体解释:

图片表示方法

  1. 一张图片用shape为[h,w]的矩阵来表示;

  2. 多张图片前面加上维度dimension,使用shape为[b,h,w]的张量来表示,其中b表示batch size(批量)

  3. 多张彩色图片使用shape为[b,h,w,c]表示,c表示的是通道数量channel,彩色图片c=3

调用batch()函数即可构建带batch功能的数据集对象

模型构建

向量形式的生成

  1. 回归模型中,一组长度为​d_{in}的输入向量​​x=[x_1,x_2,…,x_n]^T简化为​​x,表达式为​​
    y=x*w+b

  2. 多输入、单输出的模型结构,借助向量形式
    y=w^Tx+b=[w_1,...,w_n]\cdot[x_1,x_2,...,x_{d_{in}}]^T+b

    Qp03kD.png
  3. 多输出节点、批量训练方式,模型写成张量形式
    Y=X@W+b
    其中X\in R^{b \times d_{in}}b \in R^{d_{out}}Y\in R^{b \times d_{out}}W\in R^{b_{in} \times d_{out }}

QprEtS.png QprEtS.png

对应模型为:

QprYp4.png

x_1^1中的上标表示样本索引号(表示第几个样本),下标表示样本向量的元素(样本的第几个特征)

图片识别任务转成张量形式

  1. 图片的输入格式

一张图片使用的是矩阵方式存储,shape为:[h,w];

b张图片使用shape为[b,h,w]的张量X进行存储

模型只接受向量形式的输入特征向量,需要将矩阵形式平铺成[h*w]​的向量,输入特征的长度为​d_{in}=h*w

Qpy9dP.png
  1. 对于输出标签

数字编码的结果(比如1表示猫,2表示鱼,3表示狗)之间存在天然的大小关系。

解决方法

QpgRT1.png
  1. 手写数字图片数据

总类别数是10,即输出节点总数值​,假设某个样本的类别是i,即图片中的数字是​,需要一个长度为10的向量​,索引号为​的位置设置为1,其余是0。

One-hot编码是非常稀疏Sparse的,占用的存储空间多,所以在存储的时候还是采用数字编码。

# 数字编码转成 one-hot 编码

y = tf.constant([0,1,2,3])  # 数字编码
y = tf.ont_hot(y, depth=10)  # one-hot编码

关于手写数字图片:

  1. 输入是一张打平后的图像量x \in R^{28*28}

  2. 输出是长度为10的向量o \in R^{10}

  3. 真实标签y经过one-hot变成长度为10的稀疏向量y\in \{0,1\}^{10}

  4. 多输入和多输出的线性预测模型是o=W^Tx+b,希望其更接近真实标签y

误差计算

对于分类问题,目标是优化某个性能指标,比如准确度acc。常用的做法是设立一个平滑可导的代理目标函数:模型输出o和真实标签y之间的距离。

通过优化损失函数来找到最优解,采用的是交叉熵cross entropy损失函数
W^*,b^* = arg\min L(o,y)

L(o,y)=\frac{1}{N}\sum^n_{i=1}\sum^{10}_{j=1}(o^i_j-y^i_j)^2

1. 存在的问题:

QpI1MV.png

2. 非线性模型

给线性模型套上一个非线性函数,称之为激活函数\sigma
o=\sigma(Wx+b)

QpoBfs.png
layers.Dense(256, activation='relu')  # 长度为256的向量

3. 多层神经网络

体验手写数字识别

网络搭建

# 构建3层网络
model = keras.Sequential([
  layers.Dense(256, activation='relu'),  # 第1层的输出节点数为256
  layers.Dense(128, activation='relu'),
  layers.Dense(10)  # 输出层节点数设计为10
])

模型训练

对数据集中的所有图片迭代一遍叫做一个Epoch

with tf.GradientTape() as tape:  # 构建梯度记录环境
  
  # 1. 拍平 [b, 28, 28] ---> [b, 784]
  x = tf.reshape(x, (-1, 28*28))   
  # 2. 输出 [b,784]  --->[b,10]
  out = model(x)   
  # 3. 计算梯度:自带的自动求导函数求解
  grads = tape.gradient(loss, model.trainable_variables)
  # 4. 更新网络参数 
  optimizer.apply_gradients = (zip(grads, model.trainable_variables))
上一篇 下一篇

猜你喜欢

热点阅读