1 import tensorflow as tf
2 import numpy as np
3 """
4 tf.keras.datasets 获得数据集 并预处理
5 """
6 class MNISTLoader():
7 def __init__(self): #加载类的构造函数
8 mnist = tf.keras.datasets.mnist
9 (self.train_data,self.train_label),(self.test_data,self.test_label) = mnist.load_data() #(6000,28,28)
10 #axis = 1 ,相当于在最内层每个元素加括号变成 n, 1 ,在后面加个1 这个维度; axis = 0,就是维度变成 1,n,在中间加个1这个维度
11 self.train_data = np.expand_dims(self.train_data.astype(np.float32)/255.0,axis = -1)
12 self.test_data = np.expand_dims(self.test_data.astype(np.float32)/255.0,axis = -1)
13 self.test_label = self.test_label.astype(np.int32) # [10000]
14 self.train_label = self.train_label.astype(np.int32) # [60000]
15 self.num_train_data, self.num_test_data = self.train_data.shape[0], self.test_data.shape[0]
16 def get_batch(self,betch_size):
17 index = np.random.randint(0,np.shape(self.train_data)[0],batch_size) #(low, high, size),size可以是一个元组,那么会生成一个多维数组
18 #从(0,6000)中随机抽取batch_size个随机整数,数字包括下界,不包括上界
19 return self.train_data[index, :], self.train_label[index] #返回抽取的batch数字对应的样本,[[],[],[],[],...], [1,3,4,5,7,...] 一个batch返回两个tensor
20
21 """
22 模型构建,tf.keras.Model ,tf.keras.layers
23 """
24 class MLP(tf.keras.Model):
25 def __init__(self):
26 super().__init__()
27 self.flatten = tf.keras.layers.Flatten()
28 self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)
29 self.dense2 = tf.keras.layers.Dense(units=10)
30
31 def call(self, inputs):
32 x = self.flatten(inputs)
33 x = self.dense1(x)
34 x = self.dense2(x)
35 output = tf.nn.softmax(x) # 用了多分类激活函数在最后输出层
36 # softmax,归一化指数函数。且变得可导了。平滑化的 argmax 函数,平滑功能就是使各类的直接数字差别不会特别大了,即soft.
37 return output
38 """
39 模型的训练 tf.keras.losses , tf.keras.optimizer
40 """
41 if __name__ =="__main__":
42 num_epochs = 5
43 batch_size = 50
44 lr = 0.001
45 model = MLP()
46 data_loader = MNISTLoader()
47 optimizer = tf.keras.optimizers.Adam(learning_rate = lr) #优化器就两点 :1.哪种优化算法,2.优化算法里超参的定义,如学习率等
48
49 num_batches = int(data_loader.num_train_data // batch_size * num_epochs) # //向下取整
50 for batch_index in range(num_batches):
51 X, y = data_loader.get_batch(batch_size)
52 with tf.GradientTape() as tape:
53 y_pred = model(X)
54 loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)
55 loss = tf.reduce_mean(loss) # 就是计算给定tensor的某个轴向上的平均值,此处是loss张量
56 print("batch %d:loss %f" % (batch_index, loss.numpy()))
57 grads = tape.gradient(loss, model.variables)
58 optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables)) # 这里是因为参数更新函数接受的是(1,w1),(2,w2),;;;参数对的形式
59
60 """
61 模型评估 tf.keras.metrics
62 """
63 sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy() #实例化一个评估器
64 num_batches = int(data_loader.num_test_data // batch_size)
65 for batch_index in range(num_batches): #测试集也分了batch
66 start_index, end_index = batch_index * batch_size, (batch_index + 1) * batch_size
67 y_pred = model.predict(data_loader.test_data[start_index: end_index])
68 sparse_categorical_accuracy.update_state(y_true=data_loader.test_label[start_index: end_index], y_pred=y_pred)
69 #update_state方法记录并处理结果
70 print("test accuracy: %f" % sparse_categorical_accuracy.result())