Scikit-learn平衡子采样

mik*_*kom 39 python subsampling pandas scikit-learn

我正在尝试创建我的大型非平衡数据集的N个平衡随机子样本.有没有办法简单地使用scikit-learn/pandas或者我必须自己实现它?任何指向这样做的代码的指针?

这些子样本应该是随机的,并且可以重叠,因为我在非常大的分类器集合中将每个子样本提供给单独的分类器.

在Weka中有一个名为spreadsubsample的工具,sklearn中有相同的东西吗? http://wiki.pentaho.com/display/DATAMINING/SpreadSubsample

(我知道加权但这不是我想要的.)

mik*_*kom 22

这是我的第一个版本,似乎工作正常,随意复制或提出如何更高效的建议(我有一个很长的编程经验,但没有那么长的python或numpy)

此函数创建单个随机平衡子样本.

编辑:子样本大小现在采样少数类,这应该可以改变.

def balanced_subsample(x,y,subsample_size=1.0):

    class_xs = []
    min_elems = None

    for yi in np.unique(y):
        elems = x[(y == yi)]
        class_xs.append((yi, elems))
        if min_elems == None or elems.shape[0] < min_elems:
            min_elems = elems.shape[0]

    use_elems = min_elems
    if subsample_size < 1:
        use_elems = int(min_elems*subsample_size)

    xs = []
    ys = []

    for ci,this_xs in class_xs:
        if len(this_xs) > use_elems:
            np.random.shuffle(this_xs)

        x_ = this_xs[:use_elems]
        y_ = np.empty(use_elems)
        y_.fill(ci)

        xs.append(x_)
        ys.append(y_)

    xs = np.concatenate(xs)
    ys = np.concatenate(ys)

    return xs,ys
Run Code Online (Sandbox Code Playgroud)

对于任何尝试使用Pandas DataFrame进行上述工作的人,您需要进行一些更改:

  1. 更换np.random.shuffle用线

    this_xs = this_xs.reindex(np.random.permutation(this_xs.index))

  2. 用.替换np.concatenate线

    xs = pd.concat(xs) ys = pd.Series(data=np.concatenate(ys),name='target')


eic*_*erg 21

现在有一个完整的python包来解决不平衡的数据.它可以通过https://github.com/scikit-learn-contrib/imbalanced-learn作为sklearn-contrib软件包获得.


gc5*_*gc5 8

熊猫系列的一个版本:

import numpy as np

def balanced_subsample(y, size=None):

    subsample = []

    if size is None:
        n_smp = y.value_counts().min()
    else:
        n_smp = int(size / len(y.value_counts().index))

    for label in y.value_counts().index:
        samples = y[y == label].index.values
        index_range = range(samples.shape[0])
        indexes = np.random.choice(index_range, size=n_smp, replace=False)
        subsample += samples[indexes].tolist()

    return subsample
Run Code Online (Sandbox Code Playgroud)


小智 8

I found the best solutions here

And this is the one I think it's the simplest.

dataset = pd.read_csv("data.csv")
X = dataset.iloc[:, 1:12].values
y = dataset.iloc[:, 12].values

from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(return_indices=True)
X_rus, y_rus, id_rus = rus.fit_sample(X, y)
Run Code Online (Sandbox Code Playgroud)

then you can use X_rus, y_rus data

For versions 0.4<=:

from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler()
X_rus, y_rus= rus.fit_sample(X, y)
Run Code Online (Sandbox Code Playgroud)

Then, indices of the samples randomly selected can be reached by sample_indices_ attribute.


eic*_*erg 5

中公开的内置数据拆分技术中提供这种类型的数据拆分sklearn.cross_validation

看起来与您的需求相似的是sklearn.cross_validation.StratifiedShuffleSplit,它可以生成任何大小的子样本,同时保留整个数据集的结构,即精心执行相同的主数据集中不平衡。虽然这不是您要查找的内容,但您可以使用其中的代码并将强制比率始终更改为 50/50。

(如果您愿意,这可能是对 scikit-learn 的一个很好的贡献。)