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

在Keras中使用ImageDataGenerator时,如何定义依赖于输入的自定义成本函数?,keras,Keras,我想定义一个自定义成本函数 def custom_objective(y_true, y_pred): .... return L 这不仅取决于y\u true和y\u pred,还取决于产生y\u pred的相应x的某些特性。我能想到的唯一方法是在y\u-true中“隐藏”相关功能,以便y\u-true=[通常的y\u-true,相关的x\u功能],或者类似的东西 在实施这一点时,我面临两个主要问题: 1) 更改y\u true的形状意味着我需要用一些垃圾填充y\u pred

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

def custom_objective(y_true, y_pred):
    ....
    return L
这不仅取决于
y\u true
y\u pred
,还取决于产生
y\u pred
的相应
x
的某些特性。我能想到的唯一方法是在
y\u-true
中“隐藏”相关功能,以便
y\u-true=[通常的y\u-true,相关的x\u功能]
,或者类似的东西

在实施这一点时,我面临两个主要问题:

1) 更改
y\u true
的形状意味着我需要用一些垃圾填充
y\u 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\u augmenter
计算的功能


我想我可以在增强的
x\u列
中隐藏特征,在我的模型设置中立即复制它们,然后直接将它们输入到
y\u-true
或类似的东西中,但肯定有更好的方法可以做到这一点?

也许您可以创建一个包含两部分的模型:

  • 内部模型:预测期望输出的原始模型
  • 外部模型:
    • 将y_真实数据作为输入
    • 将功能作为输入
    • 输出损失本身(而不是预测数据)
因此,假设您已经定义了
originalModel
。让我们定义外部模型

#此模型有三个输入:
originalInputs=originalModel.input
yTrueInputs=输入(列车的形状)
特征输入=输入(特征的形状)
#原始输出将成为自定义损耗层的输入
originalOutputs=originalModel.output
#此层包含我们的自定义丢失
损耗=λ(内部损耗)([OriginalOutput,yTrueInputs,featureInputs])
#外部模型
最外层模型=模型([初始输入、初始输入、特征输入],损耗)
现在,我们的自定义内部损失:

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

    .... calculate and return loss here .... 
现在,对于已经包含“内部”自定义损耗的模型,我们实际上不需要最终损耗函数,但由于keras需要它,我们将使用最终损耗作为返回y_pred:

def finalLoss(true,pred):
    return pred
这将允许我们训练通过一个虚拟
y\u true


当然,我们还需要一个定制的生成器,否则我们无法获得这些特性

假设您已经定义了
originalGenerator=datagen.flow(x\u列,y\u列,批量大小=1)

def自定义生成器(原始生成器):
尽管如此:#keras需要无限的生成器
x、 y=下一个(原始发电机)
features=\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
产量(x,y,特征),y
#最后一个y将是一个虚拟输出,必要但未使用
如果您想要随机批处理顺序的额外功能并使用多处理,还可以按照相同的逻辑实现
类CustomGenerator(keras.utils.Sequence)
。这说明了如何

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

outerModel.compile(优化器=…,loss=finalLoss)
外部模型装配发电机(客户发电机(原始发电机)、批次原始发电机、,
时代=…)

可能。谢谢您的详细回答!我正试着把我的头都绕过去。。。我目前在
loss=Lambda(innerLoss)([originalOutputs,yTrueInputs,featureInputs])
中遇到一个错误,说“Layer Lambda_1是用一个非符号张量的输入调用的。”列表中的某些内容不是张量。如果你完全遵循我的代码,那就不会发生。注意原始模型输出的行。原始模型有多个输出吗?我不确定“多个”是什么意思,但原始模型输出一个图像(它是一个自动编码器)。最后一层是
decoded=Conv2D(1,(3,3),activation='sigmoid',padding='same')(x)
。下面是完整的错误:
layer lambda_2是用非符号张量的输入调用的。收到的类型:。完整输入:[[],]。层的所有输入都应该是张量。