第T1周:实现mnist手写数字识别

学习心得

在学习tensorflow的过程中,它与pytorch的相同点以及不同点十分突出。但是总的来说,在代码实现的过程中,最大的感受还是两者只是在代码格式上的区别,基本内核和核心的部分基本是一样的。不过tensorflow在使用时,对兼容性的要求非常高,很容易出现各种不兼容的报错。建议是在要用的时候再去下载对应的包,不然资源冗杂很容易出现不兼容的情况。还有就是在学习教案上的代码时,尽量做到将涉及的函数的含义和用法全部搞清楚,这样的学习比较系统和科学。

一、前期工作

1.设置GPU

import tensorflow as tf 
gpus = tf.config.list_physical_devices("GPU")
# 这段代码使用了TensorFlow库中的tf.config.list_physical_devices()函数来获取可用的物理设备列表。参数"GPU"表示我们只关心GPU设备,而不关心其他类型的设备(如CPU)。

if gpus:
    gpu0 = gpus[0] #在多个GPU里只选择第0个gpu使用
# 将第一个GPU设备(gpu0)设置为内存增长模式。在这种模式下,TensorFlow会根据需要动态地分配和释放GPU内存,而不是一开始就占用所有可用的GPU内存。
    tf.config.experimental.set_memory_growth(gpu0,True)
# 设置TensorFlow的可见设备。
    tf.set_visible_devices([gpu0],"GPU")

2.导入数据

import tensorflow as tf 
from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt

(train_images, train_labels),(test_images, test_labels) = datasets.mnist.load_data()

Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11490434/11490434 [==============================] - 4s 0us/step

3.归一化

参考文章:K同学啊:归一化与标准化
归一化的作用是使不同量纲的特征处于同一个数量级,减少方差带来的影响,同时加快收敛速度。 特征值较大时,梯度值也较大。在模型反向传播时,梯度值更新与学习率一样。学习率小时会导致收敛缓慢,学习率过大又会导致模型不易收敛。因此将图像归一化可以将不同维度的特征调整到相近的区间内,就可以用统一的学习率加速模型的训练。

归一化:将数收敛到(0,1)之间;缩放仅与最大值最小值有关 标准化:将数据按比例缩放,使其落入特定的区间,与每个值都有关
标准化:与每个点都有关;将数据按比例缩放,使其落入一个特定区间

标准化将数值转化成均值为0,标准差为1的分布(不一定是正态分布)

# 对于灰度图片来说,每个像素最大值是255,每个像素最小值是0,也就是直接除以255就可以完成归一化。
train_images, test_images = train_images / 255.0, test_images / 255.0
train_images.shape, test_images.shape, train_labels.shape, test_labels.shape

((60000, 28, 28), (10000, 28, 28), (60000,), (10000,))

4.可视化图片图

plt.figure(figsize = (20,5))

for i in range(20):
    plt.subplot(2,10,i+1)     # subplot(子图行数,子图列数,子图索引(从1开始))
    # 不显示轴刻度
    plt.xticks([])
    plt.yticks([])
    # 不显示子图网格线
    plt.grid(False)
    # cmap为颜色图谱,“plt.cm.binary将像素值映射为黑色和白色。”
    plt.imshow(train_images[i], cmap = plt.cm.binary)
    # 设置x轴标签显示为对应的数字
    plt.xlabel(train_labels[i])
    
plt.show()

这里是引用

5.调整图片格式

train_images = train_images.reshape((60000,28,28,1)) # 对灰度图像来说,通道数为1
test_images = test_images.reshape((10000,28,28,1))

test_images.shape,test_images.shape, train_labels.shape, test_labels.shape

((10000, 28, 28, 1), (10000, 28, 28, 1), (60000,), (10000,))

构建CNN网络模型

ReLU(整流线性单元)激活函数在神经网络中得到了广泛的应用,主要有以下原因:
缓解梯度消失问题:在深度神经网络中,ReLU可以帮助缓解梯度消失的问题。这是因为ReLU激活函数在输入值小于0时为0,大于0时保持原样,因此不存在梯度为0的情况,从而使得模型训练过程中的梯度求解变得容易。
计算简单且高效:ReLU激活函数的实现只需要一个max()函数,这使得模型的训练过程更加高效。
强大的非线性拟合能力:ReLU函数具有强大的非线性拟合能力,可以最大限度地发挥神经元的筛选能力。虽然从单看ReLU函数的左边或者右边,确实是线性的,整体来看,也确实是分段函数,说它是非线性函数也勉强说得过去。

不会对模型的泛化准确度造成显著影响:ReLU激活函数在保持模型训练速度的同时,并不会对模型的泛化性能产生负面影响。

model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape = (28, 28, 1)),
    layers.MaxPool2D((2, 2)),
    layers.Conv2D(64, (3, 3),activation='relu'),
    layers.MaxPooling2D((2, 2)),
    
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dense(10)
])
model.summary()

这里是引用

使用layers.Dense()的语法如下:

