【问题标题】:How to make Keras have two different initialisers in a dense layer?如何让 Keras 在密集层中有两个不同的初始化器?
【发布时间】:2018-05-07 07:51:10
【问题描述】:

我有两个单独设计的 CNN,用于相同数据的两个不同特征(图像和文本),输出有两个类

在最后一层:

对于图像(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(展平)(无,512)

flatten_2(展平)(无,192)

无论如何我可以连接这两个扁平层并有一个大小为 192+512 = 704 的长密集层,其中第一个 192 和第二个 512 有两个单独的 kernel_initializer,并产生一个 2 类输出?

类似这样的:

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],除了它应该没问题

【问题讨论】:

    标签: python tensorflow keras resnet convolutional-neural-network


    【解决方案1】:

    哦,天哪,我玩得开心吗?您必须创建自己的内核初始化程序:

    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>
    

    【讨论】:

    • 非常感谢,我从来不知道我们实际上可以创建自己的初始化程序,我会尝试一下并分享我的答案
    • 请注意顺序(concat、shape1、shape2..)!确保输入乘以匹配初始化程序初始化的权重。
    • 谢谢!!!!,....dtype=None, *, 是什么?我们不能做到def my_init(shape, shape1, shape2): 吗?另外,在您的情况下,shape1 到底是什么? (25,64) --> (input_len, output_len) 的元组?因为我在网上找不到任何关于keras.initializers.he_normal()之后的输入格式的例子,所以应该是(tuple shape, dtype)?
    • 我已经更新了我的解决方案,如果你能检查这对你是否有意义,非常感谢。谢谢
    猜你喜欢
    • 2018-06-16
    • 2019-11-14
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多