如何在Keras中添加正交性正则化?

6

我希望对CNN的层进行正则化处理。

|(W^T * W - I)|

我该如何在Keras中实现这个功能?

1
你想使用哪种规范? - Marcin Możejko
@MarcinMożejko 很好的问题。直觉上,我会选择2-范数(Frobeniusnorm)。然而,这个选择相当随意。我不确定它如何影响训练。 - Martin Thoma
3个回答

4

文档中指出:

任何接受权重矩阵并返回损失贡献张量的函数都可以作为正则化器使用。

下面是实现的示例:

from keras import backend as K

def l1_reg(weight_matrix):
    return 0.01 * K.sum(K.abs(weight_matrix))

model.add(Dense(64, input_dim=64,
                kernel_regularizer=l1_reg)

你的帖子中所提到的损失将是:
from keras import backend as K
def fro_norm(w):
    return K.sqrt(K.sum(K.square(K.abs(w))))

def cust_reg(w):
    m = K.dot(K.transpose(w), w) - np.eye(w.shape)
    return fro_norm(m)

这是一个最简示例:
import numpy as np
from keras import backend as K
from keras.models import Sequential
from keras.layers import Dense, Activation

X = np.random.randn(100, 100)
y = np.random.randint(2, size=(100, 1))

model = Sequential()

# apply regularization here. applies regularization to the 
# output (activation) of the layer
model.add(Dense(32, input_shape=(100,), 
                activity_regularizer=fro_norm))
model.add(Dense(1))
model.add(Activation('softmax'))

model.compile(loss="binary_crossentropy",
              optimizer='sgd',
              metrics=['accuracy'])

model.fit(X, y, epochs=1, batch_size=32)

@Marcin评论所暗示的下面的方法不可行,因为正则化器必须返回张量,而LA.norm()并不能返回。

def orth_norm(w)
    m = K.dot(k.transpose(w), w) - np.eye(w.shape)
    return LA.norm(m, 'fro')

from keras import backend as K

import numpy as np

def orth_norm(w)
    m = K.dot(k.transpose(w), w) - np.eye(w.shape)
    return LA.norm(m, 'fro')

Keras正则化

弗罗贝尼乌斯范数


这个是否真的有效?Norm似乎不是keras.backend函数? - Marcin Możejko
谢谢,你说得对。我在后端似乎找不到一个标准函数,有什么提示吗? - parsethis
你已经实现了Frobenious范数,但是cust_reg似乎无法工作:https://pastebin.com/CgX5rdvE 和 https://gist.github.com/MartinThoma/f29b640caa237e413e05c98d8c334ddd - Martin Thoma
我认为应该是 m = K.dot(K.transpose(w), w) - K.eye(w[1].shape[0])。我可以替换它吗? - Martin Thoma

2

我认为对于卷积层,您可以使用以下代码。虽然效率不高,但我认为它是可行的:

最初的回答:

import keras.backend as K
import tensorflow as tf
def orthogonality_regularization(weight_matrix):
    identity = K.eye(int(weight_matrix.shape[-1]))
    orthogonality_reg_mat = []
    for i in range(weight_matrix.shape[-1]):
        for j in range(weight_matrix.shape[-1]):
            orthogonality_reg_mat.extend([K.sum(tf.multiply(K.flatten(weight_matrix[:,:,:,i]), K.flatten(weight_matrix[:,:,:,j]))) - identity[i, j]])

    orthogonality_reg = tf.linalg.norm(tf.convert_to_tensor(orthogonality_reg_mat))


    return orthogonality_reg

有人知道应该如何更高效地实现吗? - Panda

0

现如今(在{{link1:tensorflow 2.9.0}}中),keras提供了一种正则化运算符,即正交正则化OrthogonalRegularizer。它允许在列和行之间强制实施正交性,不确定哪个是您的特定情况。

因此,您可以像这样调用它:

import tensorflow as tf

reg = tf.keras.regularizers.OrthogonalRegularizer(factor=0.01, mode="rows")

# now you can use reg in your layer(s)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接