本章为学习笔记,并不是教程,如有错误,大家可以留言告诉我 上一章讲解了如何安装keras,现在我们开始上手对mnist数据集进行训练,并且对比两次训练情况来验证dropout的减少过拟合的作用。
废话少说先把代码贴上来
import numpy as np import pandas as pd from keras.utils import np_utils import matplotlib.pyplot as plt from keras.datasets import mnist from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout # 获取mnist数据 (x_train_image, y_train_label), (x_test_image, y_test_label) = mnist.load_data() # 对图像进行预处理 # 将图像转化为一维数组 x_Test = x_test_image.reshape(10000, 784).astype('float32') x_Train = x_train_image.reshape(60000, 784).astype('float32') # 将灰度控制在(0-1)的范围 x_Train_normalize = x_Train / 255 x_Test_normalize = x_Test / 255 # 将标签转化为onehot形式 y_Train_OneHot = np_utils.to_categorical(y_train_label) y_Test_OneHot = np_utils.to_categorical(y_test_label) # 显示图像和预测结果 def plot_image_prediction(images, labels, prediction, idx, num = 25): fig = plt.gcf() fig.set_size_inches(12, 14) if num > 25: num = 25 for i in range(0, num): # 将画布分割为 5 * 5 个子图 ax = plt.subplot(5, 5, 1 + i) ax.imshow(images[idx], cmap='binary') title = "label=" + str(labels[idx]) if len(prediction) > 0: title = ",prediction=" + str(prediction[idx]) ax.set_title(title, fontsize=10) ax.set_xticks([]) ax.set_yticks([]) idx += 1 plt.show() # 显示训练结果 def show_history(train_history, train, validation): plt.plot(train_history.history[train]) plt.plot(train_history.history[validation]) # print(train_history.history[train]) # print(train_history.history[validation]) plt.title('Train History') plt.ylabel(train) plt.xlabel('Epoch') plt.legend(['train', 'validation'], loc='upper left') plt.show() # 第二种训练模式 def train1(): # 采用顺序模型 model = Sequential() # 设置输入层 model.add(Dense(units=1000, input_dim=784, kernel_initializer='normal', activation='relu')) # 添加dropout 方法减少过拟合的情况 model.add(Dropout(0.5)) model.add(Dense(units=1000, kernel_initializer='normal', activation='relu')) model.add(Dropout(0.5)) # 设置输出层,有10个输出结果对应手写数字的预测结果(0-9) model.add(Dense(units=10, kernel_initializer='normal', activation='softmax')) # 设置损失函数为交叉熵,利用adam方法对梯度进行操作,目标指数为精确度 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # split 为验证数据分割比例(用于确定适合的超参数) train_history = model.fit(x=x_Train_normalize, y=y_Train_OneHot, validation_split=0.2, epochs=10, batch_size=200, verbose=2) # 显示训练结果 show_history(train_history, 'acc', 'val_acc') show_history(train_history, 'loss', 'val_loss') # 利用test进行预测 scores = model.evaluate(x_Test_normalize, y_Test_OneHot) print() # 输出预测经度 print(scores[1]) # 从340号图片开始显示25张图片与其预测结果 prediction = model.predict_classes(x_Test) plot_image_prediction(x_test_image, y_test_label, prediction, idx=340) # 显示混淆矩阵 crossTable = pd.crosstab(y_test_label, prediction, rownames=['label'], colnames=['predict']) print(crossTable) # 第一种训练模式 def train(): # 采用顺序模型 model = Sequential() # 设置输入层 model.add(Dense(units=256, input_dim=784, kernel_initializer='normal', activation='relu')) # 设置输出层,有10个输出结果对应手写数字的预测结果(0-9) model.add(Dense(units=10, kernel_initializer='normal', activation='softmax')) # 设置损失函数为交叉熵,利用adam方法对梯度进行操作,目标指数为精确度 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # split 为验证数据分割比例(用于确定适合的超参数) # split 为验证数据分割比例(用于确定适合的超参数) train_history = model.fit(x=x_Train_normalize, y=y_Train_OneHot, validation_split=0.2, epochs=10, batch_size=200, verbose=2) # 显示训练结果 show_history(train_history, 'acc', 'val_acc') show_history(train_history, 'loss', 'val_loss') # 利用test进行预测 scores = model.evaluate(x_Test_normalize, y_Test_OneHot) print() # 输出预测经度 print(scores[1]) # 从340号图片开始显示25张图片与其预测结果 prediction = model.predict_classes(x_Test) plot_image_prediction(x_test_image, y_test_label, prediction, idx=340) # 显示混淆矩阵 crossTable = pd.crosstab(y_test_label, prediction, rownames=['label'], colnames=['predict']) print(crossTable) train() train1()上面的代码这里不再过多解释(可以看注解),我们进行了两次训练,输出训练结果和混淆矩阵,结果如下
可以看到,验证数据和训练数据在不断训练的过程中精度一直在上升,但是需要注意的是,在训练结束后训练数据会略高于验证数据,这样就有了过拟合的嫌疑。 可以看到,第一次训练的混淆矩阵如下,test测试精度为0.9783
第二次训练我们添加了dropout方法,并且添加了一层隐藏层用于提高精确度,结果如下 我们可以明显看到,添加了dropout的第二次训练,验证数据和训练数据在训练结束后并没有太大区别,即减少了训练数据自己验证的精确度,减少了过拟合的情况 由于添加了一层隐藏层,我们的预测进度也相对提高了
输出一部分识别结果,如图