Keras:class_weight 实际上试图平衡啥?

Posted

技术标签:

【中文标题】Keras:class_weight 实际上试图平衡啥?【英文标题】:Keras: what does class_weight actually try to balance?Keras:class_weight 实际上试图平衡什么? 【发布时间】:2018-12-28 04:51:07 【问题描述】:

我的数据存在严重的类别不平衡。大约 99.99% 的样本是阴性的;积极因素(大致)在其他三个类别中平均分配。我认为我正在训练的模型基本上一直都在预测大多数类别。出于这个原因,我正在尝试对课程进行加权。

型号

model = Sequential()

#Layer 1
model.add(Conv1D( choice([32, 64, 90, 128]), choice([3, 4, 5, 6, 8]), activation='relu', kernel_initializer=kernel_initializer, input_shape=X_train.shape[1:]))
model.add(BatchNormalization())

#Layer 2
model.add(Conv1D(choice([32, 64, 90, 128]), choice([3, 4, 5, 6]), activation='relu',kernel_initializer=kernel_initializer))
model.add(Dropout(uniform(0, 0.9)))

#Flatten
model.add(Flatten())

#Output
model.add(Dense(4, activation='softmax'))

... 与Hyperas 一起使用。)

我是如何尝试称重的

\1。在model.fit() 中使用class_weight

model.fit(X_train, Y_train, batch_size=64, epochs=10, verbose=2, validation_data=(X_test, Y_test), class_weight=0: 9999, 1:9999, 2: 9999, 3:1)

\2。在model.fit() 中使用class_weightsklearn compute_class_weight()

model.fit(..., class_weight=class_weight.compute_class_weight("balanced", np.unique(Y_train), Y_train)

\3。带有自定义损失函数

from keras import backend as K
def custom_loss(weights):
    #gist.github.com/wassname/ce364fddfc8a025bfab4348cf5de852d

    def loss(Y_true, Y_pred):
        Y_pred /= K.sum(Y_pred, axis=-1, keepdims=True)
        Y_pred = K.clip(Y_pred, K.epsilon(), 1 - K.epsilon())

        loss = Y_true * K.log(Y_pred) * weights
        loss = -K.sum(loss, -1)
        return loss

    return loss

extreme_weights = np.array([9999, 9999, 9999, 1])
model.compile(loss=custom_loss(extreme_weights),
            metrics=['accuracy'],
            optimizer=choice(['rmsprop', 'adam', 'sgd','Adagrad','Adadelta'])
            )

#(then fit *without* class_weight)

结果

可怜。所有类的准确度为 ~.99,所有类的不平衡准确度为 ~.5。但更有意义的指标,如 auPRC,讲述的是不同的故事。大多数类的 auPRC 接近1,其余的接近0

这就是 Keras 平衡类的方式吗?它只是确保它们之间的准确性是相同的——或者任何一个指标也应该相等或可比?还是我指定的权重有误?

【问题讨论】:

【参考方案1】:

Keras 在训练期间使用类权重,但准确度并​​不能反映这一点。准确度是针对所有样本计算的,与类之间的权重无关。这是因为您在 compile() 中使用了度量标准“准确度”。您可以定义自定义且更准确的加权准确度并使用它或使用 sklearn 指标(例如 f1_score() 可以是“二进制”、“加权”等)。

例子:

def macro_f1(y_true, y_pred):
     return f1_score(y_true, y_pred, average='macro')


model.compile(loss=custom_loss(extreme_weights),
        metrics=['accuracy', macro_f1],
        optimizer=choice(['rmsprop', 'adam', 'sgd','Adagrad','Adadelta'])
        )

【讨论】:

以上是关于Keras:class_weight 实际上试图平衡啥?的主要内容,如果未能解决你的问题,请参考以下文章

不平衡数据的 class_weight - Keras

keras中model.compile的参数'weighted_metrics'和model.fit_generator的参数'class_weight'之间的区别?

如何为 Keras 计算 Pandas DataFrame 的类权重?

如何为Keras计算Pandas DataFrame的类权重?

class_weight 在 linearSVC 和 LogisticRegression 的损失函数中的作用

keras中二元分类的类不平衡