我的模型是否过拟合?

数据挖掘 随机森林 逻辑回归 准确性 离群值
2021-10-11 18:27:07

我有 50000 个观察值,其中 70% 为正目标变量,30% 为负目标变量。我得到了大约 96-99% 的准确率,这当然看起来不真实,我担心我的模型过度拟合,我不明白为什么。我用第 5 和第 95 分位数替换了所有异常值。标准化了数据,但它显示了这种不真实的准确性。进行了一些在线搜索,人们建议检查训练和测试数据准确性之间的差异,我这样做了,而对于随机森林,它来了

Training Accuracy: 0.997975
Test Accuracy: 0.9715

对于逻辑回归,它显示

Training Accuracy: 0.967225
Test Accuracy: 0.9647

这是我用于运行模型的代码:

clf = LogisticRegression()
trained_model = clf.fit(X_train, y_train)
trained_model.fit(X_train, y_train)
predictions = trained_model.predict(X_test)      

accuracy_score(y_train, trained_model.predict(X_train))
accuracy_score(y_test, predictions)

我还尝试了 kfold 交叉验证,它给出了类似的结果

skfold = StratifiedKFold(n_splits=10, random_state=100)
model_skfold = LogisticRegression()
results_skfold = model_selection.cross_val_score(model_skfold, X, Y, cv=skfold)
print("Accuracy: %.2f%%" % (results_skfold.mean()*100.0))

最后我应用正则化技术来检查结果,这就是我得到的结果

for c in C:
    clf = LogisticRegression(penalty='l1', C=c, solver='liblinear')
    clf.fit(X_train, y_train)
    y_pred_log_reg = clf.predict(X_test)
    acc_log_reg = round( clf.score(X_train, y_train) * 100, 2)
    print (str(acc_log_reg) + ' percent')
    print('C:', c)
    print('Coefficient of each feature:', clf.coef_)
    print('Training accuracy:', clf.score(X_train_std, y_train))
    print('Test accuracy:', clf.score(X_test_std, y_test))
    print('')

结果

96.72 percent
C: 10
Coefficient of each feature: [[-2.50e+00 -1.40e-03  2.65e+00  4.09e-02 -2.03e-03  2.75e-04  1.79e-02
  -2.13e-03 -2.18e-03  2.90e-03  2.69e-03 -4.93e+00 -4.89e+00 -4.88e+00
  -3.27e+00 -3.30e+00]]
Training accuracy: 0.5062
Test accuracy: 0.5027

96.72 percent
C: 1
Coefficient of each feature: [[-2.50e+00 -1.41e-03  2.66e+00  4.10e-02 -2.04e-03  2.39e-04  1.68e-02
  -3.29e-03 -3.80e-03  2.52e-03  2.62e-03 -4.22e-02 -9.55e-03  0.00e+00
  -1.73e+00 -1.77e+00]]
Training accuracy: 0.482525
Test accuracy: 0.4738

96.74 percent
C: 0.1
Coefficient of each feature: [[-2.46e+00 -1.38e-03  2.58e+00  4.03e-02 -1.99e-03  2.22e-04  1.44e-02
  -4.49e-03 -5.13e-03  2.03e-03  2.20e-03  0.00e+00  0.00e+00  0.00e+00
   0.00e+00 -6.54e-03]]
Training accuracy: 0.616675
Test accuracy: 0.6171

95.92 percent
C: 0.001
Coefficient of each feature: [[-1.43e+00 -6.82e-04  1.19e+00  2.73e-02 -1.10e-03  1.22e-04  0.00e+00
  -2.74e-03 -2.55e-03  0.00e+00  0.00e+00  0.00e+00  0.00e+00  0.00e+00
   0.00e+00  0.00e+00]]
Training accuracy: 0.655075
Test accuracy: 0.6565

我用于标准化和替换异常值的代码

std_scale = preprocessing.StandardScaler().fit(X_train)
X_train_std = std_scale.transform(X_train)
X_test_std  = std_scale.transform(X_test)

X.clip(lower=X.quantile(0.05), upper=X.quantile(0.95), axis = 1, inplace = True)

如果需要任何其他信息,请告诉我,我们将不胜感激

在此处输入图像描述

3个回答

我没有足够的业力发表评论,但我想支持 Derek O 的评估,但还要再补充一点:如果您的 50K 观察结果是重复测量(多行来自同一个人或单位)-那么您我要确保在您的交叉折叠设置中,您要确保每个人 100% 的观察结果都属于同一折叠。

一个类比是,如果您正在模拟牙齿形成蛀牙的概率 - 一个人的头部有 32 颗牙齿,并且如果某个特定人的牙齿最终出现在您的测试和训练折叠中,这将被视为一种泄漏形式。这是因为 32 颗牙齿并不是完全独立的,而是与同一个头部的其他牙齿相关联。这种特殊形式的泄漏常常让人忘记。

这是一个不平衡的类问题,但是,它不是一个非常不平衡的数据集。这是面试中常见的问题/任务。您可能会获得较高的准确度,因为次要类在模型中的权重较小。

这个话题已经在这里这里讨论过好几次了。

如果您的结果看起来好得令人难以置信,那可能是。

我认为最可能的原因是数据泄露如果您执行任何标准化/归一化,甚至使用整个数据集而不使用 k 折叠管道进行插补,则您的数据集存在偏差,并且当您进行 k 折叠交叉验证时,每个“训练折叠”都是使用创建的模型不应该知道的信息(即“训练折叠”使用来自“测试折叠”的信息进行标准化)。这导致有偏见的模型基本上已经提前知道了答案,从而导致一旦您在以前没有见过的数据上运行模型时,准确性就不会泛化。

解决这个问题的方法是在每个 k-fold 中执行标准化/插补,或者保留一个验证集并分别对训练集和验证集执行标准化/插补。

Jason Brownlee 关于数据泄漏的文章是更深入地了解该问题的好资源。

我想你的数据集中的类不平衡也可能是罪魁祸首,但我认为 70/30 的类不平衡不能解释 96-99% 的准确率。