【问题标题】:Keras Functional API and loss function with multiple inputsKeras 函数式 API 和具有多个输入的损失函数
【发布时间】:2018-11-09 09:57:17
【问题描述】:

我正在尝试使用自定义 Keras 损失函数,除了通常的签名 (y_true, y_pred) 之外,还需要另一个参数 sigma(这也是由网络的最后一层产生的)。 训练效果很好,但是我不确定如何执行前向传播并返回sigma(而mumodel.predict方法的输出)。 这是我正在使用的代码,它具有一个自定义层 GaussianLayer,它返回列表 [mu, sigma]

import tensorflow as tf
from keras import backend as K
from keras.layers import Input, Dense, Layer, Dropout
from keras.models import Model
from keras.initializers import glorot_normal
import numpy as np

def custom_loss(sigma):
    def gaussian_loss(y_true, y_pred):
        return tf.reduce_mean(0.5*tf.log(sigma) + 0.5*tf.div(tf.square(y_true - y_pred), sigma)) + 10
    return gaussian_loss

class GaussianLayer(Layer):

    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(GaussianLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        self.kernel_1 = self.add_weight(name='kernel_1', 
                                      shape=(30, self.output_dim),
                                      initializer=glorot_normal(),
                                      trainable=True)
        self.kernel_2 = self.add_weight(name='kernel_2', 
                                      shape=(30, self.output_dim),
                                      initializer=glorot_normal(),
                                      trainable=True)
        self.bias_1 = self.add_weight(name='bias_1',
                                    shape=(self.output_dim, ),
                                    initializer=glorot_normal(),
                                    trainable=True)
        self.bias_2 = self.add_weight(name='bias_2',
                                    shape=(self.output_dim, ),
                                    initializer=glorot_normal(),
                                    trainable=True)
        super(GaussianLayer, self).build(input_shape) 

    def call(self, x):
        output_mu  = K.dot(x, self.kernel_1) + self.bias_1
        output_sig = K.dot(x, self.kernel_2) + self.bias_2
        output_sig_pos = K.log(1 + K.exp(output_sig)) + 1e-06  
        return [output_mu, output_sig_pos]

    def compute_output_shape(self, input_shape):
        return [(input_shape[0], self.output_dim), (input_shape[0], self.output_dim)]

# This returns a tensor
inputs = Input(shape=(1,))
x = Dense(30, activation='relu')(inputs)
x = Dropout(0.3)(x)
x = Dense(30, activation='relu')(x)
x = Dense(40, activation='relu')(x)
x = Dropout(0.3)(x)
x = Dense(30, activation='relu')(x)
mu, sigma = GaussianLayer(1)(x)

model = Model(inputs, mu)
model.compile(loss=custom_loss(sigma), optimizer='adam')
model.fit(train_x, train_y, epochs=150)

【问题讨论】:

    标签: function tensorflow keras loss


    【解决方案1】:

    由于您的模型返回两个张量作为输出,您还需要在调用fit() 方法时传递两个数组的列表作为输出。这基本上就是错误试图传达的内容:

    检查模型目标时出错:

    所以错误在目标(即标签)中。怎么了?

    您传递给模型的 Numpy 数组列表不是模型预期的大小预计会看到 2 个数组,但得到以下 1 个数组的列表:

    【讨论】:

    • 感谢您的回答。我正在尝试使用 Keras this Tensorflow 实现 MLPGaussianRegressor 进行重现。这需要将 y_true(单个标量)传递给损失函数,而 y_pred 是 2 个元素的列表。对不起,也许我以错误的方式处理这个问题
    • @Alberto 我没有查看该实现,但如果您的模型输出两个张量(或两个标量),那么 y_true 也应该是两个数组,您将传递给 fit() 方法。否则,您需要更改模型的实现(通过修改自定义层的实现或向模型添加其他层)使其只有一个输出。
    • 谢谢',我已经用相关细节更新了问题!
    【解决方案2】:

    我可能在Keras FAQs 中找到了答案。 我发现可以使用下面的代码 sn-p 检索中间步骤的输出:

    layer_name = 'main_output'
    intermediate_layer_model = Model(inputs=model.input,
                                     outputs=model.get_layer(layer_name).output)
    intermediate_output = intermediate_layer_model.predict(train_x[0])
    intermediate_output
    

    在这种情况下intermediate_output 是两个值[mu, sigma] 的列表(只需将输出层命名为main_output 并稍后检索)

    【讨论】:

      猜你喜欢
      • 2021-05-23
      • 1970-01-01
      • 1970-01-01
      • 2019-06-23
      • 2019-05-17
      • 2020-01-21
      • 2018-01-09
      • 2019-05-19
      • 2019-01-11
      相关资源
      最近更新 更多