gpt4 book ai didi

machine-learning - keras 中使用类权重的 U-net 的自定义损失函数 : `class_weight` not supported for 3+ dimensional targets

转载 作者:太空宇宙 更新时间:2023-11-03 19:44:50 24 4
gpt4 key购买 nike

这是我正在使用的代码(主要从 Kaggle 中提取):

inputs = Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))
...
outputs = Conv2D(4, (1, 1), activation='sigmoid') (c9)

model = Model(inputs=[inputs], outputs=[outputs])
model.compile(optimizer='adam', loss='dice', metrics=[mean_iou])

results = model.fit(X_train, Y_train, validation_split=0.1, batch_size=8, epochs=30, class_weight=class_weights)

我有 4 个非常不平衡的类。 A 级 = 70%,B 级 = 15%,C 级 = 10%,D 级 = 5%。不过,我最关心的是 D 类。因此,我进行了以下类型的计算:D_weight = A/D = 70/5 = 14 等等,计算 B 类和 A 类的权重。(如果有更好的方法来选择这些权重,然后随意)

在最后一行中,我尝试正确设置 class_weights,并且这样做:class_weights = {0: 1.0, 1: 6, 2: 7, 3: 14}.

但是,当我这样做时,出现以下错误。

class_weight not supported for 3+ dimensional targets.

我是否可以在最后一层之后添加一个密集层,并将其用作虚拟层,以便我可以传递 class_weights,然后仅使用最后一个 conv2d 层的输出来进行预测?

如果这是不可能的,我将如何修改损失函数(我知道这个 post ,但是,仅将权重传递给损失函数不会削减它,因为损失函数是每个类(class)分别打电话)?目前,我正在使用以下损失函数:

def dice_coef(y_true, y_pred):
smooth = 1.
y_true_f = K.flatten(y_true)
y_pred_f = K.flatten(y_pred)
intersection = K.sum(y_true_f * y_pred_f)
return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)

def bce_dice_loss(y_true, y_pred):
return 0.5 * binary_crossentropy(y_true, y_pred) - dice_coef(y_true, y_pred)

但我没有看到任何可以输入类别权重的方法。如果有人想要完整的工作代码,请参阅此 post 。但请记住将最终 conv2d 层的 num 类更改为 4 而不是 1。

最佳答案

您始终可以自己应用权重。

下面的originalLossFunc可以从keras.losses导入。
weightsList 是您的列表,其中包含按类别排序的权重。

def weightedLoss(originalLossFunc, weightsList):

def lossFunc(true, pred):

axis = -1 #if channels last
#axis= 1 #if channels first


#argmax returns the index of the element with the greatest value
#done in the class axis, it returns the class index
classSelectors = K.argmax(true, axis=axis)
#if your loss is sparse, use only true as classSelectors

#considering weights are ordered by class, for each class
#true(1) if the class index is equal to the weight index
classSelectors = [K.equal(i, classSelectors) for i in range(len(weightsList))]

#casting boolean to float for calculations
#each tensor in the list contains 1 where ground true class is equal to its index
#if you sum all these, you will get a tensor full of ones.
classSelectors = [K.cast(x, K.floatx()) for x in classSelectors]

#for each of the selections above, multiply their respective weight
weights = [sel * w for sel,w in zip(classSelectors, weightsList)]

#sums all the selections
#result is a tensor with the respective weight for each element in predictions
weightMultiplier = weights[0]
for i in range(1, len(weights)):
weightMultiplier = weightMultiplier + weights[i]


#make sure your originalLossFunc only collapses the class axis
#you need the other axes intact to multiply the weights tensor
loss = originalLossFunc(true,pred)
loss = loss * weightMultiplier

return loss
return lossFunc
<小时/>

编译中使用它:

model.compile(loss= weightedLoss(keras.losses.categorical_crossentropy, weights), 
optimizer=..., ...)

直接在输入数据上更改类别平衡

您也可以更改输入样本的平衡。

例如,如果您有 5 个来自类别 1 的样本和来自类别 2 的 10 个样本,请在输入数组中传递两次类别 5 的样本。

使用sample_weight参数。

您也可以“按样本”工作,而不是“按类别”工作。

为输入数组中的每个样本创建一个权重数组:len(x_train) == len(weights)

并将该数组fit传递给sample_weight参数。
(如果是 fit_generator,则生成器必须返回权重以及训练/真实对:返回/yield 输入、目标、权重)

关于machine-learning - keras 中使用类权重的 U-net 的自定义损失函数 : `class_weight` not supported for 3+ dimensional targets,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60207583/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com