Keras层中参数和的约束

Keras层中参数和的约束,keras,constraints,keras-layer,activation-function,Keras,Constraints,Keras Layer,Activation Function,我想在图层的参数上添加自定义约束。 我用两个可训练参数a和b s.t编写了一个自定义激活层: 激活\u fct=a*fct()+b*fct()。 我需要使参数(a+b)之和等于1,但我不知道如何编写这样的约束。 你能给我一些建议吗 提前谢谢 我想到了两种方法 第一个是锁定其中一个参数,比如说b,并仅使另一个(a在本例中)可训练。然后您可以按如下方式计算b b = 1 - a 第二种方法是使a和b都可培训,并通过softmax功能对其进行转换。Softmax函数将确保其总和始终为1 from s

我想在图层的参数上添加自定义约束。 我用两个可训练参数a和b s.t编写了一个自定义激活层:
激活\u fct=a*fct()+b*fct()
。 我需要使参数(a+b)之和等于1,但我不知道如何编写这样的约束。 你能给我一些建议吗


提前谢谢

我想到了两种方法

第一个是锁定其中一个参数,比如说
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()

我想到了两种方法

第一个是锁定其中一个参数,比如说
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()

可以使用单个权重而不是两个,并使用此自定义约束:

import keras.backend as K

class Between_0_1(keras.constraints.Constraint):
    def __call__(self, w):
        return K.clip(w, 0, 1)
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)
然后,在构建权重时,只构建一个约束并使用约束

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
在调用中,
b=1-a

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

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

您也可以尝试@MatusDubrava
softmax
方法,但在这种情况下,您的权重需要具有形状
(2,)
,并且没有约束:

import keras.backend as K

class Between_0_1(keras.constraints.Constraint):
    def __call__(self, w):
        return K.clip(w, 0, 1)
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)

可以使用单个权重而不是两个,并使用此自定义约束:

import keras.backend as K

class Between_0_1(keras.constraints.Constraint):
    def __call__(self, w):
        return K.clip(w, 0, 1)
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)
然后,在构建权重时,只构建一个约束并使用约束

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
在调用中,
b=1-a

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

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

您也可以尝试@MatusDubrava
softmax
方法,但在这种情况下,您的权重需要具有形状
(2,)
,并且没有约束:

import keras.backend as K

class Between_0_1(keras.constraints.Constraint):
    def __call__(self, w):
        return K.clip(w, 0, 1)
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)

答案很好,但是使用
keras.backend.softmax
,而权重应该是一个带形状的张量
(2,)
。然后
a=weights[0]
b=weights[1]
。谢谢Matus Dubrava和Daniel Möller。我决定使用keras.backend.softmax,并按照Daniel所说的更改权重(单张量)。它起作用了!答案很好,但是使用
keras.backend.softmax
,而权重应该是一个带形状的张量
(2,)
。然后
a=weights[0]
b=weights[1]
。谢谢Matus Dubrava和Daniel Möller。我决定使用keras.backend.softmax,并按照Daniel所说的更改权重(单张量)。它起作用了!