常见问题#

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

有关该项目#

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

scikit-learn,但不是scikit或SciKit也不是sci-Kit learn。也不是以前使用过的scikits.learn或scikits-learn。

项目名称如何发音?#

sy-kit学习sci代表科学!

为什么选择scikit?#

有多个scikits,它们是围绕SciPy构建的科学工具箱。除了scikit-learn之外,另一个受欢迎的是 scikit-image .

你支持PyPy吗?#

由于维护者资源有限且用户数量较少,使用scikit-learn PyPy (an具有内置即时编译器的替代Python实现)不受官方支持。

How can I obtain permission to use the images in scikit-learn for my work?#

中包含的图像 scikit-learn repository 以及内生成的图像 scikit-learn documentation 可以通过 BSD 3-Clause License 为了您的工作。高度鼓励和赞赏引用scikit-learn。看到 citing scikit-learn .

实施决策#

为什么深度学习或强化学习不支持?未来还会有这样的支持吗?#

深度学习和强化学习都需要丰富的词汇来定义架构,深度学习还需要图形处理器来进行高效计算。然而,这两者都不符合scikit-learn的设计限制。因此,深度学习和强化学习目前超出了scikit-learn所寻求实现的目标的范围。

您可以在以下网址找到有关添加图形处理器支持的更多信息 Will you add GPU support? .

请注意,scikit-learn目前在 sklearn.neural_network .我们只接受此模块的错误修复。如果您想实现更复杂的深度学习模型,请转向流行的深度学习框架,例如 tensorflow , keras ,而且 pytorch .

您会向scikit-learn添加图形模型或序列预测吗?#

在可预见的未来不会。scikit-learn试图为机器学习中的基本任务提供统一的API,通过管道和网格搜索等元算法将所有内容联系在一起。结构化学习所需的概念、API、算法和专业知识与scikit-learn所提供的不同。如果我们开始进行任意结构化学习,我们需要重新设计整个包,而项目可能会在其自身的重量下崩溃。

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

  • pystruct 处理一般结构化学习(重点关注具有近似推理的任意图结构上的SSVMs;将样本的概念定义为图结构的实例)。

  • seqlearn 仅处理序列(专注于精确推断;具有螺旋式,但主要是为了完整性;将特征载体视为样本,并对特征载体之间的依赖性使用偏置编码)。

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

看到 您会向scikit-learn添加图形模型或序列预测吗? .

你会添加图形处理器支持吗?#

默认情况下添加GPU支持将引入严重的特定于硬件的软件依赖性,并且需要重新实现现有算法。这将使普通用户更难安装scikit-learn,开发人员更难维护代码。

然而,自2023年以来,有限但不断增长 list of scikit-learn estimators 如果输入数据以PyTorch或CuPy阵列的形式提供,并且scikit-learn已配置为接受此类输入,则可以在图形处理器上运行,如中所述 数组API支持(实验性) .这种Array API支持允许scikit-learn在图形处理器上运行,而不会向主包引入严重的硬件特定软件依赖性。

大多数依赖NumPy进行计算密集型操作的估计器都可以考虑支持Array API,从而支持图形处理器。

然而,出于基本算法原因,并非所有scikit-learn估计器都适合通过Array API在图形处理器上高效运行。例如,目前在scikit-learn中使用Cython实现的基于树的模型从根本上不是基于数组的算法。其他算法(例如k-means或k-近邻)依赖于基于数组的算法,但也在Cython中实现。Cython用于手动交织连续的阵列操作,以避免对大型中间阵列引入性能降低内存访问:这种低级算法重写称为“内核融合”,在可预见的未来无法通过数组API表达。

为无法使用Array API有效实现的估计器添加高效的图形处理器支持需要设计和采用更灵活的scikit-learn扩展系统。在以下GitHub问题(正在讨论中)中正在考虑这种可能性:

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

