(三)深度学习计算 -- 1 模型构造

1. 模型构造

相比于先前代码示例中的 tf.keras.Sequential 类,tf.keras.Model 的模型构造方法更加灵活。


1.1 build model from block

tf.keras.Model 类是 tf.keras 模块里提供的一个模型构造类,可以继承它来定义需要的模型。

1.1.1 构造

构造多层感知机,代码示例如下:

import tensorflow as tf
class MLP(tf.keras.Model):
    def __init__(self):
        # Initialize self
        super().__init__()
        
        self.flatten = tf.keras.layers.Flatten()
        self.dense1 = tf.keras.layers.Dense(units=256, activation=tf.nn.relu)
        self.dense2 = tf.keras.layers.Dense(units=10)
    
    def call(self, inputs):
        x = self.flatten(inputs)
        x = self.dense1(x)
        output = self.dense2(x)
        return output

以上的MLP类中无须定义反向传播函数,系统将通过自动求梯度而自动生成反向传播所需的backward函数。


1.1.2 调用及输出

实例化MLP类得到模型变量net,代码示例如下:

# Outputs random values from a uniform distribution.
X = tf.random.uniform((2,20))
net = MLP()
net(X)

代码初始化net并传入输入数据X做一次前向计算。
其中,net(X)调用MLP类定义的call函数完成前向计算。

输出:

<tf.Tensor: id=62, shape=(2, 10), dtype=float32, numpy=
array([[ 0.2037605 ,  0.49271488,  0.23174636, -0.16000518,  0.29224387,
         0.28200507, -0.18656507, -0.13471593, -0.00501121, -0.2199152 ],
       [ 0.18346256,  0.2195911 ,  0.05488815, -0.07237642,  0.40799558,
         0.3671595 , -0.36161992, -0.05363751, -0.1569711 , -0.14399342]],
      dtype=float32)>


1.2 Sequential

事实上,Sequential类继承自tf.keras.Model类。当模型的前向计算为串联各层的简单计算时,可以通过这种更加简便的方式来定义模型。

Sequential类的目的:提供add函数来逐一添加串联的Block子类实例,而模型的前向计算就是将这些实例按添加的顺序逐一计算。


Sequential类来实现1.1小节的MLP类,并用随机初始化的模型做一次前向计算,代码示例如下:

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(units=256, activation=tf.nn.relu),
    tf.keras.layers.Dense(units=10)
])
model(X)

输出:

<tf.Tensor: id=200, shape=(2, 10), dtype=float32, numpy=
array([[-0.05212587, -0.02922452, -0.08287363,  0.14752318,  0.07725549,
        -0.2653394 , -0.15807061, -0.07166141, -0.1762014 , -0.1454198 ],
       [ 0.03376006,  0.08956617, -0.01811027, -0.04343057, -0.04205497,
        -0.26812813, -0.23462416,  0.008449  , -0.16048843, -0.22188428]],
      dtype=float32)>


1.3 build complex model

虽然Sequential类使模型构造更简单,但继承tf.keras.Model类可以极大拓展模型构造的灵活性。

1.3.1 FancyMLP

构造一个略复杂的网络FancyMLP,代码示例如下:

class FancyMLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.flatten = tf.keras.layers.Flatten()
        self.rand_weight = tf.constant(tf.random.normal((20,20)))
        self.dense = tf.keras.layers.Dense(units=20, activation=tf.nn.relu)
    
    def call(self, inputs):
        x = self.flatten(inputs)
        # hidden layer
        x = tf.nn.relu(tf.matmul(x, self.rand_weight) + 1)
        x = self.dense(x)
        
        # control l2 norm
        """
        Signature: tf.norm(tensor, ord='euclidean', axis=None, keepdims=None, name=None)
		Docstring: Computes the norm of vectors, matrices, and tensors.
        """
        while tf.norm(x) > 1:
            x /= 2
        if tf.norm(x) < 0.8:
            x *= 10
        return tf.reduce_sum(x)
    

在该网络中,通过constant函数创建训练中不被迭代的参数,即常数参数。

使用了常数权重rand_weight(并非模型参数)、做了矩阵乘法操作(tf.matmul),并重复使用了相同的Dense层。


该模型进行随机初始化和前向计算:

net = FancyMLP()
net(X)

输出:

<tf.Tensor: id=689, shape=(), dtype=float32, numpy=3.374749>

1.3.2 NestMLP

FancyMLPSequential类都是tf.keras.Model类的子类,嵌套调用示例如下:

class NestMLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.net = tf.keras.models.Sequential()
        self.net.add(tf.keras.layers.Flatten())
        self.net.add(tf.keras.layers.Dense(units=64, activation=tf.nn.relu))
        self.net.add(tf.keras.layers.Dense(units=32, activation=tf.nn.relu))
        self.dense = tf.keras.layers.Dense(units=16, activation=tf.nn.relu)
        
    def call(self, inputs):
        return self.dense(self.net(inputs))
    
net = tf.keras.models.Sequential()
net.add(NestMLP())
net.add(tf.keras.layers.Dense(20))
net.add(FancyMLP())
net(X)

输出:

<tf.Tensor: id=2267, shape=(), dtype=float32, numpy=18.456535>


参考

《动手学深度学习》(TF2.0版)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值