导入模块和数据
在Keras中已经内置了多种公共数据集,其中就包含CIFAR-10数据集
官网下载链接:http://www.cs.toronto.edu/\~kriz/cifar.html
python
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt
import numpy as np
(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
#加载数据
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))
train_x:(50000, 32, 32, 3), train_y:(50000, 1), test_x:(10000, 32, 32, 3), test_y:(10000, 1)
归一化
python
#数据预处理
X_train,X_test = tf.cast(train_images/255.0,tf.float32),tf.cast(test_images/255.0,tf.float32) #归一化
y_train,y_test = tf.cast(train_labels,tf.int16),tf.cast(test_labels,tf.int16)
# 将像素的值标准化至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))
可视化
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 )。
python
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer','dog', 'frog', 'horse', 'ship', 'truck']
plt.figure(figsize=(20,10))
for i in range(60):
plt.subplot(5,12,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网络
python
#建立模型
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()) #查看网络结构和参数信息
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 32, 32, 16) 448
conv2d_1 (Conv2D) (None, 32, 32, 16) 2320
max_pooling2d (MaxPooling2 (None, 16, 16, 16) 0
D)
conv2d_2 (Conv2D) (None, 16, 16, 32) 4640
conv2d_3 (Conv2D) (None, 16, 16, 32) 9248
max_pooling2d_1 (MaxPoolin (None, 8, 8, 32) 0
g2D)
flatten (Flatten) (None, 2048) 0
dense (Dense) (None, 128) 262272
dense_1 (Dense) (None, 10) 1290
=================================================================
Total params: 280218 (1.07 MB)
Trainable params: 280218 (1.07 MB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
None
python
####delete
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"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 30, 30, 32) 896
max_pooling2d (MaxPooling2 (None, 15, 15, 32) 0
D)
conv2d_1 (Conv2D) (None, 13, 13, 64) 18496
max_pooling2d_1 (MaxPoolin (None, 6, 6, 64) 0
g2D)
conv2d_2 (Conv2D) (None, 4, 4, 64) 36928
flatten (Flatten) (None, 1024) 0
dense (Dense) (None, 64) 65600
dense_1 (Dense) (None, 10) 650
=================================================================
Total params: 122570 (478.79 KB)
Trainable params: 122570 (478.79 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________
配置模型训练方法
adam算法参数采用keras默认的公开参数,损失函数采用稀疏交叉熵损失函数,准确率采用稀疏分类准确率函数
python
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['sparse_categorical_accuracy'])
模型训练
python
#训练模型
#批量训练大小为64,迭代5次,测试集比例0.2(48000条训练集数据,12000条测试集数据)
import time
print('--------------')
nowtime = time.strftime('%Y-%m-%d %H:%M:%S')
print(nowtime)
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))
--------------
2024-05-09 08:38:42
--------------
训练前时刻:2024-05-09 08:38:42
Epoch 1/5
625/625 [==============================] - 9s 6ms/step - loss: 1.5114 - sparse_categorical_accuracy: 0.4525 - val_loss: 1.2983 - val_sparse_categorical_accuracy: 0.5391
Epoch 2/5
625/625 [==============================] - 4s 6ms/step - loss: 1.1277 - sparse_categorical_accuracy: 0.6010 - val_loss: 1.0337 - val_sparse_categorical_accuracy: 0.6372
Epoch 3/5
625/625 [==============================] - 3s 6ms/step - loss: 0.9434 - sparse_categorical_accuracy: 0.6684 - val_loss: 0.9594 - val_sparse_categorical_accuracy: 0.6607
Epoch 4/5
625/625 [==============================] - 4s 7ms/step - loss: 0.8311 - sparse_categorical_accuracy: 0.7100 - val_loss: 0.8849 - val_sparse_categorical_accuracy: 0.6873
Epoch 5/5
625/625 [==============================] - 3s 5ms/step - loss: 0.7294 - sparse_categorical_accuracy: 0.7453 - val_loss: 0.8902 - val_sparse_categorical_accuracy: 0.6915
--------------
训练后时刻:2024-05-09 08:39:25
预测
python
#评估模型
model.evaluate(X_test,y_test,verbose=2) #每次迭代输出一条记录,来评价该模型是否有比较好的泛化能力
313/313 - 1s - loss: 0.8857 - sparse_categorical_accuracy: 0.6992 - 902ms/epoch - 3ms/step
[0.8857089877128601, 0.6991999745368958]
保存模型
python
#保存整个模型
model.save('CIFAR10_CNN_weights.h5')
/usr/local/lib/python3.10/dist-packages/keras/src/engine/training.py:3103: UserWarning: You are saving your model as an HDF5 file via `model.save()`. This file format is considered legacy. We recommend using instead the native Keras format, e.g. `model.save('my_model.keras')`.
saving_api.save_model(
结果可视化
python
#结果可视化
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'] #测试集准确率
{'loss': [1.5113933086395264, 1.1277204751968384, 0.9433806538581848, 0.83107590675354, 0.7294103503227234], 'sparse_categorical_accuracy': [0.45252498984336853, 0.6009500026702881, 0.6684250235557556, 0.7100499868392944, 0.7452999949455261], 'val_loss': [1.2982960939407349, 1.033674955368042, 0.9594402313232422, 0.8848526477813721, 0.8902430534362793], 'val_sparse_categorical_accuracy': [0.5390999913215637, 0.6371999979019165, 0.6607000231742859, 0.6873000264167786, 0.6915000081062317]}
python
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()
<matplotlib.legend.Legend at 0x78eb8af75d20>
使用已经保存的模型
python
#使用模型
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('label:'+str(test_y[num])+'\n predict:'+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()
1/1 [==============================] - 0s 19ms/step
1/1 [==============================] - 0s 19ms/step
1/1 [==============================] - 0s 18ms/step
1/1 [==============================] - 0s 19ms/step
1/1 [==============================] - 0s 19ms/step
1/1 [==============================] - 0s 21ms/step
1/1 [==============================] - 0s 19ms/step
1/1 [==============================] - 0s 20ms/step
1/1 [==============================] - 0s 19ms/step
1/1 [==============================] - 0s 19ms/step
参考文献: