【发布时间】:2015-09-24 10:17:32
【问题描述】:
在我的分类方案中,有几个步骤,包括:
- SMOTE(合成少数过采样技术)
- Fisher 特征选择标准
- 标准化(Z 分数标准化)
- SVC(支持向量分类器)
上述方案中要调优的主要参数是百分位数 (2.) 和 SVC 的超参数 (4.),我想通过网格搜索进行调优。
当前的解决方案构建了一个“部分”管道,包括方案clf = Pipeline([('normal',preprocessing.StandardScaler()),('svc',svm.SVC(class_weight='auto'))]) 中的第 3 步和第 4 步
并将方案分为两部分:
-
调整特征的百分位数以通过第一次网格搜索
skf = StratifiedKFold(y) for train_ind, test_ind in skf: X_train, X_test, y_train, y_test = X[train_ind], X[test_ind], y[train_ind], y[test_ind] # SMOTE synthesizes the training data (we want to keep test data intact) X_train, y_train = SMOTE(X_train, y_train) for percentile in percentiles: # Fisher returns the indices of the selected features specified by the parameter 'percentile' selected_ind = Fisher(X_train, y_train, percentile) X_train_selected, X_test_selected = X_train[selected_ind,:], X_test[selected_ind, :] model = clf.fit(X_train_selected, y_train) y_predict = model.predict(X_test_selected) f1 = f1_score(y_predict, y_test)将存储 f1 分数,然后对所有百分位数的所有折叠分区进行平均,并返回具有最佳 CV 分数的百分位数。将“percentile for loop”作为内部循环的目的是允许公平竞争,因为我们在所有百分位数的所有折叠分区中拥有相同的训练数据(包括合成数据)。
-
确定百分位数后,通过第二次网格搜索调整超参数
skf = StratifiedKFold(y) for train_ind, test_ind in skf: X_train, X_test, y_train, y_test = X[train_ind], X[test_ind], y[train_ind], y[test_ind] # SMOTE synthesizes the training data (we want to keep test data intact) X_train, y_train = SMOTE(X_train, y_train) for parameters in parameter_comb: # Select the features based on the tuned percentile selected_ind = Fisher(X_train, y_train, best_percentile) X_train_selected, X_test_selected = X_train[selected_ind,:], X_test[selected_ind, :] clf.set_params(svc__C=parameters['C'], svc__gamma=parameters['gamma']) model = clf.fit(X_train_selected, y_train) y_predict = model.predict(X_test_selected) f1 = f1_score(y_predict, y_test)
它以非常相似的方式完成,除了我们调整 SVC 的超参数而不是要选择的特征的百分位数。
我的问题是:
-
在当前的解决方案中,我只在
clf中涉及 3. 和 4. 并在如上所述的两个嵌套循环中“手动”执行 1. 和 2.。有没有办法将所有四个步骤都包含在一个管道中并一次完成整个过程? -
如果可以保留第一个嵌套循环,那么是否可以(以及如何)使用单个管道来简化下一个嵌套循环
clf_all = Pipeline([('smote', SMOTE()), ('fisher', Fisher(percentile=best_percentile)) ('normal',preprocessing.StandardScaler()), ('svc',svm.SVC(class_weight='auto'))])只需使用
GridSearchCV(clf_all, parameter_comb)进行调优?请注意,
SMOTE和Fisher(排名标准)都必须仅针对每个折叠分区中的训练数据进行。
如果您有任何评论,我们将不胜感激。
SMOTE和Fisher如下图:
def Fscore(X, y, percentile=None):
X_pos, X_neg = X[y==1], X[y==0]
X_mean = X.mean(axis=0)
X_pos_mean, X_neg_mean = X_pos.mean(axis=0), X_neg.mean(axis=0)
deno = (1.0/(shape(X_pos)[0]-1))*X_pos.var(axis=0) +(1.0/(shape(X_neg[0]-1))*X_neg.var(axis=0)
num = (X_pos_mean - X_mean)**2 + (X_neg_mean - X_mean)**2
F = num/deno
sort_F = argsort(F)[::-1]
n_feature = (float(percentile)/100)*shape(X)[1]
ind_feature = sort_F[:ceil(n_feature)]
return(ind_feature)
SMOTE来自https://github.com/blacklab/nyan/blob/master/shared_modules/smote.py,返回合成数据。我对其进行了修改,以返回与合成数据及其标签和合成数据堆叠在一起的原始输入数据。
def smote(X, y):
n_pos = sum(y==1), sum(y==0)
n_syn = (n_neg-n_pos)/float(n_pos)
X_pos = X[y==1]
X_syn = SMOTE(X_pos, int(round(n_syn))*100, 5)
y_syn = np.ones(shape(X_syn)[0])
X, y = np.vstack([X, X_syn]), np.concatenate([y, y_syn])
return(X, y)
【问题讨论】:
标签: machine-learning scikit-learn pipeline cross-validation feature-selection