如何在 Keras 中实现 Salt&Pepper 层?

Posted

技术标签:

【中文标题】如何在 Keras 中实现 Salt&Pepper 层?【英文标题】:how do I implement Salt& Pepper layer in Keras? 【发布时间】:2019-09-03 08:31:42 【问题描述】:

我需要在 keras 中实现盐和胡椒层,例如高斯噪声,我尝试使用以下代码,但它产生了几个错误。你能告诉我有什么问题吗?您对实施标准普尔层还有其他建议吗?谢谢。

from keras.engine.topology import Layer

class SaltAndPepper(Layer):

    def __init__(self, ratio, **kwargs):
        super(SaltAndPepper, self).__init__(**kwargs)
        self.supports_masking = True
        self.ratio = ratio

    def call(self, inputs, training=None):
        def noised():
            r = self.ratio*10
            s = inputs.shape[1]
            n = int( s * r/10 )
            perm = np.random.permutation(r)[:n]
            inputs[perm] = (np.random.rand(n) > 0.5)
            return inputs

        return K.in_train_phase(noised(), inputs, training=training)

    def get_config(self):
        config = 'ratio': self.ratio
        base_config = super(SaltAndPepper, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

Traceback(最近一次调用最后一次):

文件“”,第 125 行,在 decoded_noise=SaltAndPepper(0.5)(解码)

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\base_layer.py", 第 457 行,在 调用 output = self.call(inputs, **kwargs)

文件“”,第 57 行,调用中 return K.in_train_phase(noised(), inputs, training=training)

文件“”,第 52 行,噪声 n = int(s * r/10)

TypeError: /: 'Dimension' 和 'int' 的操作数类型不受支持

更新:

我用@today的解决方案,写了如下代码:

decoded_noise=call(0.05,bncv11)#16

which bncv11 是它之前的批量归一化层的输出。

但它会产生这个错误,为什么会发生?

Traceback(最近一次调用最后一次):

文件“”,第 59 行,在 decoded_noise=call(0.05,bncv11)#16

文件“”,第 34 行,调用中 return K.in_train_phase(noised(), inputs, training=training)

文件“”,第 29 行,噪声 mask_select = K.random_binomial(shape=shp, p=self.ratio)

AttributeError: 'float' 对象没有属性 'ratio'

保存模型并使用后会产生此错误:

Traceback(最近一次调用最后一次):

文件“”,第 1 行,在 b=load_model('Desktop/los4x4_con_tile_convolw_FBN_SigAct_SandPAttack05.h5',custom_objects='tf':tf)

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\saving.py", 第 419 行,在 load_model 中 model = _deserialize_model(f, custom_objects, compile)

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\saving.py", 第 225 行,在 _deserialize_model model = model_from_config(model_config, custom_objects=custom_objects)

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\saving.py", 第 458 行,在 model_from_config 返回反序列化(配置,custom_objects=custom_objects)

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\layers__init__.py", 第 55 行,在反序列化中 printable_module_name='layer')

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\utils\generic_utils.py", 第 145 行,在 deserialize_keras_object 中 列表(custom_objects.items())))

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\network.py", 第 1022 行,在 from_config process_layer(layer_data)

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\engine\network.py", 第 1008 行,在 process_layer custom_objects=custom_objects)

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\layers__init__.py", 第 55 行,在反序列化中 printable_module_name='layer')

文件 "D:\software\Anaconda3\envs\py36\lib\site-packages\keras\utils\generic_utils.py", 第 138 行,在 deserialize_keras_object 中 ': ' + 类名)

ValueError:未知层:SaltAndPepper

我将这段代码放在我定义网络结构的程序中:

from keras.engine.topology import Layer

class SaltAndPepper(Layer):

    def __init__(self, ratio, **kwargs):
        super(SaltAndPepper, self).__init__(**kwargs)
        self.supports_masking = True
        self.ratio = ratio

    # the definition of the call method of custom layer
    def call(self, inputs, training=True):
        def noised():
            shp = K.shape(inputs)[1:]
            mask_select = K.random_binomial(shape=shp, p=self.ratio)
            mask_noise = K.random_binomial(shape=shp, p=0.5) # salt and pepper have the same chance
            out = inputs * (1-mask_select) + mask_noise * mask_select
            return out

        return K.in_train_phase(noised(), inputs, training=training)

    def get_config(self):
        config = 'ratio': self.ratio
        base_config = super(SaltAndPepper, self).get_config()
        return dict(list(base_config.items()) + list(config.items()))

【问题讨论】:

