自定义权重初始化 tensorflow tf.layers.dense

Posted

技术标签:

【中文标题】自定义权重初始化 tensorflow tf.layers.dense【英文标题】:Custom weight initialization tensorflow tf.layers.dense 【发布时间】:2018-09-05 04:37:32 【问题描述】:

我正在尝试将自定义初始化程序设置为 tf.layers.dense,在此我使用已有的权重矩阵初始化 kernel_initializer

u_1 = tf.placeholder(tf.float32, [784, 784])
first_layer_u = tf.layers.dense(X_, n_params, activation=None, 
                              kernel_initializer=u_1,
                              bias_initializer=tf.keras.initializers.he_normal())

这是抛出错误说ValueError: If initializer is a constant, do not specify shape.

将占位符分配给kernel_initializer 是否有问题,还是我遗漏了什么?

【问题讨论】:

kernel_initializer 是“权重矩阵的初始化函数函数”,所以在里面放一个占位符是没有意义的 @JonathanR 我可以传递一个numpy 数组吗? 【参考方案1】:

至少有两种方法可以做到这一点:

1 创建您自己的图层

  W1 = tf.Variable(YOUR_WEIGHT_MATRIX, name='Weights')
  b1 = tf.Variable(tf.zeros([YOUR_LAYER_SIZE]), name='Biases') #or pass your own
  h1 = tf.add(tf.matmul(X, W1), b1)

2 使用tf.constant_initializer

init = tf.constant_initializer(YOUR_WEIGHT_MATRIX)
l1 = tf.layers.dense(X, o, kernel_initializer=init)

【讨论】:

我明白了,我想用tf.layers.dense来实现这个功能 我更新了答案,向您展示如何使用密集层实现它 你好。我在密集层上使用 tf.constant_initializer(YOUR_WEIGHT_MATRIX, dtype=tf.float32) 来初始化我的权重,但是,对于 300 万个权重,初始化需要 5 秒。使用您的方法大约需要 4.2 秒。有更快的方法吗?我只需要评估一次训练集并保存错误,而这需要将近 50% 的时间,只是为了构建网络、测试并删除它。 如果你使用方法 2 (constant_initializer) 是否更新了 YOUR_WEIGHT_MATRIX 的权重?【参考方案2】:

我认为您可以定义自己的初始化函数。该函数需要接受 3 个参数:shapedtypepartition_info。它应该返回一个tf.Tensor,它将用于初始化权重。既然你有一个numpy 数组,我认为你可以使用tf.constant 来创建这个张量。例如:

def custom_initializer(shape_list, dtype, partition_info):
    # Use np.ones((7, 3)) as an example
    return tf.constant(np.ones((7, 3)))

然后您可以将其传递给kernel_initializer。如果尺寸都匹配,它应该可以工作。我在gist 上放了一个例子,使用Estimator 构建模型并使用LoggingTensorHook 记录dense/kernel 在每个步骤中。您应该能够看到权重已正确启动。

编辑:

我刚刚发现使用tf.constant_initializer 会更好。它用于tensorflow guide。你可以kernel_initializer=tf.constant_initializer(np.ones((7, 3)))

【讨论】:

不会让内核成为tf.constant 使其无法学习——总是等于它的初始值吗?我怀疑这是 OP 的意图...... @mikkola 我刚刚发现 TensorFlow 中有一个 tf.constant_initializer 可用(更新了我的答案)。如果我理解正确,它用于初始化内核但不会“锁定”它。我只有间接证据:1)我的要点示例表明内核确实每一步都发生了变化。 2)tf.constant_initializer 在guide 中使用,我认为该示例不打算使bias 保持不变。 是的,使用tf.constant_initializer 是正确的方法。 @mikkola 需要明确的是,tf.constant_initializer 绝对是更好的方法。但是根据source,tf.constant_initializer 返回一个可调用的Constant 类,它实际上返回tf.constant。如果人们想做的事情超出了tf.constant_initializer 的能力,custom_initializer 是有效的。 我正在使用它,但是,它需要将近 5 秒来初始化一个 300 万个权重网络。有更快的方法吗?顺便说一句:接受的答案需要 4 秒,仍然太多:它消耗了我算法 50% 的时间。【参考方案3】:

乔纳森的回答在 conv 上也对我有用 -

kernel_in = np.random.uniform(100,1000,(filter_width, filter_height, input_channels, output_channels)).astype(np.float32)
init = tf.constant_initializer(kernel_in)
def model(x):
    x = tf.layers.conv2d(x, filters=3, kernel_size=1, strides=1, kernel_initializer=init)

【讨论】:

以上是关于自定义权重初始化 tensorflow tf.layers.dense的主要内容,如果未能解决你的问题,请参考以下文章

Keras 中具有样本权重的自定义损失函数

TensorFlow中权重的随机初始化

自定义权重初始化导致错误 - pytorch

Keras中带有权重的自定义损失函数

如何为 biLSTM 层 Keras 设置自定义初始权重?

model.compile() 是不是初始化 Keras(tensorflow 后端)中的所有权重和偏差?