3. 自定义层
本节将介绍如何自定义一个层,从而可以被重复调用。
import tensorflow as tf
import numpy as np
3.1 custom layer without parameters
3.1.1 自定义层
定义一个不含模型参数的自定义层:
class CenteredLayer(tf.keras.layers.Layer):
def __init__(self):
super().__init__()
def call(self,inputs):
return inputs - tf.reduce_mean(inputs)
其中,CenteredLayer
类通过继承tf.keras.layers.Layer
类,自定义了一个将输入减掉均值后输出的层,并将层的计算定义在了call
函数里。
该层的实例化及前向计算:
layer = CenteredLayer()
layer(np.array([1,2,3,4,5]))
输出:
<tf.Tensor: id=16, shape=(5,), dtype=int64, numpy=array([-2, -1, 0, 1, 2])>
3.1.2 模型构造
利用该层构造模型:
net = tf.keras.Sequential()
net.add(tf.keras.layers.Flatten())
net.add(tf.keras.layers.Dense(20))
net.add(CenteredLayer())
Y = net(X)
Y
输出:
<tf.Tensor: id=47, shape=(2, 20), dtype=float32, numpy=
array([[ 0.34438056, 0.06978315, -0.41926566, 0.2242881 , 0.29170805,
0.11057639, 0.23599279, -0.23065972, 0.63485736, 0.21090072,
-0.330887 , -0.3979441 , 0.1462583 , -0.12568481, 0.5106406 ,
0.77171034, 0.17244986, -0.67148066, 0.807409 , -0.07428499],
[ 0.3037144 , -0.58068335, -0.3071456 , -0.2411271 , -0.00998123,
-0.21790652, -0.10612971, -0.7001431 , 0.40697873, -0.58122313,
-0.97674805, -0.13996252, 0.07470441, -0.5286119 , 0.4424529 ,
0.20922649, 0.3125742 , 0.2707773 , 1.024564 , -0.9360792 ]],
dtype=float32)>
自定义层输出的均值:
tf.reduce_mean(Y)
输出:
<tf.Tensor: id=49, shape=(), dtype=float32, numpy=-1.7881394e-08>
3.2 custom layer with parameters
此外,支持自定义含模型参数的自定义层。
3.2.1 自定义层
模型参数可通过训练学得:
class myDense(tf.keras.layers.Layer):
def __init__(self, units):
super().__init__()
self.units = units
def build(self, input_shape):
"""
input_shape: 第一次运行call()时,参数inputs的形状。
tf.keras.layers.Layer.add_weight: Adds a new variable to the layer.
"""
self.w = self.add_weight(name='w',
shape=(input_shape[-1], self.units),
initializer=tf.random_normal_initializer())
self.b = self.add_weight(name='b',
shape=(self.units),
initializer=tf.zeros_initializer())
def call(self, inputs):
y_pred = tf.matmul(inputs, self.w) + self.b
return y_pred
实例化及前向计算:
dense = myDense(3)
Y = dense(X)
Y
输出:
<tf.Tensor: id=32, shape=(2, 3), dtype=float32, numpy=
array([[-0.05748406, 0.128207 , -0.02014272],
[-0.07343882, 0.11930768, -0.09989622]], dtype=float32)>
访问模型参数:
dense.get_weights()
输出:
[array([[ 0.03788483, 0.05446365, -0.00342109],
[ 0.01979028, 0.07090656, -0.00471796],
[-0.00542502, 0.07547017, -0.07470261],
[ 0.00170084, -0.00170659, -0.07881869],
[ 0.02729396, 0.07794935, -0.01462456],
[-0.01458358, -0.01152581, 0.0183306 ],
[-0.05630199, 0.0834111 , 0.05665946],
[-0.03011301, -0.01305497, 0.01113685],
[ 0.07111349, 0.04045207, -0.00295244],
[ 0.06290419, -0.02640768, -0.04089865],
[ 0.02854273, 0.04196091, -0.01317766],
[-0.01049933, -0.04766244, -0.04543113],
[-0.05666549, 0.06246523, -0.06552341],
[ 0.02021227, 0.0038689 , 0.11742865],
[ 0.06721621, 0.00784351, -0.00665099],
[-0.04588777, -0.02955816, -0.01156068],
[-0.0953302 , -0.04818133, 0.01506012],
[-0.02355155, -0.03037887, -0.09637806],
[-0.04718609, 0.02179381, 0.02490507],
[ 0.02174933, -0.01841915, -0.00988414]], dtype=float32),
array([0., 0., 0.], dtype=float32)]
查看模型参数shape:
dense.get_weights()[0].shape
输出:
(20, 3)
3.2.2 模型构造
模型构造及实例化:
net = tf.keras.models.Sequential()
net.add(myDense(8))
net.add(myDense(1))
Y = net(X)
Y
输出:
<tf.Tensor: id=57, shape=(2, 1), dtype=float32, numpy=
array([[0.01952953],
[0.01150553]], dtype=float32)>