您是否对您的机器学习算法产生了不同的结果?
也许您的结果与教程不同,您想了解原因。
也许您的模型在每次训练时都会做出不同的预测,即使它每次都在相同的数据集上进行训练。
这是可以预期的,甚至可能是算法的一个特性,而不是一个错误。
在本教程中,您将了解在使用机器学习算法时为什么会得到不同的结果。
完成本教程后,您将了解:
- 机器学习算法会在训练数据集发生变化时训练不同的模型。
- 随机机器学习算法在学习过程中使用随机性,确保每次运行都训练出不同的模型。
- 开发环境的差异,例如软件版本和 CPU 类型,可能导致预测和模型评估中的舍入误差差异。
让我们开始吧。

为什么我在机器学习中每次都得到不同的结果?
照片来自 Bonnie Moreland,部分权利保留。
教程概述
本教程分为五个部分;它们是:
- 救命,我得到的结果不一样了!?
- 训练数据引起的差异
- 学习算法引起的差异
- 评估程序引起的差异
- 平台引起的差异
1. 救命,我得到的结果不一样了!?
别慌。机器学习算法或模型可能会产生不同的结果。
这不是你的错。事实上,它通常是一个特性,而不是一个错误。
我们将清楚地说明并解释您遇到的问题。
首先,让我们掌握基本知识。
在应用机器学习中,我们在一组数据集上运行机器学习“算法”以获得机器学习“模型”。然后,该模型可以在训练期间未使用的或在训练期间未使用的用于在新数据上进行预测的数据上进行评估。
- 算法:在数据上运行以产生模型的程序(例如,训练或学习)。
- 模型:用于对数据进行预测的数据结构和系数。
有关机器学习算法和模型之间差异的更多信息,请参阅教程
监督机器学习意味着我们有包含输入和输出变量的示例(行)(列)。我们无法编写代码来预测给定输入的输出来预测输出,因为这太难了,所以我们使用机器学习算法来学习如何在给定历史示例的情况下从输入预测输出。
这被称为 函数逼近,我们正在学习或搜索一个函数,该函数以一种具有技巧的方式将输入映射到输出,也就是说,映射的性能优于随机性,并且理想情况下优于我们尝试过的所有其他算法和算法配置。
- 监督学习:自动从输入示例到输出示例学习映射函数。
从这个意义上说,机器学习模型是我们打算用于某个项目或应用程序的程序;恰好这个程序是从示例(使用算法)学习的,而不是显式地用 if 语句等编写的。这是一种自动编程。
- 机器学习模型:一个从历史数据中自动学习的“程序”。
与我们可能习惯的编程不同,程序可能不是完全确定的。
机器学习模型每次训练时可能都不同。反过来,模型可能会做出不同的预测,在评估时,它们的误差或准确性水平也可能不同。
至少有四种情况会导致您得到不同的结果;它们是
- 由于训练数据差异导致的结果不同。
- 由于随机学习算法导致的结果不同。
- 由于评估程序差异导致的结果不同。
- 由于平台差异导致的结果不同。
让我们依次仔细看看每一个。
我是否错过了结果差异的可能原因?
在下面的评论中告诉我。
2. 训练数据引起的差异
当您在不同数据上运行相同的算法时,您将获得不同的结果。
这被称为机器学习算法的方差。您可能在偏差-方差权衡的背景下听说过它。
方差是衡量算法对训练期间使用的特定数据的敏感程度。
- 方差:算法对训练期间使用的特定数据的敏感程度。
更敏感的算法具有更大的方差,这将导致模型产生更多差异,进而影响预测和模型评估。反之,不敏感的算法方差较小,并且在使用不同训练数据时产生的模型差异较小,进而导致产生的预测和模型评估差异较小。
- 高方差:算法对训练期间使用的特定数据更敏感。
- 低方差:算法对训练期间使用的特定数据不那么敏感。
有关方差和偏差-方差权衡的更多信息,请参阅教程
所有有用的机器学习算法都有一定的方差,而一些最有效的算法将具有高方差。
高方差的算法通常需要比低方差算法更多地训练数据。如果我们考虑模型从输入和输出近似映射函数以及 大数定律,这是直观的。
尽管如此,当您在不同的训练数据上训练机器学习算法时,您将获得一个具有不同行为的不同模型。这意味着不同的训练数据将给出不同的预测模型,并具有不同的性能估计(例如,误差或准确性)。
结果的差异程度将与每个模型的训练数据的差异程度,以及您选择的特定模型和模型配置的方差有关。
我该怎么办?
您通常可以通过更改算法的超参数来降低模型的方差。
例如,k-最近邻中的“k”控制着算法的方差,其中像 k=1 这样的小值会导致高方差,而像 k=21 这样的大值会导致低方差。
您可以通过更改算法来降低方差。例如,线性回归和逻辑回归等简单算法的方差低于其他类型的算法。
您还可以通过增加训练数据集的大小来降低高方差算法的方差,这意味着您可能需要收集更多数据。
3. 学习算法引起的差异
当您在相同数据上运行相同算法时,由于学习算法的性质,您可能会得到不同的结果。
这很可能是您阅读本教程的原因。
您运行相同的代码在相同的数据集上,每次都会得到一个做出不同预测或具有不同性能的模型,您认为这是一个错误或者别的什么。我说对了吗?
这不是错误,这是一个特性。
有些机器学习算法是确定性的。就像您习惯的编程一样。这意味着,当算法获得相同的数据集时,它每次都会学习相同的模型。例如,线性回归或逻辑回归算法。
有些算法不是确定性的;相反,它们是随机的。这意味着它们的行为包含随机元素。
随机性不等于随意性。随机机器学习算法不是学习一个随机模型。它们是基于您提供历史数据学习一个条件模型。相反,算法在学习过程中做出的具体小决策可能会随机变化。
其影响是,每次随机机器学习算法在相同数据上运行时,它都会学习一个略有不同的模型。反过来,模型可能会做出略有不同的预测,在用误差或准确性评估时,可能会有略有不同的性能。
有关随机性和它在机器学习中的含义的更多信息,请参阅教程
向算法的某些决策添加随机性可以提高解决难题的性能。使用来自该域的有限样本数据来学习监督学习映射函数是一个非常困难的问题。
为数据集找到一个好的或最佳的映射函数是一种搜索问题。我们测试不同的算法和测试定义搜索空间形状并为我们提供搜索空间起始点的算法配置。然后,我们运行算法,算法接着导航搜索空间到一个单一的模型。
添加随机性有助于避免陷入好的解决方案,并有助于在搜索空间中找到真正好的和优秀的解决方案。它们允许模型跳出学习算法可能陷入的局部最优或欺骗性局部最优,并帮助找到更好的解决方案,甚至是全局最优。
有关将监督学习视为搜索问题的更多信息,请参阅教程
在学习过程中使用随机性的算法的一个例子是神经网络。它在两个方面使用随机性
- 随机初始权重(模型系数)。
- 每个 epoch 随机打乱样本。
神经网络(深度学习)是随机机器学习算法。随机初始权重允许模型在每次算法运行时尝试从搜索空间的另一个起点进行学习,并允许学习算法在学习过程中“打破对称”。训练过程中的示例随机打乱确保每个梯度估计和权重更新都略有不同。
有关神经网络随机性质的更多信息,请参阅教程
另一个例子是集成机器学习算法,例如装袋法 (bagging),它们是随机的。
随机性用于训练数据集的抽样过程,以确保为集成中的每个贡献成员都准备了不同的决策树。在集成学习中,这被称为集成多样性,是一种模拟来自单个训练数据集的独立预测的方法。
有关装袋集成随机性质的更多信息,请参阅教程
我该怎么办?
学习算法使用的随机性是可以控制的。
例如,您可以设置伪随机数生成器使用的种子,以确保算法每次运行时都能获得相同的随机性。
有关随机数生成器和设置固定种子的更多信息,请参阅教程
这可能是教程的好方法,但在实践中不是个好方法。这会导致出现诸如
- 伪随机数生成器的最佳种子是什么?
随机机器学习算法没有最佳种子。您正在对抗算法的本质,强迫随机学习变成确定性的。
您可以认为最终模型是使用固定种子拟合的,以确保从相同数据创建相同的模型,然后用于生产环境进行任何部署前的系统测试。尽管如此,只要训练数据集发生变化,模型就会随之改变。
一个更好的方法是拥抱机器学习算法的随机性。
考虑您的数据集没有一个单一的模型。相反,有一个随机过程(算法管道)可以为您的问题生成模型。
有关此内容的更多信息,请参阅教程
然后,您可以将这些模型(算法管道)的性能概括为具有平均预期误差或准确性以及标准差的分布。
然后,当您需要对新数据进行预测时,可以通过在数据集上拟合多个最终模型并对它们的预测进行平均来确保实现模型的平均性能。
有关最终模型的集成方法的更多信息,请参阅教程
4. 评估程序引起的差异
由于评估程序,您可以在相同数据上运行相同算法时得到不同的结果。
两个最常见的评估程序是训练-测试拆分和 k 折交叉验证。
一个 训练-测试拆分 涉及随机分配行,用于训练模型或评估模型,以满足预定义的训练或测试集大小。
有关训练-测试拆分的更多信息,请参阅教程
k 折交叉验证程序涉及将数据集划分为 k 个不重叠的子集,并使用一个折作为测试集,其余折作为训练集。模型在训练集上拟合,并在保持的折上进行评估,这个过程重复 k 次,让每个折都有机会作为保持的折。
有关 k 折交叉验证的更多信息,请参阅教程
这两种模型评估程序都是随机的。
同样,这并不意味着它们是随意的;这意味着过程中所做的具体小决策包含随机性。特别是,将哪些行分配给给定数据子集的选择。
这种随机性的使用是一个特性,而不是一个错误。
在这种情况下,随机性的使用允许重采样来近似估计模型性能,该估计独立于从域中抽取的特定数据样本。此近似是存在偏差的,因为我们只有少量数据可用,而不是完整的可能观察集。
性能估计提供了模型在域中对训练期间未见过的数据进行预测时的预期或平均能力的 ধারণা。无论用于训练或测试模型的数据行具体是哪些,至少在理想情况下。
有关更广泛的统计抽样主题的更多信息,请参阅教程
因此,确定性机器学习算法(如线性回归或逻辑回归)的每次评估都可能产生不同的误差或准确性估计。
我该怎么办?
在这种情况下,解决方案与随机学习算法的情况非常相似。
伪随机数生成器的种子可以固定,或者可以拥抱该过程的随机性。
与随机学习算法不同,这两种解决方案都相当合理。
如果大量机器学习算法和算法配置在预测建模任务上被系统地评估,那么固定评估过程的随机种子可能是一个好主意。任何值都可以。
这样做的目的是,每个候选解决方案(每个算法或配置)都将以相同的方式进行评估。这确保了公平的比较。它还允许稍后使用配对统计假设检验来检查算法之间的差异是否具有统计学意义。
拥抱随机性也是适用的。这包括多次重复评估过程,并报告性能分数分布的摘要,例如均值和标准差。
也许重复评估最不具偏差的方法是使用 重复的 k 折交叉验证,例如三次重复 10 折(3×10),这很常见,或者五次重复 2 折(5×2),当比较算法与统计假设检验时,这也很常用。
有关比较算法的统计假设检验的入门教程,请参阅教程
有关使用假设检验比较平均算法性能的教程,请参阅教程
5. 平台引起的差异
当您在不同计算机上使用相同数据运行相同算法时,您可能会得到不同的结果。
即使您固定了随机数种子以解决学习算法和评估过程的随机性,也可能发生这种情况。
这种情况的原因是运行示例的平台或开发环境,结果通常在细微方面有所不同,但并非总是如此。
这包括
- 系统架构的差异,例如 CPU 或 GPU。
- 操作系统的差异,例如 MacOS 或 Linux。
- 底层数学库的差异,例如 LAPACK 或 BLAS。
- Python 版本的差异,例如 3.6 或 3.7。
- 库版本的差异,例如 scikit-learn 0.22 或 0.23。
- …
机器学习算法是一种数值计算。
这意味着它们通常涉及大量的浮点数数学运算。例如,架构和操作系统等方面的差异可能导致舍入误差差异,这些差异会随着计算次数的增加而累积,从而产生非常不同的结果。
此外,库版本中的差异可能意味着错误的修复和功能的更改,这些也可能导致不同的结果。
此外,这也解释了为什么在用不同语言(如 R 和 Python)实现的相同机器上的相同算法会得到不同的结果。实现和/或使用的底层数学库的微小差异会导致结果模型和该模型产生的预测产生差异。
我该怎么办?
这并不意味着平台本身可以被视为超参数并针对预测建模问题进行调整。
相反,它意味着平台是评估机器学习算法时的重要因素,并且应固定或完整描述,以确保在从开发迁移到生产时,或在学术研究中报告性能时,能够完全重现。
一种方法可能是使用虚拟化,例如 docker 或虚拟机实例,以确保环境保持不变,如果完全可重现性对项目至关重要。
老实说,实践中这种影响通常很小(至少根据我有限的经验),只要主要的软件版本是良好或足够接近的。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
相关教程
- 机器学习中算法与模型的区别
- 机器学习中偏差-方差权衡的温和介绍
- 机器学习中的“随机”(Stochastic)是什么意思?
- 将应用机器学习作为一个搜索问题的简明介绍
- 为什么用随机权重初始化神经网络?
- 如何使用 Python 开发 Bagging 集成算法
- 如何减少最终机器学习模型的方差
- Python 机器学习中的随机数生成器简介
- 统计抽样与重抽样入门
- 用于比较机器学习算法的统计显著性检验
总结
在本教程中,您发现了为什么在使用机器学习算法时可以预期得到不同的结果。
具体来说,你学到了:
- 机器学习算法会在训练数据集发生变化时训练不同的模型。
- 随机机器学习算法在学习过程中使用随机性,确保每次运行都训练出不同的模型。
- 开发环境的差异,例如软件版本和 CPU 类型,可能导致预测和模型评估中的舍入误差差异。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
第 3 节“学习算法引起的差异”中的句子
“添加随机性有助于避免陷入好的解决方案,并有助于在搜索空间中找到真正好的和优秀的解决方案。”
我们是指“好的解决方案”=局部最优解。并且
我们是指“真正好的和优秀的解决方案=全局最优解”
还是句子中有一些不妥之处,我们需要这样理解
添加随机性有助于避免“坏”的解决方案,并有助于在搜索空间中找到真正好的和优秀的解决方案。
哪种说法是正确的,请帮助解释一下。
是的,这是一种解释。另一种是欺骗性最优解与不太欺骗性和更好的最优解。
在第 4 节“评估程序引起的差异”中
“此近似值存在偏差,因为我们仅使用少量数据,而不是完整的可能观测集。”
在监督学习中,如果我们能够拥有完整的可能观测集(总体),我认为根本不需要建模。希望我说得对。
没错,您无需预测任何内容,因为您已经可以访问所有数据。这在实践中永远不会发生。
不同的平台会以何种方式改变结果?
例如:
在线性回归模型中,答案如何从 6 变为 8?
当我使用不同的操作系统、Python 版本或 sklearn 版本时
实际上这种情况从来没有发生在我身上!
多种原因,例如
由机器/CPU 精度和舍入误差引起的变化。
由不同的底层数学库版本(例如 BLAS)引起的变化。
由不同的更高级库版本(Python、scikit-learn)引起的变化。
关于数值误差。我来自嵌入式编程领域,由于性能问题,我大量避免使用浮点数,但我了解到某些编译器可以指定浮点数的格式,例如宽松或 IEEE 表示法(参考 IAR 编译器)。
我不确定 Python 中是否可以使用相同的方法,如果可以,那么这个问题肯定会得到缓解。我只是想知道训练库的时间。
Marcelo,你说得太对了,感谢分享!
我列出了库版本/硬件原因,这是为了覆盖我的基础,但我并不期望在实践中会遇到。如果这是原因,其影响会很小。
嗨,Jason,
我想问一个关于随机学习算法随机性的问题。同一算法管道的运行结果会有多大差异?我的问题是一个 CNN 模型——如果我运行训练程序,例如五次,在大多数情况下,我都会得到令人满意的模型结果(AUC ~90%)在我的训练和验证集上。然而,通常有 1-2 次模型根本不想学习,经过 100 个 epoch 后,我的 AUC 指标仍在 50% 左右波动。可能是什么原因?我该如何解决这个问题?忽略那些根本没有学习的模型,只关注那些运行良好的模型,是否合理且合法?
非常感谢您的帮助,您的网站真是信息宝库!
没有限制,取决于模型和数据。
通过重复的经验量化方差并报告均值/标准差。
选择性地忽略模型是无效的。
你好,很棒的文章!
我开发了一个用于识别潜在抗生素的元模型,并筛选了 10 万种化合物。我注意到每次拟合元模型时,我都会得到不同的预测概率和不同的化合物。这是由每个单独模型的随机性引起的吗?
谢谢!
可能是元模型中学习算法的随机性。
我开发了一个卷积神经网络,每次运行时结果都不同,但当我多次运行预测并取平均预测值时,结果相当好。我的逃避局部极小值的方法是否合理,还是仅仅是巧合?
这不是逃避局部极小值,而是降低预测的方差——如上文教程所述。
非常感谢您提供的所有见解和分享的科学知识。
我正在对时间序列训练各种分类模型(多类,带密集层、LSTM、卷积和 ResNet)。效果还不错(即使效果不 equally well)。
我最近决定将我的计算机 GPU 从 RTX 2060S(8GB 内存)升级到全新的 RTX 3090(24GB 内存)。速度的提升非常惊人(快一倍多)……但结果却令人震惊,因为模型不再区分任何东西了(并且对于更复杂的模型,使用种子实现的重现性消失了 :-O)。
一切都完全没有改变,但 GPU……有没有办法在保持速度提升的同时处理这个问题?
提前感谢您的帮助。
祝好,
Jean
太神奇了。我以前从未听说过这种情况。
也许这里的一些想法能帮助你
https://machinelearning.org.cn/reproducible-results-neural-networks-keras/
你好,
我正在使用 AWS DeepAR 预测算法来预测多个品牌的信用卡销售情况。每次我尝试重现它时,我都会得到不同的结果。我希望您能提供任何解决方案。
提前感谢。
是的,请参阅上面的教程,其中详细介绍了这个问题,并选择最适合您项目的解决方案。
我正在使用 k-means 聚类算法对 nsl-kdd 数据集进行入侵检测。
我尝试了不同的种子数进行每次运行,它给出了不同的结果。我认为 k-means 的正确初始化对于获得良好的最终解决方案至关重要。好的,现在我已经通过试错法知道了产生良好准确率(小误差)的种子数。在这里,当我说试错法时,我首先设置种子数,然后运行算法并计算准确率,然后再次设置另一个不同的种子数运行算法并计算准确率,并为每次运行的不同种子数重复此过程,最后选择产生最佳准确率的种子数。在我的 k-means 算法参数设置中使用此种子作为种子数是否可取(可接受)?
如果我使用相同的算法和这个种子数并在另一个数据集上运行,我会得到一个糟糕的结果(准确率较低)。但是通过对这个数据集重复上述过程,我也得到了不同的种子数,可以产生良好的准确率。
你说的“准确率”在聚类中是指什么?
也许可以通过拟合多个最终模型并集成它们的结果来控制模型的方差——例如,也许可以计算模型之间的概率聚类成员关系。
谢谢Jason的回复
当我提到准确率时,我指的是聚类结果的质量。我使用的数据集是带标签的数据集。首先,将第一个类别属性(标签)移除并存储为一个数组,然后进行k-means聚类(不使用类别),最后计算同一类别的实例被聚类到同一簇中的数量。WEKA中的k-means就是这样做的。
感谢分享。
谢谢你的建议。
当对具有不同随机种子(seed)的多次运行取平均值时,我们应该报告开发集(dev set)的平均度量值还是测试集(test set)的平均度量值?
我在多篇论文中看到过这种方法。
测试集。
嗨 Jason
每次运行我的模型时,在尝试使用RandomSearchCv来对抗过拟合时,都会得到不同的超参数值。那么,我该如何选择最终模型来预测未见过的数据呢?
使用一组看起来效果不错的超参数。
谢谢 jason
不客气。
您好,Jason。
我为我的数据集训练了Mask R-CNN,在2个epoch后,损失函数的值为1.20。
每个epoch的网络训练时间非常长,大约需要3个小时。
这个结果合理吗?
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/how-to-know-if-a-model-has-good-performance
在监督学习中,例如分类算法,我如何看到在训练结束时创建/学习到的完整函数组合?
这取决于算法。对于大多数算法来说,这是不可行的(例如,几页的决策树或几页的权重)。
我遇到了一个与预测阶段相关的问题,当我使用相同的模型在相同的数据上重新运行predict_generator函数时,我会得到不同的准确率值。
例如,我的问题主要是针对视频帧的二元识别。
第一次运行结果是68%,下一次运行结果是80%。我对此感到怀疑,我该如何分析和讨论这种情况?我需要您的帮助,让我对这个问题更有信心。
请看 https://machinelearning.org.cn/different-results-each-time-in-machine-learning/
我需要告知您以下几点:
1. 在训练过程开始前,我将数据分为三组[训练-验证-测试],并在分割之前对数据进行了打乱。
2. 数据生成器经过定制,可以生成序列帧样本而不进行打乱。因此,由于我创建了一个用于测试数据的test_generator,所以测试数据被认为是固定的,因此,在训练阶段完成后,predict_generator多次运行的结果应该是固定的,没有任何变化,但实际结果每次运行都不同。
这个信息很棒,谢谢!我有一个关于第4节的问题,我认为我的问题就在那里。差异多大才算太多?我正在使用R的caret包,对一个岭回归模型进行10折交叉验证,并遵循一个教程。我使用TuneGrid来查找最优的lambda值,并用它来确定正确的模型。但是,如果我再次运行代码,有时会得到一个非常不同的R平方值,尽管lambda通常相似。我有一大组来自不同测量类型(measurement types)的变量,我使用每种类型的平均R平方来查看变量是否可以预测其他测量类型(vs. 预测自身类型),或者它们是否应该分开分组。这只是我用来探索大型数据集的几种方法之一,还有聚类和因子分析。所以,这些模型并不是最终分析,只是一个探索性方法。但我确实需要知道这些模型是否相当有效!什么时候应该接受随机性,什么时候运行两次代码得到不同结果是个问题?
嗨Caitlin…您可能会发现以下信息有帮助
https://machinelearning.org.cn/stochastic-in-machine-learning/
嗨,Jason,
我训练了一个深度强化学习(Deep RL)代理,并保存了权重用于回测。当我使用这些权重进行回测时,每次运行的结果都不同。代码中唯一的随机过程是在经验回放(experience replay)中生成输入和目标时。我知道这是我得到不同结果的主要原因,因为预测是基于这些输入和目标的。然而,这对我来说似乎是个问题,因为当我将算法部署到实时交易环境中时,我可能会面临损失。您对这个问题有什么建议吗?
嗨Emre…以下资源可能对您有帮助。
https://machinelearning.org.cn/stochastic-in-machine-learning/#:~:text=A%20variable%20or%20process%20is,randomness%20during%20optimization%20or%20learning.