本实验目的主要是掌握梯度下降法的优化算法;能够使用tf.keras构建Sequential模型,完成多分类任务。
1. 实验目的
①掌握梯度下降法的优化算法;
②能够使用tf.keras构建Sequential模型,完成多分类任务。
2. 实验内容
①下载MNIST数据集,建立神经网络模型,实现对MNIST手写数字数据集的识别,调整超参数和训练参数,并以可视化的形式输出模型训练的过程和结果;
②下载Fashion MNIST数据集,建立神经网络模型,实现对Fashion MNIST数据集的分类,调整超参数和训练参数,并以可视化的形式输出模型训练的过程和结果。
3. 实验过程
题目一:
使用神经网络模型,实现对MNIST手写数字数据集的识别,并测试模型性能,记录和分析结果。
要求:
(1)编写代码实现上述功能;
(2)记录实验过程和结果:
调整超参数和训练参数,使模型在测试集达到最优的性能,并以恰当的方式记录和展示实验过程和结果。
(3)分析和总结:
这个模型中的超参数有哪些?训练参数有哪些?结合训练过程,说明它们对模型性能的影响。
(4)保存上述训练好的模型,并使用它对自制的手写数字图像的识别(自制的手写数字图像见期中试题题目二)。
① 代码
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
plt.rcParams['font.family'] = "SimHei"
#导入mnist的训练集和测试集
mnist = tf.keras.datasets.mnist
(train_x,train_y),(test_x,test_y) = mnist.load_data()
img_testx = test_x
img_testy = test_y
#对属性进行归一化,使取值范围在0-1之间,同时转换为tensor张量,标签值转换为张量,0-9的整数
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)
X_img = X_test
#建立Sequential模型,使用add方法添加层
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) #Flatten不进行计算,将输入的二维数组转换为一维数组,进行形状转换
model.add(tf.keras.layers.Dense(128,activation="relu")) #添加隐含层,隐含层是全连接层,128个结点,激活函数使用relu函数
model.add(tf.keras.layers.Dense(10,activation="softmax"))#添加输出层,输出层是全连接层,激活函数是softmax函数
#配置训练方法
#优化器使用adam,损失函数使用稀疏交叉熵损失函数,准确率使用稀疏分类准确率函数
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['sparse_categorical_accuracy'])
## 训练模型
## 使用训练集中的数据训练,从中划分20%作为测试数据,用在每轮训练后评估模型的性能,每个小批量使用64条数据,训练5轮
model.fit(X_train,Y_train,batch_size=64,epochs=5,validation_split=0.2)
model.save_weights("result.h5")
#使用测试集评估模型
model.evaluate(X_test,Y_test,verbose=2)
#使用模型预测随机5个数据
for i in range(5):
num = np.random.randint(1,10000)
plt.subplot(1,5,i+1)
plt.axis("off")
plt.imshow(test_x[num],cmap="gray")
# argmax取出值最大的索引,predict中参数的数据范围和维数与训练集一致
y_pred = np.argmax(model.predict(tf.convert_to_tensor(X_test[num].numpy().reshape(1,28,28))))#使用argmax函数得到预测值
plt.title("原值="+str(test_y[num])+"\n预测值:"+str(y_pred))
plt.show()
#使用模型预测自己的手写数据集
img_arr = []
for i in range(10):
img = Image.open(r"D:\WorkSpace\pythonProject\qizhong\picture\%d.png" % i)
img_temp = np.array(img)
img_arr.append(img_temp)
for i in range(5):
num = np.random.randint(1,10000)
plt.subplot(1,5,i+1)
plt.axis("off")
plt.imshow(img_testx[num],cmap = "gray")
#argmax取出值最大的索引,predict中参数的数据范围和维数与训练集一致
#y_pred = np.argmax(model.predict([[X_test[num]]]))
#tensor = tf.convert_to_tensor(X_test[num].numpy().reshape(1,28*28))
y_pred = np.argmax(model.predict(tf.convert_to_tensor(X_img[num].numpy().reshape(1,28,28))))
plt.title("原值=" + str(img_testy[num]) + "\n预测值:" + str(y_pred))
plt.show()
② 结果记录
③ 实验总结
卷积神经网络模型中的超参数和训练参数包括超参数,卷积层的数量和参数,池化层的参数,全连接层的参数,学习率、优化器和损失函数等超参数。训练参数包括权重和偏置,训练批次大小,训练迭代次数。这些超参数和训练参数对模型的性能有着重要的影响。例如,调整卷积核大小和数量可以影响模型在不同图像尺寸上的能力;池化层的使用可以降低模型复杂度并加快训练速度,而学习率、优化器等超参数也会影响模型的训练收敛速度和稳定性。另外,训练批次大小和迭代次数也会影响模型的训练速度和精度。
题目二:
使用神经网络模型,实现对Fashion MNIST数据集的分类,并测试模型性能,记录和分析结果。
要求:
(1)编写代码实现上述功能;
(2)记录实验过程和结果:
调整超参数,综合考虑准确率、交叉熵损失、和训练时间等,使模型在测试集达到最优的性能,并以恰当的方式记录和展示实验结果。
(3)分析和总结:
这个模型中的超参数有哪些?简要说明你寻找最佳超参数的过程,并对结果进行分析和总结。
① 代码
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = "SimHei"
fashion_mnist = tf.keras.datasets.fashion_mnist
(train_x,train_y),(test_x,test_y) = fashion_mnist.load_data()
names = ['T-shirt/top','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle book']
#对属性进行归一化,使取值范围在0-1之间,同时转换为tensor张量,标签值转换为张量,0-9之间的整数
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)
#建立Sequential模型,使用add方法添加层
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) #Flatten不进行计算,将输入的二维数组转换为一维数组
model.add(tf.keras.layers.Dense(128,activation="relu")) #添加隐含层,隐含层是全连接层,128个结点,激活函数使用relu函数
model.add(tf.keras.layers.Dense(10,activation="softmax")) #添加输出层,输出层是全连接层,激活函数是softmax函数
#配置训练方法
#优化器使用adam,损失函数使用稀疏交叉熵损失函数,准确率使用稀疏分类准确率函数
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['sparse_categorical_accuracy'])
#训练模型
#使用训练集中的数据训练,从中划分20%作为测试数据,用在每轮训练后评价模型的性能,每个小批量使用64条数据,训练5轮
model.fit(X_train,Y_train,batch_size=64,epochs=5,validation_split=0.2)
#使用测试集评估模型,verbose = 2表示每一轮输出一行记录
model.evaluate(X_test,Y_test,verbose=2)
#使用模型
for i in range(4):
num = np.random.randint(1,10000)
plt.subplot(1,4,i + 1)
plt.axis("off")
plt.imshow(test_x[num],cmap="gray")
y_pred = np.argmax(model.predict(test_x[num].reshape(1,28,28)))
plt.title("原值:"+names[test_y[num]]+"\n预测值"+ names[y_pred])
plt.show()
② 结果记录
③ 实验总结
Fashion MNIST数据集的CNN模型的超参数包括卷积核数、大小和步长,池化区域大小和步长,全连接层神经元数、dropout率和学习率等。为了寻找最佳超参数,通常需要进行参数组合试验,对不同超参数进行组合和训练,通过比较模型的表现来选择最优组合。调整超参数可以影响训练速度和模型精度,需要权衡二者。最终模型的性能不仅与超参数有关,还受到网络结构、训练轮数、优化器等训练参数的影响。
题目三:
使用低阶API实现Softmax函数和交叉熵损失函数,并使用它们修改题目二。
在此使用低阶API
① 代码
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = "SimHei"
def softmax(logits):
exp_logits = np.exp(logits)
return exp_logits / np.sum(exp_logits, axis=1, keepdims=True)
def sparse_categorical_crossentropy(y_true, logits):
num_samples = y_true.shape[0]
y_pred = softmax(logits)
loss = -np.log(y_pred[range(num_samples), y_true])
return loss.mean()
fashion_mnist = tf.keras.datasets.fashion_mnist
(train_x,train_y),(test_x,test_y) = fashion_mnist.load_data()
names = ['T-shirt/top','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle book']
#对属性进行归一化,使取值范围在0-1之间,同时转换为tensor张量,标签值转换为张量,0-9之间的整数
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)
#建立Sequential模型,使用add方法添加层
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) #Flatten不进行计算,将输入的二维数组转换为一维数组
model.add(tf.keras.layers.Dense(128,activation="relu")) #添加隐含层,隐含层是全连接层,128个结点,激活函数使用relu函数
model.add(tf.keras.layers.Dense(10,activation="softmax")) #添加输出层,输出层是全连接层,激活函数是softmax函数
#配置训练方法
#优化器使用adam,损失函数使用稀疏交叉熵损失函数,准确率使用稀疏分类准确率函数
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['sparse_categorical_accuracy'])
#训练模型
#使用训练集中的数据训练,从中划分20%作为测试数据,用在每轮训练后评价模型的性能,每个小批量使用64条数据,训练5轮
model.fit(X_train,Y_train,batch_size=64,epochs=5,validation_split=0.2)
#使用测试集评估模型,verbose = 2表示每一轮输出一行记录
model.evaluate(X_test,Y_test,verbose=2)
#使用模型
for i in range(4):
num = np.random.randint(1,10000)
plt.subplot(1,4,i + 1)
plt.axis("off")
plt.imshow(test_x[num],cmap="gray")
y_pred = np.argmax(model.predict(test_x[num].reshape(1,28,28)))
plt.title("原值:"+names[test_y[num]]+"\n预测值"+ names[y_pred])
plt.show()
② 实验结果
4. 实验小结&讨论题
请结合题目1-3回答下述问题:
①什么是小批量梯度下降法?每个小批量中的样本数对迭代次数有何影响?
答:小批量梯度下降法是梯度下降法的一个变种,它将所有样本一次性输入模型进行训练的过程,改为将样本划分为若干小批量进行迭代训练。每次迭代,使用一个小批量样本集计算损失函数并根据其梯度更新模型参数。这种方法可以加速模型收敛,并减少计算负载和内存使用量。
每个小批量中的样本数会影响迭代次数和每个迭代的计算量。较小的小批量样本数量有助于收敛速度的加快,保留了样本的随机性,但增加了每个迭代的计算量;相反,较大的小批量样本数量可以减少计算量,但可能会导致模型陷入局部最优,并减缓收敛速度。因此,我们需要考虑数据集的大小和复杂度,并进行超参数调整以达到最佳的训练结果。
②可以从哪些方面对梯度下降法进行优化?典型的优化方法有哪些?它们对模型训练过程有何影响?
答:梯度下降算法是深度学习中的核心优化算法。我们可以从调整学习率、优化参数初始化、使用正则化和dropout等方面进行优化,以提高模型训练的速度和精度。典型的优化方法有随机梯度下降(SGD)、动量法、Adagrad、Adam等。这些优化方法可以通过调整超参数、监测训练集和验证集上的损失函数、调整网络结构等方式,对模型的收敛速度和稳定性产生影响。
③在设计神经网络时,为MNIST设计的神经网络是否可以直接应用到Fashion-MNIST上?请从数据集的图片大小,样本数以及分类数等角度解释这个现象。
答:MNIST和Fashion-MNIST都是手写数字和服装的灰度图像数据集,但它们的数据集的图片大小、样本数和分类数不同。MNIST是28x28的灰度图像,有6万个训练样本和1万个测试样本,其中包含10个类别的手写数字。而Fashion-MNIST是28x28的灰度图像,有6万个训练样本和1万个测试样本,其中包含10个类别的服装。因此,为MNIST设计的神经网络不能直接应用于Fashion-MNIST数据集上,因为数据集之间的差异会影响模型性能。新的模型应该经过适当的调整和训练,以适应数据集的特征和规模。
④Fashion-MNIST创建之初希望替代MNIST数据集,比较相同的神经网络在这两个数据集上的准确率,并思考在模型评估方面,使用Fashion-MNIST数据集有什么优势?
答:MNIST数据集过于简单,可以在MNIST数据集成功的模型在别的数据集未必可以成功,不具有准确性。Fashion-MNIST是为了替代MNIST数据集而创建的,然而,相同的神经网络在这两个数据集上的准确率可能会有很大的差异。这是因为它们的图像特征和特定维度上类别的区别不同。对于模型评估方面,使用Fashion-MNIST数据集有以下优势,更具挑战性。相较于MNIST数据集,Fashion-MNIST数据集有更多的类别、更多的样本和更多的复杂度,更具有挑战性,能更好地评估模型的鲁棒性和泛化能力。更加真实。Fashion-MNIST数据集包含真实的服装图像,更符合真实生活中的场景,能更好地应用到实际场景中。