2016-11-16 62 views
1

我在这里问这个问题,尽管我犹豫是否将它发布在CrossValidated(或DataScience)StackExchange上。我有一个包含60个标记对象(用于训练)和150个未标记对象(用于测试)的数据集。问题的目的是预测150个对象的标签(这是作为一个家庭作业问题给出的)。对于每个对象,我计算了258个特征。考虑到每个对象作为示例,我有X_train : (60,258)y_train : (60,)(用于训练的对象的标签)和X_test : (150,258)。由于给出了作业问题的解决方案,因此我也有y_test : (150,)中的150个对象的标签。如何解释测试数据的性能下降?

为了预测150个对象的标签,我选择使用LogisticRegression(Scikit-learn实现)。分类器在(X_train, y_train)上进行了训练,数据经过归一化后,用于对150个对象进行预测。这些预测与y_test进行比较以评估模型的性能。为了再现性,我复制了我用过的代码。

from sklearn import metrics 
from sklearn.preprocessing import StandardScaler 
from sklearn.linear_model import LogisticRegression 
from sklearn.pipeline import make_pipeline 
from sklearn.model_selection import cross_val_score, crosss_val_predict 

# Fit classifier 
LogReg = LogisticRegression(C=1, class_weight='balanced') 
scaler = StandardScaler() 
clf = make_pipeline(StandardScaler(), LogReg) 
LogReg.fit(X_train, y_train) 

# Performance on training data 
CV_score = cross_val_score(clf, X_train, y_train, cv=10, scoring='roc_auc') 
print(CV_score) 

# Performance on test data 
probas = LogReg.predict_proba(X_test)[:, 1] 
AUC = metrics.roc_auc_score(y_test, probas) 
print(AUC) 

矩阵X_trainy_trainX_testy_test保存在可用this link一个.MAT文件。我的问题如下:

使用这种方法,我在训练数据(CV_score = 0.8)上获得了很好的性能,但测试数据的性能更差:对于LogReg中的C = 1,AUC = 0.54 =对于C = 0.01,为0.40。如果一个天真的分类器应该得到AUC = 0.5,我怎样才能得到0.5的AUC?这是因为我有少量训练样本? 我注意到,如果我改变的代码上的测试数据的性能提高:

y_pred = cross_val_predict(clf, X_test, y_test, cv=5) 
AUC = metrics.roc_auc_score(y_test, y_pred) 
print(AUC) 

事实上,AUC = 0.87 C = 1和0.9 C = 0.01。为什么使用交叉验证预测的AUC得分更好?是否因为交叉验证允许对不包含降低AUC的对象/样本的测试数据的子集进行预测?

回答

0

首先,为60个训练项目提供258个特征是没有意义的。其次,对于60个项目,CV = 10表示将数据分成10个列车/测试集。其中每个只有6个项目在测试集中。所以你获得的任何结果都是无用的。您需要更多的培训数据和更少的功能。

1

看起来您正遇到过度拟合问题,即使用训练数据训练的分类器过度训练数据。泛化能力差。这就是测试数据集的性能不佳的原因。

cross_val_predict实际上是使用部分测试数据对分类器进行训练,然后对其余部分进行预测。所以表现要好得多。

总的来说,你的训练和测试数据集似乎有一些差异。所以具有最高训练精度的分类器在您的测试集上运行得并不好。

另一点与您的问题没有直接关系:由于训练样本的数量远小于特征尺寸,因此在输入分类器之前执行降维可能会有帮助。

1

它看起来像你的训练和测试过程不一致。尽管从您的代码中您打算将您的数据标准化,但是在测试过程中您没有这样做。我的意思是:

clf = make_pipeline(StandardScaler(), LogReg) LogReg.fit(X_train, y_train) 虽然您定义了一个管道,但您不适合管道(clf.fit),但只适用Logistic回归。这很重要,因为您的交叉验证分数是使用管道(CV_score = cross_val_score(clf, X_train, y_train, cv=10, scoring='roc_auc'))计算得出的,但是在测试期间(而不是预期使用的管线)可以预测,因此仅使用LogReg,因此测试数据不是标准化的。

你提出的第二点是不同的。在y_pred = cross_val_predict(clf, X_test, y_test, cv=5) 中,您可以通过对测试数据进行交叉验证来预测,而忽略列车数据。在这里,你使用clf进行数据标准化,因此你的分数很高;这是标准化步骤很重要的证据。

总之,标准化测试数据,我相信会提高你的测试分数。