【问题标题】:Trying to balance my dataset through sample_weight in scikit-learn试图通过 scikit-learn 中的 sample_weight 平衡我的数据集
【发布时间】:2015-10-20 05:30:42
【问题描述】:

我正在使用 RandomForest 进行分类,我得到了一个不平衡的数据集,如:5830-否,1006-是。我尝试用 class_weight 和 sample_weight 平衡我的数据集,但我做不到。

我的代码是:

X_train,X_test,y_train,y_test = train_test_split(arrX,y,test_size=0.25)
cw='auto'
clf=RandomForestClassifier(class_weight=cw) 
param_grid = { 'n_estimators': [10,50,100,200,300],'max_features': ['auto', 'sqrt', 'log2']}
sw = np.array([1 if i == 0 else 8 for i in y_train])
CV_clf = GridSearchCV(estimator=clf, param_grid=param_grid, cv= 10,fit_params={'sample_weight': sw})

但是当使用 class_weight 和 sample_weight 时,我的比率 TPR、FPR、ROC 没有任何改善。

为什么?我做错什么了吗?

不过,如果我使用称为 balance_subsample 的函数,我的比率会得到很大的改善:

def balanced_subsample(x,y,subsample_size):

    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 

我的新代码是:

X_train_subsampled,y_train_subsampled=balanced_subsample(arrX,y,0.5)
X_train,X_test,y_train,y_test = train_test_split(X_train_subsampled,y_train_subsampled,test_size=0.25)
cw='auto'
clf=RandomForestClassifier(class_weight=cw) 
param_grid = { 'n_estimators': [10,50,100,200,300],'max_features': ['auto', 'sqrt', 'log2']}
sw = np.array([1 if i == 0 else 8 for i in y_train])
CV_clf = GridSearchCV(estimator=clf, param_grid=param_grid, cv= 10,fit_params={'sample_weight': sw})

谢谢

【问题讨论】:

  • 我无法在玩具数据集上重现它(我的意思是我的第一个 sn-p 获得了更好的精度/召回率)。您能否发布有关 TP、FP 率等的结果?例如print(classification_report(y_test, CV_clf.predict(X_test) 的输出。我对您的“新代码”感到困惑,因为您在自定义平衡之上仍在使用class_weightsample_weight
  • 我的错,我没有使用不平衡的类。对于我来说,第一个 sn-p 的 auc 结果仍然比第二个更好,所以如果你能发布你的指标就好了。
  • 案例 1:使用 class_weight='auto' 和 sample_weight='1-8' (如代码所示),我得到 TPR=0.17 和 FPR=0.004。案例 2:但是当我使用函数 balance_subsample 时 subsample_size=0.5(如代码所示),我得到 TPR=0.85 和 FPR=0.13。在第二种情况下,我意识到再次尝试使用相同的值,比率会发生很大变化,但总是比 CASE 1 好得多。

标签: class scikit-learn random-forest balance


【解决方案1】:

这还不是一个完整的答案,但希望它会帮助到达那里。

首先是一些一般性的评论:

  • 要调试此类问题,确定性行为通常很有用。您可以将 random_state 属性传递给 RandomForestClassifier 和各种具有固有随机性的 scikit-learn 对象,以便在每次运行时获得相同的结果。您还需要:

    import numpy as np
    np.random.seed()
    import random
    random.seed()
    

让您的 balanced_subsample 函数在每次运行时都以相同的方式运行。

  • 不要在 n_estimators 上进行网格搜索:随机森林中的树越多越好。
  • 请注意,sample_weightclass_weight 具有相似的目标:实际样本权重将为 sample_weight * 权重从 class_weight 推断

你可以试试:

  • balanced_subsample 函数中使用 subsample=1。除非有特殊的理由不这样做,否则我们最好比较相似数量的样本的结果。
  • 使用您的二次抽样策略,将class_weightsample_weight 都设置为无。

编辑:再次阅读您的评论,我意识到您的结果并不那么令人惊讶!
您获得了更好(更高)的 TPR,但更差(更高)FPR
这只是意味着您的分类器会努力从第 1 类中获取正确的样本,从而产生更多的误报(当然,同时也获得更多正确的样本!)。
如果您继续沿同一方向增加类/样本权重,您将看到这种趋势继续下去。

【讨论】:

  • 非常感谢您宝贵的cmets。我会尝试你的方法来获得一个更“稳定”的准确分类器。
【解决方案2】:

有一个不平衡学习 API 可帮助对在这种情况下可能有用的数据进行过采样/欠采样。您可以将训练集传递给其中一种方法,它会为您输出过采样数据。请参阅下面的简单示例

from imblearn.over_sampling import RandomOverSampler

ros = RandomOverSampler(random_state=1)

x_oversampled, y_oversampled = ros.fit_sample(orig_x_data, orig_y_data)

这里是 API 的链接:http://contrib.scikit-learn.org/imbalanced-learn/api.html

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2013-02-10
    • 2015-04-20
    • 2014-05-01
    • 2014-06-20
    • 2017-11-23
    • 2019-04-23
    • 2018-05-04
    • 2017-03-26
    • 2015-08-28
    相关资源
    最近更新 更多