行业报告 AI展会 数据标注 标注供求
数据标注数据集
主页 > 机器学习 > 正文

TensorFlow 帮你实现更好的结构化图层和模型

今天主要向大家介绍的内容是:自定义层。
 
我们建议使用 tf.keras 作为构建的高级 API。也就是说,大多数 TensorFlow API 都可以通过 eager execution(即时执行)来使用。
import tensorflow as tf
 
tf.enable_eager_execution()
 
层:常用的操作集
大多数情况下,在编写模型代码时,您希望在比单个操作和操作单个变量更高的抽象级别上进行操作。
 
许多机器学习模型可以表达为相对简单的层的组合和堆叠,TensorFlow 提供了一组常见层作为一种简单的方法,您可以从头编写自己的特定于应用程序的层,或者将其作为现有层的组合。
 
TensorFlow 在 tf.keras 包中封装了完整的 Keras API,并在构建模型时 Keras 层和 Keras 包发挥着巨大的作用。
# In the tf.keras.layers package, layers are objects. To construct a layer,
# simply construct the object. Most layers take as a first argument the number
# of output dimensions / channels.
layer = tf.keras.layers.Dense(100)
# The number of input dimensions is often unnecessary, as it can be inferred
# the first time the layer is used, but it can be provided if you want to 
# specify it manually, which is useful in some complex models.
layer = tf.keras.layers.Dense(10, input_shape=(None, 5))
 
可以在文档中看到已存在层的完整列表。它包括 Dense(完全连接层),Conv2D,LSTM,BatchNormalization(批处理标准化),Dropout 等等。
# To use a layer, simply call it.
layer(tf.zeros([10, 5]))
# Layers have many useful methods. For example, you can inspect all variables
# in a layer by calling layer.variables. In this case a fully-connected layer
# will have variables for weights and biases.
layer.variables
[,
 ]
# The variables are also accessible through nice accessors
layer.kernel, layer.bias
(,
 )
 
实现自定义层
实现自定义层的较佳方法是扩展 tf.keras.Layer 类并实现:* __init__,您可以在其中执行所有与输入无关的初始化 * build,您可以在其中了解输入张量的形状,并可以执行其余的初始化 * call,以及在此进行正演计算。
 
请注意,您不必等到调用 build 来创建变量,您还可以在 __init__ 中创建变量。然而,在 build 中创建变量的优势在于它使后期的变量创建基于层将要操作的输入的形状。另一方面,在 __init__ 中创建变量意味着需要明确指定创建变量所需的形状。
class MyDenseLayer(tf.keras.layers.Layer):
  def __init__(self, num_outputs):
    super(MyDenseLayer, self).__init__()
    self.num_outputs = num_outputs
    
  def build(self, input_shape):
    self.kernel = self.add_variable("kernel", 
                                    shape=[int(input_shape[-1]), 
                                           self.num_outputs])
    
  def call(self, input):
    return tf.matmul(input, self.kernel)
  
layer = MyDenseLayer(10)
print(layer(tf.zeros([10, 5])))
print(layer.variables)
tf.Tensor(
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]], shape=(10, 10), dtype=float32)
[<tf.Variable 'my_dense_layer/kernel:0' shape=(5, 10) dtype=float32, numpy=
array([[ 0.2774077 , -0.0018627 ,  0.35655916,  0.5582008 ,  0.17234564,
        -0.15487313, -0.417266  , -0.50856596, -0.5074028 ,  0.01600116],
       [ 0.534511  , -0.4714492 , -0.23187858,  0.53936654,  0.53503364,
        -0.617422  , -0.6192259 ,  0.29145825,  0.0223884 , -0.5270795 ],
       [-0.2874091 ,  0.16588253,  0.0788359 , -0.1317451 ,  0.2750584 ,
        -0.5630307 , -0.07108849, -0.38031346, -0.30722007, -0.5128627 ],
       [-0.5630339 , -0.4541433 , -0.3941666 , -0.26502702,  0.10295987,
        -0.41846734, -0.18145484,  0.28857005,  0.0117566 ,  0.10138774],
       [ 0.5869536 , -0.35585892, -0.32530165,  0.52835554, -0.29882053,
        -0.26029676, -0.2692049 , -0.2949    ,  0.13486022, -0.40910304]],
      dtype=float32)>]
 
请注意,您不必等到调用 build 来创建变量,您还可以在 __init__ 中创建变量。
 
