为端到端 CNN 组合不同的基本事实时处理输入

Handling input when combining different ground truth for end-to-end CNNs

我希望设计一个端到端的 CNN 来提取三个特征:事物 A 的分割和分叉,以及事物 B 的检测。将有一个共同的权重主干,然后三个分支有自己的三种特征类型的权重,然后分支将被合并。我希望通过自定义随机梯度体面函数来实现这一点。

我需要合并相同主题的不同数据集,其中每个图像包含 A 和 B,但不同的数据集包含不同的基本事实。我希望为每个图像添加一个额外的向量,指示三个基本事实中的哪一个可用(例如 [0 0 1])。这样一来,公共权重 w_0 将始终更新,但各个分支权重 w_t 知道在遇到不合适的图像时忽略不合适的图像,甚至在批次中没有遇到足够的图像时忽略合适的图像。

问题是我不确定如何处理。

我正在考虑用 Lasagne 中的 Theano 来做这件事,而不是我的初衷是 Keras,因为 Keras 的抽象层次更高。如果事物 B 过于复杂,也可以忽略对事物 B 的检测。

所以,你有两种不同的基本事实形状。

但既然它们是“真相”,它们就应该放在 Y 边,而不是 X 边。

假设A的分割结果是一个与输入图像大小相同的二维(边,边)矩阵,分叉的结果是一维(2,)数组,你可以这样做:

创建具有两个输出的模型

#this is the data you already have

batch = the amount of training images you have
side = the size in pixels of one side of your training images

segTruth = your truth images for segmentation, shaped (batch,side,side)     
bifTruth = your truth coordinates for bifurcations, shaped (batch,2)   
trainImages = your training images, shaped (batch,side,side)    

现在,让我们创建主干:

from keras.models import Model
from keras.layers import *

inp = Input((side,side))
x = Convolution2D(blablabla)(inp)
x = AnyOtherLayerYouNeed(blablabla)(x)
....
trunkOut = TheLastTrunkLayer(balblabla)(x)

现在,我们拆分模型:

b1 = FirstLayerInBranch1(blablaba)(trunkOut)
b2 = FirstLayerInBranch2(blablabl)(trunkOut)

....

out1 = LastLayerInBranch1(blablabla)(b1)    
out2 = LastLayerInBranch2(blablabla)(b2)

最后,当我们定义模型时,我们传递两个输出:

model = Model(inp, [out1,out2])

编译的时候可以定义loss = [lossfunction1, lossfunction2]。或者简单地给出一个对两个输出都相同的损失函数。

并且在训练时,也在列表中传递真值:

model.fit(trainImages, [segTruth,bifTruth],.....)

如您所见,结果没有合并,模型有两个输出。每个输出都有单独的损失函数。

如果您确实需要合并输出,那将是一项非常复杂的任务,因为它们具有不同的形状。如果您需要一个损失函数更重要,您可以在 compile 调用中传递 loss_weights 参数。

分别训练每一侧:

如果您只想使用一个分支进行训练或预测,您只需创建一个新的Model,无需更改任何层:

modelB1 = Model(inp, out1)    
modelB2 = Model(inp, out2)   

因此,假设您只有一组特定图像的“bifTruth”。然后只需使用 modelB2 进行训练。它根本不考虑其他分支。

在训练之前,您必须 compile 每个模型。但是它们的权重对于所有三个模型(model、modelB1 和 modelB2)都是通用的。

如果你希望模型的某些部分在训练时保持不变,你可以在编译之前去每个model.layer[i]并制作它们的.trainable = False。 (这不会更改已编译的模型)。