在Keras中仅训练神经网络的一个输出

12

我在Keras中有一个具有多个输出的网络,然而我的训练数据每次只提供一个输出的信息。

目前我的训练方法是对所涉及的输入进行预测,在更改我正在训练的特定输出的值,然后进行单批次更新。如果我没错的话,这与将所有输出的损失设置为零,除了我正在尝试训练的那个输出是相同的。

是否有更好的方法?我尝试过使用类权重,其中我为除我正在训练的输出之外的所有输出设置了零权重,但它没有给我期望的结果?

我正在使用Theano后端。


这是一种不常见的监督学习设置。展示一些示例数据并解释一下为什么要使用这种设置。 - sascha
我正在使用它进行深度 Q-Learning。输入是一个状态,每个输出都是一个动作的分数。你选择一个动作,然后根据该动作的结果更新网络。然而,你只想更新一个输出,因为你不知道其他动作的结果... - simeon
1
我明白了。这是不同的处理方式。看看这些源代码(我在链接中标记了该行)。你只需要保留其他动作的当前值即可! - sascha
我想实现一个类似的具有多个输出的CNN(多任务学习)。我将在输入(图像)上运行网络,获取其中一个输出;然后根据输出选择另一个输出来运行网络并获得最终输出。在训练中,我每次只更新一个流。我认为这是一个非常普遍的问题,但奇怪的是,没有例子或文档描述解决方案。@simeon:你是否成功解决了你的问题?如果是,怎么做的?谢谢。 - Blackberry
我其实前几天已经做过了,只是忘记回复这篇帖子了。今晚我会提供更详细的回复。在Keras中,你可以使用相同的层创建多个模型,其中值是共享的(从我的记忆中来看,你需要使用“Sequence”的替代方法)。我基本上为每个输出创建了一个模型,这些模型共享了层。效果很好。 - simeon
2个回答

18

输出多个结果并仅优化其中一个

假设您想从多个层返回输出,可能是一些中间层,但您只需要优化一个目标输出,那么可以按照以下方式操作:

让我们从这个模型开始:

inputs = Input(shape=(784,))
x = Dense(64, activation='relu')(inputs)

# you want to extract these values
useful_info = Dense(32, activation='relu', name='useful_info')(x)

# final output. used for loss calculation and optimization
result = Dense(1, activation='softmax', name='result')(useful_info)

编译时使用多个输出,对于额外的输出设置损失为None

对于不想用于损失计算和优化的输出,请将其设置为None

model = Model(inputs=inputs, outputs=[result, useful_info])
model.compile(optimizer='rmsprop',
              loss=['categorical_crossentropy', None],
              metrics=['accuracy'])

仅在训练时提供目标输出。跳过额外的输出:

model.fit(my_inputs, {'result': train_labels}, epochs=.., batch_size=...)

# this also works:
#model.fit(my_inputs, [train_labels], epochs=.., batch_size=...)

一次预测,获取所需全部输出

只需要运行一个模型的predict方法一次,即可获得所需的所有输出:

predicted_labels, useful_info = model.predict(new_x)

1
在v2.3.0中,某种原因导致它无法正常工作,因为我收到了错误消息:“ValueError:两个结构的序列长度不相同。输入结构长度为1,而浅层结构长度为3。” - omsrisagar
当我试图将此应用于我的网络时,出现以下错误:“ValueError: 变量<tf.Variable 'name1/kernel:0' shape=(61440, 1200) dtype=float32>的梯度为 None。请确保您的所有操作都有定义梯度(即可微分)。没有梯度的常见操作:K.argmax,K.round,K.eval。” 我使用的tensorflow版本是1.14.0。我的损失是[None,''categorical_crossentropy"]。 - Cam K
@omsrisagar 是的,我也是!你有没有找到解决方案呢? - MJimitater

3
为了实现这一目标,我最终使用了“功能API”。你基本上创建多个模型,使用相同的输入和隐藏层,但不同的输出层。
例如:

https://keras.io/getting-started/functional-api-guide/

from keras.layers import Input, Dense
from keras.models import Model

# This returns a tensor
inputs = Input(shape=(784,))

# a layer instance is callable on a tensor, and returns a tensor
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions_A = Dense(1, activation='softmax')(x)
predictions_B = Dense(1, activation='softmax')(x)

# This creates a model that includes
# the Input layer and three Dense layers
modelA = Model(inputs=inputs, outputs=predictions_A)
modelA.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])
modelB = Model(inputs=inputs, outputs=predictions_B)
modelB.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

1
这里的问题是 - 你必须运行两次预测才能获得两个输出。 - Serhiy
1
@Serhiy 他可以创建第三个 predictions = Concatenate()([predictions_A, predictions_B]),并将其设置为第三个模型的输出。 - Bersan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接