使用SelectPercentile(来自sklearn)和SVM作为分类器时得分过高

时间:2016-06-17 22:13:34

标签: python scikit-learn svm cross-validation tf-idf

在Python中,我应用了SelectPercentile(来自sklearn),以便仅使用最相关的功能并训练SVM分类器。 我想提一下,我只有一个语料库,所以我必须在这个语料库上执行cross_validation 使用SelectPercentile选择功能后,当我使用cross_validation时,我得分过高,我认为我做错了,但我无法弄清楚是什么。我认为X_all矩阵有重复的行或重复的列,但它没有。

我不明白为什么会得到这个结果。任何人都可以让我了解幕后发生的事情以及我做错了什么?

实施

#仅提取数据集中的单词
#使用Pandas创建数据框

数据框具有以下结构:
  - 数据:仅包含没有任何停用词的单词
  - 性别:1或0

vectorizer = TfidfVectorizer(lowercase=False, min_df=1)
X_all = vectorizer.fit_transform(dataframe.data)
y_all = dataframe.gender

selector = SelectPercentile(f_classif, percentile=10)

selector.fit(X_all, y_all)
X_all = selector.transform(X_all)

classifier = svm.SVC()

param_grid = [
    {'C': [1, 10, 100, 1000], 'kernel': ['linear']},
    {'C': [1, 10, 100, 1000], 'gamma': [0.001, 0.0001], 'kernel': ['rbf']},
]

gs = GridSearchCV(classifier, param_grid, cv=5, n_jobs=4)
gs.fit(X_all.toarray(), y_all)
sorted(gs.grid_scores_, key=lambda x: x.mean_validation_score, reverse=True)

print gs.best_score_
print gs.best_params_

使用所有 150个样本获得的分数
SelectPercentile:0.756(9704个功能)

百分位= 90:0.822(8733个特征)
百分位= 70:0.947(6792个特征)
百分位= 50:0.973(4852个特征)
百分位= 30:0.967(2911个特征)
百分位= 10:0.970(971个特征)
百分位= 3:0.910(292个特征)
百分位= 1:0.820(98个特征)

另一方面,我尝试了另一种方法,然后将我拥有的150个样本分成火车并进行如下测试:

features_train, features_test, target_train, target_test = train_test_split(X_all, y_all, test_size=0.20, random_state=0)


selector = SelectPercentile(f_classif, percentile=10)
selector.fit(features_train, target_train)

features_train = selector.transform(features_train).toarray()
features_test = selector.transform(features_test).toarray()

classifier = svm.SVC().fit(features_train, target_train)
print("Training score: {0:.1f}%".format(classifier.score(features_test, target_test) * 100))

使用这种方法,我收到警告:

“/ usr / local / lib / python2.7 / dist-packages / sklearn / feature_selection / univariate_selection.py:113:UserWarning:Features [0 0 0 ...,0 0 0]是常量.UserWarning)”

所有结果都是常数,无论百分位数是多少(10,30,50,... 99): 44.3%

1 个答案:

答案 0 :(得分:0)

我认为您不应该使用所有数据(SelectPercentile)执行功能选择(X_all)。通过这样做,您在交叉验证中进行测试的数据“泄漏”到您的模型中。因此,您的功能选择类型可以看到测试集中的数据,并告诉您的分类器与训练集和测试集中的标签相关的功能子集。

您应该使用Pipeline将FS链接到您的分类器并执行交叉验证以进行模型评估。

但我认为使用单变量特征选择后跟SVM的方法可能会被SVD-SVM管道用于文本分类问题。查看this answer示例脚本。