CIFAR10数据集共有60000个样本,每个样本都是一张32*32像素的RGB图像(彩色图像),每个RGB图像又必定分为3个通道(R通道、G通道、B通道)。这60000个样本被分成了50000个训练样本和10000个测试样本。
CIFAR10数据集是用来监督学习训练的,那么每个样本就一定都配备了一个标签值(用来区分这个样本是什么),不同类别的物体用不同的标签值,CIFAR10中有10类物体,标签值分别按照0~9来区分,他们分别是飞机( airplane )、汽车( automobile )、鸟( bird )、猫( cat )、鹿( deer )、狗( dog )、青蛙( frog )、马( horse )、船( ship )和卡车( truck )。
CIFAR10数据集的内容,如图所示。
(该图源于官网)
CIFAR-10数据集有多种下载方式,本文仅介绍两种。
CIFAR10数据集结构组成可分为这四个部分:
·train_x:(50000, 32, 32, 3)——训练样本
·train_y:(50000, 1)——训练样本标签
·test_x:(10000, 32, 32, 3)——测试样本
·test_y:(10000, 1)——测试样本标签
方法一:
官网下载链接:http://www.cs.toronto.edu/~kriz/cifar.html
可以下载这三个版本,分别是python版本、Matlab版本和C编译好的二进制版本。
方法二:
在Keras中已经内置了多种公共数据集,其中就包含CIFAR-10数据集,如图所示。
所以可以直接调用 tf.keras.datasets.cifar10,直接下载数据集。
这个数据集与CIFAR-10类似,只不过它有100个类,每个类包含600个图像。每个类有500个训练图像和100个测试图像。CIFAR-100中的100个子类被分为20个大类。每个图像都有一个“fine”标签(它所属的子类)和一个“coarse”标签(它所属的大类)。
CIFAR-100的结构组成:
大类 | 子类 |
---|---|
水栖哺乳动物 | 海狸,海豚,水獭,海豹,鲸鱼 |
鱼类 | 水族鱼,比目鱼,鳐,鲨鱼,鳟鱼 |
花 | 兰花,罂粟,玫瑰,向日葵,郁金香 |
食物容器 | 瓶子,碗,罐头,杯子,盘子 |
水果和蔬菜 | 苹果,蘑菇,橘子,梨,甜椒 |
家用电器 | 时钟,电脑键盘,灯,电话,电视 |
家居家具 | 床,椅子,沙发,桌子,衣柜 |
昆虫 | 蜜蜂、甲虫、蝴蝶、毛虫、蟑螂 |
大型食肉动物 | 熊,豹,狮子,老虎,狼 |
大型人造户外用品 | 桥梁、城堡、房屋、道路、摩天大楼 |
大型户外自然景观 | 云、森林、高山、平原、大海 |
大型杂食动物和食草动物 | 骆驼,牛,黑猩猩,大象,袋鼠 |
中型哺乳动物 | 狐狸,豪猪,负鼠,浣熊,臭鼬 |
非昆虫无脊椎动物 | 螃蟹,龙虾,蜗牛,蜘蛛,蠕虫 |
人类 | 宝贝,男孩,女孩,男人,女人 |
爬行动物 | 鳄鱼,恐龙,蜥蜴,蛇,乌龟 |
小型哺乳动物 | 仓鼠,老鼠,兔子,鼩鼱,松鼠 |
树木 | 枫树、橡树、棕榈树、松树、柳树 |
交通工具 | 自行车、公共汽车、摩托车、小货车、火车 |
其他车类 | 割草机,火箭,有轨电车,坦克,拖拉机 |
CIFAR-10数据集与CIFAR-100数据集的区别也就显而易见啦。
关于MNIST数据集的介绍,我写过一篇文章,并也附带了MNIST数据集的模型训练完整代码,感兴趣的朋友可以看它。
使用MNIST数据集训练手写数字识别模型——附完整代码和训练好的模型文件——直接用
链接:https://blog.csdn.net/weixin_45954454/article/details/114455209?spm=1001.2014.3001.5501
CIFAR-10数据集与MNIST数据集二者的区别主要是在以下几点:
·维度不同:CIFAR-10数据集有4个维度,MNIST数据集有3个维度
·图像类型不同:CIFAR-10数据集是RGB图像(有三个通道),MNIST数据集是灰度图像,这也是为什么CIFAR-10数据集比MNIST数据集多出一个维度的原因。
·图像内容不同:CIFAR-10数据集展示的是各种不同的物体(猫、狗、飞机、汽车…),MNIST数据集展示的是不同人的手写0~9数字。
主要使用函数:tf.keras.layers.Conv2D()
tf.keras.layers.Conv2D(
filters, kernel_size, strides=(1, 1), padding='valid', data_format=None,
dilation_rate=(1, 1), activation=None, use_bias=True,
kernel_initializer='glorot_uniform', bias_initializer='zeros',
kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None,
kernel_constraint=None, bias_constraint=None, **kwargs
)
这一层创建了一个卷积核,它与层输入进行卷积以产生输出张量。如果use_bias为真,则创建一个偏差向量并添加到输出中。最后,如果激活不是None,它也会应用到输出。
当使用这一层作为模型的第一层时,提供关键字参数input_shape(整数元组,不包括样本轴),例如,对于data_format="channels_last"中的128x128 RGB图片,输入input_shape=(128, 128, 3)。
参数 | 说明 |
---|---|
filters | 整数,即输出空间的维数(即卷积中输出滤波器的数量) |
kernel_size | 一个整数或2个整数的元组/列表,指定2D卷积窗口的高度和宽度。可以是单个整数,为所有空间维度指定相同的值。 |
strides | 一个整数或2个整数的元组/列表,指定沿高度和宽度卷积的步长。可以是单个整数,为所有空间维度指定相同的值。指定任何stride值!= 1与指定任何dilation_rate值!= 1是不兼容的。 |
padding | “valid”或“same”(不区分大小写)。补0策略。“valid”代表只进行有效的卷积,即对边界数据不处理。“same”代表保留边界处的卷积结果,通常会导致输出shape与输入shape相同。 |
data_format | 字符串,channels_last(默认)或channels_first之一。输入中维度的顺序。channels_last对应于形状的输入(batch_size,高度,宽度,通道),而channels_first对应于形状的输入(batch_size,通道,高度,宽度)。默认值为在Keras配置文件~/. Keras / Keras .json中找到的image_data_format值。如果您从未设置它,那么它将是“channels_last”。 |
dilation_rate | 一个整数或2个整数的元组/列表,指定用于膨胀卷积的膨胀率。可以是单个整数,为所有空间维度指定相同的值。目前,指定任何dilation_rate值!= 1与指定任何stride值!= 1是不兼容的。 |
activation | 使用的激活功能。如果不指定任何内容,则不会应用任何激活(参见keras.activation)。 |
use_bias | boolean,这个层是否使用偏差向量。 |
kernel_initializer | 内核权重矩阵的初始化器(参见keras.initializer)。 |
bias_initializer | 偏置向量的初始化器(参见keras.initializer)。 |
kernel_regularizer | 应用于内核权重矩阵的正则化函数(参见keras.regularizers)。 |
bias_regularizer | 应用于偏置向量的正则化函数(参见keras.regularizers)。 |
activity_regularizer | 应用于层输出的正则化函数(它的“激活”)(参见keras.regularizers)。 |
kernel_constraint | 约束函数应用于内核矩阵(参见keras.constraints)。 |
bias_constraint | 应用于偏差向量的约束函数(参见keras.constraints)。 |
input_shape:
如果data_format=‘channels_first’,则4D张量的形状:(batch_size, channels, rows, cols);或者如果data_format=‘channels_last’,则4D张量的形状:(batch_size, rows, cols, channels)。
output_shape:
4D张量的形状:(batch_size, filters, new_rows, new_cols)如果data_format=‘channels_first’,或者4D张量的形状:(batch_size, new_rows, new_cols, filters)如果data_format=‘channels_last’。rows和cols值可能由于填充而改变。
(仅翻译的官方说明文档)
Tensorflow官方API网址如下,可以用来查询Tensorflow其他API的使用。(很全很详细)
Tensorflow官方API链接:https://tensorflow.google.cn/versions
CIFAR-10数据集的模型训练思路与下面这篇文章相似,想了解设计过程和每一步代码作用的朋友可以看我写的这篇文章,这里就不赘述了。
使用MNIST数据集训练手写数字识别模型——附完整代码和训练好的模型文件——直接用
链接:https://blog.csdn.net/weixin_45954454/article/details/114455209?spm=1001.2014.3001.5501
本人使用的是Tensorflow2.2.0—gpu版本,就目前已更新的版本来看,2.0.0以上版本都可以直接使用。
如果你的GPU没有配置好,代码会在指定GPU那里报错的,如果是这种报错还不知道如何解决的话,就选择用CPU跑程序,即注释掉这两行代码:
gpus = tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(gpus[0],True)
注释掉后,基本就能跑通啦。
强调:其中model.save( )里的路径根据自己需要自行修改,若省去路径,默认保存到当前的工作路径。
########cifar10数据集##########
###########保存模型############
########卷积神经网络##########
#train_x:(50000, 32, 32, 3), train_y:(50000, 1), test_x:(10000, 32, 32, 3), test_y:(10000, 1)
#60000条训练数据和10000条测试数据,32x32像素的RGB图像
#第一层两个卷积层16个3*3卷积核,一个池化层:最大池化法2*2卷积核,激活函数:ReLU
#第二层两个卷积层32个3*3卷积核,一个池化层:最大池化法2*2卷积核,激活函数:ReLU
#隐含层激活函数:ReLU函数
#输出层激活函数:softmax函数(实现多分类)
#损失函数:稀疏交叉熵损失函数
#隐含层有128个神经元,输出层有10个节点
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import time
print('--------------')
nowtime = time.strftime('%Y-%m-%d %H:%M:%S')
print(nowtime)
#指定GPU
#import os
#os.environ["CUDA_VISIBLE_DEVICES"] = "0"
gpus = tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(gpus[0],True)
#初始化
plt.rcParams['font.sans-serif'] = ['SimHei']
#加载数据
cifar10 = tf.keras.datasets.cifar10
(train_x,train_y),(test_x,test_y) = cifar10.load_data()
print('\n train_x:%s, train_y:%s, test_x:%s, test_y:%s'%(train_x.shape,train_y.shape,test_x.shape,test_y.shape))
#数据预处理
X_train,X_test = tf.cast(train_x/255.0,tf.float32),tf.cast(test_x/255.0,tf.float32) #归一化
y_train,y_test = tf.cast(train_y,tf.int16),tf.cast(test_y,tf.int16)
#建立模型
model = tf.keras.Sequential()
##特征提取阶段
#第一层
model.add(tf.keras.layers.Conv2D(16,kernel_size=(3,3),padding='same',activation=tf.nn.relu,data_format='channels_last',input_shape=X_train.shape[1:])) #卷积层,16个卷积核,大小(3,3),保持原图像大小,relu激活函数,输入形状(28,28,1)
model.add(tf.keras.layers.Conv2D(16,kernel_size=(3,3),padding='same',activation=tf.nn.relu))
model.add(tf.keras.layers.MaxPool2D(pool_size=(2,2))) #池化层,最大值池化,卷积核(2,2)
#第二层
model.add(tf.keras.layers.Conv2D(32,kernel_size=(3,3),padding='same',activation=tf.nn.relu))
model.add(tf.keras.layers.Conv2D(32,kernel_size=(3,3),padding='same',activation=tf.nn.relu))
model.add(tf.keras.layers.MaxPool2D(pool_size=(2,2)))
##分类识别阶段
#第三层
model.add(tf.keras.layers.Flatten()) #改变输入形状
#第四层
model.add(tf.keras.layers.Dense(128,activation='relu')) #全连接网络层,128个神经元,relu激活函数
model.add(tf.keras.layers.Dense(10,activation='softmax')) #输出层,10个节点
print(model.summary()) #查看网络结构和参数信息
#配置模型训练方法
#adam算法参数采用keras默认的公开参数,损失函数采用稀疏交叉熵损失函数,准确率采用稀疏分类准确率函数
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['sparse_categorical_accuracy'])
#训练模型
#批量训练大小为64,迭代5次,测试集比例0.2(48000条训练集数据,12000条测试集数据)
print('--------------')
nowtime = time.strftime('%Y-%m-%d %H:%M:%S')
print('训练前时刻:'+str(nowtime))
history = model.fit(X_train,y_train,batch_size=64,epochs=5,validation_split=0.2)
print('--------------')
nowtime = time.strftime('%Y-%m-%d %H:%M:%S')
print('训练后时刻:'+str(nowtime))
#评估模型
model.evaluate(X_test,y_test,verbose=2) #每次迭代输出一条记录,来评价该模型是否有比较好的泛化能力
#保存整个模型
model.save('CIFAR10_CNN_weights.h5')
#结果可视化
print(history.history)
loss = history.history['loss'] #训练集损失
val_loss = history.history['val_loss'] #测试集损失
acc = history.history['sparse_categorical_accuracy'] #训练集准确率
val_acc = history.history['val_sparse_categorical_accuracy'] #测试集准确率
plt.figure(figsize=(10,3))
plt.subplot(121)
plt.plot(loss,color='b',label='train')
plt.plot(val_loss,color='r',label='test')
plt.ylabel('loss')
plt.legend()
plt.subplot(122)
plt.plot(acc,color='b',label='train')
plt.plot(val_acc,color='r',label='test')
plt.ylabel('Accuracy')
plt.legend()
#暂停5秒关闭画布,否则画布一直打开的同时,会持续占用GPU内存
#根据需要自行选择
#plt.ion() #打开交互式操作模式
#plt.show()
#plt.pause(5)
#plt.close()
#使用模型
plt.figure()
for i in range(10):
num = np.random.randint(1,10000)
plt.subplot(2,5,i+1)
plt.axis('off')
plt.imshow(test_x[num],cmap='gray')
demo = tf.reshape(X_test[num],(1,32,32,3))
y_pred = np.argmax(model.predict(demo))
plt.title('标签值:'+str(test_y[num])+'\n预测值:'+str(y_pred))
#y_pred = np.argmax(model.predict(X_test[0:5]),axis=1)
#print('X_test[0:5]: %s'%(X_test[0:5].shape))
#print('y_pred: %s'%(y_pred))
#plt.ion() #打开交互式操作模式
plt.show()
#plt.pause(5)
#plt.close()
运行结果:
从红色框选的内容分别是训练样本的损失函数值和准确率、测试样本的损失函数值和准确率,可以看到它每次训练迭代时损失函数和准确率的变化,从最后一次迭代结果上看,测试样本的损失函数值达到0.9423,准确率仅达到0.6761。这个结果并不是很好,我尝试过增加迭代次数,发现训练样本的损失函数值可以达到0.04,准确率达到0.98;但实际上训练模型却产生了越来越大的泛化误差,这就是训练过度的现象,从图中可以看出泛化能力最好时是在迭代第5次的状态,故只能选择迭代5次。
但为了可以达到更高的准确率,和泛化能力,可以通过修改小批量梯度下降的数量、训练模型的方法、修改网络层的参数等等办法……。
csdn资源下载链接:【神经网络与深度学习】CIFAR10数据集介绍,并使用卷积神经网络训练图像分类模型——附完整代码和训练好的模型文件——直接用。:https://download.csdn.net/download/weixin_45954454/15648644?spm=1001.2014.3001.5501
<本文内容主要参考于《神经网络与深度学习-Tensorflow实践》>
出现问题可私信我解决,不定期查看。
————————————————
<后续还会继续整理【神经网络与深度学习】相关内容,如果需要,可持续关注我哦~> |
<整理不易,留个赞或评论支持一下我吧^^>
如有疑问,欢迎批评指正^^