如何为 Keras 中的不平衡类设置类权重?

数据挖掘 深度学习 分类 喀拉斯 加权数据
2021-09-23 19:15:58

我知道 Keras 有可能class_weights在拟合时使用参数字典,但我找不到任何示例。有人会这么好心提供一个吗?

顺便说一句,在这种情况下,适当的实践只是简单地根据少数群体的代表性不足对少数群体进行加权?

4个回答

您可以简单地实现class_weightfrom sklearn

  1. 我们先导入模块

    from sklearn.utils import class_weight
    
  2. 为了计算班级权重,请执行以下操作

    class_weights = class_weight.compute_class_weight('balanced',
                                                     np.unique(y_train),
                                                     y_train)
    
  3. 第三也是最后将其添加到模型拟合中

    model.fit(X_train, y_train, class_weight=class_weights)
    

注意:我编辑了这篇文章并将变量名从class_weight 更改class_weight s,以免覆盖导入的模块。从注释中复制代码时进行相应调整。

如果您谈论的是常规情况,即您的网络仅产生一个输出,那么您的假设是正确的。为了强制您的算法将1 类的每个实例视为0类的 50 个实例,您必须:

  1. 使用您的标签及其相关权重定义字典

    class_weight = {0: 1.,
                    1: 50.,
                    2: 2.}
    
  2. 将字典作为参数提供:

    model.fit(X_train, Y_train, nb_epoch=5, batch_size=32, class_weight=class_weight)
    

编辑:“将1 类的每个实例视为0类的 50 个实例”意味着在您的损失函数中,您为这些实例分配了更高的值。因此,损失变为加权平均值,其中每个样本的权重由class_weight及其对应的类指定。

来自Keras 文档

class_weight:可选字典将类索引(整数)映射到权重(浮点)值,用于加权损失函数(仅在训练期间)。

我将这种规则用于class_weight

import numpy as np
import math

# labels_dict : {ind_label: count_label}
# mu : parameter to tune 

def create_class_weight(labels_dict,mu=0.15):
    total = np.sum(list(labels_dict.values()))
    keys = labels_dict.keys()
    class_weight = dict()
    
    for key in keys:
        score = math.log(mu*total/float(labels_dict[key]))
        class_weight[key] = score if score > 1.0 else 1.0
    
    return class_weight

# random labels_dict
labels_dict = {0: 2813, 1: 78, 2: 2814, 3: 78, 4: 7914, 5: 248, 6: 7914, 7: 248}

create_class_weight(labels_dict)

math.log平滑非常不平衡的类的权重!这返回:

{0: 1.0,
 1: 3.749820767859636,
 2: 1.0,
 3: 3.749820767859636,
 4: 1.0,
 5: 2.5931008483842453,
 6: 1.0,
 7: 2.5931008483842453}

class_weight很好,但正如@Aalok 所说,如果你是单热编码多标签类,这将不起作用。在这种情况下,使用sample_weight

sample_weight: 与 x 长度相同的可选数组,包含应用于每个样本的模型损失的权重。在时间数据的情况下,您可以传递一个形状为 (samples, sequence_length) 的二维数组,以对每个样本的每个时间步应用不同的权重。在这种情况下,您应该确保 sample_weight_mode="temporal"compile().

sample_weights用于为每个训练样本提供一个权重这意味着您应该传递一个元素数量与训练样本相同的一维数组(表示每个样本的权重)。

class_weights用于为每个输出类提供权重或偏差这意味着您应该为您尝试分类的每个类传递一个权重。

sample_weight 必须给定一个 numpy 数组,因为它的形状将被评估。

另请参阅此答案