欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

tensorflow2.0更普遍的构建模型

程序员文章站 2022-07-13 13:10:00
...

在tensorflow2.0里面,最典型和常用的神经网络结构是将一堆层按特定顺序叠加起来,那么,我们是不是只需要提供一个层的列表,就能由 Keras 将它们自动首尾相连,形成模型呢?Keras 的 Sequential API 正是如此。通过向 tf.keras.models.Sequential() 提供一个层的列表,就能快速地建立一个 tf.keras.Model 模型并返回,就如我之前写到的博客一样。
但这种的写法和其他流行的深度学习的框架(如PyTorch)不能很好的贯通,灵活性也不是很高,比较适合搭建一个相对简单或者是比较典型的神经网络(例如CNN,MLP)

下面就以一个mnist数据集来看看这种用类继承的方式怎么搭建一个神经网络。

#先把数据集引入
class MnistLoader():
	def __init__(self):
		mnist = tf.keras.datasets.mnist
        (self.train_data, self.train_label), (self.test_data, self.test_label) = mnist.load_data()
        '''
        对数据集归一化,并加一个通道来输入颜色,由于这里读入的是灰度图片,
        色彩通道数为 1(彩色 RGB 图像色彩通道数为 3),所以我们使用 
        np.expand_dims() 函数为图像数据手动在最后添加一维通道。
        '''
        self.train_data = np.expand_dims(self.train_data.astpye(np.float32)/255.0.axis = -1)
        self.test_data = np.expand_dims(self.test_data.astpye(np.float32)//255.0,axis = -1)
        self.train_label = self.train_label.astype(np.int32)    # [60000]
        self.test_label = self.test_label.astype(np.int32)      # [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):
        # 从数据集中随机取出batch_size个元素并返回
        index = np.random.randint(0, np.shape(self.train_data)[0], batch_size)
        return self.train_data[index, :], self.train_label[index]

下面就是通过类的继承来搭建一个数据集

class MLP(tf.keras.Model):
	def __init__(self):
		super().__init__()
		self.flatten = tf.keras.layers.Flatten() # Flatten层将除第一维(batch_size)以外的维度展平
		self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)
		#注意这里的**函数relu和之前的写法不一样
        self.dense2 = tf.keras.layers.Dense(units=10)
		
	def call(self,inputs):
		x1 = self.flatten(inputs)
		x2 = self.dense1(x1)
		x3 = self.dense2(x2)
		output = tf.nn.softmax(x3)
		return output

为了使得模型的输出能始终满足这两个条件,我们使用 Softmax 函数 (归一化指数函数, tf.nn.softmax )对模型的原始输出进行归一化。不仅如此,softmax 函数能够凸显原始向量中最大的值,并抑制远低于最大值的其他分量,这也是该函数被称作 softmax 函数的原因(即平滑化的 argmax 函数)。
输出的形式大致是[0.001,0.02,0.93,…,0.003]把十种分类的可能概率输出出来

接下里就是定义一些超参数和实例化的过程

batch_size = 50
epochs = 5
learning_rata = 0.001
data_load = MnistLoader()
model = MLP()
optimizer = tf.keras.optimizers.Adam(learning_rata = learning_rata)

接下里就是计算出损失函数,开始训练模型

 num_batches = int(data_loader.num_train_data // batch_size * num_epochs)
 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_predict = y_pred)
            loss = tf.reduce_mean(loss)
            print("batch %d: loss %f" % (batch_index, loss.numpy()))
            #算梯度
            grads = tape.gradient(loss, model.variables)
            #调参
            optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))

这一块的内容如果有看不懂的,可以看我之前的博客,tensorflow基础,里面有详细的解释。

最后就是对我们的模型进行评估

#我们用tf.keras.metrics
    sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()
    num_batches = int(data_loader.num_test_data // batch_size)
    for batch_index in range(num_batches):
        start_index, end_index = batch_index * batch_size, (batch_index + 1) * batch_size
        y_pred = model.predict(data_loader.test_data[start_index: end_index])
        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())

最后,我们使用测试集评估模型的性能。这里,我们使用 tf.keras.metrics 中的 SparseCategoricalAccuracy 评估器来评估模型在测试集上的性能,该评估器能够对模型预测的结果与真实结果进行比较,并输出预测正确的样本数占总样本数的比例。我们迭代测试数据集,每次通过 update_state() 方法向评估器输入两个参数: y_pred 和 y_true ,即模型预测出的结果和真实结果。评估器具有内部变量来保存当前评估指标相关的参数数值(例如当前已传入的累计样本数和当前预测正确的样本数)。迭代结束后,我们使用 result() 方法输出最终的评估指标值(预测正确的样本数占总样本数的比例)。

在以下代码中,我们实例化了一个 tf.keras.metrics.SparseCategoricalAccuracy 评估器,并使用 For 循环迭代分批次传入了测试集数据的预测结果与真实结果,并输出训练后的模型在测试数据集上的准确率。