首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于RFECV的SciKit学习特征选择和交叉验证

基于RFECV的SciKit学习特征选择和交叉验证
EN

Stack Overflow用户
提问于 2015-08-20 04:55:26
回答 1查看 4K关注 0票数 1

我对机器学习还是很陌生的,并且试图自己解决问题。我正在使用SciKit学习,并拥有一组包含大约20,000个功能(n_features=20,000)的tweet。到目前为止,我的查准率、召回率和f1分数都在79%左右。我想使用RFECV进行特征选择,并提高我的模型的性能。我已经阅读了SciKit学习文档,但对于如何使用RFECV仍然有些困惑。

这是我到目前为止掌握的代码:

代码语言:javascript
复制
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.cross_validation import StratifiedShuffleSplit
from sklearn.cross_validation import cross_val_score
from sklearn.feature_selection import RFECV
from sklearn import metrics

# cross validation
sss = StratifiedShuffleSplit(y, 5, test_size=0.2, random_state=42)
for train_index, test_index in sss:
    docs_train, docs_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

# feature extraction
count_vect = CountVectorizer(stop_words='English', min_df=3, max_df=0.90, ngram_range=(1,3))
X_CV = count_vect.fit_transform(docs_train)

tfidf_transformer = TfidfTransformer()
X_tfidf = tfidf_transformer.fit_transform(X_CV)

# Create the RFECV object
nb = MultinomialNB(alpha=0.5)

# The "accuracy" scoring is proportional to the number of correct classifications
rfecv = RFECV(estimator=nb, step=1, cv=2, scoring='accuracy')

rfecv.fit(X_tfidf, y_train)
X_rfecv=rfecv.transform(X_tfidf)

print("Optimal number of features : %d" % rfecv.n_features_)

# train classifier
clf = MultinomialNB(alpha=0.5).fit(X_rfecv, y_train)

# test clf on test data

X_test_CV = count_vect.transform(docs_test)
X_test_tfidf = tfidf_transformer.transform(X_test_CV)
X_test_rfecv = rfecv.transform(X_test_tfidf)

y_predicted = clf.predict(X_test_rfecv)

#print the mean accuracy on the given test data and labels

print ("Classifier score is: %s " % rfecv.score(X_test_rfecv,y_test))

三个问题:

1)这是使用交叉验证和RFECV的正确方法吗?我特别想知道我是否有过度适应的风险。

2)在使用上述代码实现RFECV之前和之后,我的模型的准确性几乎相同( 78-79%),这使我感到困惑。我希望通过使用RFECV来提高性能。在这里我可能错过了什么,或者可以采取不同的方法来提高我的模型的性能?

( 3)你还能推荐我尝试哪些其他的特征选择方法?到目前为止,我已经尝试过RFE和SelectKBest,但它们在模型准确性方面都没有给我带来任何改进。

EN

回答 1

Stack Overflow用户

发布于 2015-08-20 08:58:53

回答你的问题:

  1. 在RFECV特性选择中构建了交叉验证(因此就是名称),因此您实际上不需要对这一步进行额外的交叉验证。然而,由于我知道您正在运行几个测试,所以最好有一个全面的交叉验证,以确保您不过分适应一个特定的火车测试分割。我想在此提两点:
代码语言:javascript
复制
1. I doubt the code behaves exactly like you think it does ;).
# cross validation    sss = StratifiedShuffleSplit(y, 5, test\_size=0.2, random\_state=42)    for train\_index, test\_index in sss:        docs\_train, docs\_test = X[train\_index], X[test\_index]        y\_train, y\_test = y[train\_index], y[test\_index]    # feature extraction    count\_vect = CountVectorizer(stop\_words='English', min\_df=3, max\_df=0.90, ngram\_range=(1,3))    X\_CV = count\_vect.fit\_transform(docs\_train)

这里我们首先遍历这个循环,它有5个迭代(n_iter参数在StratifiedShuffleSplit中)。然后,我们将从循环中移出,然后使用train_index, test_index的最后一个值运行所有的代码。因此,这相当于一个单一的火车测试分割,其中您可能意味着有5个。如果您想让代码像“正确的”交叉验证那样运行,您应该将代码移回循环中。

代码语言:javascript
复制
1. You are worried about overfitting: indeed when 'looking for the best method' the risk exists that we're going to pick the method that works best... only on the small sample we're testing the method on.

这里的最佳实践是先进行一次列车测试分割,然后仅使用列车集执行交叉验证。当你认为你发现了什么东西时,测试集可以被“谨慎地”使用,以确保你得到的分数是一致的,而且你没有过度适应。

看起来你扔掉了30%的数据(你的测试集),但这是绝对值得的。

  1. 令人费解的是,功能选择并没有产生那么大的影响。为了更深入地反思,您可以通过所选特性的数量来查看分数的演变(请参见文档中的示例)。 尽管如此,我不认为这是RFE的正确用例。基本上,使用您的代码,您正在逐个消除功能,这些功能可能需要很长时间才能运行,而当您有20000个特性时,就没有太多意义了。
  2. 其他特性选择方法:这里您提到了SelectKBest,但是您没有告诉我们您使用哪种方法来评分您的特性!SelectKBest将根据评分函数选择K个最佳特性。我猜您使用的是默认值,这是可以的,但是最好知道默认值是做什么的;)。 我会尝试使用SelectPercentilechi2作为评分函数。SelectPercentile可能比SelectKBest更方便一些,因为如果您的数据集增长了一定的百分比,那么可能比硬编码的特性数量更有意义。 另一个来自文档的例子就是这样做的(还有更多)。

补充意见:

  • 您可以使用一个TfidfVectorizer,而不是一个CountVectorizer和一个TfidfTransformer。这是完全等同的。
  • 您可以使用管道对象将分类器的不同步骤打包到一个可以运行交叉验证的对象中(我鼓励您阅读文档,它非常有用)。 从sklearn.feature_selection进口chi2_sparse从sklearn.feature_selection进口SelectPercentile从sklearn.pipeline进口管道从sklearn.feature_extraction.text进口TfidfVectorizer管道=管道(steps=(“向量器”,TfidfVectorizer(stop_words='English',min_df=3,max_df=0.90,ngram_range=(1,3),(“选择器”,SelectPercentile(score_func=chi2,percentile=70)),('NB',MultinomialNB(alpha=0.5))

然后,您就可以在管道对象上运行交叉验证,以找到alpha和百分位数的最佳组合,这对于单独的估值器来说要困难得多。

希望这有帮助,快乐学习;)

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32109810

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档