大多数scikit-learn都假设数据处于NumPy数组或单个数字d类型的SciPy稀疏矩阵中。目前这些尚未明确表示分类变量。因此,与R不同 data.framespandas.DataFrame ,我们需要将分类特征显式转换为数字值,如中所讨论的 编码类别特征 .另见 混合类型的列Transformer 用于处理异类(例如分类和数字)数据的示例。

请注意,最近, HistGradientBoostingClassifierHistGradientBoostingRegressor 通过该选项获得了对分类功能的本地支持 categorical_features="from_dtype" .此选项依赖于根据 pandas.CategoricalDtypepolars.datatypes.Categorical d类型。

scikit-learn是否可以原生地与各种类型的框架一起工作?#

Scikit-learn的支持有限 pandas.DataFramepolars.DataFrame . Scikit-learn估计器可以接受这两种格式作为输入,而Scikit-learn转换器可以使用 set_output API.更多详情请参见 介绍 set_output API .

然而,scikit-learn估计器中的内部计算依赖于在同质数据结构(例如NumPy数组或SciPy稀疏矩阵)上更有效地执行的数字操作。因此,大多数scikit-learn估计器都会在内部将Instrame输入转换为这些同质数据结构。同样,收件箱输出是从这些同质数据结构生成的。

还注意到 ColumnTransformer 通过将按名称或dype选择的pandas列的同质子集映射到专用的scikit-learn转换器,可以方便地处理异类pandas pandem。因此 ColumnTransformer 通常在scikit-learn管道的第一步中使用,当处理异构嵌套框架时(请参见 管道:连锁估计器 了解更多详情)。

另见 混合类型的列Transformer 用于处理异类(例如分类和数字)数据的示例。

您是否计划为目标实现transform y 在管道中?#

Currently transform only works for features X in a pipeline. There's a long-standing discussion about not being able to transform y in a pipeline. Follow on GitHub issue #4143. Meanwhile, you can check out TransformedTargetRegressor, pipegraph, and imbalanced-learn. Note that scikit-learn solved for the case where y has an invertible transformation applied before training and inverted after prediction. scikit-learn intends to solve for use cases where y should be transformed at training time and not at test time, for resampling and similar uses, like at imbalanced-learn. In general, these use cases can be solved with a custom meta estimator rather than a Pipeline.

为什么线性模型有这么多不同的估计量?#

通常,每个模型类型有一个分类器和一个回归量,例如 GradientBoostingClassifierGradientBoostingRegressor .两者都有相似的选项并且都有参数 loss ,这在回归情况下特别有用,因为它可以估计条件均值和条件分位数。

对于线性模型,有许多彼此非常接近的估计器类。让我们来看看

Maintainer perspective: 他们原则上做的都是一样的,不同之处在于他们所施加的惩罚。然而,这对潜在优化问题的解决方式产生了很大影响。最终,这相当于使用线性代数的不同方法和技巧。特殊情况是 SGDRegressor 它包括所有4个之前的模型,并且通过优化程序有所不同。另一个副作用是不同的估计器倾向于不同的数据布局 (X C连续或F连续、稀疏csr或csc)。看似简单的线性模型的复杂性是对不同惩罚使用不同估计器类别的原因。

User perspective: 首先,当前的设计受到科学文献的启发,其中具有不同正规化/罚分的线性回归模型被赋予了不同的名称,例如 ridge regression .拥有具有相应名称的不同模型类使用户更容易找到这些回归模型。其次,如果上面提到的所有5个线性模型都统一到一个类别中,就会有带有很多选项的参数,例如 solver 参数.最重要的是,不同参数之间会有很多排他性的交互。例如,参数的可能选项 solver , precomputeselection 将取决于所选择的惩罚参数值 alphal1_ratio .

贡献#

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

看到 贡献 .在想要添加新算法(这通常是一项重大且漫长的任务)之前,建议从 known issues .请不要直接联系scikit-learn的贡献者,以帮助scikit-learn。