layers.Dense(units, activation=None, use_bias=True, kernel_initializer=‘glorot_uniform’, bias_initializer=‘zeros’, kernel_regularizer=null, bias_regularizer=null, activity_regularizer=null, kernel_constraint=null, bias_constraint=null)
units 参数表示输出空间的维度;
activation 参数用于指定激活函数,如 ‘relu’、'sigmoid’等;
use_bias 参数是一个布尔值,用于决定是否使用偏置项;
kernel_initializer、bias_initializer等参数用于设置权重和偏置项的初始化方法;
kernel_regularizer、bias_regularizer等参数用于设置权重和偏置项的正则化方法;
activity_regularizer 参数用于设置层的正则化方法;
kernel_constraint、bias_constraint等参数用于设置权重和偏置项的约束条件。

三、编译模型

model.compile()是Keras中用于配置模型的编译过程的方法。

model.compile(loss=None, optimizer=None, metrics=None, loss_weights=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None)

参数的说明:
1.loss:损失函数,用于衡量模型预测结果与真实标签之间的差异。常用的损失函数有均方误差(MSE)、交叉熵(categorical_crossentropy)等。
2.optimizer:优化器,用于更新模型的权重以最小化损失函数。常用的优化器有随机梯度下降(SGD)、Adam等。
3.metrics:评估指标,用于衡量模型的性能。常用的评估指标有准确率(accuracy)、精确率(precision)、召回率(recall)等。可以传入一个列表,包含多个评估指标。
4.loss_weights:用于指定不同样本的损失权重。如果提供了这个参数,那么在计算总损失时,每个样本的损失将乘以相应的权重。
5.sample_weight_mode:指定样本权重的模式。可选的值有"temporal"(时间序列模式)和"class_weight"(类别权重模式)。
6.weighted_metrics:用于指定哪些评估指标需要使用权重进行加权平均。可以传入一个列表,包含需要加权的评估指标的名称。
7.target_tensors:用于指定目标张量。在某些情况下,如多输入模型或自定义输出层,可能需要手动指定目标张量。

model.compile(
     optimizer='adam',
     loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
     metrics=['accuracy'])

SparseCategoricalCrossentropy()是Keras中用于计算稀疏类别交叉熵损失函数的方法。它适用于处理稀疏数据集,其中类别的数量相对较少。

四、训练模型

model.fit()是Keras中用于训练模型的方法。它接收一些参数,包括训练数据、验证数据、批次大小、迭代次数等,并使用这些参数来更新模型的权重以最小化损失函数。
它的一般用法为:

model.fit(x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)

参数说明:

x:训练数据的特征。可以是单个输入张量或包含多个输入张量的列表。
y:训练数据的目标值。可以是单个输出张量或包含多个输出张量的列表。
batch_size:每个批次的训练样本数量。
epochs:训练模型的总迭代次数。
verbose:日志显示级别。可选的值有0(不显示任何信息)、1(显示进度条)和2(显示详细计算信息)。
callbacks:一个回调函数列表,用于在训练过程中执行特定操作。常用的回调函数有ModelCheckpoint(保存模型)、EarlyStopping(提前停止训练)等。
validation_split:指定训练数据中用于验证的比例。例如,如果设置为0.2,则表示20%的数据将用于验证。
validation_data:验证数据的特征和目标值。可以是单个输入张量或包含多个输入张量的列表,以及单个输出张量或包含多个输出张量的列表。
shuffle:是否在每个批次之前对训练数据进行洗牌。默认为True。
class_weight:类别权重,用于处理不平衡数据集。可以是一个字典,将类别映射到相应的权重。
sample_weight:样本权重,用于对不同样本进行加权处理。可以是一个数组,与训练数据的形状相同。
initial_epoch:从哪个迭代次数开始训练。默认为0,即从第一个迭代开始。

history = model.fit(
        train_images,
        train_labels,
        epochs = 10,
        validation_data = (test_images, test_labels))

Epoch 1/10
1875/1875 - 23s 12ms/step - loss: 0.1465 - accuracy: 0.9550 - val_loss: 0.0578 - val_accuracy: 0.9806
Epoch 2/10
1875/1875 - 25s 13ms/step - loss: 0.0491 - accuracy: 0.9850 - val_loss: 0.0362 - val_accuracy: 0.9882
Epoch 3/10
1875/1875 - 21s 11ms/step - loss: 0.0334 - accuracy: 0.9895 - val_loss: 0.0451 - val_accuracy: 0.9866
Epoch 4/10
1875/1875 - 20s 11ms/step - loss: 0.0112 - accuracy: 0.9966 - val_loss: 0.0364 - val_accuracy: 0.9899
Epoch 8/10
1875/1875 - 23s 12ms/step - loss: 0.0104 - accuracy: 0.9967 - val_loss: 0.0366 - val_accuracy: 0.9899
Epoch 9/10
1875/1875 - 22s 11ms/step - loss: 0.0078 - accuracy: 0.9974 - val_loss: 0.0501 - val_accuracy: 0.9877
Epoch 10/10
1875/1875 - 22s 12ms/step - loss: 0.0065 - accuracy: 0.9977 - val_loss: 0.0412 - val_accuracy: 0.9905

五、预测

plt.imshow(test_images[1])

在这里插入图片描述

pre = model.predict(test_images)
pre[1]

313/313 [==============================] - 2s 6ms/step
array([ 1.8541143, -3.2595177, 29.620302 , -11.129237 , -4.489938 ,
-20.663198 , 2.7213254, -6.5041213, -1.9739916, -24.11983 ],
dtype=float32)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值