综合实训——tensorflow深度学习基于cifar10数据集的模型训练与识别
目录
一、实验要求:
1、按照深度学习流程框架图,代码中需体现这一层次感(可以用空行的形式隔开即可,亦可以添加注释)
2、训练轮次需要用回调函数的形式提前结束
3、模型的编写需要用自定义模型的形式
4、最好有多个模型,便于进行比较
5、对模型的准确率不做严格要求,但准确率越高必然会是一个很好的加分项,要注意防止过拟合
6、代码分为 模型的构建保存 和 模型的调用 两个工程,模型调用即是对图片进行识别
7、测试图片可以从数据集中任意挑3张即可
8、训练的过程中(每一轮)需要有可视化的体现
9、验证集上或者测试集上也需要做可视化
10、如果有多个模型进行比较的,可以给出多个模型的可视化方便比较
二、实验目的:
运用所学的tensorflow相关知识自己搭建一个网络模型对cifar10数据集进行训练,用训练好的模型对数据集进行预测。其目的在于,考察对所学基础知识的掌握程度,以及增强我们的自主学习能力和动手能力。
三、实验环境:
开发环境:Anacona3、python等
编程窗口:jupyter lab
四、实验步鄹(包含代码、可视化、结果的截图):
(一)数据准备与分析阶段
1.1.导入库
1.2.1下载数据集(下载后的数据的路径为:C:\Users\Administrator\.keras\datasets)
1.2.2下载后路径下的数据集如图
1.3分别查看训练集、训练集标签、测试集、测试集标签的形状,了解数据
1.4找到下载后的数据集,点开网页可以看到如图所示的页面
CIFAR-10数据集由10类60000幅32x32彩色图像组成,每类6000幅图像。有50000个训练图像和10000个测试图像。 数据集分为五个训练批次和一个测试批次,每个批次有10000幅图像。测试批次包含从每个类别中随机选择的1000个图像。训练批次以随机顺序包含剩余的图像,但是一些训练批次可能包含来自一个类别的比来自另一个类别的更多的图像。
1.5.1把数据集拉为一维的数据显示,方便后续操作(数据前后如图所示)
1.5.2对训练集和测试集进行归一化处理,保证值在0,1之间
1.6标签的名字为
1.7为了验证数据的格式是否正确,以及您是否已准备好构建和训练网络,让我们显示训练集中的 25 个图像,并在每个图像下方显示类名称
1.7.1代码为
1.7.2结果为
二、网络的构建(自定义网络)
1.模型一(自定义神经网络模型)
1.1导入库、数据加载以及数据简单处理
1.2自定义模型
1.3模型编译
1.4模型训练
1.5模型训练结果
1.6可视化代码
1.7可视化结果
2.模型二
2.1导入库、加载数据及数据处理
2.2自动定义模型
2.3模型编译、模型保存、模型训练,显示信息
2.4训练结果
2.5可视化代码
2.6可视化结果图
4.对比出好的模型保存此模型
经对比我选择了第一个模型
三、用训练好的最佳模型识别预测图片
1.综合考虑选择Baseline模型
1.1模型保存
1.2模型调用
1.3.1进行预测
1.3.2测试第一个预测结果
1.3.3测试前20个预测结果
1.4.绘制可视化图识别图像
1.4.1绘制代码
1.4.2预测第0张图片
1.4.3预测第12张图片
1.4.4预测第20张图片
1.5预测前15张图片
1.5.1代码如图
1.5.2可视化结果如图
六、实验总结:
本次实验综合性很强,对于cifar10数据集,可以采取多个模型来训练和调用模型来识别图片,在本次实验中,主要采用了Baseline,LeNet5,这两个模型来进行对比,并最终综合选择较好的一个模型来对图片进行识别。这两个模型都需多次调参,不断的优化来提高准确率,但调的过程中又容易导致训练过拟合,而每次训练都需要花费太多时间,特别是网络结构复杂的模型需要足够的时间。对于Baseline,LeNet5模型网路结构相对简化,神经元个数对比相对较少,所以花费时间相对较少,而LeNet5模型我多次调参,没能较好的处理过拟合现象,所以综合考虑,我最终选择了Baseline模型来实现图像的识别。经过此次实验,我觉得的最重要的是做实验的过程,说实话每次的实验都能学到很多的东西,也是对自己一学期所学的内容进行一个总结。
七、附上源码:
(一)cifar10数据分析
#导入必要的库
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.datasets import cifar10
#下载数据
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
#查看训练集形状
x_train.shape
#查看测试集形状
y_train.shape
#查看训练集标签
x_test.shape
#查看测试集标签
y_test.shape
#把数据拉直,变为一维的
y_train = np.array(y_train)
y_test = np.array(y_test)
#print(y_test[:2])
print(y_train[:2])
y_train = y_train.flatten()
y_test = y_test.flatten()
print(y_train[:2])
#对训练集和测试集进行归一化处理,保证值在0,1之间
x_train, x_test = x_train / 255.0, x_test / 255.0
#类名创建
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck']
#可视化显示前25张图片
plt.figure(figsize=(10, 10))
for i in range(25):
plt.subplot(5, 5, i + 1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(x_train[i], cmap=plt.cm.binary)
plt.xlabel(class_names[y_train[i]],color = 'r')
plt.show()
(二)模型一(Baseline)
#导入库
import tensorflow as tf
import numpy as np
import os
from matplotlib import pyplot as plt
from tensorflow.keras.layers import Dense,Flatten,Activation,Conv2D,MaxPool2D
from tensorflow.keras import Model
#数据加载
cifar10=tf.keras.datasets.cifar10
(x_train,y_train),(x_test,y_test)=cifar10.load_data()
#将数据拉直
y_train = np.array(y_train)
y_test = np.array(y_test)
y_train = y_train.flatten()
y_test = y_test.flatten()
#归一化
x_train=x_train/255.
x_test=x_test/255.
#自定义网路
class LeNet5(Model):
def __init__(self):
#初始化
super(LeNet5,self).__init__()
#卷积层
self.c1=Conv2D(filters=6,kernel_size=(5,5),strides=1,padding='same')
#激活层
self.a1=Activation('sigmoid')
#池化层
self.p1=MaxPool2D(pool_size=(2,2),strides=2,padding='valid')
self.c2=Conv2D(filters=16,kernel_size=(5,5),strides=1,padding='same')
self.a2=Activation('sigmoid')
self.p2=MaxPool2D(pool_size=(2,2),strides=2,padding='valid')
self.flatten=Flatten()
self.f1=Dense(120,activation='sigmoid')
self.f2=Dense(84, activation='sigmoid')
self.f3=Dense(10, activation='softmax')
def call(self,x):
x = self.c1(x)
x = self.a1(x)
x = self.p1(x)
x = self.c2(x)
x = self.a2(x)
x = self.p2(x)
x = self.flatten(x)
x = self.f1(x)
x = self.f2(x)
y= self.f3(x)
return y
model=LeNet5()
#网路编译
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
#checkpoint_save_path='./checkpoint/LeNet.ckpt'
#if os.path.exists(checkpoint_save_path+'.index'):
# print('-----------load model-----------')
# model.load_weights(checkpoint_save_path)
#cp_callback=tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
# save_best_only=True,
# save_weights_only=True)
#定义打印轮次
class Printepochs(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs):
print('当前轮次:', epoch +1)
#提前终止
earlyStop = tf.keras.callbacks.EarlyStopping(monitor='val_loss',patience=20)
history = model.fit(x_train,y_train, epochs=1000,verbose=2,batch_size=100,
callbacks = [earlyStop,cp_callback, Printepochs()], validation_split= 0.3)
# history=model.fit(x_train,y_train,batch_size=32,epochs=5,validation_data=(x_test,y_test),validation_freq=1,
# callbacks=[cp_callback])
model.summary()
# file=open('./LeNet_weights.txt','w')
# for v in model.trainable_variables:
# file.write(str(v.name)+'\n')
# file.write(str(v.shape) + '\n')
# file.write(str(v.numpy()) + '\n')
# file.close()
#---------------可视化图像---------------------------------
acc=history.history['sparse_categorical_accuracy']
val_acc=history.history['val_sparse_categorical_accuracy']
loss=history.history['loss']
val_loss=history.history['val_loss']
plt.subplot(1,2,2)
plt.plot(acc,label='sparse_categorical_accuracy')
plt.plot(val_acc,label='val_sparse_categorical_accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
plt.subplot(1,2,1)
plt.plot(loss,label='loss')
plt.plot(val_loss,label='val_loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()
#模型保存
#tf.keras.Model.save(model, 'LeNet.f5')
check_save_path='./checkpoint/Baseline.ckpt'
tf.keras.Model.save(model,check_save_path)
#模型调用
#probability_model = tf.keras.models.load_model('./LeNet.f5')
probability_model = tf.keras.models.load_model(check_save_path)
#probability_model = tf.keras.Sequential([model,
# tf.keras.layers.Softmax()])
#predictions = probability_model.predict(x_test)#test_images
#类名
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck']
#进行预测
#测试第一个预测结果
print(predictions[0])
print('````````````````````````')
#找出置信度最大的标签
print(np.argmax(predictions[0]))
#检查测试标签
print(y_test[0])#test_labels
#将其绘制成图表,看看模型对于全部 10 个类的预测
def plot_image(i, predictions_array, true_label, img):
predictions_array, true_label, img = predictions_array, true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
def plot_value_array(i, predictions_array, true_label):
predictions_array, true_label = predictions_array, true_label[i]
plt.grid(False)
plt.xticks(range(10))
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
#显示第0张图片
i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], y_test, x_test)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], y_test)
plt.show()
#显示第12张图片
i = 12
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], y_test, x_test)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], y_test)
plt.show()
#显示15张图片
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*2*num_rows))
for i in range(num_images):
plt.subplot(num_rows, 2*num_cols, 2*i+1)
plot_image(i, predictions[i], y_test, x_test)
plt.subplot(num_rows, 2*num_cols, 2*i+2)
plot_value_array(i, predictions[i], y_test)
plt.tight_layout()
plt.show()
#使用训练好的模型对单个图像进行预测
# Grab an image from the test dataset.
img = x_test[1]
print(img.shape)
#将其添加到列表中
# Add the image to a batch where it's the only member.
img = (np.expand_dims(img,0))
print(img.shape)
#预测这个图像的正确标签
predictions_single = probability_model.predict(img)
print(predictions_single)
plot_value_array(1, predictions_single[0], y_test)
_ = plt.xticks(range(10), class_names, rotation=45)
plt.show()
print(np.argmax(predictions_single[0]))
(三)模型二(LeNet5)
# 导入库
import tensorflow as tf
import os
import numpy as np
from keras import datasets, layers, models
from tensorflow.keras.datasets import cifar10
import matplotlib.pyplot as plt
from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout, Flatten, Dense
from tensorflow.keras import Model
# 下载数据集(下载后的数据的路径为:C:\Users\Administrator\.keras\datasets)
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
# 数据拉直,把数据变为一维
y_train = np.array(y_train)
y_test = np.array(y_test)
y_train = y_train.flatten()
y_test = y_test.flatten()
# 对训练集和测试集进行归一化处理,保证值在0,1之间
x_train, x_test = x_train / 255.0, x_test / 255.0
# 类名
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck']
#————————————————————————————————————————————————————————————————
# 0 飞机(airplane)
# 1 汽车(automobile)
# 2 鸟(bird)
# 3 猫(cat)
# 4 鹿(deer)
# 5 狗(dog)
# 6 蛙类(frog)
# 7 马(horse)
# 8 船(ship)
# 9 卡车(truck)
#——————————————————————————————————————————————————————————————————
# 自定义卷积网路网路
class Baseline(Model):
def __init__(self):
# 网络开始
# 初始化
super(Baseline, self).__init__()
# 卷积层 (卷积个数6,卷积核大小5X5,填充方式same进行边缘沿拓,让卷积后的通道尺寸保持不变)
self.c1 = Conv2D(filters=6, kernel_size=(5, 5), padding='same')
# BN层(批量正则划层)
self.b1 = BatchNormalization()
# 激活层 (使用relu函数)
self.a1 = Activation('relu')
# 池化层
self.p1 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')
# dropout层(随机丢弃层)
self.d1 = Dropout(0.4)
self.flatten = Flatten()
# 全连接层
self.f1 = Dense(128, activation='relu')
# 随机丢弃层
self.d2 = Dropout(0.4)
self.f2 = Dense(10, activation='softmax')
def call(self, x):
x = self.c1(x)
x = self.b1(x)
x = self.a1(x)
x = self.p1(x)
x = self.d1(x)
x = self.flatten(x)
x = self.f1(x)
x = self.d2(x)
y = self.f2(x)
return y
model = Baseline()
# 网络编译(传入优化器,损失函数,准确率指标)
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
#check_save_path='./checkpoint/Baseline.ckpt'
# if os.path.exists(check_save_path+'.index'):
# print('-------------lodel the model------------')
# model.load_weights(check_save_path)
#history = model.fit(x_train, y_train, batch_size=32, epochs=20, validation_data=(x_test, y_test), validation_freq=1)
# 定义打印轮次
class Printepochs(tf.keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs):
print('当前轮次:', epoch +1)
# 定义回调函数
callbacks_list = [
tf.keras.callbacks.ReduceLROnPlateau(
monitor='val_loss' , # 监控模型的验证损失
factor=0.1, # 触发时将学习率除以 10
patience=10, ) ] #如果验证损失在 10 轮内都没有改善,那么就触发这个回调函数
# 早停
earlyStop = tf.keras.callbacks.EarlyStopping(monitor='val_loss',patience=20)
# 模型训练
history = model.fit(x_train,y_train, epochs=1000,verbose=2,batch_size=100,
callbacks = [earlyStop,callbacks_list, Printepochs()], validation_split= 0.2)
model.summary()
#------------------------------------------------------------------------------------------
# 可视化展示,显示训练集和验证集的acc和loss曲线
acc = history.history['sparse_categorical_accuracy']
val_acc = history.history['val_sparse_categorical_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
plt.subplot(1, 2, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()
#模型保存
check_save_path='./CKPT/Baseline.ckpt'
tf.keras.Model.save(model,check_save_path)
#模型调用
#测试
#probability_model = tf.keras.Sequential([model,
# tf.keras.layers.Softmax()])
#predictions = probability_model.predict(x_test) #测试集图片
probability_model = tf.keras.models.load_model(check_save_path)
#测试第一个预测结果
print(predictions[0])
print('````````````````````````')
#找出置信度最大的标签
print(np.argmax(predictions[0]))
#检查测试标签
print(y_test[0])#test_labels
#绘制图表
def plot_image(i, predictions_array, true_label, img):
predictions_array, true_label, img = predictions_array, true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
def plot_value_array(i, predictions_array, true_label):
predictions_array, true_label = predictions_array, true_label[i]
plt.grid(False)
plt.xticks(range(10))
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
#显示第0张图片
i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], y_test, x_test)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], y_test)
plt.show()
#显示第15张图片
i = 15
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], y_test, x_test)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], y_test)
plt.show()
#显示地44张图片
i = 44
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], y_test, x_test)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], y_test)
plt.show()
#显示前15张图片
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
plt.subplot(num_rows, 2*num_cols, 2*i+1)
plot_image(i, predictions[i], y_test, x_test)
plt.subplot(num_rows, 2*num_cols, 2*i+2)
plot_value_array(i, predictions[i], y_test)
plt.tight_layout()
plt.show()
#使用训练好的模型对单个图像进行预测
# Grab an image from the test dataset.
img = x_test[1]
print(img.shape)
#将其添加到列表中
# Add the image to a batch where it's the only member.
img = (np.expand_dims(img,0))
print(img.shape)
#预测这个图像的正确标签
predictions_single = probability_model.predict(img)
print(predictions_single)
plot_value_array(1, predictions_single[0], y_test)
_ = plt.xticks(range(10), class_names, rotation=45)
plt.show()
print(np.argmax(predictions_single[0]))