如何在 Keras 中正确实现自定义活动正则化器?

Posted

技术标签:

【中文标题】如何在 Keras 中正确实现自定义活动正则化器?【英文标题】:How do I correctly implement a custom activity regularizer in Keras? 【发布时间】:2016-08-23 03:15:41 【问题描述】:

我正在尝试根据 Andrew Ng 的讲义实现稀疏自动编码器,如 here 所示。 它要求通过引入惩罚项(K-L 散度)在自动编码器层上应用稀疏约束。经过一些小改动后,我尝试使用here 提供的方向来实现这一点。 这是由 SparseActivityRegularizer 类实现的 K-L 散度和稀疏惩罚项,如下所示。

def kl_divergence(p, p_hat):
return (p * K.log(p / p_hat)) + ((1-p) * K.log((1-p) / (1-p_hat)))

class SparseActivityRegularizer(Regularizer):
sparsityBeta = None

    def __init__(self, l1=0., l2=0., p=-0.9, sparsityBeta=0.1):
        self.p = p
        self.sparsityBeta = sparsityBeta

    def set_layer(self, layer):
        self.layer = layer

    def __call__(self, loss):
        #p_hat needs to be the average activation of the units in the hidden layer.      
        p_hat = T.sum(T.mean(self.layer.get_output(True) , axis=0))

        loss += self.sparsityBeta * kl_divergence(self.p, p_hat)
        return loss

    def get_config(self):
        return "name": self.__class__.__name__,
            "p": self.l1

模型是这样构建的

X_train = np.load('X_train.npy')
X_test = np.load('X_test.npy')

autoencoder = Sequential()
encoder = containers.Sequential([Dense(250, input_dim=576, init='glorot_uniform', activation='tanh', 
    activity_regularizer=SparseActivityRegularizer(p=-0.9, sparsityBeta=0.1))])

decoder = containers.Sequential([Dense(576, input_dim=250)])
autoencoder.add(AutoEncoder(encoder=encoder, decoder=decoder, output_reconstruction=True))
autoencoder.layers[0].build()
autoencoder.compile(loss='mse', optimizer=SGD(lr=0.001, momentum=0.9, nesterov=True))
loss = autoencoder.fit(X_train_tmp, X_train_tmp, nb_epoch=200, batch_size=800, verbose=True, show_accuracy=True, validation_split = 0.3)
autoencoder.save_weights('SparseAutoEncoder.h5',overwrite = True)
result = autoencoder.predict(X_test)

当我调用 fit() 函数时,我得到负损失值,并且输出与输入完全不同。我想知道我哪里出错了。计算层的平均激活并使用此自定义稀疏正则化器的正确方法是什么?任何形式的帮助将不胜感激。谢谢!

我正在使用带有 Python 2.7 的 Keras 0.3.1,因为最新的 Keras (1.0.1) 版本没有自动编码器层。

【问题讨论】:

【参考方案1】:

您已定义 self.p = -0.9 而不是原始海报和您提到的讲义都使用的 0.05 值。

【讨论】:

【参考方案2】:

我纠正了一些错误:

class SparseRegularizer(keras.regularizers.Regularizer):
    
    def __init__(self, rho = 0.01,beta = 1):
        """
        rho  : Desired average activation of the hidden units
        beta : Weight of sparsity penalty term
        """
        self.rho = rho
        self.beta = beta
        

    def __call__(self, activation):
        rho = self.rho
        beta = self.beta
        # sigmoid because we need the probability distributions
        activation = tf.nn.sigmoid(activation)
        # average over the batch samples
        rho_bar = K.mean(activation, axis=0)
        # Avoid division by 0
        rho_bar = K.maximum(rho_bar,1e-10) 
        KLs = rho*K.log(rho/rho_bar) + (1-rho)*K.log((1-rho)/(1-rho_bar))
        return beta * K.sum(KLs) # sum over the layer units

    def get_config(self):
        return 
            'rho': self.rho,
            'beta': self.beta
        

【讨论】:

以上是关于如何在 Keras 中正确实现自定义活动正则化器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PHP + MySQL 中正确实现自定义会话持久化器?

Keras:内核和活动正则化器之间的区别

如何在 Android 中正确定义 2 个主要的启动器活动

在 Rails 4 中正确实现 Parsley.js 自定义远程验证器

在 TF2/Keras 中正确实现 Autoencoder MSE 损失函数

如何在python的类中正确实现辅助函数