如何让 Keras 在密集层中有两个不同的初始化程序?
How to make Keras have two different initialisers in a dense layer?
我针对同一数据的两个不同特征(图像和文本)分别设计了两个 CNN,输出有两个 classes
最后一层:
对于图像(resnet),我想使用 "he_normal" 作为初始化程序
flatten1 = Flatten()(image_maxpool)
dense = Dense(output_dim=2, kernel_initializer="he_normal")(flatten1)
但对于文本 CNN,我想使用默认值 "glorot_normal"
flatten2 = Flatten()(text_maxpool)
output = Dense(output_dim=2, kernel_initializer="glorot_normal")(flatten2)
flatten1 和 flatten2 的尺寸:
flatten_1 (展平) (None, 512)
flatten_2(展平)(None, 192)
无论如何我可以连接这两个扁平层并有一个长的密集层,大小为 192+512 = 704,其中第一个 192 和第二个 512 有两个单独的 kernel_initializer,并产生 2 -class 输出?
像这样:
merged_tensor = merge([flatten1, flatten2], mode='concat', concat_axis=1)
output = Dense(output_dim=2,
kernel_initializer for [:512]='he_normal',
kernel_initializer for [512:]='glorot_normal')(merged_tensor)
编辑:我想我已经通过以下代码完成了这项工作(感谢@Aechlys):
def my_init(shape, shape1, shape2):
x = initializers.he_normal()(shape1)
y = initializers.glorot_normal()(shape2)
return tf.concat([x,y], 0)
class_num = 2
flatten1 = Flatten()(image_maxpool)
flatten2 = Flatten()(text_maxpool)
merged_tensor = concatenate([flatten1, flatten2],axis=-1)
output = Dense(output_dim=class_num, kernel_initializer=lambda shape: my_init(shape,\
shape1=(512,class_num),\
shape2=(192,class_num)),\
activation='softmax')(merged_tensor)
我必须手动添加形状大小 512 和 192,因为我无法通过代码获取 flatten1 和 flatten1 的大小
flatten1.get_shape().as_list()
,这给了我 [none,none],虽然它应该是 [None,512],除此之外它应该没问题
天哪,我玩这个玩得开心吗?您必须创建自己的内核初始化器:
def my_init(shape, dtype=None, *, shape1, shape2):
x = keras.initializers.he_normal()(shape1, dtype=dtype)
y = keras.initializers.glorot_normal()(shape2, dtype=dtype)
return tf.concat([x,y], 0)
然后您将通过 Dense
函数中的 lambda 函数调用它:
不幸的是,如您所见,我还无法以编程方式推断出形状。当我这样做时,我可能会更新这个答案。但是,如果你事先知道形状,你可以将它们作为常量传递:
DENSE_UNITS = 64
input_t = Input((1,25))
input_i = Input((1,35))
input_a = Concatenate(axis=-1)([input_t, input_i])
dense = Dense(DENSE_UNITS, kernel_initializer=lambda shape: my_init(shape,
shape1=(int(input_t.shape[-1]), DENSE_UNITS),
shape2=(int(input_i.shape[-1]), DENSE_UNITS)))(input_a)
tf.keras.Model(inputs=[input_t, input_i], outputs=dense)
Out: <tensorflow.python.keras._impl.keras.engine.training.Model at 0x19ff7baac88>
我针对同一数据的两个不同特征(图像和文本)分别设计了两个 CNN,输出有两个 classes
最后一层:
对于图像(resnet),我想使用 "he_normal" 作为初始化程序
flatten1 = Flatten()(image_maxpool)
dense = Dense(output_dim=2, kernel_initializer="he_normal")(flatten1)
但对于文本 CNN,我想使用默认值 "glorot_normal"
flatten2 = Flatten()(text_maxpool)
output = Dense(output_dim=2, kernel_initializer="glorot_normal")(flatten2)
flatten1 和 flatten2 的尺寸:
flatten_1 (展平) (None, 512)
flatten_2(展平)(None, 192)
无论如何我可以连接这两个扁平层并有一个长的密集层,大小为 192+512 = 704,其中第一个 192 和第二个 512 有两个单独的 kernel_initializer,并产生 2 -class 输出?
像这样:
merged_tensor = merge([flatten1, flatten2], mode='concat', concat_axis=1)
output = Dense(output_dim=2,
kernel_initializer for [:512]='he_normal',
kernel_initializer for [512:]='glorot_normal')(merged_tensor)
编辑:我想我已经通过以下代码完成了这项工作(感谢@Aechlys):
def my_init(shape, shape1, shape2):
x = initializers.he_normal()(shape1)
y = initializers.glorot_normal()(shape2)
return tf.concat([x,y], 0)
class_num = 2
flatten1 = Flatten()(image_maxpool)
flatten2 = Flatten()(text_maxpool)
merged_tensor = concatenate([flatten1, flatten2],axis=-1)
output = Dense(output_dim=class_num, kernel_initializer=lambda shape: my_init(shape,\
shape1=(512,class_num),\
shape2=(192,class_num)),\
activation='softmax')(merged_tensor)
我必须手动添加形状大小 512 和 192,因为我无法通过代码获取 flatten1 和 flatten1 的大小
flatten1.get_shape().as_list()
,这给了我 [none,none],虽然它应该是 [None,512],除此之外它应该没问题
天哪,我玩这个玩得开心吗?您必须创建自己的内核初始化器:
def my_init(shape, dtype=None, *, shape1, shape2):
x = keras.initializers.he_normal()(shape1, dtype=dtype)
y = keras.initializers.glorot_normal()(shape2, dtype=dtype)
return tf.concat([x,y], 0)
然后您将通过 Dense
函数中的 lambda 函数调用它:
不幸的是,如您所见,我还无法以编程方式推断出形状。当我这样做时,我可能会更新这个答案。但是,如果你事先知道形状,你可以将它们作为常量传递:
DENSE_UNITS = 64
input_t = Input((1,25))
input_i = Input((1,35))
input_a = Concatenate(axis=-1)([input_t, input_i])
dense = Dense(DENSE_UNITS, kernel_initializer=lambda shape: my_init(shape,
shape1=(int(input_t.shape[-1]), DENSE_UNITS),
shape2=(int(input_i.shape[-1]), DENSE_UNITS)))(input_a)
tf.keras.Model(inputs=[input_t, input_i], outputs=dense)
Out: <tensorflow.python.keras._impl.keras.engine.training.Model at 0x19ff7baac88>