【问题标题】:How can I explain this drop in performance on test data?我如何解释测试数据的性能下降?
【发布时间】:2016-11-17 02:43:05
【问题描述】:

我在这里问这个问题,尽管我犹豫是否将其发布在 CrossValidated(或 DataScience)StackExchange 上。我有一个包含 60 个标记对象(用于训练)和 150 个未标记对象(用于测试)的数据集。该问题的目的是预测 150 个对象的标签(这曾经是作为作业问题给出的)。对于每个对象,我计算了 258 个特征。将每个对象视为样本,我有X_train : (60,258)y_train : (60,)(用于训练的对象的标签)和X_test : (150,258)。由于给出了作业问题的解决方案,我也有这150个对象的true标签,在y_test : (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 的 AUC = 0.40。如果一个天真的分类器应该得分 AUC = 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)

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

【问题讨论】:

    标签: python scikit-learn classification


    【解决方案1】:

    您似乎遇到了过拟合问题,即使用训练数据训练的分类器与训练数据过拟合。泛化能力差。这就是为什么在测试数据集上表现不佳的原因。

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

    总体而言,您的训练和测试数据集之间似乎存在相当大的差异。因此,训练准确率最高的分类器在您的测试集上效果不佳。

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

    【讨论】:

      【解决方案2】:

      您的训练和测试过程似乎不一致。尽管您打算从您的代码中标准化您的数据,但在测试期间您没有这样做。我的意思:

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

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

      【讨论】:

        【解决方案3】:

        首先,为 60 个训练项目设置 258 个特征是没有意义的。其次,60 个项目的 CV=10 意味着您将数据分成 10 个训练/测试集。这些中的每一个仅在测试集中有 6 个项目。所以你得到的任何结果都是无用的。您需要更多的训练数据和更少的特征。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-28
          • 1970-01-01
          • 1970-01-01
          • 2018-11-16
          • 1970-01-01
          • 2016-09-08
          相关资源
          最近更新 更多