【问题标题】:How to make one/some of the filters in the Conv layer in tensorflow?如何在 tensorflow 的 Conv 层中制作一个/一些过滤器?
【发布时间】:2020-10-21 10:41:08
【问题描述】:

我的意思是: 假设 Conv 内核有 64 个通道输出,我只想训练 64 个通道中的通道 1。

问题来自阅读本文https://arxiv.org/abs/1911.09659

在本文中,它建议我们可以冻结一些过滤器并在迁移学习中训练其余的过滤器。

但是,我想知道如何在 Tensorflow 中实现它。

如果我们能够冻结一些层,那是很明显的,只需迭代网络中的层并将它们的可训练布尔值设为 False。

但是,当涉及到内核时,我比我想象的要麻烦。

我找到了Get the value of some weights in a model trained by TensorFlow这个anwser。

我试着得到所有的重量,然后把它们像这样:

def get_weights_bias(model, layer_name):
"""
This function aims to extract kernel and its bias from the original weight
:param model: the model we want to extract weight from
:param layer_name: the name of the layer we want to extract the weight from
:return: kernel_list and bias_list of particular layer
"""
for layer in model.layers:
    if layer_name == layer.name:
        weights = layer.get_weights()
        print(type(weights))
        print(weights[0].shape, type(weights[0])) # weights
        print(weights[1].shape, type(weights[1])) # biases
        kernel_list = []
        bias_list = weights[1]
        print(type(bias_list))
        for j in range(weights[0].shape[-1]):
            name_weight = layer_name + "_weight_" + str(j)
            kernel = tf.Variable(initial_value=weights[0][:, :, :, j], name=name_weight, trainable=True)
            kernel = tf.expand_dims(kernel, -1)
            kernel_list.append(kernel)
return kernel_list, bias_list

根据这个答案的建议,我遇到了一些问题。我发现很难将它们恢复到 conv 层,因为 layer.set_weights() 只接受 numpy 数组而不是 tf.Variable。

有什么建议吗??

【问题讨论】:

    标签: python tensorflow keras deep-learning


    【解决方案1】:

    据我所知,没有一种干净的方法可以仅冻结内核并使用 keras API 保持偏差可训练。尽管如此,您可以通过以下方式使用私有属性:

    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Conv2D, Dense
    
    # initialize the model
    m = Sequential([Conv2D(1,(3,3), input_shape=(3,3,1)),Dense(1,)])
    
    for layer in m.layers:
        # pop the kernel from the trainable weights
        kernel_w = layer._trainable_weights.pop(0)
        # add it to the non trainable weights
        layer._non_trainable_weights.append(kernel_w)
    

    检查它是否有效

    一个小实验看看这个技巧是否奏效:让我们看看 Dense 层的内核和偏差:

    >>> m.layers[1].kernel
    <tf.Variable 'dense/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[0.586058]], dtype=float32)>
    >>> m.layers[1].bias
    <tf.Variable 'dense/bias:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>
    

    然后我们编译我们的模型并在虚拟数据上训练它:

    import numpy as np
    # random data
    X = np.random.random((100,3,3,1))
    y = 5 + X[:,0,0,0] * 34 
    # training
    m.compile(loss='mse')
    

    如果我们再次检查我们的权重:

    >>> m.layers[1].kernel
    <tf.Variable 'dense/kernel:0' shape=(1, 1) dtype=float32, numpy=array([[0.586058]], dtype=float32)>
    >>> m.layers[1].bias
    <tf.Variable 'dense/bias:0' shape=(1,) dtype=float32, numpy=array([0.00957833], dtype=float32)>
    

    偏见改变了,但内核没有改变!


    注意事项

    你必须小心这种方法:内核可能并不总是在层的索引 0 处。检查您要使用的层及其内核的索引。据我测试,它适用于 Dense 和 Conv2D 层。

    另请注意,此方法依赖于 Layer 类的私有属性。它现在可以工作,但有一天可能会坏掉。

    【讨论】:

    • 但是,是否可以训练与内核中的神经元相对应的特定通道之一?
    • 你的意思是冻结所有内核,除了一个/几个值?不是直接使用 keras。使用 tensorflow 的低级 API 或许可以实现一些目标,但我认为性能不会很好。
    • “你的意思是冻结所有内核,除了一个/几个值?” 是的!想知道这些吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    相关资源
    最近更新 更多