学习曲线(高偏差/高方差)为啥测试学习曲线变平

Posted

技术标签:

【中文标题】学习曲线(高偏差/高方差)为啥测试学习曲线变平【英文标题】:Learning curve (high bias / high variance) why the testing learning curve gets flat学习曲线(高偏差/高方差)为什么测试学习曲线变平 【发布时间】:2017-04-27 02:39:10 【问题描述】:

我使用梯度提升决策树作为分类器实现了一个模型,并绘制了训练集和测试集的学习曲线,以决定下一步做什么来改进我的模型。 结果如图:

(Y 轴是准确率(正确预测的百分比),而 x 轴是我用来训练模型的样本数。)

我知道训练和测试分数之间的差距可能是由于高方差(过度拟合)。但图像也显示,当样本数量从 2000 增加到 3000 时,测试分数(绿线)几乎没有增加。测试分数的曲线越来越平坦。即使有更多样本,该模型也没有变得更好。

我的理解是,平坦的学习曲线通常表示高偏差(欠拟合)。在这个模型中是否可能同时发生欠拟合和过拟合?或者对于平坦曲线还有其他解释吗?

任何帮助将不胜感激。提前致谢。

======================================

我使用的代码如下。基本我使用与sklearn中的示例相同的代码document

def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None,
                    n_jobs=1, train_sizes=np.linspace(.1, 1.0, 5)):
    plt.figure()
    plt.title(title)
    if ylim is not None:
        plt.ylim(*ylim)
    plt.xlabel("Training examples")
    plt.ylabel("Score")
    train_sizes, train_scores, test_scores = learning_curve(
        estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes)
    train_scores_mean = np.mean(train_scores, axis=1)
    train_scores_std = np.std(train_scores, axis=1)
    test_scores_mean = np.mean(test_scores, axis=1)
    test_scores_std = np.std(test_scores, axis=1)
    plt.grid()

    plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
                     train_scores_mean + train_scores_std, alpha=0.1,
                     color="r")
    plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
                     test_scores_mean + test_scores_std, alpha=0.1, color="g")
    plt.plot(train_sizes, train_scores_mean, 'o-', color="r",
             label="Training score")
    plt.plot(train_sizes, test_scores_mean, 'o-', color="g",
             label="Cross-validation score")

    plt.legend(loc="best")
    return plt

title = "Learning Curves (GBDT)"
# Cross validation with 100 iterations to get smoother mean test and train
# score curves, each time with 20% data randomly selected as a validation set.
cv = ShuffleSplit(n_splits=100, test_size=0.2, random_state=0)

estimator = GradientBoostingClassifier(n_estimators=450)
X,y= features, target #features and target are already loaded
plot_learning_curve(estimator, title, X, y, ylim=(0.6, 1.01), cv=cv, n_jobs=4)

plt.show()

【问题讨论】:

【参考方案1】:

您应该更加注意训练的准确性。如果它在训练期间下降,那么你做错了什么。再次检查您的数据(您的标签是否正确?)和您的模型的正确性。

通常,训练和测试的准确率都应该提高,但测试的准确率会落后。

【讨论】:

在学习曲线中(x 轴是提供的训练样本的数量),预计准确度会随着样本的增多而下降。 这个家伙从一开始就有大约 100% 的准确度,随着样本数量从 500 增加到 1k,它会下降。如果这是意料之中的 - 我不知道该说什么...... 没错。对于学习曲线,任何没有以 100% 准确率开始并且下降的东西都表明存在问题【参考方案2】:

首先,当您添加更多示例时,您的训练准确度会下降很多。所以这仍然可能是高方差。但是,我怀疑这是唯一的解释,因为差距似乎太大了。

训练准确度和测试准确度之间存在差距的原因可能是训练样本和测试样本的分布不同。但是,通过交叉验证,这不应该发生(您是否进行了 k 折交叉验证,并为每个 k 折重新训练?)

【讨论】:

我使用了 shufflesplit 交叉验证 (testsize=0.2) 作为我刚刚添加的代码。如果您能指出该方法是否有错误,我将不胜感激【参考方案3】:

我会说你过拟合了。考虑到您正在使用交叉验证,训练和交叉验证分数之间的差距可能太大了。如果没有交叉验证或随机拆分,您的训练数据和测试数据可能会在某些方面有所不同。

有几种方法可以尝试缓解这种情况:

添加更多数据(训练分数可能还会再下降一点) 减少估计器的数量,甚至更好地使用提前停止 增加 gamma 以进行修剪 使用二次抽样(按树、按列...)

有lots of parameters that you can play with,玩得开心! :-D

【讨论】:

以上是关于学习曲线(高偏差/高方差)为啥测试学习曲线变平的主要内容,如果未能解决你的问题,请参考以下文章

斯坦福大学公开课机器学习:advice for applying machine learning | learning curves (改进学习算法:高偏差和高方差与学习曲线的关系)

偏差和方差

机器学习模型的实用建议

SkikitLearn学习曲线强烈依赖于MLPClassifier的批量大小???或者:如何诊断NN的偏差/方差?

SkikitLearn 学习曲线强烈依赖于 MLPClassifier 的批量大小???或者:如何诊断 NN 的偏差/方差?

模型方差与偏差