10、模型概览与一个实例

2020-12-15  本文已影响0人  是黄小胖呀

一、模型概览

#基本概念

#0Keras 有两个重要的概念: 模型(Model) 和 层(Layer) 

#1层将各种计算流程和变量进行了封装(例如基本的全连接层,CNN 的卷积层、池化层等)

#2模型则将各种层进行组织和连接,并封装成一个整体,描述了如何将输入数据通过各种层以及运算而得到输出。

#3Keras 在 tf.keras.layers 下内置了深度学习中大量常用的的预定义层,同时也允许我们自定义层。

#4Keras 模型以类的形式呈现,我们可以通过继承 tf.keras.Model 这个 Python 类来定义自己的模型。

#5在继承类中,我们需要重写 init() (构造函数,初始化)和 call(input) (模型调用)两个方法,同时也可以根据需要增加自>    定义的方法。

class MyModel(tf.keras.Model):

    def __init__(self):

        super().__init__()    # Python 2 下使用 super(MyModel, self).__init__()

        # 此处添加初始化代码(包含 call 方法中会用到的层),例如

        # layer1 = tf.keras.layers.BuiltInLayer(...)

        # layer2 = MyCustomLayer(...)

    def call(self, input):

        # 此处添加模型调用的代码(处理输入并返回输出),例如

        # x = layer1(input)

        # output = layer2(x)

        return output

    # 还可以添加自定义的方法

模型图示

例子:

import tensorflow as tf

X = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])

y = tf.constant([[10.0], [20.0]])

class Linear(tf.keras.Model):

    def __init__(self):

        super().__init__()

        self.dense = tf.keras.layers.Dense(

            units=1,

            activation=None,

            kernel_initializer=tf.zeros_initializer(),

            bias_initializer=tf.zeros_initializer()

        )

    def call(self, input):

        output = self.dense(input)

        return output

# 以下代码结构与前节类似

model = Linear()

optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)

for i in range(100):

    with tf.GradientTape() as tape:

        y_pred = model(X)      # 调用模型 y_pred = model(X) 而不是显式写出 y_pred = a * X + b

        loss = tf.reduce_mean(tf.square(y_pred - y))

    grads = tape.gradient(loss, model.variables)    # 使用 model.variables 这一属性直接获得模型中的所有变量

    optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))

print(model.variables)

1、我们没有显式地声明 a 和 b 两个变量并写出 y_pred = a X + b 这一线性变换,而是建立了一个继承了 tf.keras.Model 的模型类 Linear 。这个类在初始化部分实例化了一个 *全连接层 ( tf.keras.layers.Dense ),并在 call 方法中对这个层进行调用,实现了线性变换的计算。

2、Keras 的全连接层:线性变换 + 激活函数

全连接层 主要参数

3、为什么模型类是重载 call() 方法而不是 call() 方法?

在 Python 中,对类的实例 myClass 进行形如 myClass() 的调用等价于 myClass.call() (具体请见本章初 “前置知识” 的 call() 部分)。那么看起来,为了使用 ypred = model(X) 的形式调用模型类,应该重写 call() 方法才对呀?原因是 Keras 在模型调用的前后还需要有一些自己的内部操作,所以暴露出一个专门用于重载的 call() 方法。 tf.keras.Model 这一父类已经包含 call() 的定义。 _call() 中主要调用了 call() 方法,同时还需要在进行一些 keras 的内部操作。这里,我们通过继承 tf.keras.Model 并重载 call() 方法,即可在保持 keras 结构的同时加入模型调用的代码。

二、一个实例:使用多层感知机完成 MNIST 手写体数字图片数据集 [LeCun1998] 的分类任务。

模型的构建: tf.keras.Model 和 tf.keras.layers

多层感知机的模型类实现与上面的线性模型类似,使用 tf.keras.Model 和 tf.keras.layers 构建,所不同的地方在于层数增加了(顾名思义,“多层” 感知机),以及引入了非线性激活函数(这里使用了 ReLU 函数 , 即下方的 activation=tf.nn.relu )。该模型输入一个向量(比如这里是拉直的 1×784 手写体数字图片),输出 10 维的向量,分别代表这张图片属于 0 到 9 的概率。

代码主要分为几个部分:

1、引入/导入包

2、定义训练数据处理

3、定义模型

4、进行训练

5、评估结果

代码如下:它跑成功了呀~~~

10 import tensorflow as tf

 11import numpy as np

 12 

 13 class MNISTLoader():

 14    def __init__(self):

 15        mnist = tf.keras.datasets.mnist

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

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

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

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

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

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

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

 23 

 24    def get_batch(self, batch_size):

 25        # 从数据集中随机取出batch_size个元素并返回

 26        index = np.random.randint(0, np.shape(self.train_data)[0], batch_size)

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

 28 

 29 class MLP(tf.keras.Model):

 30    def __init__(self):

 31        super().__init__()

 32        self.flatten = tf.keras.layers.Flatten()    # Flatten层将除第一维(batch_size)以外的维度展平

 33        self.dense1 = tf.keras.layers.Dense(units=100, activation=tf.nn.relu)

 34        self.dense2 = tf.keras.layers.Dense(units=10)

 35 

 36    def call(self, inputs):        # [batch_size, 28, 28, 1]

 37        x = self.flatten(inputs)    # [batch_size, 784]

 38        x = self.dense1(x)          # [batch_size, 100]

 39        x = self.dense2(x)          # [batch_size, 10]

 40        output = tf.nn.softmax(x)

 41        return output

 42 

 43num_epochs = 5

 44batch_size = 50

 45learning_rate = 0.001

 46 

 47model = MLP()

 48data_loader = MNISTLoader()

 49optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)

 50 

 51num_batches = int(data_loader.num_train_data // batch_size * num_epochs)

 52 for batch_index in range(num_batches):

 53        X, y = data_loader.get_batch(batch_size)

 54        with tf.GradientTape() as tape:

 55            y_pred = model(X)

 56            loss = tf.keras.losses.sparse_categorical_crossentropy(y_true=y, y_pred=y_pred)

 57            loss = tf.reduce_mean(loss)

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

 59        grads = tape.gradient(loss, model.variables)

 60        optimizer.apply_gradients(grads_and_vars=zip(grads, model.variables))

 61 

 62sparse_categorical_accuracy = tf.keras.metrics.SparseCategoricalAccuracy()

 63num_batches = int(data_loader.num_test_data // batch_size)

 64 for batch_index in range(num_batches):

 65        start_index, end_index = batch_index * batch_size, (batch_index +1) * batch_size

 66        y_pred = model.predict(data_loader.test_data[start_index: end_index])

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

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

参考资料

1、简单粗暴 TensorFlow 2.0 模型(Model)与层(Layer)

https://www.bookstack.cn/read/TensorFlow2.0/spilt.1.c868281a01ad8ec0.md

2、简单粗暴 TensorFlow 2.0 基础示例:多层感知机(MLP) 

https://www.bookstack.cn/read/TensorFlow2.0/spilt.2.c868281a01ad8ec0.md

上一篇下一篇

猜你喜欢

热点阅读