在 Keras 中实现自定义 Activity 正则化器

Implement Custom Activity Regularizer inside Keras

我正在尝试在 Andrew Ng Sparse Autoencoder 的损失函数内实现正则化项。在第 15 页,引入了一个稀疏惩罚项,它是根据所有隐藏层单元的 rho 和 rho_hat_j 之间的 Kullback-Leibor (KL) 散度求和计算得出的。 rho 是强制神经元大部分关闭的静态数字,rho_hat_j 是整个训练集上神经元 j 的平均输出(激活)。

我正在使用 Keras 来实现自动编码器,我知道 Keras Blog, but I want to implement described sparsity penalty term with custom regularizer in Keras. Some old implementation about this question found on Link, Link 上提供了一个关于使用 Keras 构建自动编码器的很棒的教程,但是随着 Keras 1.2 版以来正则化 API 的变化。 0,它们已被弃用,不再起作用。

所以我试图用这样的东西来实现它:

from keras import backend as K

def kl_divergence(rho, rho_hat):
    return rho * tf.log(rho) - rho * tf.log(rho_hat) + (1 - rho) * tf.log(1 - rho) - (1 - rho) * tf.log(1 - rho_hat)

class SparseActivityRegularizer(Regularizer):

    def __init__(self, p=0.1, sparsityBeta=3):
        self.p = p
        self.sparsityBeta = sparsityBeta

    def __call__(self, x):
        regularization = 0            

        p_hat = K.mean(x, axis=0)
        regularization += self.sparsityBeta * K.sum(kl_divergence(self.p, p_hat))

        return regularization

    def get_config(self):
        return {"name": self.__class__.__name__} 

正确吗?!

一个我在任何地方都找不到的大问题,传递给 callable __ call __(作为 x 参数)的究竟是什么?

我是否更正 x 是二维张量,其中每一行属于每个神经元,每一列属于训练集上的每个样本,并且每个单元格 (i,j) 将是神经元 i 对于样本 j 的输出训练集?

更新:更短的问题

考虑 Keras 中的 3 层自动编码器,应该如何实现这个总体成本函数?

beta:稀疏惩罚系数(例如3)

s_2: 隐藏层单元数

rho:固定值(例如0.2)

m:训练集中的样本数

x_i: 第i个训练集样本

a_2_j(x_i): 训练集第i个样本第2层第j个单元的输出

你的代码是正确的。但是似乎没有关于您的自动编码器模型的任何代码。它只是隐藏层的正则化器。

  1. 因为你定义了一个activity正则化器,__call__函数中的X是activity(隐藏层的输出),其形状应该是( ?,hidden_dim)。 “?”表示样本数,在拟合前未知。 hidden_dim是隐藏层的神经元个数,在我下面的例子中应该是250个。

如果你想构建整体,你应该知道如何定义其他层。这是一个玩具示例。

x_input = Input(shape=(576,))
regularizer = SparseActivityRegularizer(0.1, 6)
encoded = Dense(250, activation='relu', activity_regularizer=regularizer)(x_input)
decoded = Dense(576, activation ='relu')(encoded)
ae = Model(inputs=x_input, outputs=decoded)

然后您可以通过以下方式编译和拟合模型:

ae.compile(optimizer='adam', loss='mse')
ae.fit(x_train, x_train, epochs=1, batch_size=50)

所以整个损失函数由两部分组成:1)编译模型时分配的 mse 和 2)定义隐藏层时 activity 的正则化(encoded 在我的例子中)