Tensorflow 数字识别分类应用实例

@@@@@@@@@@@@@@@@@@@@
基于MOOC中国慕课大学,浙江大学城市学院课程:深度学习应用开发-TensorFlow实践
基于Tensorflow的版本: 2.0.0-beta0 和 Jupyter 编程工具
@@@@@@@@@@@@@@@@@@@@

多分类: MNIST手写数字识别

有监督学习实例:

通过给予的 60000 条 训练集 数据 和 10000 条 测试集 数据,来给不同的手写数字图象进行分类。

准备数据

加载tensorflow库等

# 这是一个 有监督学习 的分类问题
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

通过接口下载数据

# 通过接口去下载数据
mnist = tf.keras.datasets.mnist
(train_images, train_labels),(test_images,test_labels) = mnist.load_data()

读取数据

# 本例中包含了 60000 条数据作为 训练集,10000 条数据作为 测试集
print("Train image shape:",train_images.shape,"Train label",train_labels.shape)
# 每条数据是以图像形式存放的 ,都是28像素 * 28像素的 28*28=784
print("Test image shape:",test_images.shape,"Test label",test_labels.shape)

显示结果如下图所示:
训练集的 特征数据 是 60000 条,每条数据是 2 维矩阵,28行 乘 28列 ,标签数据 是一个标量
测试集的 特征数据 是 10000 条,每条数据是 2 维矩阵,28行 乘 28列 ,标签数据 是一个标量
在这里插入图片描述
显示数据的基本信息

# 显示训练集的特征数据
print("image data:",train_images[0])
# 查看训练集标签数据
print("label data:",train_labels[0])

定义显示图像的函数,用来查看数据

# 定义 显示图像的函数,用来查看数据
def plot_image(image):
    # 把图片绘制成 28 * 28的 灰度模式(只有灰和白) 显示
    plt.imshow(image.reshape(28,28),cmap="binary")
    plt.show()

plt.imshow()第二个参数是这个图像的模式参数,“binary”表示以灰度模式(只有黑色和白色)显示。
plt.imshow()函数中的图像数据参数支持以下数据形状:

  • (M,N) :二维数值,代表图像大小为M行N列,值为每个像素点的取值。
  • (M,N,3) :三维度数值,代表图像大小为M行N列(即图片的高和宽),每个像素点的取值具有RGB三个通道的值(float或uint8)。
  • 参数cmap缺省值为none,将把图像数据映射为彩色图显示
# 查看 训练集 数据
plot_image(train_images[0])

如下图所示:图片中显示的数字是 5,由 28 行 28 列组成

Tensorflow 数字识别分类应用实例_第1张图片

划分验证集

# 划分验证集,把训练集后 20% 的数据作为验证集来使用

total_num = len(train_images) # 获取训练集的长度,这里是60000

valid_split = 0.2 # 定义验证集比例

train_num = int (total_num * (1-valid_split)) # 训练集的数目 = 训练集的长度 * (1 - 验证集的比例)

train_x = train_images[:train_num] # 训练集特征
train_y = train_labels[:train_num] # 训练集标签

valid_x = train_images[train_num:] # 验证集特征
valid_y = train_labels[train_num:] # 验证集标签

test_x = test_images # 测试集特征
test_y = test_labels # 测试集标签

数据的 降维 处理和数据 归一化 处理

# 把 28 * 28 的元素拉直成 1行 784列
# 二维变成了一维
train_x = train_x.reshape(-1,784)
valid_x = valid_x.reshape(-1,784)
test_x = test_x.reshape(-1,784)

# 特征数据归一化 除以255.0 ,因为二维数组的每个值在 0~255 之间 颜色
train_x = tf.cast(train_x/255.0,tf.float32)
valid_x = tf.cast(valid_x/255.0,tf.float32)
test_x = tf.cast(test_x/255.0,tf.float32)
train_x[0]

下图所示:数据归一化后的结果 0~1 之间 ,处理后的形状为 shape=(784,)
Tensorflow 数字识别分类应用实例_第2张图片

处理标签数据
这里将数据 变成 独热编码 的形式

