继承tf.layers.Layer创建新的TensorFlow层

以下代码在TensorFlow版本1.13下运行通过。

tf.layers.Layer类是tf.layers里所有层都继承的基类,实现了通用的基础功能。用户只需要实例化它,就可以直接调用得到的实例。

Layer的子类一般这样子实现:

__init__():先初始化父类。然后在成员变量中保存配置。

build():一般用于初始化层内的参数和变量。在调用call()方法前,类会自动调用该方法。在该方法末尾需要设置self.built = True,保证build()方法只被调用一次。

call():用于定义层对输入张量的实际操作。

下面是我们自定义一个全连接层的例子。

# Python3
import tensorflow as tf
from tensorflow.python.framework import tensor_shape


class DenseLayer(tf.layers.Layer):
  """定义全连接层"""
  def __init__(self, hidden_size, bias=None, activation=None):
    super().__init__()  # 初始化父类
    self.hidden_size = hidden_size  # 保存配置
    self.bias = bias
    self.activation = activation

  def build(self, input_shape):
    self.W = self.add_variable(
      "weight", [input_shape[-1], self.hidden_size],
      dtype=self.dtype, initializer=tf.glorot_normal_initializer()) # 添加全连接层核
    if self.bias:  # bias是可选的
      self.bias = self.add_variable(
        "bias", [self.hidden_size], dtype=self.dtype, 
        initializer=tf.glorot_normal_initializer())
    self.built = True  # 说明bulid方法已经被调用

  def call(self, inputs):
    tmp = tf.matmul(inputs, self.W)  
    if self.bias:   # 判断是否要使用bias
      tmp += self.bias
    if self.activation:   # 判断是否使用激活函数
      tmp = self.activation(tmp)
    return tmp

我们调用这个类进行实验,如下所示:

if __name__ == "__main__":
  x = tf.reshape(tf.range(27, dtype=tf.float32), (9, 3))
  dense1 = DenseLayer(5, True, tf.nn.relu)
  dense2 = DenseLayer(4, True)
  y1 = dense1(x)
  y2 = dense2(x)

  sess = tf.Session()
  sess.run(tf.global_variables_initializer())
  y1_value, y2_value = sess.run([y1, y2])
  pprint(y1_value)
  pprint(y2_value)

然后我们得到这样的输出

array([[0.0000000e+00, 6.0458672e-01, 1.5364885e-01, 0.0000000e+00,
        1.1281629e+00],
       [2.8744671e-02, 0.0000000e+00, 1.7403680e+00, 0.0000000e+00,
        5.2644248e+00],
       [2.0210516e-01, 0.0000000e+00, 3.3270869e+00, 0.0000000e+00,
        9.4006872e+00],
       [3.7546554e-01, 0.0000000e+00, 4.9138060e+00, 0.0000000e+00,
        1.3536949e+01],
       [5.4882616e-01, 0.0000000e+00, 6.5005255e+00, 0.0000000e+00,
        1.7673212e+01],
       [7.2218633e-01, 0.0000000e+00, 8.0872440e+00, 7.0604742e-02,
        2.1809473e+01],
       [8.9554715e-01, 0.0000000e+00, 9.6739635e+00, 1.4449155e-01,
        2.5945736e+01],
       [1.0689070e+00, 0.0000000e+00, 1.1260683e+01, 2.1837932e-01,
        3.0081997e+01],
       [1.2422680e+00, 0.0000000e+00, 1.2847402e+01, 2.9226708e-01,
        3.4218258e+01]], dtype=float32)
array([[-3.14725101e-01, -3.68262529e-02, -1.37817276e+00,
        -1.94278789e+00],
       [ 1.73463374e-02, -2.78897429e+00, -3.81491590e+00,
        -4.29053593e+00],
       [ 3.49417806e-01, -5.54112244e+00, -6.25165939e+00,
        -6.63828325e+00],
       [ 6.81489170e-01, -8.29327106e+00, -8.68840218e+00,
        -8.98603058e+00],
       [ 1.01356053e+00, -1.10454178e+01, -1.11251459e+01,
        -1.13337784e+01],
       [ 1.34563196e+00, -1.37975664e+01, -1.35618887e+01,
        -1.36815262e+01],
       [ 1.67770326e+00, -1.65497150e+01, -1.59986315e+01,
        -1.60292740e+01],
       [ 2.00977468e+00, -1.93018627e+01, -1.84353752e+01,
        -1.83770218e+01],
       [ 2.34184670e+00, -2.20540104e+01, -2.08721199e+01,
        -2.07247677e+01]], dtype=float32)

对于TensorFlow我们只需要定义前向传播的计算图,它就会自动配置完成反向传播。我们上面定义的DenseLayer里的权重会被自动更新。

你可能感兴趣的:(人工智能,深度学习基础理论与技术实践,笔记)