堆栈跟踪表明您的比率是 Dimension 对象而不是数字变量。 这是什么意思?因为我是初学者,我不知道这段代码是做什么的。我应该怎么解决? 是否可以使用 lambda 层实现 s&p 噪声,或者我们应该生成这样的层? 说实话,我对标普层了解不多。但是您遇到的错误是一个非常基本的 python 错误。在您的代码中,您尝试执行以下除法r/10,错误消息告诉您这是不可能的,因为r 变量不是数字。 r 值来自比率(创建图层时使用的第二个参数。它应该是一个数字,我想它不是。您能提供用于创建图层的代码吗? 【参考方案1】:

在图像处理中,椒盐噪声基本上将随机选择的像素比率的值更改为盐(即白色,根据图像值的范围通常为 1 或 255)或胡椒(即黑色,通常为 0)。虽然,我们可以在图像处理之外的其他领域使用相同的想法。所以你必须首先指定三件事:

    应该改变多少像素? (噪声比) 应选择和更改哪些像素? 哪些选定的像素应该加盐(而另一个加盐)?

由于 Keras 后端有一个函数可以从具有给定概率的二项分布(即 0 或 1)生成随机值,因此我们可以通过生成两个掩码轻松完成上述所有步骤:一个用于选择具有给定比例的像素,另一个用于将盐或胡椒应用于这些选定的像素。操作方法如下:

from keras import backend as K

# NOTE: this is the definition of the call method of custom layer class (i.e. SaltAndPepper)
def call(self, inputs, training=None):
    def noised():
        shp = K.shape(inputs)[1:]
        mask_select = K.random_binomial(shape=shp, p=self.ratio)
        mask_noise = K.random_binomial(shape=shp, p=0.5) # salt and pepper have the same chance
        out = inputs * (1-mask_select) + mask_noise * mask_select
        return out

    return K.in_train_phase(noised(), inputs, training=training)

请注意,在上面的代码中,我假设了一些事情:

给定噪声比的值在 [0,1] 范围内。 如果您使用此图层直接将其应用于图像,那么您必须注意它假定图像是灰度的(即单色通道)。要将其用于 RGB 图像(即三个颜色通道),您可能需要对其进行一些修改,以便选择具有所有通道的像素来添加噪声(尽管这取决于您如何定义和使用椒盐噪声)。

假设 salt 的值为 1,pepper 的值为 0。不过,您可以通过更改 mask_noise 的定义,轻松地将 salt 的值更改为 x,将 pepper 的值更改为 y,如下所示:

mask_noise = K.random_binomial(shape=shp, p=0.5) * (x-y) + y

对批次中的所有样本应用相同的噪声模式(但是,批次之间会有所不同)。

【讨论】:

谢谢。如何在我的代码中使用它作为一个层?我使用了这个 decoded_noise=call(0.05,bncv11) 但它产生了这个错误 Traceback (最近一次调用最后): File "", line 59, in decoded_noise=call(0.05, bncv11)#16 文件“”,第 34 行,调用中 return K.in_train_phase(noised(), inputs, training=training) 文件“”,第 29 行,在噪声 mask_select = K.random_binomial(shape=shp, p=self.ratio) AttributeError: 'float' object has no attribute 'ratio' @david 请不要编辑其他人的答案以添加有关您的问题的更多信息。使用评论部分,或者如果您的更新很大并且包含代码,则编辑您自己的问题并在其末尾添加更新的信息。然后在该人的回答下方发表评论,以通知他/她您的更新。 @david 不,那是您定义的层的call 方法。我没有包含完整的代码,因为其余的都是一样的。所以不要直接使用call。把它放在你的自定义层中,然后使用你的自定义层(就像你原来的那样)。 对不起,我发现我的错误。非常感谢。这一层在训练和测试期间应用 S&P,它不起作用,对吧?当我也测试时是否可以工作? @david 见this answer。您需要在load_model 中将'SaltAndPepper': SaltAndPepper 作为custom_objects 传递。此外,我想更正我之前提到的一些事情:为了使层(通常不会在测试阶段应用)同时应用于训练和测试阶段,您需要将 training=True 参数传递给 该层的调用(我之前提到它应该传递给层本身;这是错误的)。有关示例,请参见 this answer。

以上是关于如何在 Keras 中实现 Salt&Pepper 层?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 keras 模型中实现汉明损失作为自定义指标

如何在 Keras 中实现高斯模糊层?

如何在 keras 层中实现 GlobalMinPool2D 函数?

如何在 Keras 中实现分层 Transformer 用于文档分类?

如何在 keras 中实现 ssim 的损失函数?

如何从零开始在 Keras 中实现 Leaky ReLU? [关闭]