不平衡多分类场景下如何基于类别频率通过sklearn计算类别权重向量
可以通过sklearn生成符合需求的类别权重向量,具体实现方式如下:
方法1:直接调用sklearn内置接口
sklearn的compute_class_weight函数默认的balanced模式计算逻辑刚好匹配你的需求:样本占比越高的类别分配的权重越低,少数类分配的权重越高,计算规则为:单类别权重 = 总样本数 / (类别总数 * 对应类别样本数)。
具体代码示例:
from sklearn.utils.class_weight import compute_class_weight import numpy as np # 你的原始参数 classLabelList = [0, 1, 2, 3] classFrequencyList = [150751, 79995, 65858, 69102] # 构造标签数组:每个类别标签重复对应样本数量次 y = np.concatenate([np.full(fill_value=label, shape=freq) for label, freq in zip(classLabelList, classFrequencyList)]) # 计算平衡类别权重 class_weights = compute_class_weight( class_weight="balanced", classes=np.array(classLabelList), y=y ) # 输出结果顺序和classLabelList一一对应,你的场景输出近似为:[0.607, 1.143, 1.388, 1.323] print(class_weights)
方法2:手动实现等价逻辑(更省内存)
如果样本量级极大,构造全量标签数组会占用过多内存,可以直接按照上述计算规则手动计算,结果和sklearn接口输出完全一致:
classLabelList = [0, 1, 2, 3] classFrequencyList = [150751, 79995, 65858, 69102] total_samples = sum(classFrequencyList) n_classes = len(classLabelList) class_weights = [total_samples / (n_classes * freq) for freq in classFrequencyList]
损失适配说明
后续要将权重用到CategoricalCrossentropy损失中时:
- 如果使用Keras框架,直接在
model.fit()方法中传入class_weight=dict(zip(classLabelList, class_weights))参数即可自动生效 - 如果自定义损失逻辑,将每个类别的损失值乘以对应类别的权重再求和即可
内容的提问来源于stack exchange,提问作者Stupid420
相关产品推荐
相关产品推荐

