使用scikit-learn进行子采样和分类

4
我正在进行一个二分类任务,使用Scikit-learn.. 我有: 类别0: 200个观察值 类别1: 50个观察值。
因为我有一个不平衡的数据.. 我想从多数类别中随机抽取一个子样本,使得观察数量与少数类别相同,并希望使用新获得的数据集作为分类器的输入.. 子采样和分类的过程可以重复多次.. 我有以下代码用于子采样,主要是在Ami Tavory的帮助下。
docs_train=load_files(rootdir,categories=categories, encoding='latin-1')

X_train = docs_train.data
y_train = docs_train.target

majority_x,majority_y=x[y==0,:],y[y==0]  # assuming that class 0 is the majority class
minority_x,minority_y=x[y==1,:],y[y==1]

inds=np.random.choice(range(majority_x.shape[0]),50)
majority_x=majority_x[inds,:]
majority_y=majority_y[inds]

它的运作非常出色,但是在处理majority_x和majority_y的最后,我希望能够用新的较小集合替换X_train、y_train中代表class0的旧集合,以便将其传递给分类器或管道。
pipeline = Pipeline([
    ('vectorizer',  CountVectorizer( tokenizer=tokens, binary=True)),
    ('classifier',SVC(C=1,kernel='linear')) ])

pipeline.fit(X_train, y_train)

为了解决这个问题,我尝试将两个结果数组majority_x和minority_x合并起来,以形成所需的训练数据。但是,由于这些数组是numpy数组,并且我对整个领域都很新手,我真的很努力学习…我不能成功合并它们,因为出现了一些错误,我正在努力解决…即使我能够合并它们,如何保持它们的索引,以便majority_y和minority_y也是正确的呢!

2
只是为了确保这不是一个XY问题:您是否在寻找类似于sklearn中的分层交叉验证的东西?如果有的话,也许您可以简要解释一下为什么这与通常构建CV管道以解决不平衡数据的问题不同。 - Ami Tavory
从您给我的页面示例来看,分层函数似乎总是会返回一个训练和测试集,这与我的情况不同...到目前为止,我只在训练集上工作...我想稍后提供测试集,因为它是基于不同的标准进行拆分而不是随机拆分。 - Ophilia
如果我理解你的问题(如何合并新的子采样集),你可能需要查看 numpy.concatenate((majority_x,minority_x))。另外,作为补充说明,你可能需要在 random.choice 中添加 replace=False,以防止多次采样相同的样本。 - Robin Spiess
1个回答

1
在处理完majority_x和minority_y之后,您可以将训练集合并。
X_train = np.concatenate((majority_x,minority_x))
y_train = np.concatenate((majority_y,minority_y))

现在,X_train和y_train将首先包含y=0的选择样本,然后是y=1的样本。
对于您的相关问题,一个想法是:通过创建与大多数样本数量相同长度的随机置换向量来选择大多数样本。然后选择该向量的前50个索引,然后选择下一个50个索引,以此类推。当您完成该向量时,每个样本都会被选择一次。如果您需要更多迭代或剩余置换向量太短,则可以回到随机选择。正如我在评论中提到的,如果您想要防止在一个迭代中多次使用相同的样本,则可能还需要在np.random.choice中添加参数"replace=False"。

谢谢,我已经按照你的建议做了,并且在一个小程序中一切都非常顺利...直到我将它移植到我的原始程序中...看起来原始的x_train并不像我们想象的那样是一个列表的列表!它只是一个列表,在每个项目的开头附加了'u'!我正在从文本文件中加载我的原始数据,这是原因吗?我该如何解决这个问题? - Ophilia
@user2739381 print(type(x_train)) 的输出是什么?如果它真的只是一个列表,我不认为你可以使用 majority_x = x_train[y==0,:](顺便说一下,在你的问题中,你有 majority_x = x[y==0,:],那个 x 和 x_train 是一样的吗?)你也可以尝试使用 np.array(x_train) 将列表转换为 numpy 数组,但我不确定会发生什么。 - Robin Spiess
是的,它是一个列表,我已经将其转换为numpy数组,并且我已经将大部分代码更改为majority_x = x [y == 0]..它有效了..你认为会发生什么错误吗? - Ophilia
现在concatenate是否有效?如果它是一个列表,你应该可以用majority_x + minority_x合并它们。 - Robin Spiess

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接