У меня есть слой фильтра свертки 2D (назовите его 7x7) в нейронной сети. Я хочу ограничить фильтр, чтобы его веса добавлялись к 0. (Это общее требование к сверточным фильтрам при обработке изображений - идея состоит в том, что фильтр чувствителен к локальным изменениям яркости, но не к абсолютному уровню яркость.) Это более или менее эквивалентно наличию слоя с 48 весами, чьи входы составляют x [-3, -3] -x [0,0], x [-3, -2] -x [0,0] , ... x [3,3] -x [0,0].
По какой-то причине я не вижу никакой нативной функциональности для наложения этого ограничения.
То, что я пробовал до сих пор:
Не навязывайте ограничения. Очень плохо для конвергенции (изменяющиеся общие уровни яркости действуют как массивный источник шума, который препятствует конвергенции сети.)
Код пользовательского регуляризатора для слоя:
например.
class FixSum(Regularizer):
def call(self, x):
reg=0.01*math_ops.reduce_sum(math_ops.abs(math_ops.reduce_sum(x,axis=(0,1))))
return reg
Плохо для сходимости, особенно при силе регуляризатора, где он фактически эффективен при переносе суммы весов в окрестности нуля.
- Код пользовательского ограничения для слоя:
, например
class TestConstraint(Constraint):
def __init__(self, N, target_sum):
self.target_sum = tf.keras.backend.variable(target_sum,dtype="float32")
self.N = N
def __call__(self, w):
t = math_ops.reduce_sum(x,axis=(0,1),keepdims=True) - self.target_sum
t /= self.N
return w - tf.keras.backend.repeat_elements(tf.keras.backend.repeat_elements(t, w.shape[0], 0), w.shape[1], 1)
Вроде работает, но скорость сходимости оставляет желать лучшего
Я бы сделал
Conv2D(48, (7,7), trainable=False, ...)
Conv2D(n, (1,1), ...)
, где первый Conv2D имеет веса, установленные в самом начале для получения x [-3, -3] -x [0,0] и т. Д.
Скорость сходимости хорошая, но производительность не такая хорошая. И он не слишком хорошо масштабируется (если я увеличу ядро с 7x7 до 15x15, это увеличит вычислительную сложность этого «поддельного слоя» примерно в 20 раз.)
Есть что-нибудь еще, что я должен попробовать?