为什么我的拉取请求没有得到任何关注?#

scikit-learn审查过程需要大量时间,贡献者不应因缺乏活动或对其拉取请求的审查而感到沮丧。我们非常关心第一次就把事情做好,因为维护和后来的更改成本很高。我们很少发布任何“实验性”代码,因此我们所有的贡献都将立即得到大量使用,并且最初应该尽可能达到最高质量。

除此之外,scikit-learn的审查带宽有限;许多审查人员和核心开发人员都在利用自己的时间研究scikit-learn。如果对拉取请求的审查进展缓慢,很可能是因为审查者很忙。我们请求您的理解,并要求您不要仅仅因为这个原因而关闭您的pull request或停止您的工作。

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

我们只考虑纳入成熟的算法。经验法则是出版以来至少3年,引用次数超过200次,并且广泛使用和有用。还将考虑纳入对广泛使用的方法提供明确改进的技术(例如增强的数据结构或更有效的逼近技术)。

从满足上述标准的算法或技术来看,只有那些非常适合scikit-learn当前API的算法或技术,即 fit , predict/transform 接口并且通常具有Numpy数组或稀疏矩阵的输入/输出是可以接受的。

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

如果出现以下情况,则更容易纳入加速现有模型的新算法:

  • 它不会引入新的超参数(因为它使库更加面向未来),

  • 很容易清楚地记录贡献何时提高速度以及何时没有提高速度,例如“当 n_features >> n_samples ",

  • 基准数据清楚地显示了速度的提高。

另外,请注意,您的实现不需要在scikit-learn中与scikit-learn工具一起使用。你可以用scikit-learn兼容的方式实现你喜欢的算法,上传到GitHub并告诉我们。我们很乐意将其列在 相关项目 .如果您在GitHub上已经有一个遵循scikit-learn API的包,您可能也有兴趣查看 scikit-learn-contrib .

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

代码伴随着维护成本,我们需要平衡我们拥有的代码量与团队规模(再加上复杂性与功能数量呈非线性扩展的事实)。该包依赖核心开发人员利用空闲时间修复错误、维护代码和审查贡献。添加的任何算法都需要开发人员未来的关注,此时原作者可能早就失去了兴趣。另见 新算法的纳入标准是什么? .要了解有关开源软件长期维护问题的精彩读物,请参阅 the Executive Summary of Roads and Bridges .

使用scikit-learn#

如何开始使用scikit-learn?#

如果您是scikit-learning的新手,或者希望加强您的理解,我们强烈推荐 scikit-learn MOOC (Massive Open Online Course) .

看到我们 External Resources, Videos and Talks page 了解更多详细信息。

获取scikit-learn使用帮助的最佳方法是什么?#

请确保包含最少的复制代码片段(最好短于10行),以突出显示玩具数据集上的问题(例如来自 sklearn.datasets 或使用以下功能随机生成 numpy.random 具有固定的随机种子)。请删除重现您的问题不必要的任何代码行。

只需将您的代码片段复制粘贴到安装了scikit-learn的Python shell中,就可以重现该问题。不要忘记包含导入声明。有关编写良好复制代码片段的更多指导,请访问:https://stackoverflow.com/help/mcve

如果您的问题引发了您不理解的异常(即使在Google搜索之后),请确保包含您在运行复制脚本时获得的完整追溯。

有关错误报告或功能请求,请使用 issue tracker on GitHub .

警告

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

我应该如何保存、出口或部署估计器以进行生产?#

看到 模型持久性 .

如何创建一个堆对象?#

束对象有时用作函数和方法的输出。他们通过允许通过键访问值来扩展字典, bunch["value_key"] ,或者通过属性, bunch.value_key .

它们不应用作输入。因此,您几乎永远不需要创建一个 Bunch 对象,除非您正在扩展scikit-learn的API。

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

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

有关将数据文件加载到这些可用数据结构中的更多信息,请参阅 loading external datasets .

