尝试通过 scikit-learn 中的 sample_weight 来平衡我的数据集
Trying to balance my dataset through sample_weight in scikit-learn
我正在使用 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 比率没有任何改善。
为什么?我做错了什么吗?
不过,如果我使用名为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_weight
和 class_weight
具有相似的 objective:实际样本权重将是 sample_weight
* 从 [=16= 推断的权重].
你能试试吗:
- 在
balanced_subsample
函数中使用 subsample=1。除非有特殊原因不这样做,否则我们最好比较相似数量样本的结果。
- 将
class_weight
和 sample_weight
都设置为 None 的二次采样策略。
编辑:再次阅读您的评论,我意识到您的结果并不令人惊讶!
您获得更好(更高)的 TPR 但 更差(更高)FPR.
这只是意味着你的 classifier 努力从 class 1 中获得正确的样本,从而产生更多的误报(当然也会得到更多正确的样本!)。
如果您继续沿同一方向增加 class/sample 权重,您将看到这种趋势继续。
有一个 imbalanced-learn API 可以帮助处理 oversampling/undersampling 可能在这种情况下有用的数据。您可以将训练集传递给其中一种方法,它会为您输出过采样数据。请参阅下面的简单示例
from imblearn.over_sampling import RandomOverSampler
ros = RandomOverSampler(random_state=1)
x_oversampled, y_oversampled = ros.fit_sample(orig_x_data, orig_y_data)
这里是 link 到 API: http://contrib.scikit-learn.org/imbalanced-learn/api.html
希望对您有所帮助!
我正在使用 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 比率没有任何改善。
为什么?我做错了什么吗?
不过,如果我使用名为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_weight
和class_weight
具有相似的 objective:实际样本权重将是sample_weight
* 从 [=16= 推断的权重].
你能试试吗:
- 在
balanced_subsample
函数中使用 subsample=1。除非有特殊原因不这样做,否则我们最好比较相似数量样本的结果。 - 将
class_weight
和sample_weight
都设置为 None 的二次采样策略。
编辑:再次阅读您的评论,我意识到您的结果并不令人惊讶!
您获得更好(更高)的 TPR 但 更差(更高)FPR.
这只是意味着你的 classifier 努力从 class 1 中获得正确的样本,从而产生更多的误报(当然也会得到更多正确的样本!)。
如果您继续沿同一方向增加 class/sample 权重,您将看到这种趋势继续。
有一个 imbalanced-learn API 可以帮助处理 oversampling/undersampling 可能在这种情况下有用的数据。您可以将训练集传递给其中一种方法,它会为您输出过采样数据。请参阅下面的简单示例
from imblearn.over_sampling import RandomOverSampler
ros = RandomOverSampler(random_state=1)
x_oversampled, y_oversampled = ros.fit_sample(orig_x_data, orig_y_data)
这里是 link 到 API: http://contrib.scikit-learn.org/imbalanced-learn/api.html
希望对您有所帮助!