TensorFlow2编程练习——多层感知机MLP

import numpy as np

import tensorflow as tf

import os

os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"                  # 运行硬件选择

os.environ["CUDA_VISIBLE_DEVICES"] = "0"                        #-1 CPU 0 GPU1,1 GPU2 ,以此类推

''' 数据获取及预处理 '''

class MNISTLoader():

     # 从网络上自动下载 MNIST 数据集并加载。如果运行时出现网络连接错误,可以从

     # https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz

     #

     # https://s3.amazonaws.com/img-datasets/mnist.npz

     # 下载 MNIST 数据集 mnist.npz 文件,并放置于用户目录的 .keras/dataset 目录下( Windows 下用户目录为 C:\Users\ 用户名 ,

     # Linux 下用户目录为 /home/ 用户名 )

     def __init__(self):

         mnist = tf.keras.datasets.mnist

         (self.train_data, self.train_label), (self.test_data, self.test_label) = mnist.load_data()

         # MNIST 中的图像默认为 uint8 0-255 的数字)。以下代码将其归一化到 0-1 之间的浮点数,并在最后增加一维作为颜色通道

         self.train_data = np.expand_dims(self.train_data.astype(np.float32)/255.0, axis=-1)  # [60000, 28, 28, 1]

         # 保存训练数据,手动增加一个张量维度给通道数( size=-1

         self.test_data = np.expand_dims(self.test_data.astype(np.float32)/255.0, axis=-1)  # [10000, 28, 28, 1]

         # 保存测试数据,手动增加一个张量维度给通道数( size=-1

         self.train_label = self.train_label.astype(np.float32)  # [60000]

         self.test_label = self.test_label.astype(np.float32)  # [10000]

         self.num_train_data, self.num_test_data = self.train_data.shape[0],self.test_data.shape[0]  

         # 提取训练集和测试集图片数量

     def get_batch(self, batch_size):

         index = np.random.randint(0, self.num_train_data, batch_size)

         return self.train_data[index, :], self.train_label[index]

'''end'''

''' 模型构建 '''

class MLP(tf.keras.Model):

     def __init__(self):

         super().__init__()

         self.flatten = tf.keras.layers.Flatten()  # 28*28 的图片拉直成 1*784 向量

         self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)  # 增加隐层 1 100 个神经元,激活函数 ReLu

         self.dense2 = tf.keras.layers.Dense(units=10)  # 增加隐层 2,10 个神经元, 无激活函数

     def call(self, inputs):  # 调用数据运算,输入张量外汇跟单gendan5.com [batch_size, 28, 28, 1]

         x = self.flatten(inputs)  # 拉直输入 [batch_size, 784]

         x = self.dense1(x)  # 隐层 1[batch_size, 100]

         x = self.dense2(x)  # 隐层 2[batch_size, 10]

         output = tf.nn.softmax(x)  # 输出 softmax 分类

         return output

'''end'''

''' 模型训练 '''

# 定义超参数,参数定义参见 https://blog.csdn.net/u013041398/article/details/72841854/

num_epochs = 5  # 轮次、周期,完整遍历数据集的次数,过小可能会欠拟合,过大可能会过拟合

batch_size = 50  # 批次,通常使用 mini-batch 方法,训练一批后计算损失函数进行梯度下降和权重更新

learning_rate = 0.001  # 学习率

# 实例化

model = MLP()  # 实例化模型

data_loader = MNISTLoader()  # 实例化数据读取类

optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)  # 实例化优化器,使用 Adam 优化器,算法讲解

# 参见 https://www.jianshu.com/p/aebcaf8af76e

'''end'''

''' 训练与迭代 '''

num_batches = int(data_loader.num_train_data // batch_size * num_epochs)  # 求训练集 batch 总个数,即训练总周期数

for batch_index in range(num_batches):

     X, Y = data_loader.get_batch(batch_size)  # 提取输入输出

     with tf.GradientTape() as tape:

         y_pred = model(X)  # 计算模型输出

         loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=Y, y_pred=y_pred)  # 使用交叉熵函数做损失函数,

         # 算法讲解参见 https://blog.csdn.net/tsyccnh/article/details/79163834

         # loss = tf.keras.losses.categorical_crossentropy(

         #     y_true=tf.one_hot(Y, depth=tf.shape(y_pred)[-1]),

         #     y_pred=y_pred

         # )  # 与上式等效

         loss = tf.reduce_mean(loss)  # 求一维均方误差 MSE

         print("batch %d: loss %f" % (batch_index, loss.numpy()))

     grads = tape.gradient(loss, model.variables)  # 损失函数关于自变量的梯度自动计算,

     # 使用 model.variables 属性直接获得模型中所有变量

     optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))  # 根据梯度自动更新参数,

     # zip() 为拼装成元组函数

'''end'''

''' 模型评估 '''

sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()  # 计算预测正确样本数占总样本数的比例实例化

num_batches = int(data_loader.num_test_data // batch_size)  # 计算测试集批次 batch

for batch_index in range(num_batches):

     start_index, end_index = batch_index * batch_size, (batch_index + 1) * batch_size  # 每个 batch 逐个样本标号

     y_pred = model.predict(data_loader.test_data[start_index: end_index])  # 计算一个 batch 预测模型输出

     sparse_categorical_accuracy.update_state(y_true=data_loader.test_label[start_index: end_index], y_pred=y_pred)  

     # 更新预测精度

     print("test accuracy: %f" % sparse_categorical_accuracy.result())

'''end'''


请使用浏览器的分享功能分享到微信等