自定义层和自定义模型
创建一个自定义的全连接层(Dense)
1 | class Linear(keras.layers.Layer): |
x = tf.ones((2,2))
1
2
3 <tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[1., 1.],
[1., 1.]], dtype=float32)>
my_linear = Linear(4,2)
y = my_linear(x)
1
2
3
4 <tf.Tensor: shape=(2, 4), dtype=float32, numpy=
array([[ 0.00905943, 0.10692596, -0.07619047, 0.04650879],
[ 0.00905943, 0.10692596, -0.07619047, 0.04650879]],
dtype=float32)>
my_linear.weights
1
2
3
4
5 [<tf.Variable 'Variable:0' shape=(2, 4) dtype=float32, numpy=
array([[ 0.0006441 , 0.11491605, -0.07707106, -0.01418747],
[ 0.00841848, -0.00800045, 0.00089693, 0.06069225]],
dtype=float32)>,
<tf.Variable 'Variable:0' shape=(4,) dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>]
使用更快捷的方法为层添加权重:add_weight()方法
1 | class Linear(keras.layers.Layer): |
an_later = Linear()
an_later.weights
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 [<tf.Variable 'Variable:0' shape=(32, 32) dtype=float32, numpy=
array([[-0.02809566, 0.00103881, 0.05861744, ..., 0.06338453,
0.0538682 , -0.03630157],
[-0.00649852, -0.05861601, -0.01545036, ..., 0.0073656 ,
-0.03227425, -0.08600676],
[ 0.08083364, 0.03803931, 0.07166076, ..., -0.03101794,
0.01622724, -0.07307748],
...,
[ 0.08931817, 0.00320732, 0.03871277, ..., -0.019708 ,
-0.00081164, 0.00713481],
[-0.03456153, -0.075034 , 0.04615847, ..., -0.0993882 ,
-0.04810502, 0.06305873],
[ 0.09911603, -0.01343805, -0.02753673, ..., 0.01256844,
-0.030287 , -0.01860095]], dtype=float32)>,
<tf.Variable 'Variable:0' shape=(32,) dtype=float32, numpy=
array([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.],
dtype=float32)>]
与内置层一样在初始化时不初始化权重:build(self,inputs_shape)方法中创建层的权重
==注意trainable参数==
==将权重创建推迟到得知输入的形状之后==
==在层的build(self,inputs_shape)方法中创建层的权重==
my_linear(inputs) __call__ 层的 __call__() 方法将在首次调用时自动运行构建训练参数
1 | class Linear(keras.layers.Layer): |
my_linear = Linear(4)
my_linear.weights
1 []
x = tf.ones((2,2))
my_linear(x)
1
2
3
4 <tf.Tensor: shape=(2, 4), dtype=float32, numpy=
array([[ 0.09677124, -0.05200195, 0.01205444, -0.06474304],
[ 0.09677124, -0.05200195, 0.01205444, -0.06474304]],
dtype=float32)>
my_linear.weights
1
2
3
4
5 [<tf.Variable 'linear_4/Variable:0' shape=(2, 4) dtype=float32, numpy=
array([[ 0.06728531, -0.01315262, -0.00903699, 0.0252159 ],
[ 0.02951044, -0.03885547, 0.02108227, -0.08997723]],
dtype=float32)>,
<tf.Variable 'linear_4/Variable:0' shape=(4,) dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>]
层可递归组合
==将一个层实例分配为另一个层的特性,则外部层将开始跟踪内部层的权重。==
==建议在 init() 方法中创建此类子层(由于子层通常具有构建方法,它们将与外部层同时构建)。==
1 | class Linear(keras.layers.Layer): |
1 | class MLPBlock(keras.layers.Layer): |
1 | class MLPBlock_2(keras.layers.Layer): |
tf.concat(concat_dim, values, name=’concat’)
除去name参数用以指定该操作的name,与方法有关的一共两个参数:
第一个参数concat_dim:必须是一个数,表明在哪一维上连接
t1 = [[1, 2, 3], [4, 5, 6]]
t2 = [[7, 8, 9], [10, 11, 12]]
tf.concat(0, [t1, t2]) == > [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
tf.concat(1, [t1, t2]) ==> [[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]]
自定义模型
==通常使用 Layer 类来定义内部计算块,并使用 Model 类来定义外部模型,即将训练的对象。==
Model 类具有与 Layer 相同的 API,但有如下区别: 它会公开内置训练、评估和预测循环(model.fit()、model.evaluate()、model.predict())。 它会通过 model.layers 属性公开其内部层的列表。 它会公开保存和序列化 API(save()、save_weights()…)
1 | class MLPB_model(keras.Model): |
因此,如果您想知道“我应该用 Layer 类还是 Model 类?”,
请问自己:我是否需要在它上面调用 fit()?
我是否需要在它上面调用 save()?
如果是,则使用 Model。如果不是(要么因为您的类只是更大系统中的一个块,要么因为您正在自己编写训练和保存代码),则使用 Layer。





