类别不均衡处理办法总结

深度学习中数据量不平衡是常见问题,本文总结了解决样本类别不均衡的方法,包括过采样欠采样、创造数据、合并新的少数类别、调整类权重、更改损失函数(Focal Loss)、更改评价标准以及提高判别阈值等,并给出部分方法的代码链接和适用场景。
部署运行你感兴趣的模型镜像

   对于深度学习而言,数据量不平衡是很常见的问题,如:工厂的产品缺陷率一般在 0.1% 左右,患者病例比较少等。最近遇到个项目,样本类别极其不均衡,多的类别有上万张,少的仅有几百张,为了有好的训练效果,尝试了很多方法,在这篇博客总结下我使用的,还有见到的一些方法。

一、过采样欠采样

   既然不平衡,那就想办法让他平衡,增加数据和减少数据。一般的方法是过采样和欠采样。

  过采样的意思就是:把少数类别数量重复利用,相当于某个类别100张,复制后,数据量就成为200张。不过这种方法不推荐,可能会造成过拟合。最好是通过数据增强的方式来对少数类别的数量进行数据扩充。数据增强方式与代码:链接

  欠采样的意思就是:数据量大的类别数据并不是全部都使用,比如一万张图像,使用三四千张来作为训练数据。根据自己的数据量进行调整,尽量平衡。我就是使用了这个方法。