# 对标签数据进行独热编码,且分类为10 第一个元素是5,第二个是0
# 0 的话就这样编码[1., 0., 0., ..., 0., 0., 0.],
# 5 的话这样编码[0.,0.,0.,0.,0.,1.,..., 0., 0.], 
train_y = tf.one_hot(train_y,depth=10)
valid_y = tf.one_hot(valid_y,depth=10)
test_y = tf.one_hot(test_y,depth=10)

train_y
构建模型
Tensorflow 数字识别分类应用实例_第3张图片

如上图 所示就是进行此次分类应用的模型,该模型相当于全连接的神经网络
其中 x 代表了输入的数字图片,w代表了权重,b代表了偏置,y代表了 分类 的类别(0-9),

x 是 1 * 784(1行784列) w 是 784 * 10 (784行10列)b 是 1 行 10 列的向量 ,x * w = 1 * 10 (1行10列的矩阵)
x * w + b = y

  • softmax函数的原理:
    • 逻辑回归公式:
      Tensorflow 数字识别分类应用实例_第4张图片
    • 预期结果:
      Tensorflow 数字识别分类应用实例_第5张图片

利用这个softmax函数,我们把 输出的类别值 y 变成了 这个 样本x 在模型中 属于这个类别的 概率,这张图片的 所有 类别 概率和为 1

Tensorflow 数字识别分类应用实例_第6张图片

构建模型

# 构建模型 
def model(x,w,b):
    pred = tf.matmul(x, w) + b
    
    # softmax 函数 返回的是 x样本 中 被分为 y 类别的概率 (一张图片有10种可能,10个概率值)
    return tf.nn.softmax(pred)

定义模型变量

# 以正太分布的随机数初始化权重 W,以常数0初始化偏置 B
# 矩阵 W 784 行 10 列
W = tf.Variable(tf.random.normal([784,10],mean = 0.0,stddev=1.0,dtype=tf.float32))
# B 是一个一维数组,包含十个 0
B = tf.Variable(tf.zeros([10]),dtype = tf.float32)

定义损失函数
损失函数采用:

def loss(x,y,w,b):
    pred = model(x,w,b)
    # 传入真实的标签值和根据模型预测的样本值
    loss_ = tf.keras.losses.categorical_crossentropy(y_true = y,y_pred = pred)
    return tf.reduce_mean(loss_) # 返回均值

定义梯度函数

# 定义梯度函数
def grad(x,y,w,b):
    with tf.GradientTape() as tape:
        loss_ = loss(x, y, w, b)
    return tape.gradient(loss_,[w,b]) # 返回梯度向量
# 定义准确率
def accuracy(x,y,w,b): 
    
    pred = model(x,w,b) # 获取预测值
    # 比较预测值与标签值是否相同 equal 方法比对预测值和标签值,如果两者相等,返回True,否则返回False
    correct_prediction = tf.equal(tf.argmax(pred,1), tf.argmax(y,1))
    # 准确率,将布尔值转换为浮点数,并计算平均值 
    return tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
训练模型
training_epochs = 20 # 训练轮数
batch_size = 50 # 单批次训练样本数
learning_rate = 0.001 # 学习率
# 定义梯度下降优化器
optimizer = tf.keras.optimizers.Adam(learning_rate = learning_rate)

total_step = int(train_num/batch_size) # 计算总共训练的轮数
loss_list_train = [] # 保存训练集损失值的列表
loss_list_valid = [] # 保存验证集损失值的列表
acc_list_train = [] # 保存训练集准确率值的列表
acc_list_valid = [] # 保存验证机准确率值的列表
for epoch in range(training_epochs):
    for step in range(total_step):
        
        # 每轮、单批次训练样本数的切片
        xs = train_x[step * batch_size:(step+1) * batch_size]
        ys = train_y[step * batch_size:(step+1) * batch_size]
        
        grads = grad(xs, ys, W, B) # 计算梯度
        optimizer.apply_gradients(zip(grads, [W,B])) # 优化器根据梯度自动调整变量w和b
    
    loss_train = loss(train_x, train_y, W, B).numpy() # 当前轮 训练集的损失
    loss_valid = loss(valid_x, valid_y, W, B).numpy() # 当前轮 验证集的损失
    
    acc_train = accuracy(train_x, train_y, W, B).numpy()
    acc_valid = accuracy(valid_x, valid_y, W, B).numpy()
    
    loss_list_train.append(loss_train)
    loss_list_valid.append(loss_valid)
    
    acc_list_train.append(acc_train)
    acc_list_valid.append(acc_valid)
    
    print("epoch={:3d},train_loss={:.4f},train_acc={:.4f},val_loss={:.4f},val_acc={:.4f}".format(epoch+1, loss_train, acc_train,loss_valid,acc_valid))
