如何在Keras中使用ImageDataGenerator时定义依赖于输入的自定义成本函数?

时间:2018-06-05 17:51:52

标签: keras

我想定义一个自定义成本函数

def custom_objective(y_true, y_pred):
    ....
    return L

不仅取决于y_truey_pred,还取决于生成x的相应y_pred的某些功能。我能想到这样做的唯一方法是“隐藏”y_true中的相关功能,以便y_true = [usual_y_true, relevant_x_features]或类似的内容。

我在实施这个问题时遇到两个主要问题:

1)改变y_true的形状意味着我需要用一些垃圾填充y_pred,以便它们的形状相同。我可以通过模仿我模型的最后一层来做到这一点

2)我像这样使用数据扩充:

datagen = ImageDataGenerator(preprocessing_function=my_augmenter)

其中my_augmenter()是一个函数,它还应该为我提供在x上面使用的相关custom_objective()功能。但是,培训

model.fit_generator(datagen.flow(x_train, y_train, batch_size=1), ...)

似乎无法让我访问使用my_augmenter计算的功能。

我想我可以隐藏增强版x_train中的功能,在我的模型设置中立即复制它们,然后直接将它们反馈到y_true或类似的东西,但肯定必须有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

也许你可以创建一个两部分模型:

  • 内部模型:预测所需输出的原始模型
  • 外型:
    • 将y_true数据作为输入
    • 将功能作为输入
    • 输出损失本身(而不是预测数据)

因此,假设您已经定义了originalModel。让我们定义外部模型。

#this model has three inputs:
originalInputs = originalModel.input  
yTrueInputs = Input(shape_of_y_train)
featureInputs = Input(shape_of_features)

#the original outputs will become an input for a custom loss layer
originalOutputs = originalModel.output

#this layer contains our custom loss
loss = Lambda(innerLoss)([originalOutputs, yTrueInputs, featureInputs])

#outer model
outerModel = Model([originalInputs, yTrueInputs, featureInputs], loss)

现在,我们定制的内心损失:

def innerLoss(x):
    y_pred = x[0] 
    y_true = x[1]
    features = x[2] 

    .... calculate and return loss here .... 

现在,对于已经包含自定义丢失的此模型"内部"它,我们实际上并不想要最终的损失函数,但由于keras要求它,我们将最终损失用作return y_pred

def finalLoss(true,pred):
    return pred

这将允许我们训练只传递一个假人y_true

但当然,我们还需要一个自定义生成器,否则我们无法获得这些功能。

考虑您已定义originalGenerator =datagen.flow(x_train, y_train, batch_size=1)

def customGenerator(originalGenerator):

    while True: #keras needs infinite generators
        x, y = next(originalGenerator)

        features = ____extract features here____(x)

        yield (x,y,features), y 
            #the last y will be a dummy output, necessary but not used

如果您想要随机化批量订单和使用多处理的额外功能,您也可以按照相同的逻辑实现class CustomGenerator(keras.utils.Sequence)help page显示了如何。

所以,让我们编译和训练外部模型(这也训练内部模型,以便您以后可以使用它进行预测):

outerModel.compile(optimizer=..., loss=finalLoss)
outerModel.fit_generator(customGenerator(originalGenerator), batchesInOriginalGenerator, 
                         epochs=...)