处理数据不平衡问题
1. 传统方法
1.1 随机过采样
随机过采样的核心思想,就是随机的复制、重复少数类样本,最终使得少数类与多数类的个数相同从而得到一个新的均衡的数据集。
但是这样做很容易引起“过拟合”问题
1.2 欠采样
丢弃大量数据,和过采样一样会存在过拟合的问题。
1.3 数据合成
SMOTE(Synthetic Minority Oversampling Technique)即合成少数类过采样技术,它是基于随机过采样算法的一种改进方案,SMOTE算法的基本思想是对少数类样本进行分析并根据少数类样本人工合成新样本添加到数据集中。
其思想是:对于少数类样本a, 随机选择一个最近邻的样本b, 然后从a与b的连线上随机选取一个点c作为新的少数类样本。
2. 利用keras中的fit方法里的参数
2.1 class_weight
参数类型为字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)。该参数在处理非平衡的训练数据(某些类的训练样本数很少)时,可以使得损失函数对样本数不足的数据更加关注。
2.1.1 利用sklearn.utils.class_weight来计算权重
代码实现:
from sklearn.utils import class_weight
import pandas as pd
train_df = pd.read_csv("input/train.csv")
x_train = train_df['Image']
y_train = train_df['Class']
class_weight = class_weight.compute_class_weight('balanced',
np.unique(y_train),
y_train)
cw = dict(enumerate(class_weight))
2.1.2 计算total_num/sample_num*t来设置权重
代码实现:
import math
# 权重超参数
mu = 0.15
def create_class_weight(labels_dict, mu):
keys = labels_dict.keys()
class_weight = dict()
for key in keys:
score = math.log(mu * num_train_sample / float(labels_dict[key]))
class_weight[key] = score if score > 1.0 else 1.0
return class_weight
labels_dict = {0: 28,
1: 12,
2: 5}
cw = create_class_weight(labels_dict, mu)
2.2 sample_weight
权值的numpy array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode=‘temporal’。
2.3 注意的点
1.sample_weight会覆盖class_weight,所以二者用其一;
2.如果仅仅是类不平衡,则使用class_weight,sample_weights则是类内样本之间还不平衡的时候使用。
3.keras已经在新版本中加入了 class_weight = ‘auto’。
设置了这个参数后,keras会自动设置class weight让每类的sample对损失的贡献相等。
4.在设置类别权重的时候,类别序列可以使用.class_indices获取。
print(train_generator.class_indices)
keras官方中文文档中有关fit函数的部分
https://keras-cn.readthedocs.io/en/latest/legacy/models/model/
参考博客
https://blog.csdn.net/weixin_38385446/article/details/88948076
https://blog.csdn.net/ssswill/article/details/90203428
简书
https://www.jianshu.com/p/e0b5941b74b9
https://www.jianshu.com/p/4d2c648bc589