如何处理字符串数据(或树、图形.)?#

scikit-learn估计器假设您将向他们提供实值特征载体。这个假设在几乎所有图书馆中都被硬编码。然而,您可以通过多种方式向估计器提供非数字输入。

如果您有文本文档,则可以使用术语频率特征;请参阅 文本特征提取 对于内置的 text vectorizers .有关从任何类型的数据中提取更一般的特征,请参阅 从文本加载功能特征哈希 .

另一种常见情况是,当您拥有非数字数据和这些数据的自定义距离(或相似性)指标时。示例包括具有编辑距离的字符串(又名。Levenshtein距离),例如DNA或RNA序列。这些可以被编码为数字,但这样做是痛苦的且容易出错的。在任意数据上使用距离指标可以通过两种方式完成。

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

>>> import numpy as np
>>> from leven import levenshtein
>>> 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(-1, 1)
>>> X
array([[0],
       [1],
       [2]])
>>> # We need to specify algorithm='brute' as the default assumes
>>> # a continuous feature space.
>>> dbscan(X, metric=lev_metric, eps=5, min_samples=2, algorithm='brute')
(array([0, 1]), array([ 0,  0, -1]))

请注意,上面的示例使用第三方编辑距离包 leven .对于树核、图核等,可以谨慎使用类似的技巧。

为什么我有时会崩溃/冻结 n_jobs > 1 在NSX还是Linux下?#

Several scikit-learn tools such as GridSearchCV and cross_val_score rely internally on Python's multiprocessing module to parallelize execution onto several Python processes by passing n_jobs > 1 as an argument.

问题是Python multiprocessing 做了一个 fork 系统调用,而不跟随 exec 由于性能原因系统调用。许多库,例如(某些版本)NSX下的Accelerate或vecLib、(某些版本)MKL、GCC的BEP运行时、nvidia的Cuda(可能还有许多其他库),管理自己的内部线程池。接到电话后 fork, the thread pool state in the child process is corrupted: the thread pool believes it has many threads while only the main thread state has been forked. It is possible to change the libraries to make them detect when a fork happens and reinitialize the thread pool in that case: we did that for OpenBLAS (merged upstream in main since 0.2.10) and we contributed a patch 到GCC的OpenMP运行时(尚未审查)。

但最终真正的罪魁祸首是Python的 multiprocessing 这并 fork 没有 exec 以减少启动和使用新的Python进程进行并行计算的费用。不幸的是,这违反了BOX标准,因此Apple等一些软件编辑器拒绝将Accelerate和vecLib中缺乏fork安全性视为一个错误。

在Python 3.4+中,现在可以配置 multiprocessing 使用 "forkserver""spawn" 启动方法(而不是默认方法 "fork" )来管理流程池。要在使用scikit-learn时解决此问题,您可以设置 JOBLIB_START_METHOD 环境变量来 "forkserver" .然而,用户应该注意,使用 "forkserver" 方法防止 joblib.Parallel 调用在shell会话中交互式定义的函数。

如果您有自定义代码, multiprocessing 直接使用,而不是通过 joblib 您可以启用 "forkserver" 为您的计划提供全球模式。在主脚本中插入以下说明::

import multiprocessing

# other imports, custom code, load data, define model...

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

    # call scikit-learn utils with n_jobs > 1 here

您可以在中找到有关新启动方法的更多详细信息 multiprocessing documentation .

为什么我的工作使用的核心比指定的更多 n_jobs ?#

这是因为 n_jobs 仅控制与 joblib ,但并行代码可以来自其他来源:

  • 某些例程可以与BEP并行化(对于用C或Cython编写的代码),

  • scikit-learn在很大程度上依赖于numpy,而numpy反过来又可能依赖于MKL、OpenBLAS或BLIS等可以提供并行实现的数字库。

欲了解更多详情,请参阅我们的 notes on parallelism .

如何设置 random_state 整个处决?#

请参阅 控制随机性 .