# 损失函数图像
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.plot(loss_list_train,"blue",label = "Train Loss")
plt.plot(loss_list_valid,"red",label = "Vaild Loss")
plt.legend(loc = 1)# 通过参数指定图例位置
# 准确率函数图像
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.plot(acc_list_train,"blue",label = "Train Acc")
plt.plot(acc_list_valid,"red",label = "Vaild Acc")
plt.legend(loc = 1)# 通过参数指定图例位置
# 显示 测试集 的准确率
acc_test = accuracy(test_x,test_y, W, B).numpy()
print("Test Accuracy:",acc_test)
进行预测
# 定义预测函数
def predict(x,w,b):
    pred = model(x,w,b) #计算预测模型
    result = tf.argmax(pred,1).numpy()
    return result
pred_test = predict(test_x,W,B)
pred_test[0]
# 可视化结果
def plot_images_labels_prediction(images,
                                  labels,
                                  preds,
                                  index = 0,
                                  num = 10 ):
    fig = plt.gcf()# 获取当前图表,Get Current Figure
    fig.set_size_inches(10,4)
    if num > 10:
        num = 10
    for i in range(0,num):
        ax = plt.subplot(2,5,i+1)
        
        ax.imshow(np.reshape(images[index],(28,28)),cmap="binary") # 显示第 index个图像
        
        title = "label = " + str(labels[index]) # 构建 该图上要显示的title信息
        
        if len(preds)>0:
            title += ",predict=" + str(preds[index])
        
        ax.set_title(title,fontsize = 10)
        ax.set_xticks([]);
        ax.set_yticks([]);
        index = index + 1
    plt.show()
课后作业

调参过程:

下图展示了训练轮数 20轮,学习率为0.01 时的函数图像

  • 训练集损失函数和验证集损失
    Tensorflow 数字识别分类应用实例_第7张图片

根据图中展示的 红色和蓝色的曲线中可以得到 当前模型对于验证数据集的 误差 越来越大
要寻找的模式是那个 验证误差不大,且损失一直下降,对测试集的准确率更高的
这里还没有过拟合,过拟合的话函数图像会有上升趋势!这样追求的是泛化能力最好的!

  • 训练集准确度和验证集准确度
    Tensorflow 数字识别分类应用实例_第8张图片
    此时测试集的准确率为:Test Accuracy: 0.9134

下图展示了训练轮数 20轮,学习率为0.005 时的函数图像

  • 训练集损失函数和验证集损失
    Tensorflow 数字识别分类应用实例_第9张图片
  • 训练集准确度和验证集准确度
    Tensorflow 数字识别分类应用实例_第10张图片
    此时测试集的准确率为:Test Accuracy: 0.9153

下图展示了训练轮数 20轮,学习率为0.001 时的函数图像

  • 训练集损失函数和验证集损失
    Tensorflow 数字识别分类应用实例_第11张图片
  • 训练集准确度和验证集准确度
    Tensorflow 数字识别分类应用实例_第12张图片
    此时测试集的准确率为:Test Accuracy: 0.9071

下图展示了训练轮数 20轮,学习率为0.00095 时的函数图像

  • 训练集损失函数和验证集损失
    Tensorflow 数字识别分类应用实例_第13张图片

  • 训练集准确度和验证集准确度
    Tensorflow 数字识别分类应用实例_第14张图片
    此时测试集的准确率为:Test Accuracy: 0.9046

选择第三次 或者 第四次的模型都可以

你可能感兴趣的:(Tensorflow)