Keras Conv2D自定义内核初始化

2024-09-29 04:30:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要用权重初始化自定义Conv2D内核

W = a1b1 + a2b2 + ... + anbn

其中W=要初始化的Conv2D层的自定义权重

a=随机权重张量,如keras.backend.variable(np.random.uniform()),shape=(64,1,10)

b=固定基过滤器,定义为keras.backend.constant(...),shape=(10,11,11)

W = K.sum(a[:, :, :, None, None] * b[None, None, :, :, :], axis=2) #shape=(64, 1, 11, 11)

我只想在保持模型不变的情况下更新模型。在

我通过海关'W's as

Conv2D(64, kernel_size=(11, 11), activation='relu', kernel_initializer=kernel_init_L1)(img)

其中kernel_init_L1返回keras.backend.variable(K.reshape(w_L1, (11, 11, 1, 64)))

Problem: 我不确定这样做是否正确。是否可以在Keras中指定哪些是trainable,哪些不是。我知道图层可以设置trainable = True,但我不确定权重。在

我认为这个实现是不正确的,因为无论有没有自定义初始化,我都会从模型中得到类似的结果。在

如果有人能指出我方法中的任何错误或提供一种方法来验证它,那将是非常有帮助的。在


Tags: 方法模型nonebackendl1initvariablekernel
1条回答
网友
1楼 · 发布于 2024-09-29 04:30:15

关于形状的警告:如果内核大小是(11,11),并且假设有64个输入通道和1个输出通道,那么最终的内核形状必须是(11,11,64,1)。在

你应该去a[None,None]和{}。在

class CustomConv2D(Conv2D):

    def __init__(self, filters, kernel_size, kernelB = None, **kwargs):
        super(CustomConv2D, self).__init__(filters, kernel_size,**kwargs)
        self.kernelB = kernelB

    def build(self, input_shape):


        #use the input_shape to calculate the shapes of A and B
        #if needed, pay attention to the "data_format" used. 

        #this is an actual weight, because it uses `self.add_weight`   
        self.kernelA = self.add_weight(
                  shape=shape_of_kernel_A + (1,1), #or (1,1) + shape_of_A
                  initializer='glorot_uniform', #or select another
                  name='kernelA',
                  regularizer=self.kernel_regularizer,
                  constraint=self.kernel_constraint)


        #this is an ordinary var that will participate in the calculation
            #not a weight, not updated
        if self.kernelB is None:
            self.kernelB = K.constant(....) 
            #use the shape already containing the new axes


        #in the original conv layer, this property would be the actual kernel,
        #now it's just a var that will be used in the original's "call" method 
        self.kernel = K.sum(self.kernelA * self.kernelB, axis=2)  
        #important: the resulting shape should be:
            #(kernelSizeX, kernelSizeY, input_channels, output_channels)   


        #the following are remains of the original code for "build" in Conv2D
        #use_bias is True by default
        if self.use_bias:
            self.bias = self.add_weight(shape=(self.filters,),
                                    initializer=self.bias_initializer,
                                    name='bias',
                                    regularizer=self.bias_regularizer,
                                    constraint=self.bias_constraint)
        else:
            self.bias = None
        # Set input spec.
        self.input_spec = InputSpec(ndim=self.rank + 2,
                                axes={channel_axis: input_dim})
        self.built = True

自定义层提示

当您从零(派生自Layer)创建自定义层时,您应该具有以下方法:

  • __init__(self, ... parameters ...)-这是creator,它在您创建层的新实例时被调用。在这里,您存储用户作为参数传递的值。(在Conv2D中,init将具有“filters”、“kernel_size”等)
  • build(self, input_shape)-这是您应该创建权重的地方(所有可学习的变量都在这里创建,基于输入形状)
  • compute_output_shape(self,input_shape)-在这里您可以根据输入形状返回输出形状
  • call(self,inputs)-在这里您可以执行实际的层计算

因为我们不是从零开始创建这个层,而是从Conv2D派生出它,所以一切都准备好了,我们所做的就是“更改”构建方法并替换Conv2D层的内核。在

有关自定义层的详细信息:https://keras.io/layers/writing-your-own-keras-layers/

conv层的call方法是here in ^{}。在

相关问题 更多 >