本文主要是介绍彩色图片分类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本文为🔗365天深度学习训练营 中的学习记录博客
原作者:K同学啊|接辅导、项目定制
我的环境:
1.语言:python3.7
2.编译器:pycharm
3.深度学习环境:TensorFlow2.5
一.前期工作
1.设置GPU
若是使用的是cpu可忽略
import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")if gpus:gpu0 = gpus[0]tf.config.experimental.set_memory_growth(gpu0, True)tf.config.set_visible_devices([gpu0],"GPU")
使用cpu训练
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
2.导入包
import os
import tensorflow as tf
from tensorflow.keras import datasets,layers,models
import matplotlib.pyplot as plt
import numpy as np
3.设置数据集
CIFAR10 数据集一共有10 类,总共 60000 张彩色图片,每类图片有 6000 张。此数据集中 50000 个样例被作为训练集,剩余 10000 个样例作为测试集。类之间相互度立,不存在重叠的部分。
#导入数据集依次为训练集图片、训练集标签、测试集图片、测试集标签
(train_images,train_labels),(test_images,test_labels) = datasets.cifar10.load_data()
tensorflow会自动下载数据保存到(C:\Users\86133\.keras\datasets)
4.归一化
把数值放缩到0到1的小区间中
好处:
- 提高迭代求解的收敛速度
- 提高迭代求解的精度
缺点:
- 最大值与最小值非常容易受异常点影响
- 鲁棒性较差,只适合传统精确小数据场景#将像素的值标准化到0到1的区间。(对于灰度图像来说,每个图像的最大值是255,每个像素最小值是0,所以直接除以255即可完成归一化) train_images,test_images = train_images / 255.0 , test_images / 255.0 train_images.shape,test_labels.shape,train_labels.shape,test_labels.shape
#将像素的值标准化到0到1的区间。(对于灰度图像来说,每个图像的最大值是255,每个像素最小值是0,所以直接除以255即可完成归一化)
train_images,test_images = train_images / 255.0 , test_images / 255.0train_images.shape,test_labels.shape,train_labels.shape,test_labels.shape
5、可视化
#打印一个标签数组,绘制前20行,每行5张共4行
class_names = ['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']plt.figure(figsize=(20,10))
for i in range(20):plt.subplot(4,5,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网络(关于卷积层可参考)
1、卷积层
(1)卷积计算
卷积层可以保持形状不变。当输入数据是图像时,卷积层会以3维数据的形式接收输入数据,并同样以3维数据的形式输出至下一层。因此在CNN中,可以(有可能)正确理解图像等具有形状的数据。
CNN中,有时将卷积层的输入输出数据称为特征图(feature map)。其中,卷积层的输入数据称为输入特征图(input feature map),输出数据称为输出特征图(output feature map)。
卷积层进行的处理就是卷积运算。卷积运算相当于图像处理中的“滤波器运算”。
假设输入图片是3*3,与一个2*2的卷积核,计算如下
输入的元素与对应核函数上的元素相乘再求和(2 * 1+3 * 2+4 * 3 +2 * 0 = 20),再将其保存在输出的对应位置上。然后将这个过程在所有位置上都进行一遍,就能得到卷积运算的输出。
输入大小为n * n的图片,通过m * m的卷积核,输出维度为(n-m+1)*(n-m+1)
(2)填充
在进行卷积层处理之前,有时需要先对输入进行一下特殊处理(为输入图像的边界四周填充数据可将其由3*3变为4*4),下图填充为0
输入大小n * n的图片,通过k * k的卷积核,填充为p,输出维度为(n-k+1+2p)*(n-k+1+2p)
每次进行卷积运算输出都所会缩小空间,若不进行填充操作,在某个时刻输出大小就有可能变为1,无法再应用卷积运算。
(3)步幅
应用于输入的位置间隔叫做步幅。以上的例子步幅都为1.有时候为了高效计算或者缩减采样次数,卷积计算有时候会跳过中间的位置,每次滑动多个元素。使用步幅为2,计算如下:
输入大小n * n的图片,通过k * k的卷积核,填充为p,步幅为s,输出维度为((n-k+2p) / s + 1)*((n-k+2p) / s + 1),若算出不为整数向下取整。
2、池化层
池化层是模仿人类视觉系统对数据进行降维,一方面使特征图变小,简化网络计算复杂度;另一方面对特征压缩,提取主要特征,提升模型的尺度不变性、旋转不变性。减少过拟合风险。
常见的池化层:最大池化层(Maxpooling)和平均池化层(AveragePooling),均值池化层对背景保留更好,最大池化层对纹理提取更好。同卷积计算,池化层计算窗口内的平均值或者最大值。例如通过一个2*2的最大池化层,计算如下:
CNN模型
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3))) #卷积层1,卷积核3*3
model.add(layers.MaxPooling2D((2, 2))) #最大池化层1,2*2采样
model.add(layers.Dropout(0.2))
model.add(layers.Conv2D(64, (3, 3), activation='relu')) # 卷积层2,卷积核3*3
model.add(layers.MaxPooling2D((2, 2))) # 最大池化层2,2*2采样
model.add(layers.Dropout(0.2))
model.add(layers.Conv2D(64, (3, 3), activation='relu')) # 卷积层3,卷积核3*3
#在模型的最后,您将把卷积后的输出张量(本例中形状为 (4, 4, 64))传给一个或多个 Dense 层来完成分类。
model.add(layers.Flatten()) # Flatten层,连接卷积层与全连接层
model.add(layers.Dense(64, activation='relu')) # 全连接层,特征进一步提取
model.add(layers.Dense(10)) # 输出层,输出预期结果
model.summary()# 打印网络结构
model = models.Sequential() #构建一个空的网络模型,它是一个线性堆叠模型,各种神经网络会被顺序添加。
layers.Conv2D()#构建一个卷积层
layers.MacxPooling2D() #构建一个最大池化层
layers.Flatten() # Flatten层,连接卷积层与全连接层,把多维的输入一维化,常用在从卷积层到全连接层的过渡。
每个最大池化层后我都加入了一个Dropout,它可以通过随机失活神经元,强制网络中的权重只取最小值,使得权重值的分布更加规则,减小样本过拟合问题,起到正则化的作用。
当Dropout应用到某个层中,它会再训练过程中对所应用的层随机丢弃(你所设置的)输出数量单位。当Dropout取一个小数作为他的输入值(如:0.1、0.2、0.3......),代表了从应用的层中随机放弃10%、20%、30%的输出单位。
三、编译
model.compile(optimizer='adam',loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),metrics=['accuracy'])
optimizer
:优化器,用于控制梯度裁剪。loss
:损失函数(或称目标函数、优化评分函数)metrics
:评价函数用于评估当前训练模型的性能。当模型编译后(compile),评价函数应该作为 metrics 的参数来输入。评价函数和损失函数相似,只不过评价函数的结果不会用于训练过程中。
四、训练模型
history = model.fit(train_images, train_labels, epochs=10,validation_data=(test_images, test_labels))
五、预测
通过模型进行预测得到的是每一个类别的概率,数字越大该图片为该类别的可能性越大。
plt.imshow(test_images[1])#预测测试集中的第一张图片
plt.show()
pre = model.predict(test_images)#对所有测试图片进行预测
print(class_names[np.argmx(pre[1])])#输出第一张图片的预测结果
六、模型评估
#评估模型
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)
print(test_acc)
这篇关于彩色图片分类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!