"""
使用全连接神经网络训练minist数据集
"""
# 导入模块
import tensorflow as tf
from tensorflow.keras.utils import to_categorical
from tensorflow.keras import models, layers, regularizers
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt
import cv2
"""
一、认识minist数据集
"""
# 加载数据集
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# print(train_images.shape, test_images.shape) # 打印训练集的数据和大小
# print("train_images:\n", train_images[0]) # 打印训练集第0组图像
# print("test_images:\n", test_images[0]) # 打印测试集第0组图像
# cv2.imshow('train_images[0]:', train_images[0]) # 以OpenCV中的imshow方式显示训练集第0组图像
# cv2.waitKey(0)
# cv2.destroyWindow()
# plt.imshow(train_images[0]) # 显示训练集第0组图像
# plt.show()
# 将图片由二维铺展成为一维
train_images = train_images.reshape(60000, 28 * 28).astype('float')
test_images = test_images.reshape(10000, 28 * 28).astype('float')
train_labels = to_categorical(train_labels) # 将训练集标签转换为独热编码
test_labels = to_categorical(test_labels) # 将测试集标签转换为独热编码
# print("train_images_shape_to_categorical:", train_labels[0])
# print("test_images_shape_to_categorical:", test_labels[0])
"""
二、搭建一个神经网络
"""
network = models.Sequential() # Sequential表示按层顺序构建网络
# Dense表示全连接层
network.add(layers.Dense(units=128, activation='relu', input_shape=(28 * 28,),
kernel_regularizer=regularizers.l1(0.0001))) # 轻微过拟合用较小的值,过度过拟合用较大的值
network.add(layers.Dropout(0.01))
network.add(layers.Dense(units=32, activation='relu',
kernel_regularizer=regularizers.l1(0.0001))) # 一般都用10^-n(0.0001,0.001,0.01,0.1等)
network.add(layers.Dropout(0.01))
network.add(layers.Dense(units=10, activation='softmax'))
# print(network.summary())
"""
三、神经网络的训练
1.编译:确定优化器和损失函数等
2.训练网络:确定训练的数据、训练的轮数和每次训练的样本数等
"""
# 编译步骤
network.compile(optimizer=RMSprop(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy'])
# 训练网络,用fit函数,epochs表示训练多少个回合,batch_size表示每次训练给多大的数据,
# verbose=2表示每个epoch都在控制台输出一行记录,verbose=1表示为输出进度条记录(默认为1)
network.fit(train_images, train_labels, epochs=20, batch_size=128, verbose=2)
"""
四、用训练好的模型进行预测,并在测试集上做出评价
"""
# 在测试集上测试一下模型的性能
y_pre = network.predict(test_images[:5]) # 在测试集上测试前五张图片
print(y_pre, "\n", test_labels[:5]) # 将网络中前五张测试图片和真实图片对比,看是否正确
test_loss, test_accuracy = network.evaluate(test_images, test_labels) # 保存网络中测试集的损失和准确率的评估值
print("test_loss:", test_loss, "test_accuracy:", test_accuracy) # 打印损失函数和准确率的评估值