简体   繁体   English

如何使用 model 输入损耗 function?

[英]How to use model input in loss function?

I am trying to use a custom loss-function which depends on some arguments that the model does not have.我正在尝试使用自定义损失函数,它取决于 model 没有的一些 arguments。

The model has two inputs ( mel_specs and pred_inp ) and expects a labels tensor for training: model 有两个输入( mel_specspred_inp )并且需要一个用于训练的labels张量:

def to_keras_example(example):
    # Preparing inputs
    return (mel_specs, pred_inp), labels

# Is a tf.train.Dataset for model.fit(train_data, ...)
train_data = load_dataset(fp, 'train).map(to_keras_example).repeat()

In my loss function I need to calculate the lengths of mel_specs and pred_inp .在我的损失 function 中,我需要计算mel_specspred_inp的长度。 This means my loss looks like this:这意味着我的损失看起来像这样:

def rnnt_loss_wrapper(y_true, y_pred, mel_specs_inputs_):
    input_lengths = get_padded_length(mel_specs_inputs_[:, :, 0])
    label_lengths = get_padded_length(y_true)
    return rnnt_loss(
        acts=y_pred,
        labels=tf.cast(y_true, dtype=tf.int32),
        input_lengths=input_lengths,
        label_lengths=label_lengths
    )

However, no matter which approach I choose, I am facing some issue.但是,无论我选择哪种方法,我都面临一些问题。


Option 1) Setting the loss-function in model.compile()选项 1) 在 model.compile() 中设置损失函数

If I actually wrap the loss function st it returns a function which takes y_true and y_pred like this:如果我实际上包装了损失 function st 它返回一个 function ,它采用y_truey_pred ,如下所示:

def rnnt_loss_wrapper(mel_specs_inputs_):
    def inner_(y_true, y_pred):
        input_lengths = get_padded_length(mel_specs_inputs_[:, :, 0])
        label_lengths = get_padded_length(y_true)
        return rnnt_loss(
            acts=y_pred,
            labels=tf.cast(y_true, dtype=tf.int32),
            input_lengths=input_lengths,
            label_lengths=label_lengths
        )
    return inner_

model = create_model(hparams)
model.compile(
    optimizer=optimizer,
    loss=rnnt_loss_wrapper(model.inputs[0]
)

Here I get a _SymbolicException after calling model.fit() :在这里我在调用model.fit()后得到一个_SymbolicException

tensorflow.python.eager.core._SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [...]

Option 2) Using model.add_loss()选项 2) 使用 model.add_loss()

The documentation of add_loss() states: add_loss()的文档指出:

 [Adds a..] loss tensor(s), potentially dependent on layer inputs. .. Arguments: losses: Loss tensor, or list/tuple of tensors. Rather than tensors, losses may also be zero-argument callables which create a loss tensor. inputs: Ignored when executing eagerly. If anything...

So I tried to do the following:所以我尝试执行以下操作:

def rnnt_loss_wrapper(y_true, y_pred, mel_specs_inputs_):
    input_lengths = get_padded_length(mel_specs_inputs_[:, :, 0])
    label_lengths = get_padded_length(y_true)
    return rnnt_loss(
        acts=y_pred,
        labels=tf.cast(y_true, dtype=tf.int32),
        input_lengths=input_lengths,
        label_lengths=label_lengths
    )

model = create_model(hparams)
model.add_loss(
    rnnt_loss_wrapper(
        y_true=model.inputs[2],
        y_pred=model.outputs[0],
        mel_specs_inputs_=model.inputs[0],
    ),
    inputs=True
)
model.compile(
    optimizer=optimizer
)

However, calling model.fit() throws a ValueError :但是,调用model.fit()会引发ValueError

ValueError: No gradients provided for any variable: [...]

Is any of the above options supposed to work?上述任何选项都应该起作用吗?

I have used the add_loss method as follow:我使用了 add_loss 方法如下:

def custom_loss(y_true, y_pred, input_):
# custom loss function
    y_estim = input_[...,0]*y_pred
    shape = tf.cast(tf.shape(y_true)[1], dtype='float32')
    return tf.reduce_mean(1/shape*tf.reduce_sum(tf.pow(y_true-y_estim, 2), axis=1))


mix_input = layers.Input(shape=(301, 257, 4)) # input 1
ref_input = layers.Input(shape=(301, 257, 1)) # input 2
target = layers.Input(shape=(301, 257))       # output target

smss_model = Model(inputs=[mix_input, ref_input], outputs=smss) # my model that accept two inputs

model = Model(inputs=[mix_input, ref_input, target], outputs=smss) # this one used just to train the model, with the additional paramters
model.add_loss(custom_loss(target, smss, mix_input)) # the add_loss where to pass the custom loss function
model.summary()

model.compile(loss=None, optimizer='sgd')
model.fit([mix, ref, y], epochs=1, batch_size=1, verbose=1)

even do I have used this method and works, I still looking for another method, that not involve creating a training model即使我使用过这种方法并且有效,我仍在寻找另一种方法,不涉及创建培训 model

Did using lambda function work?使用 lambda function 工作了吗? ( https://www.w3schools.com/python/python_lambda.asp ) https://www.w3schools.com/python/python_lambda.asp

loss = lambda x1, x2: rnnt_loss(x1, x2, acts, labels, input_lengths,
                                label_lengths, blank_label=0)

In this way your loss function should be a function accepting parameters x1 and x2 , but rnnt_loss can also be aware of acts , labels , input_lengths , label_lengths and blank_label这样你的损失 function 应该是一个 function 接受参数x1x2 ,但input_lengths也可以知道actslabels ,输入长度,标签label_lengthsblank_label标签

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

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