彩色图像分类
- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊 | 接辅导、项目定制
- 🚀 文章来源:K同学的学习圈子
环境准备
- python 3.8
- tensorflow 2.3.3
- pycharm编辑
数据集介绍
1. CIFAR-10是一个更接近普适物体的彩色图像数据集。CIFAR-10 是由Hinton 的学生Alex Krizhevsky 和Ilya Sutskever 整理的一个用于识别普适物体的小型数据集。一共包含10 个类别的RGB 彩色图片:
* 飞机( airplane
* 汽车( automobile )
* 鸟类( bird )
* 猫( cat )
* 鹿( deer )
* 狗( dog )
* 蛙类( frog )
* 马( horse )
* 船( ship )
* 卡车( truck )。
3. 每个图片的尺寸为32 × 32 ,每个类别有6000个图像,数据集中一共有50000 张训练图片和10000 张测试图片。
代码示例:
def load_data():
(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
# 将像素的值标准化至0到1的区间内。
train_images, test_images = train_images / 255.0, test_images / 255.0
# 查看数据维数信息
print("训练集Train数据的维度信息 ===> ", train_images.shape)
print("验证集Val数据的维度信息 ===> ", test_images.shape)
print("训练集Train标签的维度信息 ===> ", train_labels.shape)
print("验证集Val标签的维度信息 ===> ", test_labels.shape)
return train_images, train_labels, test_images, test_labels
在以上代码块中,可以看到从tensortflow.datasets读取cifar10数据集,并对每个数据样本进行归一化处理,便于计算与训练。
可视化部分数据
def plt_show(train_images, train_labels):
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()
网络搭建
主要包含卷积层、池化层、全连接层。
卷积层:主要包含输入特征图(input feature map)、卷积核(kernel)、输出特征图(output feature map)从数学的角度来看,这一层主要就是进行卷积运算,将卷积核与特征图进行矩阵内积,而后得到输出特征图。
池化层:包括最大池化层(MaxPooling)和平均池化层(AveragePooling)池化层对提取到的特征信息进行降维,一方面使特征图变小,简化网络计算复杂度;另一方面进行特征压缩,提取主要特征,增加平移不变性,减少过拟合风险。但其实池化更多程度上是一种计算性能的一个妥协,强硬地压缩特征的同时也损失了一部分信息,所以现在的网络比较少用池化层或者使用优化后的如SoftPool。
均值池化对背景保留更好,最大池化对纹理提取更好
全连接层:位于整个卷积神经网络的最后,负责将卷积输出的二维特征图转化成一维的一个向量,由此实现了端到端的学习过程。
全连接层的每一个结点都与上一层的所有结点相连因而称之为全连接层
全连接层的主要作用就是将前层(卷积、池化等层)计算得到的特征空间映射样本标记空间。简单的说就是将特征表示整合成一个值,其优点在于减少特征位置对于分类结果的影响,提高了整个网络的鲁棒性。
网络结构平面图:
网络立体结构图:
代码示例
def model_load():
# 创建并设置卷积神经网络
# 卷积层:通过卷积操作对输入图像进行降维和特征抽取
# 池化层:是一种非线性形式的下采样。主要用于特征降维,压缩数据和参数的数量,减小过拟合,同时提高模型的鲁棒性。
# 全连接层:在经过几个卷积和池化层之后,神经网络中的高级推理通过全连接层来完成。
model = models.Sequential([
# 设置二维卷积层1,设置32个3*3卷积核,activation参数将激活函数设置为ReLu函数,input_shape参数将图层的输入形状设置为(28, 28, 1)
# ReLu函数作为激活励函数可以增强判定函数和整个神经网络的非线性特性,而本身并不会改变卷积层
# 相比其它函数来说,ReLU函数更受青睐,这是因为它可以将神经网络的训练速度提升数倍,而并不会对模型的泛化准确度造成显著影响。
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)),
# 池化层1,2*2采样
layers.MaxPooling2D((2, 2)),
# 设置二维卷积层2,设置64个3*3卷积核,activation参数将激活函数设置为ReLu函数
layers.Conv2D(64, (3, 3), activation='relu'),
# 池化层2,2*2采样
layers.MaxPooling2D((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()
return model
模型训练
def fit_model(model):
train_images, train_labels, test_images, test_labels = load_data()
model.compile(
optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
history = model.fit(
train_images,
train_labels,
epochs=150,
validation_data=(test_images, test_labels))
model_name = f"mnist_.h5"
model_path = os.path.join("./checkpoints", model_name)
if not os.path.exists("./checkpoints"): os.mkdir("./checkpoints")
model.save(model_path)
print("Model Save to %s" % model_path)
模型预测
from tensorflow.keras.models import load_model
from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt
import numpy as np
def load_data():
(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
train_images, test_images = train_images / 255.0, test_images / 255.0
# 查看数据维数信息
print("训练集Train数据的维度信息 ===> ", train_images.shape)
print("验证集Val数据的维度信息 ===> ", test_images.shape)
print("训练集Train标签的维度信息 ===> ", train_labels.shape)
print("验证集Val标签的维度信息 ===> ", test_labels.shape)
return train_images, train_labels, test_images, test_labels
train_images, train_labels, test_images, test_labels = load_data()
model_path = "./checkpoints/mnist_.h5"
mnist_model = load_model(model_path)
print(test_images[5].shape)
plt.figure(figsize=(20,8),dpi=80)
plt.imshow(test_images[5])
plt.show()
test_img = np.expand_dims(test_images[5],0)
p = mnist_model.predict(test_img)
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
print("预测类别:", class_names[np.argmax(p)])
print("真实类别:", class_names[test_labels[5][0]])
模型评估
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()
由结果来看,感觉有些过拟合了
总结:
* 检测效果不是很好,可能是网络层数过于简单,后期尝试构建更复杂的网络模型。
* 尝试更换优化器、卷积核测试训练效果。
* cifar10数据集感觉有效特征不是很多,质量也不是很好,不太容易提取特征。