在多个TensorFlow Keras层上使用相同的初始化程序,正则化程序和约束是否安全?

时间:2019-11-15 03:02:15

标签: tensorflow keras

我担心使用相同的初始化程序,正则化程序和约束在(张量流)keras层中创建的变量可能会连接在层之间。如果它们可以是字符串(例如'he_normal'),那没有问题,但是对于那些带有参数的人,我必须传递实际的函数。例如,在自定义图层的__init__中,

initializer_1 = tf.keras.initializers.he_normal()
regularizer_1 = tf.keras.regularizers.l2(l=0.001)
constraint_1  = tf.keras.constraints.MaxNorm(max_value=2, axis=[0,1,2])

layer_A = tf.keras.layers.Conv2D(
  ...
  kernel_initializer=initializer_1,
  kernel_regularizer=regularizer_1,
  kernel_constraint=constraint_1,
  ...
  )

layer_B = tf.keras.layers.Conv2D(
  ...
  kernel_initializer=initializer_1,
  kernel_regularizer=regularizer_1,
  kernel_constraint=constraint_1,
  ...
  )

这样安全吗?

2 个答案:

答案 0 :(得分:2)

可能,但是不确定这是否是最好的主意;我运行了-结果:

  • 两个对象的.fit()损失相同:(1)相同的对象; (2)个不同的{initializer_2等对象-每个对象都可以独立工作
  • 具有相同initializer_1的层权重初始化是不同的(应该是)
  • 模型成功保存和加载。

但是,每个层的对象都是相同-您可以从它们的内存占用量中看出来:

print(layer_A.kernel_regularizer)
print(layer_B.kernel_regularizer)
<tensorflow.python.keras.regularizers.L1L2 object at 0x7f211bfd0c88>
<tensorflow.python.keras.regularizers.L1L2 object at 0x7f211bfd0c88>

然后可能会抛出某种形式的模型序列化,特别是那些与模型图有关的序列化-但我什么都没发现。最佳做法是为每个图层使用一个唯一的图层对象,但是您的方法似乎也无害。

因此:您可以“做到这一点直到崩溃”。 (但是您可能不知道何时中断,例如何时导致模型输出不同-除非您测试可重复性)。


完整测试示例

import tensorflow as tf
import numpy as np
import random
from tensorflow.keras.models import Model, load_model
from tensorflow.keras.layers import Input

np.random.seed(1)
random.seed(2)
if tf.__version__ == '2':
    tf.random.set_seed(3)
else:
    tf.set_random_seed(3)

initializer_1 = tf.keras.initializers.he_normal()
regularizer_1 = tf.keras.regularizers.l2(l=0.001)
constraint_1  = tf.keras.constraints.MaxNorm(max_value=2, axis=[0,1,2])

layer_A = tf.keras.layers.Conv2D(4, (1,1),
  kernel_initializer=initializer_1,
  kernel_regularizer=regularizer_1,
  kernel_constraint=constraint_1)

layer_B = tf.keras.layers.Conv2D(4, (1,1),
  kernel_initializer=initializer_1,
  kernel_regularizer=regularizer_1,
  kernel_constraint=constraint_1)

ipt = Input((16,16,4))
x   = layer_A(ipt)
out = layer_B(x)

model = Model(ipt, out)
model.compile('adam', 'mse')
print(model.layers[1].get_weights()[0])
print(model.layers[2].get_weights()[0])

x = np.random.randn(32, 16, 16, 4)
model.fit(x, x)

model.save('model.h5')
model = load_model('model.h5')

答案 1 :(得分:0)

简短的回答,是的,这很安全。 长答案将是为什么我们为什么需要一个初始化程序的问题的答案。 假设我们将Ax + b应用于第一个隐藏层中的所有神经元。如果我们不初始化weights(A matrix),b将是输出的结果值,并且如果我们计算导数(b是一个常数),它将为零(0)并将其反向传播到该层,因此,我们的网络不会根据实际情况调整权重。

现在我们知道了初始化权重的原因,下面我们来选择最佳的初始化器。尽管有一些研究触及了这个问题,但据我所知,答案是没有最佳的初始化方法,因为反向传播函数还取决于您拥有的数据集;简而言之,一个初始化程序可能在某些数据集上可以很好地工作(我怀疑与其他初始化程序的区别是否有意义),但在其他数据集上却变得糟糕。

在我看来,很多人选择random_normal是因为如果不是所有层,因为您更有可能找到任何过程的正确值(猜测您将选择卡片组的卡片),而不是猜测皇后永远的心。