简体   繁体   English

自定义损失 function 通过梯度下降在每一步更新

[英]Custom loss function that updates at each step via gradient descent

From this post , we can write a custom loss function.从这篇文章中,我们可以编写自定义损失 function。 Now, assume that the custom loss function depends on parameter a:现在,假设自定义损失 function 取决于参数 a:

def customLoss(yTrue,yPred):
    return (K.log(yTrue) - K.log(yPred))**2+a*yPred

How can we update parameter a at each step in a gradient descent manner like the weights?:我们如何像权重一样以梯度下降的方式在每一步更新参数a?:

a_new= a_old - alpha * (derivative of custom loss with respect to a)

PS the real custom loss is different from the above. PS真正的自定义损失与上面不同。 Please give me a general answer that works for any arbitrary custom loss function, not an answer to the example above.请给我一个适用于任意自定义损失 function 的通用答案,而不是上面示例的答案。

Create a custom layer to hold the trainable parameter.创建一个自定义层来保存可训练参数。 This layer will not return the inputs in its call, but we are going to have the inputs for complying with how you create layers.该层不会在其调用中返回输入,但我们将拥有符合您创建层的方式的输入。

class TrainableLossLayer(Layer):

    def __init__(self, a_initializer, **kwargs):
        super(TrainableLossLayer, self).__init__(**kwargs)
        self.a_initializer = keras.initializers.get(a_initializer)

    #method where weights are defined
    def build(self, input_shape):
        self.kernel = self.add_weight(name='kernel_a', 
                                  shape=(1,),
                                  initializer=self.a_initializer,
                                  trainable=True)
        self.built=True

    #method to define the layers operation (only return the weights)
    def call(self, inputs):
        return self.kernel

    #output shape
    def compute_output_shape(self, input_shape):
        return (1,)

Use the layer in your model to get a with any inputs (this is not compatible with a Sequential model):使用 model 中a层来获取任何输入(这与顺序模型不兼容):

a = TrainableLossLayer(a_init, name="somename")(anyInput)

Now, you can try to define your loss in a sort of ugly way:现在,你可以尝试用一种丑陋的方式来定义你的损失:

def customLoss(yTrue,yPred):
    return (K.log(yTrue) - K.log(yPred))**2+a*yPred

If this works, then it's ready.如果这行得通,那么它就准备好了。


You can also try a more complicated model (if you don't want to use a in the loss jumping over the layers like that, this might cause problems in model saving/loading)您也可以尝试更复杂的 model (如果您不想在跳过这样的层的损失中使用a ,这可能会导致 model 保存/加载出现问题)

In this case, you will need that y_train goes in as an input instead of an output:在这种情况下,您需要将y_train作为输入而不是 output:

y_true_inputs = Input(...)

Your loss function will go into a Lambda layer taking all parameters properly:您的损失 function 将 go 转换为Lambda层,正确获取所有参数:

def lambdaLoss(x):
    yTrue, yPred, alpha = x
    return (K.log(yTrue) - K.log(yPred))**2+alpha*yPred

loss = Lambda(lambdaLoss)([y_true_inputs, original_model_outputs, a])

Your model will output this loss:你的 model 会 output 这个损失:

model = Model([original_model_inputs, y_true_inputs], loss)

You will have a dummy loss function:您将有一个虚拟损失 function:

def dummyLoss(true, pred):
    return pred

model.compile(loss = dummyLoss, ...)

And train as:并训练为:

model.fit([x_train, y_train], anything_maybe_None_or_np_zeros ,....)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM