常见问题

在这里,我们将对邮件列表中经常出现的问题给出一些答案。

项目名称是什么(很多人都弄错了)?

scikit-learn ,不是scikit或SciKit也不是sci-kit learn。同样不是以前使用的scikits.learn或scikits-learn。

您如何发音项目的名称?

sy-kit learn。sci代表科学!

为什么选择scikit?

这里有多个scikits,它们是围绕SciPy构建的科学工具箱。您可以在https://scikits.appspot.com/scikits上找到该列表。除了scikit-learn,另一个流行的是scikit-image

我如何为scikit-learn做出贡献?

请参阅贡献。建议在添加新算法(通常是一项艰巨而漫长的工作)之前,先从已知问题开始 。关于为scikit-learn做贡献,请不要直接与scikit-learn的贡献者联系。

获取scikit-learn说明帮助的最佳方法是什么?

对于一般的机器学习问题,请使用带有[machine-learning]标签的 交叉验证

对于scikit-learn使用问题,请使用带有[scikit-learn][python]标签的Stack Overflow。您也可以使用邮件列表

请确保您提供的代码块尽量简短(最好短于10行),以突出您在虚拟数据集上的问题(例如可以通过sklearn.datasets函数或者通过可设置固定随机种子的numpy.random来生成数据集)。呈现您的问题时请删除不必要的代码行。

只需将代码块复制粘贴到安装了scikit-learn的Python shell中,就可以显示出该问题。不要忘记带上导入语句。

有关编写良好的再现代码段的更多指南,请参见:

https://stackoverflow.com/help/mcve

如果您的问题引发了一个您不理解的异常(即使在对其进行了搜索之后),也请务必要提供完整的运行代码块时得到的提示信息。

如果是错误的报告或功能的请求,请使用GitHub上问题跟踪器

另外还提供了一个scikit-learn的Gitter频道,这里可以联系某些用户及开发人员。

请不要直接给任何作者发送电子邮件,以寻求如报告错误,或与scikit-learn相关的任何其他问题的帮助。

我在工作时应该如何保存,导出或部署估算器?

请参阅模型持久性

如何创建bunch对象?

Bunch对象有时会用作函数和方法的输出。它们可以通过字典的键访问值

bunch["value_key"]或属性访问值bunch.value_key来扩展字典 。

它们不仅仅是作为输出。因此,除非你扩展了scikit-learn的API,否则几乎不需要创建Bunch对象。

如何将自己的数据集加载为scikit-learn可用的格式?

通常,scikit-learn可处理以numpy数组或scipy稀疏矩阵存储的任何数字数据。也可以接受其他可转换为数字数组的类型,例如pandas DataFrame。

有关将数据文件加载到这些可用数据结构中的更多信息,请参考加载外部数据集

新算法的纳入标准是什么?

我们只考虑完善的包含算法。经验法则是自发布以来至少已有3年,被引用200多次,并且被广泛使用。还将考虑在广泛使用的方法上提供明显改进的技术(例如,增强的数据结构或更有效的近似技术)。

从满足上述标准的算法或技术,只有那些的当前API内合身scikit学习,这是一个fitpredict/transform接口和通常具有输入/输出,一个numpy的阵列或稀疏矩阵,被接受。

贡献者应通过研究论文和/或其他类似软件包中的实现来支持所提议的添加的重要性,并通过常见的用例/应用程序来证明其有用性,并通过基准和/或图表来证实性能的改进(如果有)。预期所提出的算法至少应在某些方面优于scikit-learn中已经实现的方法。

在以下情况下,采用新算法加速现有模型更为容易:

  • 它没有引入新的超参数(因为它使库更具前瞻性),
  • 可以很容易地清楚地记录出贡献何时可以提高速度,何时不可以,例如“当n_features >> n_samples”时,
  • 基准显然表明速度有所提高。

另外,请注意,您的实现不必与scikit-learn工具一起使用在scikit-learn中。您可以以scikit-learn兼容的方式实现自己喜欢的算法,然后将其上传到GitHub并告知我们。我们很高兴将其列在“ 相关项目”下。如果您已经在scikit-learn API上的GitHub上有了一个软件包,那么您可能也有兴趣查看scikit-learn-contrib

您为什么如此选择scikit-learn中包含的算法?

代码带来了维护成本,我们需要在拥有的代码量与团队规模之间取得平衡(并在此基础上,复杂度与功能数量成非线性比例关系)。该软件包依靠核心开发人员利用他们的空闲时间来修复错误,维护代码和检查贡献。添加的任何算法都需要开发人员将来注意,这时原始作者可能早就失去了兴趣。另请参阅新算法的包含标准是什么?。有关开放源代码软件中长期维护问题的详细信息,请 参阅《道路和桥梁执行摘要》。

为什么要从scikit-learn中删除HMM?

请参阅是否将图形模型或序列预测添加到scikit-learn?

您是否将图形模型或序列预测添加到scikit-learn?

在不可预见的将来。scikit-learn尝试为机器学习中的基本任务提供统一的API,并使用管道和元算法(例如网格搜索)将所有内容结合在一起。结构化学习所需的概念,API,算法和专业知识与scikit-learn提供的内容不同。如果我们开始进行任意的结构化学习,则需要重新设计整个程序包,并且该项目可能会在其自身的负担下崩溃。

有两个API与scikit-learn类似的项目,可以进行结构化预测:

  • pystruct处理一般的结构化学习(专注于具有近似推理的任意图结构上的SSVM;将样本的概念定义为图结构的实例)
  • seqlearn仅处理序列(专注于精确推断;具有HMM,但主要是出于完整性的考虑;将特征向量视为样本,并对特征向量之间的依赖性使用偏移编码)

您会添加GPU支持吗?

不,或者至少在不久的将来不会。主要原因是GPU支持会引入许多软件依赖关系,并会引入特定于平台的问题。scikit-learn旨在易于安装在各种平台上。在神经网络之外,GPU在当今的机器学习中并未发挥重要作用,并且通过谨慎选择算法通常可以实现更大的速度提升。

你支持PyPy吗?

如果您不知道,PyPy是带有内置即时编译器的可替代Python实现。添加了对PyPy3-v5.10 +的实验支持,需要Numpy 1.14.0+和scipy 1.1.0+。

我该如何处理字符串数据(或树,图形等)?

scikit-learn估计器假定您将向他们提供实值特征向量。这个假设在几乎所有库中都是硬编码的。但是,您可以通过几种方式将非数字输入提供给估计量。

如果您有文本文档,则可以使用术语频率功能;请参阅 内置文本矢量化程序的文本特征提取。有关从任何类型的数据中提取更一般的特征的信息,请参阅 从字典加载特征特征散列

另一个常见的情况是您有非数字数据和这些数据上的自定义距离(或相似性)度量。示例包括具有编辑距离(也称为Levenshtein距离;例如DNA或RNA序列)的字符串。这些可以被编码为数字,但是这样做很麻烦且容易出错。对任意数据使用距离度量可以通过两种方式完成。

首先,许多估算器采用预先计算的距离/相似度矩阵,因此,如果数据集不太大,则可以计算所有输入对的距离。如果数据集很大,则可以仅使用带有一个“特征”的特征向量,这是一个单独数据结构的索引,并提供一个自定义指标函数来查找此数据结构中的实际数据。例如,要使用具有Levenshtein距离的DBSCAN:

>>> from leven import levenshtein       
>>> import numpy as np
>>> from sklearn.cluster import dbscan
>>> data = ["ACCTCCTAGAAG""ACCTACTAGAAGTT""GAATATTAGGCCGA"]
>>> def lev_metric(x, y):
...     i, j = int(x[0]), int(y[0])     # extract indices
...     return levenshtein(data[i], data[j])
...
>>> X = np.arange(len(data)).reshape(-11)
>>> X
array([[0],
       [1],
       [2]])
>>> # We need to specify algoritum='brute' as the default assumes
>>> # a continuous feature space.
>>> dbscan(X, metric=lev_metric, eps=5, min_samples=2, algorithm='brute')
... 
([01], array([ 0,  0-1]))

(这使用第三方编辑距离包leven。)

可以小心地将类似的技巧用于树内核,图形内核等。

为什么有时在OSX或Linux下,n_jobs> 1会导致崩溃/冻结?

一些scikit-learn工具,例如GridSearchCVcross_val_score 内部依赖于Python的multiprocessing模块,通过将n_jobs> 1作为参数,将执行并行化到多个Python进程上。

问题在于,由于性能原因,Python multiprocessing会执行fork系统调用,而不会在其后执行exec系统调用。许多库例如在OSX下运行的Accelerate / vecLib(某些版本),(某些版本的)MKL,GCC的OpenMP运行版,nvidia的Cuda(可能还有许多其他版本)都管理着自己的内部线程池。在调用fork时,子进程中的线程池状态被破坏:线程池认为它有许多线程,而只有主线程状态已经分叉。在这种情况下,可以更改库以使它们检测到何时发生分支并重新初始化线程池:我们对OpenBLAS进行了此操作(自0.2.10开始并入master),并为GCC的OpenMP运行版提供了补丁(尚未审查)。

但最终,真正的罪魁祸首是Python multiprocessing,在没有exec的情况下进行fork,以减少启动和使用新的Python进程进行并行计算的开销。不幸的是,这违反了POSIX标准,因此某些软件编辑器(例如Apple)拒绝将缺少fork安全性的Accelerate / vecLib视为一个bug。

在Python 3.4+中,现在可以配置multiprocessing使用'forkserver'或'spawn'启动方法(而不是默认的'fork')来管理进程池。要在使用scikit-learn时解决此问题,可以将JOBLIB_START_METHOD环境变量设置为“ forkserver”。但是,用户需要注意,使用“ forkserver”方法会阻止joblib.与在Shell会话中交互式定义的函数并行。

如果您直接使用multiprocessing而不是通过joblib自定义代码,则可以为程序全局用'forkserver'模式:在主脚本中插入以下说明:

import multiprocessing

# 其他导入,自定义代码,加载数据,定义模型...

if __name__ == '__main__':
    multiprocessing.set_start_method('forkserver')

    # 这里scikit-learn调用 n_jobs > 1

您可以在多进程处理文档中找到有关新启动方法的更多默认设置。

为什么我的任务使用的内核比n_jobs指定的更多?

这是因为n_jobs仅控制与joblib并行化的常规任务的数量,而并行代码可能来自其他来源:

  • 某些常规的可以与OpenMP并行化(适用于C或Cython编写的代码)。
  • scikit-learn非常依赖numpy,而numpy可能依赖于可以提供并行实现的数值库,例如MKL,OpenBLAS或BLIS。

有关更多详细信息,请参阅我们的Parallelism注释

为什么在scikit-learn中不支持深度学习或强化学习?

深度学习和强化学习都需要丰富的词汇来定义架构,同时深度学习还需要GPU才能进行有效的计算。但是,这些都不符合scikit-learn的设计约束。因此,深度学习和强化学习目前超出了scikit-learn力求实现的范围。

您可以在“你会添加GPU支持吗?”中找到有关添加gpu支持的更多信息 。

请注意,scikit-learn当前实现了一个简单的多层感知器sklearn.neural_network。我们仅接受此模块的错误修复。如果要实现更复杂的深度学习模型,请使用流行的深度学习框架,例如 tensorflowkeraspytorch

为什么我的发起请求没有引起注意?

scikit-learn审查过程会花费大量时间,投稿者不应该因为没有在线或未对发起的请求进行审查而灰心。我们非常注重在第一时间把事情做好,因为维护和后期更改的成本很高。我们很少发布任何“实验”代码,因此我们的所有贡献都将立即受到高度使用,并且最初应具有最高的质量。

除此之外,scikit-learn的审查深度是有限的。许多审稿人和核心开发人员正在用自己的时间来研发scikit-learn。如果对您的发起请求审核缓慢,则可能是因为审核者很忙。我们希望得到您的理解,并请求您不要仅由于这个原因就关闭请求或停止工作。

如何为整个执行设置 random_state

考虑到测试性和可复制性,整个执行由单个种子控制,用于具有随机成分的算法中的伪随机数生成器是非常重要的。Scikit-learn没有使用它的全局随机状态;当没有提供RandomState实例或整数随机种子作为参数时,它就依赖于numpy全局随机状态,可以通过numpy.random.seed来设置该状态。例如,要将执行的numpy全局随机状态设置为42,可以在其脚本中执行以下操作:

import numpy as np
np.random.seed(42)

但是,全局随机状态在执行期间容易被其他代码修改。因此,确保可复制性的唯一方法是将RandomState 实例传递到任何地方,并确保估计器和交叉验证拆分器都具有其random_state参数集。

与其他工具相比,为什么分类变量需要在scikit-learn中进行预处理?

大多数scikit-learn都假设数据位于单个数字类型的NumPy数组或SciPy稀疏矩阵中。这些目前还没有明确表示分类变量。因此,与R的data.frames或pandas.DataFrame不同,我们需要将分类特征显式转换为数值,如编码分类特征中所述。有关使用异构(例如分类和数字)数据的示例,另请参见具有混合类型的列转换器

为什么Scikit-learn无法直接与pandas.DataFrame等一起使用?

当前NumPy和SciPy同质的数据对象在大多数操作过程中处理效率是最高。另外还需要大量工作来支持Pandas 的分类类型。因此,将输入限制为同质类型可以减少维护成本,并鼓励使用有效的数据结构。

您是否打算在pipeline中实现目标y的转换?

当前,变换仅适用于pipeline中的特征X。关于无法在pipeline中转换y的问题由来已久。遵循github问题 #4143。同时查阅 sklearn.compose.TransformedTargetRegressor, [pipegraph](https://github.com/mcasl/PipeGraph), imbalanced-learn。请注意,Scikit-learn解决了以下情况:y在训练之前进行了可逆变换,而在预测之后也可以进行可逆变换。Scikit-learn打算解决一些用例,其中y应该在训练时而不是在测试时进行转换,以进行重采样和类似用途,例如在不平衡学习中。通常,可以使用自定义元估算器而不是pipeline来解决这些用例。