Python 如何在tensorflow中制作Conv层中的一个/部分过滤器?

Python 如何在tensorflow中制作Conv层中的一个/部分过滤器?,python,tensorflow,keras,deep-learning,Python,Tensorflow,Keras,Deep Learning,我的意思是: 假设Conv内核有64个通道输出,我只想从64个通道中训练通道1 这个问题来自于阅读这篇论文 在本文中,我们建议在迁移学习中冻结一些过滤器并训练其余的过滤器 然而,我想知道如何在Tensorflow中实现它 如果我们能够冻结某些层,很明显,只需在网络中迭代这些层,并使其可训练的布尔值为False 然而,当涉及到内核时,它将比我想象的更麻烦 我找到了这个安瑟 我试着把所有的重量都放在下面: def get_weights_bias(model, layer_name): "

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

这个问题来自于阅读这篇论文

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

然而,我想知道如何在Tensorflow中实现它

如果我们能够冻结某些层,很明显,只需在网络中迭代这些层,并使其可训练的布尔值为False

然而,当涉及到内核时,它将比我想象的更麻烦

我找到了这个安瑟

我试着把所有的重量都放在下面:

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层,因为
层。set_weights()
只接受numpy数组,而不接受tf.Variable


有什么建议吗???

据我所知,没有一种干净的方法可以冻结内核并使用kerasapi保持偏差可训练性。尽管如此,您还是可以通过使用私有属性来实现这一点:

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)

检查它是否工作

一个小实验,看看这个技巧是否有效:让我们看看内核和致密层的偏差:

>>> 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)>
如果我们再次检查我们的体重:

>>> 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)>
>m.layers[1]。内核
>>>m.layers[1]。偏差
偏差改变了,但内核没有改变


注意事项

使用此方法时必须小心:内核可能并不总是位于层的索引0处。检查要使用的层及其内核的索引。据我测试,它适用于密集的2D层


还要注意,此方法依赖于
类的私有属性。它现在可以工作,但有一天可能会中断。

但是,是否可以训练与内核中神经元对应的特定通道之一?您的意思是冻结除一个/多个值之外的所有内核?而不是直接使用keras。通过使用tensorflow的低级API,您可能可以实现一些功能,但我认为性能不会很好。“您的意思是冻结除一个/多个值之外的所有内核?”“是的!想知道这些吗?
>>> 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)>