如何在学习曲线图中制作平坦的验证准确度曲线

Posted

技术标签:

【中文标题】如何在学习曲线图中制作平坦的验证准确度曲线【英文标题】:What to make of a flat validation accuracy curve in a learning curve graph 【发布时间】:2021-02-28 22:23:56 【问题描述】:

在绘制学习曲线以查看模型构建的进展情况时,我意识到验证准确度曲线从一开始就是一条直线。我想这可能只是由于将数据拆分为训练集和验证集时出现了一些错误,但是当我对其进行 100 次迭代时,我仍然得到或多或少相同的图表。

我该如何解释?这是怎么回事?我计算准确度分数的方式是否有错误?

另外,一开始准确率不高,我怀疑我的模型拟合不足,有什么明显的方法可以改进它吗? (我没有办法获取更多数据,特征工程也是这样吗?)

我使用下面的代码来计算精度。

def learning_curve():
    
    X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.33)
    
    training_sizes = (np.linspace(0.1, 1.0, 100) * len(X_train)).astype(int)
    
    train_accuracy = []
    valid_accuracy = []
    
    clf = LogisticRegression(solver='liblinear')
    
    for size in training_sizes:
        clf.fit(X_train.iloc[:size], y_train.iloc[:size])
        train_accuracy.append(clf.score(X_train.iloc[:size], y_train.iloc[:size]))
        valid_accuracy.append(clf.score(X_valid, y_valid))
        
    return training_sizes, train_accuracy, valid_accuracy
    

training_scores = []
cross_val_scores = []
    
for i in range(num_iter):
    sizes, train_score, cross_valid_score = learning_curve()
    training_scores.append(train_score)
    cross_val_scores.append(cross_valid_score)
    
train_std = np.std(training_scores, axis=0)
train_mean = np.mean(training_scores, axis=0)
cv_std = np.std(cross_val_scores, axis=0)
cv_mean = np.mean(cross_val_scores, axis=0)
    
plt.plot(sizes, train_mean, '--', color="b",  label="Training score") 
plt.plot(sizes, cv_mean, color="g", label="Cross validation score") 
   
plt.fill_between(sizes, train_mean - train_std, train_mean + train_std, color='gray')
plt.fill_between(sizes, cv_mean - cv_std, cv_mean + cv_std, color='gray')

此代码生成以下图表:

非常感谢任何帮助。谢谢。

【问题讨论】:

我会首先尝试使用更复杂的模型(SVM 或神经网络),因为逻辑回归在您的情况下是欠拟合的,我还会确保我给模型的输入具有预测所需的所有信息正确的输出(即来自您对数据的领域知识的分析)换句话说,如果给定您为模型提供的输入,则该领域的专家可以预测正确的输出。 【参考方案1】:

首先,虽然您的实现看起来是正确的,但您应该验证learning_curve 的实现。一个快速的方法是将它与 Scikit-Learn 已经制作的 learning_curve 函数进行比较(旁注:你不需要重新发明***,如果我是你,我会使用由 Scikit-Learn 开发的)。

由于您没有提供任何数据,我不得不创建一些分类数据集。

X, y = make_classification(n_samples=1000, n_features=5, n_informative=5, 
                           n_redundant=0, n_repeated=0, n_classes=2, 
                           shuffle=True, random_state=2020)

事实证明你的实现是正确的(为了清楚起见删除了偏差):


现在我们确定了实现,问题现在出在您的数据集中。我们需要领域知识来进行一些探索性数据分析 (EDA)。

您的数据可能包含冗余信息,这会增加很多噪音。

如果我重复同样的实验,但这次我创建了很多冗余数据

X, y = make_classification(n_samples=1000, n_features=5, n_informative=2, 
                           n_redundant=3, n_repeated=0, n_classes=2, 
                           shuffle=True, random_state=2020)

你会看到几乎类似的模式出现了,就像你的结果一样:

N.B 你得到的分数无论如何都不低,>=90% 的准确率被认为是一个非常很好的分数。


总结

    您的实现是正确的。 问题很可能出在您的数据集中(例如冗余特征)。 建议的解决方案太多,无法在此处包含,尤其是在不了解您的数据集的情况下,因为它需要 EDA 和领域知识(请参阅 here 和 here 作为初学者)

【讨论】:

我听取了您的建议并尝试修剪使用的功能,但验证曲线仍然是一条直线(即使我只使用一个功能,我尝试过的所有单个功能仍然相同)。会不会是这些特征信息量不够(但话说回来,是否有可能从信息量不足的特征中获得 90% 的准确率)? @NewbieAF 没有看到您的数据集就很难判断。如果您可以拥有包含完整/部分数据集的 Git 存储库,请务必提供它们。另请注意,特征只是一个例子,正如我在总结点 3 中提到的,提出的解决方案太多了,目前我们只是闭着眼睛开车,只要我们没有你的数据集。跨度> 如果 90% 的目标标签等于 1,则可以通过无信息特征获得 90% 的准确度。所以,首先我会检查目标标签的分布方式以及您的模型是否学习什么都可以。

以上是关于如何在学习曲线图中制作平坦的验证准确度曲线的主要内容,如果未能解决你的问题,请参考以下文章

使用 BP 神经网络进行深度学习时在训练时获得平坦的误差曲线

机器学习模型评估选择与验证

如何在 Keras 中绘制 MLP 模型的训练损失和准确度曲线?

Python机器学习:6.3 使用学习曲线和验证曲线 调试算法

损失曲线和度量曲线之间的不一致性?

使用 caret 包和 R 绘制学习曲线