
本文为365天深度学习训练营中的学习记录博客原作者K同学啊学习目的初步使用tensorflow框架进行深度学习的整体运行一、 前期准备关于环境语言环境Python3.6编译器vsCode深度学习环境TensorFlow 2.6.21.数据导入import tensorflow as tf from tensorflow.keras import datasets, layers, models import matplotlib.pyplot as plt # 导入mnist数据依次分别为训练集图片、训练集标签、测试集图片、测试集标签 (train_images, train_labels), (test_images, test_labels) datasets.mnist.load_data()代码解析from tensorflow.keras import datasets, layers, models从tensorflow.keras中导入三个子模块datasets包含一些常用的公开数据集如 MNIST、CIFAR10 等方便我们加载。layers包含构建神经网络所需的各种层如卷积层、池化层、全连接层等。models包含构建模型的高级接口比如Sequential顺序模型。2.归一化# 将像素的值标准化至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代码解析train_images, test_images train_images / 255.0, test_images / 255.0图像中的像素值是 0~255 的整数。神经网络通常对输入数据的尺度敏感较大的数值会导致梯度更新不稳定、训练缓慢。这里将每个像素值除以 255.0将所有像素值缩放到[0, 1]区间。这叫做归一化Normalization能有效加速收敛并提高模型稳定性。注意这里用了浮点数除法/255.0结果变为浮点数。运行结果运行结果解读返回的数据被拆分为四个变量train_images训练集图片是一个形状为(60000, 28, 28)的 NumPy 数组代表 60000 张 28×28 像素的灰度图。train_labels训练集标签形状为(60000,)每个标签是 0~9 的数字表示图片对应的手写数字。test_images测试集图片形状为(10000, 28, 28)用于评估模型性能。test_labels测试集标签形状为(10000,)。3.查看图片# 将数据集前20个图片数据可视化显示 # 进行图像大小为20宽、10长的绘图(单位为英寸inch) plt.figure(figsize(20,10)) # 遍历MNIST数据集下标数值0~49 for i in range(20): # 将整个figure分成2行10列绘制第i1个子图。 plt.subplot(2,10,i1) # 设置不显示x轴刻度 plt.xticks([]) # 设置不显示y轴刻度 plt.yticks([]) # 设置不显示子图网格线 plt.grid(False) # 图像展示cmap为颜色图谱plt.cm.binary为matplotlib.cm中的色表 plt.imshow(train_images[i], cmapplt.cm.binary) # 设置x轴标签显示为图片对应的数字 plt.xlabel(train_labels[i]) # 显示图片 plt.show()运行结果4.图片处理#调整数据到我们需要的格式 train_images train_images.reshape((60000, 28, 28, 1)) test_images test_images.reshape((10000, 28, 28, 1)) train_images.shape,test_images.shape,train_labels.shape,test_labels.shape 输出((60000, 28, 28, 1), (10000, 28, 28, 1), (60000,), (10000,)) 运行结果原本图片形状是(高度, 宽度)即(28, 28)。但对于卷积层Conv2DKeras 要求输入形状为(高度, 宽度, 通道数)。MNIST 是灰度图通道数为 1彩色图为 3。reshape方法将每个样本从(28, 28)变为(28, 28, 1)相当于添加了最后一个维度表示通道数。训练集变为(60000, 28, 28, 1)测试集变为(10000, 28, 28, 1)。二、训练模型1. 构建CNN网络模型# 创建并设置卷积神经网络 # 卷积层通过卷积操作对输入图像进行降维和特征抽取 # 池化层是一种非线性形式的下采样。主要用于特征降维压缩数据和参数的数量减小过拟合同时提高模型的鲁棒性。 # 全连接层在经过几个卷积和池化层之后神经网络中的高级推理通过全连接层来完成。 model models.Sequential([ # 设置二维卷积层1设置32个3*3卷积核activation参数将激活函数设置为ReLu函数input_shape参数将图层的输入形状设置为(28, 28, 1) # ReLu函数作为激活励函数可以增强判定函数和整个神经网络的非线性特性而本身并不会改变卷积层 # 相比其它函数来说ReLU函数更受青睐这是因为它可以将神经网络的训练速度提升数倍而并不会对模型的泛化准确度造成显著影响。 layers.Conv2D(32, (3, 3), activationrelu, input_shape(28, 28, 1)), #池化层12*2采样 layers.MaxPooling2D((2, 2)), # 设置二维卷积层2设置64个3*3卷积核activation参数将激活函数设置为ReLu函数 layers.Conv2D(64, (3, 3), activationrelu), #池化层22*2采样 layers.MaxPooling2D((2, 2)), layers.Flatten(), #Flatten层连接卷积层与全连接层 layers.Dense(64, activationrelu), #全连接层特征进一步提取64为输出空间的维数activation参数将激活函数设置为ReLu函数 layers.Dense(10) #输出层输出预期结果10为输出空间的维数 ]) # 打印网络结构 model.summary()代码解析layers.Conv2D(32, (3, 3), activationrelu, input_shape(28, 28, 1))二维卷积层是 CNN 的核心。32该层有 32 个卷积核滤波器每个卷积核会提取一种特征因此输出特征图feature map的深度为 32。(3, 3)卷积核的大小为 3×3 像素。activationrelu激活函数使用 ReLURectified Linear Unit公式为max(0, x)。它能引入非线性并且计算简单有助于缓解梯度消失问题。input_shape(28, 28, 1)指定输入数据的形状只有第一层需要设置后续层会自动推断。该层输出形状为(None, 26, 26, 32)因为 3×3 卷积不填充时高度和宽度各减 2。layers.MaxPooling2D((2, 2))最大池化层池化窗口大小为 2×2步长默认为 2。作用在 2×2 区域内取最大值将特征图尺寸减半高度和宽度各减半减少参数数量同时保留主要特征并提高模型的平移不变性。输出形状为(None, 13, 13, 32)。layers.Conv2D(64, (3, 3), activationrelu)第二个卷积层64 个 3×3 卷积核激活函数 ReLU。输出形状为(None, 11, 11, 64)因为 13-3111。layers.MaxPooling2D((2, 2))再次最大池化输出形状为(None, 5, 5, 64)。layers.Flatten()展平层。将多维特征图5×5×64展平成一维向量长度为 5×5×641600以便输入到全连接层。layers.Dense(64, activationrelu)全连接层稠密层有 64 个神经元激活函数 ReLU。这层对提取的高层特征进行非线性组合进一步提取特征。layers.Dense(10)输出层10 个神经元对应 10 个类别数字 0~9。这里没有指定激活函数因为后续损失函数SparseCategoricalCrossentropy会设置from_logitsTrue表示直接输出未经过 softmax 的 logits原始分数内部会自动计算 softmax 并计算交叉熵。运行结果2.编辑模型 这里设置优化器、损失函数以及metrics # model.compile()方法用于在配置训练方法时告知训练时用的优化器、损失函数和准确率评测标准 model.compile( # 设置优化器为Adam优化器 optimizeradam, # 设置损失函数为交叉熵损失函数tf.keras.losses.SparseCategoricalCrossentropy() # from_logits为True时会将y_pred转化为概率用softmax否则不进行转换通常情况下用True结果更稳定 losstf.keras.losses.SparseCategoricalCrossentropy(from_logitsTrue), # 设置性能指标列表将在模型训练时监控列表中的指标 metrics[accuracy])3.训练模型 这里设置输入训练数据集图片及标签、验证数据集图片及标签以及迭代次数epochs 关于model.fit()函数的具体介绍可参考我的博客 https://blog.csdn.net/qq_38251616/article/details/122321757 history model.fit( # 输入训练集图片 train_images, # 输入训练集标签 train_labels, # 设置10个epoch每一个epoch都将会把所有的数据输入模型完成一次训练。 epochs10, # 设置验证集 validation_data(test_images, test_labels))运行结果三、模型预测plt.imshow(test_images[1])运行结果:pre model.predict(test_images) # 对所有测试图片进行预测 pre[1] # 输出第一张图片的预测结果运行结果四、总结之前已经学习了pytorch框架的深度学习基础本次开始学习tensorflow框架。二者在代码运行上还是有不一样的框架TensorFlowPyTorch数据格式加载后直接是 NumPy 数组(60000, 28, 28)。加载后是Dataset对象需要配合DataLoader才能批量取出。通道顺序HWC高、宽、通道。灰度图是(28, 28, 1)。CHW通道、高、宽。灰度图是(1, 28, 28)。你看到的imgs.shape输出为[32, 1, 28, 28]归一化手动除以255.0。使用transforms.ToTensor()它不仅把图片转为张量自动除以 255归一化到 [0,1]还自动把 HWC 转为 CHW。批量读取没有专门的加载器直接用切片。使用DataLoadertrain_dl它能自动打乱shuffleTrue数据、按批次batch_size32打包还支持多线程读取。在模型构建上TF用models.Sequential([层1, 层2, ...])按顺序“组装”层层与层之间自动传递数据。PyTorch必须新建一个类继承nn.Module。在__init__里定义好“零件”比如self.conv1self.fc1。在forward(self, x)函数里手动写清楚数据流向x self.pool1(F.relu(self.conv1(x)))。在训练过程也有明显的不同TF (T1)一行代码搞定。history model.fit(train_images, train_labels, epochs10, validation_data(test_images, test_labels))PyTorch (P1)需要双层循环for epoch套for X, y in dataloader清空梯度optimizer.zero_grad()。前向传播pred model(X)。计算损失loss loss_fn(pred, y)。反向传播loss.backward()计算每个参数的梯度。更新参数optimizer.step()用计算好的梯度去更新权重。手动计算准确率(pred.argmax(1) y).sum()。