如何解释测试数据的性能下降?

时间:2016-11-16 14:43:11

标签: python scikit-learn classification

我在这里问这个问题,即使我犹豫是否将它发布在CrossValidated(或DataScience)StackExchange上。我有一个包含60个标记对象(用于训练)和150个未标记对象(用于测试)的数据集。问题的目的是预测150个物体的标签(这曾经作为家庭作业问题给出)。对于每个对象,我计算了258个特征。考虑每个对象作为样本,我有X_train : (60,258)y_train : (60,)(用于训练的对象的标签)和X_test : (150,258)。由于给出了家庭作业问题的解决方案,我在y_test : (150,)中也有150个对象的 true 标签。

为了预测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时AUC = 0.40。如果天真的分类器得分AUC = 0.5,我怎样才能得到AUC <0.5?这是因为我有少量的训练样本吗? 我注意到,如果我更改以下代码,测试数据的性能会提高:

y_pred = cross_val_predict(clf, X_test, y_test, cv=5) 
AUC = metrics.roc_auc_score(y_test, y_pred)
print(AUC)
实际上,对于C = 1,AUC = 0.87,对于C = 0.01,AUC = 0.9。为什么使用交叉验证预测AUC得分会更好?是因为交叉验证允许对测试数据的子集进行预测,这些子集不包含降低AUC的对象/样本吗?

3 个答案:

答案 0 :(得分:1)

看起来您遇到过度拟合问题,即使用训练数据训练的分类器过度拟合训练数据。它具有较差的泛化能力。这就是为什么测试数据集的性能不好。

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

总体而言,您的培训和测试数据集之间似乎存在很大差异。因此,具有最高训练精度的分类器在您的测试集上不能很好地工作。

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

答案 1 :(得分: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进行数据标准化,因此您的分数很高;这证明标准化步骤很重要。

总而言之,标准化测试数据,我相信会提高您的测试成绩。

答案 2 :(得分:0)

首先,为60个训练项目提供258个功能是没有意义的。其次,对于60个项目,CV = 10意味着您将数据拆分为10个列车/测试集。这些中的每一项仅在测试集中有6个项目。所以无论你得到什么结果都没用。您需要更多的培训数据和更少的功能。