Ограничение на сумму параметров в слое Keras - PullRequest
0 голосов
/ 05 февраля 2020

Я хочу добавить пользовательские ограничения на параметры слоя. Я пишу пользовательский слой активации с двумя обучаемыми параметрами a и b st: activation_fct = a*fct() + b*fct(). Мне нужно, чтобы сумма параметров (a + b) была равна 1, но я не знаю, как написать такое ограничение. Можете ли вы дать мне несколько советов?

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 05 февраля 2020

Два подхода приходят мне на ум.

Первый - заблокировать один из параметров, скажем, b и сделать обучаемым только другой (в данном случае a). Затем вы можете вычислить b следующим образом

b = 1 - a

Второй подход - сделать обучаемыми a и b и преобразовать их с помощью функции softmax. Функция Softmax будет гарантировать, что их сумма всегда равна 1.

from scipy.special import softmax

a = 0.12
b = 0.3
w1, w2 = softmax([a, b])

print(f'w1: {w1}, w2: {w2}, w1 + w2: {w1 + w2}')

Это даст

w1: 0.45512110762641994, w2: 0.5448788923735801, w1 + w2: 1.0

И когда у вас есть w1 и w2, вы можете использовать их в упомянутой формуле вместо a и b.

activation_fct = w1 * fct() + w2 * fct()
0 голосов
/ 05 февраля 2020

У вас может быть один вес вместо двух, и вы можете использовать это пользовательское ограничение:

import keras.backend as K

class Between_0_1(keras.constraints.Constraint):
    def __call__(self, w):
        return K.clip(w, 0, 1)

Затем при построении весов строите только a и используйте ограничения.

def build(self, input_shape):
    self.a = self.add_weight(name='weight_a', 
                                  shape=(1,),
                                  initializer='uniform',
                                  constraint = Between_0_1(), 
                                  trainable=True)

    #if you want to start as 0.5
    K.set_value(self.a, [0.5])

    self.built = True

В call, b = 1-a:

def call(self, inputs, **kwargs):
    #do stuff
    ....

    return (self.a * something) +  ((1-self.a)*another_thing)

Вы также можете попробовать подход @MatusDubrava softmax, но в этом случае ваши веса должны иметь форму (2,) и никаких ограничений. :

def build(self, input_shape):
    self.w = self.add_weight(name='weights', 
                              shape=(2,),
                              initializer='zeros',
                              trainable=True)
    self.build = True

def call(self, inputs, **kwargs):
    w = K.softmax(self.w)

    #do stuff
    ....

    return (w[0] * something ) + (w[1] * another_thing)
...