我对机器学习还是很陌生的,并且试图自己解决问题。我正在使用SciKit学习,并拥有一组包含大约20,000个功能(n_features=20,000)的tweet。到目前为止,我的查准率、召回率和f1分数都在79%左右。我想使用RFECV进行特征选择,并提高我的模型的性能。我已经阅读了SciKit学习文档,但对于如何使用RFECV仍然有些困惑。
这是我到目前为止掌握的代码:
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,但它们在模型准确性方面都没有给我带来任何改进。
发布于 2015-08-20 08:58:53
回答你的问题:
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个。如果您想让代码像“正确的”交叉验证那样运行,您应该将代码移回循环中。
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%的数据(你的测试集),但这是绝对值得的。
SelectKBest,但是您没有告诉我们您使用哪种方法来评分您的特性!SelectKBest将根据评分函数选择K个最佳特性。我猜您使用的是默认值,这是可以的,但是最好知道默认值是做什么的;)。
我会尝试使用SelectPercentile和chi2作为评分函数。SelectPercentile可能比SelectKBest更方便一些,因为如果您的数据集增长了一定的百分比,那么可能比硬编码的特性数量更有意义。
另一个来自文档的例子就是这样做的(还有更多)。补充意见:
TfidfVectorizer,而不是一个CountVectorizer和一个TfidfTransformer。这是完全等同的。然后,您就可以在管道对象上运行交叉验证,以找到alpha和百分位数的最佳组合,这对于单独的估值器来说要困难得多。
希望这有帮助,快乐学习;)
https://stackoverflow.com/questions/32109810
复制相似问题