二、创造数据

  既然有一些类别数量很少,就想办法创造数据、生成数据。能尽量想办法找数据就找,一些公共数据集,或者去谷歌爬虫一些图片(谷歌爬虫方法链接

  方法1:根据自己数量特征,想办法生成不同的背景。即保留特征,换背景(这种生成数据方法一般适用于类别数据特征比较明显,易分割)

  方法2:SMOTE 及其衍生技术。这是个算法,我没用过,不过看到很多地方都提到这个算法,网上有实线,倒是可以试一试。

三、合并新的少数类别

意思是根据自己的项目,将一些数据量少的类别进行一定的合并,比如,自行车、摩托车,统称为非机动车类别。根据自己需求来更改。

四、调整类权重

如果类别不均衡很严重,神经网络会倾向与数据量大的类别进行预测,这显然不是我们想要的效果,所以需要对不同类别设置不同的重要程度,少类数据量少,我们更加应该关注。故需要对数据量少的类别加大权重

方法1:更改交叉商损失

交叉熵公式如下

在tensorflow中的函数是:tf.nn.softmax_cross_entropy_with_logits(logits=prediction,labels=y)

我们需要对类别设置一定的权重,设置的比例最好是与不同类别数据量比例相反。比如三类的数据量,100,200,300这样我们需要设置的比例为3:2:1.如下面代码所示。这样对数据量少的类别加大了损失权重。这个方法可以使用多类别。

class_weight = tf.constant([3,2,1])
y_class_weight = y*class_weight
loss = -tf.reduce_mean(y_class_weight*tf.log(yprediction))

该方法我试过,不过没有很好的效果,当然这个比例是要调参的,没有放之四海皆准的。

方法2:更换交叉商函数

官方函数:tf.nn.weighted_cross_entropy_with_logits 

之前普通的交叉熵函数定义为:

 

[公式]

就是在交叉熵的公式里面对应的少数类乘上一个系数:
​​​该函数实现的是:如果pos_weights > 1减小了错误负样本的权重,因此提高了recall。相反如果pos_weights < 1减小了错误正样本的权重,因此提高了precision。pos_weight是作为损失表达式中正目标项的乘法系数引入的。

[公式]

该方法也是不错的,不过我认为这个方法只适用于两类,正负样本,比如用于目标检测解决正负样本不均衡的问题,或者语义分割,如车道线检测。对于多分类效果好像没用,我试了下。

五、更改损失函数(Focal Loss)

论文:Focal Loss for Dense Object Detection 
论文链接:https://arxiv.org/abs/1708.02002 

  将损失函数更改为Focal Loss。这个损失是恺明大神提出来的。主要是来解决目标检测中正负样本不均衡的问题,这个损失函数是在标准交叉熵损失基础上修改得到的。这个函数可以通过减少易分类样本的权重,使得模型在训练时更专注于难分类的样本.这个函数已经有实现如下:

pytorch:https://github.com/clcarwin/focal_loss_pytorch

tensorflow:https://github.com/ailias/Focal-Loss-implement-on-Tensorflow

mxnet:https://github.com/unsky/focal-loss

如果需要看Focal Loss损失函数讲解,推荐一个博客:https://blog.youkuaiyun.com/u014380165/article/details/77019084

六、更改评价标准

  评价标准很重要,因为如果你不知道该如何正确度量你的成果,你也就不能取得进展。当然既然样本都不均衡了,肯定不能使用单一的准确率来评价模型是否好了,比如使用:召回率、F1分数、一个 ROC 曲线、准确度召回曲线(precision-recall curve)等。西瓜上上有详细解析。

F1 分数(F1 Score):是准确度(precision)和召回率(recall)的调和平均值

ROC 曲线下的面积(AUC):是一个很好的一般统计。它等于一个随机的正面样本将得到比一个随机的负面样本更高排名的概率。

七、提高一些判别阈值

   当你得到概率估计之后,不要盲目地使用 0.50 的决策阈值来区分类别,提高一点。

 

您可能感兴趣的与本文相关的镜像

GPT-oss:20b

GPT-oss:20b

图文对话
Gpt-oss

GPT OSS 是OpenAI 推出的重量级开放模型,面向强推理、智能体任务以及多样化开发场景

<think>好的,我现在需要帮用户解决样本不均衡的问题。用户提到了机器学习中的数据不均衡,并且希望知道最佳实践。首先,我应该回顾一下用户提供的引用资料,看看里面提到了哪些方法。 引用[1]里提到数据增强、SMOTE过采样和TomekLinks欠采样数据增强可以增加少数类的样本,比如在图像处理中旋转、翻转图片,或者在NLP中同义词替换。SMOTE是通过生成合成样本来平衡数据,而TomekLinks则是去除多数类中的冗余样本,这对提高模型区分边界可能有帮助。 引用[2]提到集成学习方法,比如EasyEnsemble和BalanceCascade。EasyEnsemble通过对多数类进行多次欠采样并训练多个模型,最后集成结果。BalanceCascade则是逐步剔除被正确分类的多数类样本,这可能更高效。另外,用户还提到了imblearn库,这应该是处理不平衡数据的重要工具,需要推荐使用。 引用[3]指出样本不均衡是实际项目中的常见问题,可能影响模型性能,导致偏向多数类。因此,除了采样方法,可能还需要结合调整类别权重或选择更适合的评估指标,比如F1-score或者AUC-ROC。 接下来,我需要整理这些方法,分步骤说明。首先应该是数据层面的方法,比如过采样欠采样数据增强。然后是算法层面的调整,比如代价敏感学习和集成方法。最后是评估指标的选择,避免准确率的误导。 需要注意的是,不同方法适用于不同场景。例如,过采样可能在数据不足时有用,但可能过拟合;欠采样适用于数据量大的多数类,但可能丢失信息。集成方法结合了多次采样的优点,可能更稳定。另外,调整类别权重在树模型或SVM中比较有效,比如class_weight参数。 用户可能需要具体的实施步骤,比如使用imblearn库中的SMOTE或RandomUnderSampler,或者集成方法中的EasyEnsemble。还要提醒他们评估时不要只看准确率,而是关注召回率、F1等。 是否遗漏了什么?比如混合采样(结合过采样欠采样),或者使用异常检测算法?不过根据提供的引用,可能集中在提到的几种方法。另外,数据增强的具体应用可能需要根据数据类型来处理,比如图像、文本、结构化数据的不同策略。 总结起来,回答的结构应该是分步骤的最佳实践,包括数据采样、算法调整、集成方法、评估指标,并结合引用中的方法给出具体例子。还要注意推荐相关库,比如imblearn,并说明不同方法的适用场景,帮助用户选择最合适的策略。</think>### 解决样本不均衡问题的最佳实践 #### 一、数据层面的处理 1. **过采样(Oversampling)** - **SMOTE算法**:通过插值生成少数类样本的合成数据,避免简单复制导致的过拟合。例如,使用`imblearn`库中的`SMOTE`实现: ```python from imblearn.over_sampling import SMOTE X_resampled, y_resampled = SMOTE().fit_resample(X, y) ``` - **数据增强**:针对图像或文本数据,通过旋转、裁剪、同义词替换等方式扩展少数类样本[^1]。 2. **欠采样(Undersampling)** - **TomekLinks**:移除多数类中与少数类样本相邻的冗余样本,优化分类边界。 - **随机欠采样**:随机删除多数类样本,适用于多数类数据量大的场景。 3. **混合采样(Hybrid Sampling)** 结合过采样欠采样,例如先使用SMOTE生成样本,再用TomekLinks清理噪声。 --- #### 二、算法层面的调整 1. **代价敏感学习(Cost-Sensitive Learning)** 为不同类别分配不同的误分类代价。例如,在逻辑回归或支持向量机中设置`class_weight='balanced'`参数: ```python from sklearn.svm import SVC model = SVC(class_weight='balanced') ``` 2. **集成学习方法** - **EasyEnsemble**:将多数类样本划分为多个子集,每个子集与少数类样本组合训练多个基分类器,最后集成结果。 - **BalanceCascade**:逐步剔除被正确分类的多数类样本,提升模型对少数类的关注度[^2]。 --- #### 三、评估指标优化 避免使用准确率(Accuracy),选择更能反映不平衡数据表现的指标: - **F1-score**:综合召回率和精确率的调和平均。 - **AUC-ROC曲线**:评估模型对类别分离的整体能力。 - **G-Mean**:几何平均召回率,适用于极端不平衡场景。 --- #### 四、实践建议 1. **优先尝试数据增强与SMOTE**:在小样本场景下,合成样本能显著提升模型性能[^1]。 2. **结合集成方法**:例如`imblearn`中的`BalancedRandomForest`或`RUSBoost`,直接处理不均衡数据[^2]。 3. **调整损失函数权重**:深度学习框架(如TensorFlow、PyTorch)中可通过加权交叉熵损失函数平衡类别。 --- ### 示例代码(SMOTE + 随机森林) ```python from imblearn.pipeline import Pipeline from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split pipeline = Pipeline([ ('smote', SMOTE(random_state=42)), ('classifier', RandomForestClassifier(class_weight='balanced')) ]) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) pipeline.fit(X_train, y_train) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值