如何在Keras中操纵(约束)Conv2D中过滤器内核的权重?

2024-09-27 23:20:48 发布

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

我知道在Keras的Conv2D中有几个内核约束选项:max_norm、non_neg或unit_norm。。在

但我需要的是将过滤器内核中的锚(中心)位置设置为零。 例如,如果我们有一个大小为(width,height)=(5,5)的过滤器内核,并且在输入中有3个通道。我需要将每个通道的这个内核的锚定点(中心)约束为0,比如w(2,2,:)=0,假设我们把通道维设为第三维。如果有多个过滤器,每个过滤器的锚定位置应为零。我如何实现这一点?在

我假设需要一个自定义的内核约束。此链接给出了如何创建一个继承自约束的类:https://github.com/keras-team/keras/issues/8196。这显示了如何实现内置约束: https://github.com/keras-team/keras/blob/master/keras/constraints.py

但是,我仍然不知道w的维数是如何被操纵的,以及如何将期望的位置设置为零。感谢任何帮助。谢谢。在

更新: 丹尼尔·默勒的回答被试过了。错误消息如下:
raise ValueError('一个操作有None表示渐变。' ValueError:操作有None表示渐变。请确保你所有的操作都有一个梯度定义(即,是可微的)。无梯度的普通操作:K.argmax,K.round,K.eval。在

由于Daniel可以毫无问题地运行它,为了检查我程序中的错误,我在这里发布了我的简化代码。我的数据有8个频道,但你有多少频道都不重要。在

from keras.layers import Input, Conv2D
from keras.models import Model, optimizers
import numpy as np
import tensorflow as tf
from keras import backend as K
from keras.callbacks import ModelCheckpoint


class ZeroCenterConv2D(Conv2D):
    def __init__(self, filters, kernel_size, **kwargs):
        super(ZeroCenterConv2D, self).__init__(filters, kernel_size, **kwargs)

    def call(self, inputs):
        assert self.kernel_size[0] % 2 == 1, "Error: the kernel size is an even number"
        assert self.kernel_size[1] % 2 == 1, "Error: the kernel size is an even number"

        centerX = (self.kernel_size[0] - 1) // 2
        centerY = (self.kernel_size[1] - 1) // 2

        kernel_mask = np.ones(self.kernel_size + (1, 1))
        kernel_mask[centerX, centerY] = 0
        kernel_mask = K.constant(kernel_mask)

        customKernel = self.kernel * kernel_mask

        outputs = K.conv2d(
            inputs,
            customKernel,
            strides=self.strides,
            padding=self.padding,
            data_format=self.data_format,
            dilation_rate=self.dilation_rate)

        if self.activation is not None:
            return self.activation(outputs)

        return outputs


size1 = 256
size2 = 256
input_img = Input(shape=(size1, size2, 8))
conv1 = ZeroCenterConv2D(8, (5, 5), padding='same', activation='relu')(input_img)
autoencoder = Model(input_img, conv1)
adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)
autoencoder.compile(optimizer=adam, loss='mean_squared_error')


import scipy.io
A = scipy.io.loadmat('data_train')
x_train = A['data']
x_train = np.reshape(x_train, (1, 256, 256, 8))


from keras.callbacks import TensorBoard

autoencoder.fit(x_train, x_train,
                epochs=5,
                batch_size=1,
                shuffle=False,
                validation_data=(x_train, x_train),
                callbacks=[TensorBoard(log_dir='/tmp/autoencoder')])


decoded_imgs = autoencoder.predict(x_train)

当conv1=ZeroCenterConv2D。。。被传统的conv1=Conv2D取代,一切正常。在

完整的错误消息:

^{pr2}$

进一步更新:在Daniel的答案中添加“bias”部分(已经完成),问题解决了!在


Tags: fromimportself过滤器datasizetrainmask
1条回答
网友
1楼 · 发布于 2024-09-27 23:20:48

您需要一个自定义的Conv2D层,在这里您可以更改其调用方法以在中心应用零。在

class ZeroCenterConv2D(Conv2D):
    def __init__(self, filters, kernel_size, **kwargs):
        super(ZeroCenterConv2D, self).__init__(filters, kernel_size, **kwargs)

    def call(self, inputs):
        assert self.kernel_size[0] % 2 == 1, "Error: the kernel size is an even number"
        assert self.kernel_size[1] % 2 == 1, "Error: the kernel size is an even number"

        centerX = (self.kernel_size[0] - 1) // 2
        centerY = (self.kernel_size[1] - 1) // 2

        kernel_mask = np.ones(self.kernel_size + (1, 1))
        kernel_mask[centerX, centerY] = 0
        kernel_mask = K.variable(kernel_mask)

        customKernel = self.kernel * kernel_mask

        outputs = K.conv2d(
            inputs,
            customKernel,
            strides=self.strides,
            padding=self.padding,
            data_format=self.data_format,
            dilation_rate=self.dilation_rate)

        if self.use_bias:
            outputs = K.bias_add(
                outputs,
                self.bias,
                data_format=self.data_format)

        if self.activation is not None:
            return self.activation(outputs)

        return outputs

虽然这不能代替实际的重量,但是中间的重量永远不会被使用。在

当您使用layer.get_weights()model.get_weights()时,您将看到初始化时的中心权重(不是零)。在

相关问题 更多 >

    热门问题