Tensorflow 2.0 Keras 中过激激活值的正则化

Regularization of over-excited activation values in Tensorflow 2.0 Keras

对于一个特定的问题,我想在我的 Keras 模型中对一个层的过度兴奋激活进行正则化。因此,我创建了一个基于高于特定阈值的激活值数量的自定义损失。

损失出现了,但没有被优化器减少。只有分类损失最小化。

使用最新版本的tensorflow 2.0 和Keras 构建模型。我当前的尝试添加了第二个输出,其中包含依赖于特定层的自定义损失。 我已经尝试提供损失作为第二个输入并将其添加到密集损失中,这给了我相同的结果,自定义损失没有最小化。

我想第二个损失的梯度无法计算,但我在 PyTorch 中有一个工作示例,这似乎可行。

import tensorflow as tf
import numpy as np

from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, Conv2D, Flatten, MaxPooling2D, SpatialDropout2D, Input
from tensorflow.keras.optimizers import SGD

import tensorflow.keras.backend as K
from tensorflow.python.keras.layers import Layer

import get_prepare_dataset

# config
REGULARIZATION_HYPERP = 0.01
(train_images, train_labels), (test_images, test_labels) = get_prepare_dataset.mnist10()


class Taboo(Layer):
    def compute_output_signature(self, input_signature):
        pass

    def __init__(self, thresholds, **kwargs):
        super(Taboo, self).__init__(**kwargs)
        self.thresholds = thresholds

    def call(self, x, mask=None):
        return x


def taboo_loss(y_true, y_pred):
    above_threshold = tf.math.greater(y_pred, y_true[0])
    return REGULARIZATION_HYPERP * K.mean(tf.reduce_sum(tf.cast(above_threshold, tf.float32)))


if __name__ == "__main__":
    y_input = Input(shape=(28, 28, 1))
    layer1 = Conv2D(filters=10, kernel_size=(5, 5), strides=(1, 1), activation='relu', padding="same")(y_input)
    layer2 = MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='valid')(layer1)
    layer3 = Conv2D(filters=20, kernel_size=(5, 5), strides=(1, 1), activation='relu', padding="valid")(layer2)
    layer4 = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid')(layer3)
    layer5 = SpatialDropout2D(0.5)(layer4)
    layer6 = Flatten()(layer5)
    output_layer = Dense(units=10, activation='softmax')(layer6)

    thresholds = [0.5]

    cr = Taboo(thresholds)(layer3)
    model = Model(inputs=y_input, outputs=[output_layer, cr])
    model.compile(optimizer=SGD(lr=0.1), loss=[K.binary_crossentropy, taboo_loss])

    model.fit(train_images, [train_labels, np.asarray([thresholds] * len(train_images))],
              validation_data=[test_images, [test_labels, np.asarray([thresholds] * len(test_images))]], epochs=40)

分类损失减少了,而第二个损失变大了。 我希望第二个损失最小化。

您的自定义损失在重要的点上不可区分:当值超过阈值时,您的损失就会增加。这意味着它不能通过基于梯度的方法最小化。但是,如果您使损失与超出阈值的数量成正比,那么它将是可区分的,因此可以通过基于梯度的方法将其最小化。