复制训练示例以处理 pandas 数据框中的类不平衡

Posted

技术标签:

【中文标题】复制训练示例以处理 pandas 数据框中的类不平衡【英文标题】:Duplicating training examples to handle class imbalance in a pandas data frame 【发布时间】:2018-06-30 13:59:17 【问题描述】:

我在 pandas 中有一个包含训练示例的 DataFrame,例如:

   feature1  feature2  class
0  0.548814  0.791725      1
1  0.715189  0.528895      0
2  0.602763  0.568045      0
3  0.544883  0.925597      0
4  0.423655  0.071036      0
5  0.645894  0.087129      0
6  0.437587  0.020218      0
7  0.891773  0.832620      1
8  0.963663  0.778157      0
9  0.383442  0.870012      0

我使用:

import pandas as pd
import numpy as np

np.random.seed(0)
number_of_samples = 10
frame = pd.DataFrame(
    'feature1': np.random.random(number_of_samples),
    'feature2': np.random.random(number_of_samples),
    'class':    np.random.binomial(2, 0.1, size=number_of_samples), 
    ,columns=['feature1','feature2','class'])

print(frame)

如您所见,训练集是不平衡的(8 个样本属于 0 类,而只有 2 个样本属于 1 类)。我想对训练集进行过采样。具体来说,我想复制第 1 类的训练样本,以使训练集保持平衡(即,第 0 类的样本数量与第 1 类的样本数量大致相同)。我该怎么做?

理想情况下,我想要一个可以推广到多类设置的解决方案(即,类列中的整数可能大于 1)。

【问题讨论】:

frame.groupby('class', group_keys=False).apply(lambda x: x.sample(10, replace=True)) 这样的东西会起作用吗(因为理论上它的替换参数设置为True,它可能不会对类中的所有唯一项进行采样)还是您在寻找手动复制? @ayhan 谢谢,它看起来不错,除了你提到的它可能不会对一个类中的所有独特项目进行抽样。你觉得有什么办法吗?另外,手动复制是什么意思? 【参考方案1】:

您可以使用

找到组的最大大小
max_size = frame['class'].value_counts().max()

在您的示例中,这等于 8。对于每个组,您可以使用替换 max_size - len(group_size) 元素进行采样。这样,如果您将它们连接到原始 DataFrame,它们的大小将相同,并且您将保留原始行。

lst = [frame]
for class_index, group in frame.groupby('class'):
    lst.append(group.sample(max_size-len(group), replace=True))
frame_new = pd.concat(lst)

您可以使用max_size-len(group) 并可能添加一些噪音,因为这将使所有组大小相等。

【讨论】:

以上是关于复制训练示例以处理 pandas 数据框中的类不平衡的主要内容,如果未能解决你的问题,请参考以下文章

如何从 python pandas 中的另一个数据框中检索数据? [复制]

如何使用 Pandas 的条件删除数据框中的某些行? [复制]

如何从 imdb 获取更多信息并将其保存在 pandas 数据框中? [复制]

pandas:如何将列表存储在数据框中? [复制]

为啥我的代码没有从 Pandas 数据框中选择数据? [复制]

Pandas 数据框中的随机行选择