-1

我有一个包含 23 个相关性非常低的特征的数据集。这两个类别之间的差异很小。

这些类别高度不平衡,就像可用于欺诈检测的数据一样。什么是采样这种数据的合适方法?

4

1 回答 1

0

感谢您来 SO 提出您的问题!

处理不平衡的数据(通常定义为一个或多个类别的案例数量与其他类别非常不同的数据——某种偏态分布)是一个持续的挑战,并且已经促使很多在线写作。我喜欢这篇文章作为起点。我将提供 Python 中的示例,尽管类似的想法也适用R

提供一个快速总结:抽样之所以重要有很多原因,其中最重要的是正确分割数据以进行训练和测试。为了过于简单化,您可以更改从数据集(样本)中提取示例的方式,以便获得每个类的机会大致相等,或者您可以尝试用更少的案例模拟该类的新示例以再次达到相等进行拆分时绘制班级的概率。

为了清楚起见,假设变量X:X = 0X = 1. 我们称X = 1这种情况发生了一些事件,出现了一些特征,观察到了一些反应,等等。我们称之为“积极类”。最后,假设您有 100,000 个观察值,其中只有 1,000 个 的情况X = 1,其余的是X = 0。因此,你的少数类是正类,你的不平衡(正到负)是 1/100。

如果您正在抽取 50,000 个随机样本,并且希望份额大致为 50/50 正负类,您可以做几件事。

  1. 过采样少数类

这种方法可以让你从数据中绘制更多的例子X = 1。为了达到 50/50 的平衡,您需要从正类中(随机)抽取更多次以达到 25,000 个示例。

为此sci-kit learn,您可以执行以下操作。

假设X您的数据是一个数据框:

from sklearn.utils import resample

# make two dataframes, each with only one class 
majority_df = X[X['outcome']==0]
minority_df = X[X['outcome']==1]

# Oversampling the minority
oversampled_minority_df = resample(minority_df,
                          replace=True, 
                          n_samples=len(majority_df), 
                          random_state=123)

几点评论:

  • “重采样”是一遍又一遍地从集合中提取数据的处理
  • replace表示您希望该过程“放回”它提取的观察结果;在这种情况下,它只是意味着系统可以在重新采样期间多次获取相同的观察结果(就像它被放回袋子中供某人抓取一样)
  • n_samples与多数类数据帧的长度相同,因此最终结果在多数/少数示例之间具有平衡

    1. 对多数类进行欠采样

既然您知道过采样少数类,这正好相反。不是重复抽样少数类直到你有与多数类相同数量的样本,这里你只取少数类的样本数量的多数类样本。

您可以按如下方式反转上述代码。仍然假设X是您的数据:

# Oversampling the minority
undersampled_majority_df = resample(majority_df,
                           replace=False, 
                           n_samples=len(minority_df), 
                           random_state=123)

几点注意事项:

  • 这仍然是“重采样”,只取更少的样本
  • replace现在是错误的,因为如果你不需要重复数据,你不想重复数据(你必须为过采样做)
  • n_samples现在匹配的长度,minority_df以便有相同数量的示例

过采样和欠采样类都带有统计问题,您可以在其他地方查看。

另一种选择是合成数据。再次过度简化统计过程,这会扰乱您拥有的数据,以使“新”示例看起来与现有数据相似,但会在过程中引入一些(有用的)噪音。

处理不平衡数据和合成数据创建的一个流行包是imblearn. 这个包本身有很多很棒的工作,但更好的是它与两者的相似sklearn程度以及两者的协同工作程度。

imblearn提供流行的方法 SMOTE,或合成少数过采样技术,以及许多其他方法。但是,在这种情况下,不是直接使用您的数据帧,而是imblearn使用 SMOTE 作为其自己的拟合过程。

from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split

y = base_df['outcome']
X = base_df.drop('outcome', axis=1)

# setting up testing and training sets
X_train, X_test, y_train, y_test = train_test_split(X,
                                                    y,
                                                    test_size=0.20,
                                                    random_state=123)

sm = SMOTE(random_state=123, ratio=1.0)
X_train, y_train = sm.fit_sample(X_train, y_train)

您会注意到该sm对象具有该fit_sample方法,并且您ratio在实例化它时设置了正/负(通过)的比例。结果是在模型拟合期间平衡且可用的数据帧。

于 2020-01-07T15:17:27.197 回答