试图通过scikit-learn中的sample_weight来平衡我的数据集



我使用RandomForest进行分类,我得到了一个不平衡的数据集,如:5830-no, 1006-yes。我尝试用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比率没有得到任何改善。

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

然而,如果我使用名为balanced_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})

这还不是一个完整的答案,但希望它能帮助你。

首先是一些一般性的注意事项:

  • 要调试这种问题,通常有一个确定性的行为是有用的。您可以将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都设置为None。

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

有一个不平衡学习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

希望这对你有帮助!

相关内容

  • 没有找到相关文章

最新更新