>- **🍨 本文为[🔗365天深度学习训练营]中的学习记录博客**
>- **🍖 原作者:[K同学啊]**
👉 要求:
- 学习如何编写一个完整的深度学习程序
- 了解分类彩色图片会灰度图片有什么区别
- 测试集accuracy到达72%
🦾我的环境:
- 语言环境:Python3.11.7
- 编译器:jupyter notebook
- 深度学习环境:TensorFlow2.13.0
一、前期工作
1. 设置GPU
如果使用的是CPU可以忽略这步
import tensorflow as tf
gpus=tf.config.list_physical_devices("GPU")
if gpus:
gpu0=gpus[0] #如果有多个GPU,仅使用第0个GPU
tf.config.experimental.set_memory_growth(gpu0u,True)#设置GPU现存用量按需使用
tf.config.set_visible_devices([gpu0],"GPU")
2. 导入数据
from tensorflow.keras import datasets
(train_images,train_labels),(test_images,test_labels)=datasets.cifar10.load_data()
运行结果:
我猜想是由于网速或者是限制等原因,所以从百度上找了个别人分享的百度网盘地址下载该数据集,然后将其放置于固定文件夹内,并在上述代码上添加路径后运行,结果却是:
发现 cifar10的load并不允许我们添加任何路径,然后我想在默认路径内添加该数据集试试看,结果仍然出错。然后搜索了下CSDN上的帖子,推荐大家看下这个:
keras】cifar10.load_data()下载数据集失败解决办法
然后我再次在我的默认路径下面添加该数据集,并将其改名为“cifar-10-batches-py.tar”,如图:
再次运行代码(其中,不添加任何数据路径),正常通过,运行后文件夹内的压缩包已经被正常加压缩,如图:
3. 归一化
#将像素的值标准化这至0到1的区间内
train_images,test_images=train_images/255.0,test_images/255.0
train_images.shape,test_images.shape,train_labels.shape,test_labels.shape
运行结果:
((50000, 32, 32, 3), (10000, 32, 32, 3), (50000, 1), (10000, 1))
4. 可视化
import matplotlib.pyplot as plt
class_names=['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']
plt.figure(figsize=(20,10))
for i in range(20):
plt.subplot(5,10,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i],cmap=plt.cm.binary)
plt.xlabel(class_names[train_labels[i][0]])
plt.show()
运行结果:
二、构建CNN网络
⭐关于卷积层:可参考【知识储备】部分
⭐池化层
池化层对提取到的特征信息进行降维,一方面使特征图变小,简化网络计算复杂度;另一方面进行特征压缩,提取主要特征,增加平移不变性,减少过拟合风险。但其实池化更多程度上是一种计算性能的一个妥协,强硬地压缩特征的同时也损失了一部分信息,所以现在的网络比较少用池化层或者使用优化后的如SoftPool。
池化层包括最大池化层(MaxPooling)和平均池化层(AveragePooling),均值池化对背景保留更好,最大池化对纹理提取更好)。同卷积计算,池化层计算窗口内的平均值或者最大值。例如通过一个 2*2 的最大池化层,其计算方式如下:
我们即将构建模型的结构图,我以分别二维和三维的形式展示出来方便大家理解。
- 平面结构图(可单击放大查看)
- 立体结构图(可单击放大查看)
from tensorflow.keras import models,layers
model=models.Sequential([
layers.Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3)), #卷积层1,卷积核3*3
layers.MaxPooling2D((2,2)), #池化层1,2*2采样
layers.Conv2D(64,(3,3),activation='relu'), #卷积层2,卷积核3*3
layers.MaxPooling2D((2,2)), #池化层2,2*2采样
layers.Conv2D(64,(3,3),activation='relu'), #卷积层3,卷积核3*3
layers.Flatten(), #Flatten层,连接卷积层与全连接层
layers.Dense(64,activation='relu'), #全连接层,特征进一步提取
layers.Dense(10) #输出层,输出预期结果
])
model.summary() #打印网络结构
运行结果:
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_6 (Conv2D) (None, 30, 30, 32) 896
max_pooling2d_4 (MaxPoolin (None, 15, 15, 32) 0
g2D)
conv2d_7 (Conv2D) (None, 13, 13, 64) 18496
max_pooling2d_5 (MaxPoolin (None, 6, 6, 64) 0
g2D)
conv2d_8 (Conv2D) (None, 4, 4, 64) 36928
flatten_2 (Flatten) (None, 1024) 0
dense_4 (Dense) (None, 64) 65600
dense_5 (Dense) (None, 10) 650
=================================================================
Total params: 122570 (478.79 KB)
Trainable params: 122570 (478.79 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
三、编译
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
四、训练模型
history=model.fit(train_images,train_labels,epochs=10,
validation_data=(test_images,test_labels))
运行结果:
Epoch 1/10
1563/1563 [==============================] - 26s 16ms/step - loss: 1.8425 - accuracy: 0.3684 - val_loss: 1.3904 - val_accuracy: 0.5023
Epoch 2/10
1563/1563 [==============================] - 25s 16ms/step - loss: 1.3429 - accuracy: 0.5201 - val_loss: 1.2992 - val_accuracy: 0.5459
Epoch 3/10
1563/1563 [==============================] - 26s 16ms/step - loss: 1.1709 - accuracy: 0.5881 - val_loss: 1.1716 - val_accuracy: 0.5936
Epoch 4/10
1563/1563 [==============================] - 24s 15ms/step - loss: 1.0638 - accuracy: 0.6297 - val_loss: 1.0926 - val_accuracy: 0.6206
Epoch 5/10
1563/1563 [==============================] - 24s 15ms/step - loss: 0.9764 - accuracy: 0.6594 - val_loss: 1.0916 - val_accuracy: 0.6250
Epoch 6/10
1563/1563 [==============================] - 26s 17ms/step - loss: 0.9057 - accuracy: 0.6850 - val_loss: 1.0735 - val_accuracy: 0.6397
Epoch 7/10
1563/1563 [==============================] - 28s 18ms/step - loss: 0.8436 - accuracy: 0.7055 - val_loss: 1.0808 - val_accuracy: 0.6401
Epoch 8/10
1563/1563 [==============================] - 27s 17ms/step - loss: 0.7977 - accuracy: 0.7226 - val_loss: 1.0314 - val_accuracy: 0.6639
Epoch 9/10
1563/1563 [==============================] - 26s 17ms/step - loss: 0.7493 - accuracy: 0.7385 - val_loss: 1.1170 - val_accuracy: 0.6504
Epoch 10/10
1563/1563 [==============================] - 24s 16ms/step - loss: 0.7129 - accuracy: 0.7535 - val_loss: 1.1397 - val_accuracy: 0.6420
五、模型评估
import matplotlib.pyplot as plt
plt.plot(history.history['accuracy'],label='accuracy')
plt.plot(history.history['val_accuracy'],label='val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.ylim([0.5,1])
plt.legend(loc='lower right')
plt.show()
test_loss,test_acc=model.evaluate(test_images,test_labels,verbose=2)
运行结果:
由于模型测试集结果未达到72%的目标,将模型训练次数修改为40次,再次运行:
Epoch 1/40
1563/1563 [==============================] - 24s 15ms/step - loss: 0.6721 - accuracy: 0.7649 - val_loss: 1.1086 - val_accuracy: 0.6633
Epoch 2/40
1563/1563 [==============================] - 25s 16ms/step - loss: 0.6432 - accuracy: 0.7747 - val_loss: 1.0868 - val_accuracy: 0.6677
Epoch 3/40
1563/1563 [==============================] - 25s 16ms/step - loss: 0.6154 - accuracy: 0.7856 - val_loss: 1.1417 - val_accuracy: 0.6559
……
Epoch 38/40
1563/1563 [==============================] - 25s 16ms/step - loss: 0.3184 - accuracy: 0.8993 - val_loss: 2.3142 - val_accuracy: 0.6385
Epoch 39/40
1563/1563 [==============================] - 25s 16ms/step - loss: 0.3146 - accuracy: 0.9004 - val_loss: 2.3704 - val_accuracy: 0.6362
Epoch 40/40
1563/1563 [==============================] - 25s 16ms/step - loss: 0.3123 - accuracy: 0.9019 - val_loss: 2.4650 - val_accuracy: 0.6397
绘制结果图:
从图中可以看出,训练集的正确率在缓步上升中,而测试集的正确率却停滞不前,猜测模型可能出现过拟合现象,故对模型进行修改:
(1)在模型中添加dropout方法,避免过拟合现象
(2)数据集中的图像像素均为224*224*3,考虑在池化过程中可能会导致图像边缘的特征存在一定丢失的现象,故在卷积过程中加入same进行填充
from tensorflow.keras import models,layers
model=models.Sequential([
layers.Conv2D(32,(3,3),activation='relu',input_shape=(32,32,3),padding='same'), #卷积层1,卷积核3*3
layers.MaxPooling2D((2,2)), #池化层1,2*2采样
layers.Conv2D(64,(3,3),activation='relu',padding='same'), #卷积层2,卷积核3*3
layers.MaxPooling2D((2,2)), #池化层2,2*2采样
layers.Conv2D(64,(3,3),activation='relu',padding='same'), #卷积层3,卷积核3*3
layers.Flatten(), #Flatten层,连接卷积层与全连接层
layers.Dropout(0.5), #添加正则化,概率为0.5
layers.Dense(64,activation='relu'), #全连接层,特征进一步提取
layers.Dropout(0.5), #添加正则化,概率为0.5
layers.Dense(10) #输出层,输出预期结果
])
model.summary() #打印网络结构
运行30轮次后结果:
Epoch 1/30
1563/1563 [==============================] - 43s 27ms/step - loss: 1.6657 - accuracy: 0.3860 - val_loss: 1.3281 - val_accuracy: 0.5355
Epoch 2/30
1563/1563 [==============================] - 41s 26ms/step - loss: 1.3417 - accuracy: 0.5198 - val_loss: 1.1073 - val_accuracy: 0.6039
Epoch 3/30
1563/1563 [==============================] - 39s 25ms/step - loss: 1.2040 - accuracy: 0.5744 - val_loss: 0.9976 - val_accuracy: 0.6427
……
1563/1563 [==============================] - 43s 28ms/step - loss: 0.6655 - accuracy: 0.7660 - val_loss: 0.7069 - val_accuracy: 0.7598
Epoch 30/30
1563/1563 [==============================] - 43s 27ms/step - loss: 0.6648 - accuracy: 0.7685 - val_loss: 0.7315 - val_accuracy: 0.7548
从结果可以看出,测试集的准确率已经达到75%,完成72%目标的任务。从图像可以看出训练集和测试集的准确率都在逐步稳定上升的过程中。
六、预测
通过模型进行预测得到的是每一个类别的概率,数字越大该图片为该类别的可能性越大
plt.imshow(test_images[1])
运行结果:
import numpy as np
pre=model.predict(test_images)
print(class_names[np.argmax(pre[1])])
预测结果:
313/313 [==============================] - 2s 5ms/step
ship
七、心得体会
在本项目的实现过程中,解决了cifar10数据集的加载问题。通过模型调整,完成了测试集72%准确率的目标。