TensorFlow2程式設計練習——多層感知機MLP

專注的阿熊發表於2021-08-09

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 資料集並載入。如果執行時出現網路連線錯誤,可以從

     #

     #

     #

     # 下載 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 最佳化器,演算法講解

# 參見

'''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'''


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2786050/,如需轉載,請註明出處,否則將追究法律責任。

相關文章