尽可能使用标准层,则整体代码更易于阅读和维护,其他读者也将熟悉标准层的行为。如果你想使用 tf.keras.layers 或 tf.contrib.layers 中不存在的图层,请考虑提交一份 github 问题,或者更好的是,你可以提交一个 pull 请求。
 
模型:组合层
机器学习模型中许多有趣的类层事物都是通过组合现有的层来实现的。例如,resnet 中的每个剩余块都是卷积、批处理规范化和快捷方式的组合。
 
在创建包含其他图层的类似图层时使用的主类是 tf.keras.Model。其实现是通过继承 tf.keras.Model 来实现的。
class ResnetIdentityBlock(tf.keras.Model):
  def __init__(self, kernel_size, filters):
    super(ResnetIdentityBlock, self).__init__(name='')
    filters1, filters2, filters3 = filters
 
    self.conv2a = tf.keras.layers.Conv2D(filters1, (1, 1))
    self.bn2a = tf.keras.layers.BatchNormalization()
 
    self.conv2b = tf.keras.layers.Conv2D(filters2, kernel_size, padding='same')
    self.bn2b = tf.keras.layers.BatchNormalization()
 
    self.conv2c = tf.keras.layers.Conv2D(filters3, (1, 1))
    self.bn2c = tf.keras.layers.BatchNormalization()
 
  def call(self, input_tensor, training=False):
    x = self.conv2a(input_tensor)
    x = self.bn2a(x, training=training)
    x = tf.nn.relu(x)
 
    x = self.conv2b(x)
    x = self.bn2b(x, training=training)
    x = tf.nn.relu(x)
 
    x = self.conv2c(x)
    x = self.bn2c(x, training=training)
 
    x += input_tensor
    return tf.nn.relu(x)
 
block = ResnetIdentityBlock(1, [1, 2, 3])
print(block(tf.zeros([1, 2, 3, 3])))
print([x.name for x in block.variables])
tf.Tensor(
[[[[0. 0. 0.]
   [0. 0. 0.]
   [0. 0. 0.]]
 
  [[0. 0. 0.]
   [0. 0. 0.]
   [0. 0. 0.]]]], shape=(1, 2, 3, 3), dtype=float32)
['resnet_identity_block/conv2d/kernel:0', 'resnet_identity_block/conv2d/bias:0', 'resnet_identity_block/batch_normalization/gamma:0', 'resnet_identity_block/batch_normalization/beta:0', 'resnet_identity_block/conv2d_1/kernel:0', 'resnet_identity_block/conv2d_1/bias:0', 'resnet_identity_block/batch_normalization_1/gamma:0', 'resnet_identity_block/batch_normalization_1/beta:0', 'resnet_identity_block/conv2d_2/kernel:0', 'resnet_identity_block/conv2d_2/bias:0', 'resnet_identity_block/batch_normalization_2/gamma:0', 'resnet_identity_block/batch_normalization_2/beta:0', 'resnet_identity_block/batch_normalization/moving_mean:0', 'resnet_identity_block/batch_normalization/moving_variance:0', 'resnet_identity_block/batch_normalization_1/moving_mean:0', 'resnet_identity_block/batch_normalization_1/moving_variance:0', 'resnet_identity_block/batch_normalization_2/moving_mean:0', 'resnet_identity_block/batch_normalization_2/moving_variance:0']
 
然而,很多时候,由许多层组成的模型只是简单地调用一个接一个的层。这可以使用 tf.keras.Sequential 在非常少的代码中完成。
my_seq = tf.keras.Sequential([tf.keras.layers.Conv2D(1, (1, 1)),
                               tf.keras.layers.BatchNormalization(),
                               tf.keras.layers.Conv2D(2, 1, 
                                                      padding='same'),
                               tf.keras.layers.BatchNormalization(),
                               tf.keras.layers.Conv2D(3, (1, 1)),
                               tf.keras.layers.BatchNormalization()])
my_seq(tf.zeros([1, 2, 3, 3]))
 
下一步
现在,您可以回到之前的笔记并调整线性回归示例,以使用更好的结构化图层和模型。
 
声明:文章收集于网络,如有侵权,请联系小编及时处理,谢谢!
 
 

微信公众号

声明:本站部分作品是由网友自主投稿和发布、编辑整理上传,对此类作品本站仅提供交流平台,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,不为其版权负责。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。

网友评论:

发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
SEM推广服务

Copyright©2005-2026 Sykv.com 可思数据 版权所有    京ICP备14056871号

关于我们   免责声明   广告合作   版权声明   联系我们   原创投稿   网站地图  

可思数据 数据标注行业联盟

扫码入群
扫码关注

微信公众号

返回顶部