贡献#

该项目是一项社区努力,欢迎每个人做出贡献。它托管在https://github.com/scikit-learn/scikit-learn上。scikit-learn的决策流程和治理结构在 Scikit-learn治理和决策 .

Scikit-learn在某种程度上 selective 当谈到添加新算法时,贡献和帮助项目的最佳方式是开始解决已知问题。看到 新贡献者的问题 开始。

如果您在使用此套餐时遇到问题,请立即向 GitHub issue tracker .还欢迎您发布功能请求或拉取请求。

贡献的方法#

有很多方法可以为scikit-learn做出贡献,其中最常见的是为项目贡献代码或文档。改进文档与改进库本身同样重要。 如果您在文档中发现拼写错误,或者进行了改进,请毫不犹豫地创建GitHub问题,或者最好提交GitHub拉取请求。完整的文档可以在Doc/目录下找到。

但还有很多其他方法可以提供帮助。尤其是帮助 improve, triage, and investigate issuesreviewing other developers' pull requests 都是非常有价值的贡献,可以减轻项目维护人员的负担。

另一种贡献的方式是报告您面临的问题,并对其他人报告的且与您相关的问题给予“大拇指”。 如果您传播这个消息,这也会对我们有帮助:从您的博客和文章中引用该项目,从您的网站链接到该项目,或者只是简单地说“我使用它”:

如果贡献/问题涉及API原则的变更或依赖项或支持版本的变更,则必须得到 改善建议(SLEPs) ,其中SLEP必须作为拉取请求提交给 enhancement proposals 使用 SLEP template 并遵循中概述的决策过程 Scikit-learn治理和决策 .

为相关项目做出贡献#

Scikit-learn在由多个相关项目组成的生态系统中蓬勃发展,这些项目也可能有相关问题需要解决,包括小型项目,例如:

以及更大的项目:

查找标记为“需要帮助”或类似的问题。帮助这些项目也可能有助于scikit-learning。另见 相关项目 .

自动缴款政策#

请避免提交问题或提取由全自动工具生成的请求。维护者保留自行决定关闭此类提交并阻止对其负责的任何帐户的权利。

理想情况下,应以问题的形式进行人与人的讨论。

提交错误报告或功能请求#

我们使用GitHub问题来跟踪所有错误和功能请求;如果您发现错误或希望看到功能实现,请随时打开问题。

如果您在使用此套餐时遇到问题,请立即向 Bug Tracker .还欢迎您发布功能请求或拉取请求。

建议在提交之前检查您的问题是否符合以下规则:

如何制作一份好的错误报告#

When you submit an issue to GitHub, please do your best to follow these guidelines! This will make it a lot easier to provide you with good feedback:

  • 理想的bug报告包含一个 short reproducible code snippet ,这样任何人都可以尝试轻松复制该错误。如果您的片段长度超过50行左右,请链接到 Gist 或者GitHub仓库

  • 如果不可行,包括可复制的片段,请具体说明是什么 estimators and/or functions are involved and the shape of the data .

  • 如果出现例外,请 provide the full traceback .

  • 请包括您 operating system type and version number ,以及您的 Python, scikit-learn, numpy, and scipy versions .此信息可以通过运行以下操作来找到:

    python -c "import sklearn; sklearn.show_versions()"
    
  • 请确保所有 code snippets and error messages are formatted in appropriate code blocks . 看到 Creating and highlighting code blocks 了解更多详细信息。

如果您想帮助策划问题,请阅读有关 错误分类和发布策展 .

贡献代码#

备注

To avoid duplicating work, it is highly advised that you search through the issue tracker and the PR list. If in doubt about duplicated work, or if you want to work on a non-trivial feature, it's recommended to first open an issue in the issue tracker to get some feedback from core developers.

One easy way to find an issue to work on is by applying the "help wanted" label in your search. This lists all the issues that have been unclaimed so far. In order to claim an issue for yourself, please comment exactly /take on it for the CI to automatically assign the issue to you.

为了保持代码库的质量并简化审查过程,任何贡献都必须符合项目的 coding guidelines ,特别是:

  • 不要修改不相关的行以使公关专注于其描述或问题中所述的范围。

  • 只写增加价值并避免陈述显而易见的内容的内联评论:解释“为什么”而不是“什么”。

  • Most importantly :不要贡献您不理解的代码。

视频资源#

这些视频是关于如何为scikit-learn做出贡献的分步介绍,是以下文本指南的绝佳伴侣。请确保仍然查看下面的指南,因为它们描述了我们最新的最新工作流程。

备注

2021年1月,默认分行名称从 mastermain 让scikit-learn GitHub存储库使用更具包容性的术语。这些视频是在分支更名之前创建的。对于查看这些视频以设置工作环境并提交公关的贡献者, master 应更换为 main .

如何贡献#

为scikit-learn做出贡献的首选方式是将 main repository 在GitHub上,然后提交“拉取请求”(PR)。

在前几步中,我们解释了如何本地安装scikit-learn,以及如何设置您的git存储库:

  1. Create an account 如果您还没有,请在GitHub上。

  2. 用叉子叉 project repository :单击页面顶部附近的“Fork”按钮。这会在您的GitHub用户帐户下创建代码的副本。有关如何分叉存储库的更多详细信息,请参阅 this guide .

  3. 将scikit-learn repo的分支从您的GitHub帐户克隆到您的本地磁盘:

    git clone git@github.com:YourLogin/scikit-learn.git  # add --depth 1 if your connection is slow
    cd scikit-learn
    
  4. 遵循中的步骤2-6 从源头建设 以开发模式构建scikit-learn并返回本文档。

  5. 安装开发依赖项:

    pip install pytest pytest-cov ruff==0.11.2 mypy numpydoc
    
  1. 添加 upstream 遥控器这保存了对主scikit-learn存储库的引用,您可以使用它使您的存储库与最新更改同步:

    git remote add upstream git@github.com:scikit-learn/scikit-learn.git
    
  2. 检查 upstreamorigin 通过运行以下操作正确配置远程别名:

    git remote -v
    

    这应该显示:

    origin    git@github.com:YourLogin/scikit-learn.git (fetch)
    origin    git@github.com:YourLogin/scikit-learn.git (push)
    upstream  git@github.com:scikit-learn/scikit-learn.git (fetch)
    upstream  git@github.com:scikit-learn/scikit-learn.git (push)
    

您现在应该已经安装了scikit-learn,并且您的git存储库已正确配置。运行一些测试来验证您的安装可能会很有用。请参阅 有用的pytest别名和标志 例如。

接下来的步骤现在描述修改代码和提交PR的过程:

  1. 同步您 main 支管和 upstream/main branch,详细信息 GitHub Docs :

    git checkout main
    git fetch upstream
    git merge upstream/main
    
  2. 创建一个功能分支来保存您的开发更改:

    git checkout -b my_feature
    

    并开始做出改变。始终使用功能分支。永远不要在 main 树枝!

  3. ( Optional )安装 pre-commit 在每次提交之前运行代码风格检查:

    pip install pre-commit
    pre-commit install
    

    可以对特定的提交禁用预提交检查 git commit -n .

  4. 在您的计算机上的特性分支上开发特性,使用Git进行版本控制。完成编辑后,使用 git add 然后 git commit :

    git add modified_files
    git commit
    

    在Git中记录您的更改,然后使用以下操作将更改推送到您的GitHub帐户:

    git push -u origin my_feature
    
  5. 遵循 these 从您的分叉创建拉取请求的说明。这将向潜在的审查者发送通知。您可能需要考虑向 discord 如果您的拉取请求几天后没有得到关注,请在开发渠道中获得更多可见性(但并不能保证立即回复)。

保持本地功能分支与scikit-learn主存储库的最新更改同步通常很有帮助:

git fetch upstream
git merge upstream/main

随后,您可能需要解决冲突。您可以参考 Git documentation related to resolving merge conflict using the command line .

拉取请求清单#

在PR可以合并之前,它需要得到两个核心开发人员的批准。一个不完整的贡献--你期望在收到完整的评论之前做更多的工作--应该被标记为 draft pull request 成熟后改为“准备审查”。PR草案可能有助于:表明您正在研究一些事情以避免重复工作、请求对功能或API进行广泛审查,或者寻找合作者。PR草案通常受益于纳入 task list 在公关描述中。

为了简化审查过程,我们建议您的贡献在将PR标记为“准备好审查”之前遵守以下规则。的 bolded 其中一些尤其重要:

  1. Give your pull request a helpful title 总结了你的贡献这个标题通常会成为合并后的提交信息,所以它应该总结你的贡献给后代。在某些情况下,“修复<ISSUE TITLE>”就足够了。“修复#<ISSUE NUMBER>“从来都不是一个好标题。

  2. Make sure your code passes the tests .整个测试套件都可以运行 pytest ,但通常不建议这样做,因为需要很长时间。通常只需运行与您的更改相关的测试即可:例如,如果您在中更改了某些内容 sklearn/linear_model/_logistic.py ,运行以下命令通常就足够了:

    • pytest sklearn/linear_model/_logistic.py 确保doctestest示例正确

    • pytest sklearn/linear_model/tests/test_logistic.py 运行特定于该文件的测试

    • pytest sklearn/linear_model 测试整体 linear_model 模块

    • pytest doc/modules/linear_model.rst 以确保用户指南示例正确。

    • pytest sklearn/tests/test_common.py -k LogisticRegression 运行我们所有的估计器检查(专门针对 LogisticRegression ,如果这是您更改的估计器)。

    可能还有其他失败的测试,但它们会被CI捕获,因此您不需要在本地运行整个测试套件。有关如何使用的指南 pytest 高效地,查看 有用的pytest别名和标志 .

  3. Make sure your code is properly commented and documented ,而且 make sure the documentation renders properly .要构建文档,请参阅我们的 文件 指南CI还将构建文档:请参阅 生成有关GitHub Action的文档 .

  4. Tests are necessary for enhancements to be accepted .应提供错误修复或新功能 non-regression tests .这些测试验证修复或功能的正确行为。以这种方式,对代码库的进一步修改被授权以与期望的行为一致。在修复错误的情况下,在PR时, main 分支并传递PR代码。

  5. 如果您的公关可能会影响用户,则需要添加一个变更日志条目来描述您的公关更改。看到 README 了解更多详细信息。

  6. 遵循 编码指南 .

  7. 如果适用,请使用中的验证工具和脚本 sklearn.utils module.可在 开发人员的实用程序 页.

  8. 拉取请求通常可以解决一个或多个其他问题(或拉取请求)。如果合并您的拉取请求意味着应该关闭一些其他问题/PR,则您应该 use keywords to create link to them (e.g., Fixes #1234 ;只要每个问题/PR前面有一个关键字,就允许多个问题/PR)。合并后,这些问题/PR将被GitHub自动关闭。如果您的拉取请求只是与一些其他问题/PR相关,或者它只部分解决了目标问题,请创建指向它们的链接,而不使用关键字(例如, Towards #1234 ).

  9. PR应该经常通过绩效和效率基准来证实变革(请参阅 监测业绩 )或通过使用示例。示例还向用户说明了该库的功能和复杂性。看看中的其他例子 examples/ 目录参考。示例应该说明为什么新功能在实践中有用,如果可能的话,将其与scikit-learn中的其他方法进行比较。

  10. 新功能需要一些维护费用。我们希望公关作者至少在最初参与他们提交的代码的维护。新功能需要在用户指南中通过叙述性文档和小代码片段来说明。如果相关,请在文献中添加参考文献,并在可能的情况下添加PDF链接。

  11. 用户指南还应包括算法的预期时间和空间复杂性以及可扩展性,例如“该算法可以扩展到大于100000的大量样本,但在维度上不扩展: n_features 预计低于100”。

您还可以查看我们的 代码审查指南 了解评论者的期望。

您可以使用以下工具检查常见的编程错误:

  • 具有良好单元测试覆盖率(至少80%,最好100%)的代码,请检查:

    pip install pytest pytest-cov
    pytest --cov sklearn path/to/tests
    

    另见 测试和提高测试覆盖率 .

  • 运行静态分析 mypy :

    mypy sklearn
    

    这不得在您的拉取请求中产生新错误。使用 # type: ignore 对于mypy不支持的少数情况,注释可以作为解决方案,特别是,

    • 当导入C或Cython模块时,

    • 有装修的房子

包含性能分析和基准脚本和分析输出的贡献将获得额外积分(请参阅 监测业绩 ).另请查看 如何优化速度 有关分析和Cython优化的更多详细信息的指南。

备注

scikit-learn代码库的当前状态不符合所有这些指导方针,但我们预计对所有新贡献实施这些限制将使整体代码库质量朝着正确的方向发展。

参见

有关开发工作流程的两个有详细记录且更详细的指南,请访问 Scipy Development Workflow - 和 Astropy Workflow for Developers 路段

持续集成(CI)#

  • Azure管道用于在Linux、Mac和Windows上测试scikit-learn,具有不同的依赖项和设置。

  • CircleCI用于构建文档以供查看。

  • Github Action用于各种任务,包括构建轮和源分发。

提交消息标记#

请注意,如果最新提交消息中出现以下标记之一,则会采取以下操作。

提交消息标记

CI采取的行动

[ci skip]

完全跳过CI

[cd build]

CD已运行(轮子和源分发已构建)

[lint skip]

Azure管道跳过棉绒

[scipy-dev]

使用我们的依赖项(numpy、scipy等)构建和测试开发版本

[free-threaded]

使用CPython 3.13自由线程构建和测试

[pyodide]

使用Pyodide构建和测试

[azure parallel]

并行运行Azure CI作业

[float32]

通过设置运行float 32测试 SKLEARN_RUN_FLOAT32_TESTS=1 .看到 环境变量 更多详情

[doc skip]

收件箱未建成

[doc quick]

已建成,但不包括示例画廊地块

[doc build]

已建成,包括示例画廊地块(非常长)

请注意,默认情况下,会生成文档,但仅执行由拉取请求直接修改的示例。

解决锁定文件中的冲突#

下面是一个bash代码片段,可以帮助解决环境和锁文件中的冲突:

# pull latest upstream/main
git pull upstream main --no-rebase
# resolve conflicts - keeping the upstream/main version for specific files
git checkout --theirs  build_tools/*/*.lock build_tools/*/*environment.yml \
    build_tools/*/*lock.txt build_tools/*/*requirements.txt
git add build_tools/*/*.lock build_tools/*/*environment.yml \
    build_tools/*/*lock.txt build_tools/*/*requirements.txt
git merge --continue

This will merge upstream/main into our branch, automatically prioritising the upstream/main for conflicting environment and lock files (this is good enough, because we will re-generate the lock files afterwards).

请注意,这仅修复环境和锁定文件中的冲突,并且您可能还有其他冲突需要解决。

最后,我们必须通过运行以下命令重新生成环境并锁定CI的文件:

python build_tools/update_environments_and_lock_files.py

暂停拉取请求#

由于贡献功能可能是一个漫长的过程,因此一些拉取请求似乎不活动但未完成。在这种情况下,接管它们对项目来说是一个很好的服务。接管的良好礼仪是:

  • Determine if a PR is stalled

    • 如果我们已经将拉取请求识别为其他贡献者的候选项,则拉取请求的标签可能会“停滞”或“需要帮助”。

    • 要决定一个不活动的PR是否被搁置,请询问贡献者是否计划在不久的将来继续处理PR。未能在2周内通过推动PR的活动做出回应,表明PR处于停滞状态,并将导致PR标记为“需要帮助”。

      请注意,如果PR收到了对该贡献的早期评论,但在一个月内没有收到回复,则可以放心地认为PR已停止并将等待时间缩短至一天。

      冲刺结束后,冲刺期间打开的未合并PR的后续信息将传达给冲刺的参与者,并且这些PR将被标记为“冲刺”。带有“sprint”标签的PR可以被sprint领导者重新分配或宣布停止。

  • Taking over a stalled PR :要接管公关,重要的是要对您正在接管的陷入停滞的公关发表评论,并将新公关链接到旧公关。新的公关应该通过从旧的公关中提取来创建。

停滞和无人认领的问题#

一般来说,可供争夺的问题都会有 "help wanted" .标签然而,并非所有需要贡献者的问题都会有此标签,因为“需要帮助”标签并不总是与问题的状态保持最新。贡献者可以使用以下指南查找仍有待解决的问题:

  • 一是 determine if an issue is claimed :

    • 检查链接的拉取请求

    • 检查对话以查看是否有人表示他们正在创建拉取请求

  • 如果贡献者对某个问题发表评论并表示他们正在解决该问题,预计将在2周内(新贡献者)或4周内(贡献者或核心开发者)发出拉取请求,除非明确给出更长的时间范围。在此之后,另一位贡献者可以处理该问题并对其提出拉取请求。我们鼓励贡献者直接对陷入停滞或无人认领的问题发表评论,让社区成员知道他们将致力于解决该问题。

  • 如果问题与 stalled pull request ,我们建议贡献者遵循中描述的程序 暂停拉取请求 而不是直接处理这个问题。

新贡献者的问题#

新贡献者在查找问题时应查找以下标签。 我们强烈建议新贡献者首先解决“简单”的问题:这有助于贡献者熟悉贡献工作流程,并帮助核心开发者熟悉贡献者;除此之外,我们经常低估问题的容易解决!

  • Good first issue tag

    开始为scikit-learn做出贡献的一个好方法是从列表中选择一个项目 good first issues 在问题跟踪器中。解决这些问题可以让您在没有太多先验知识的情况下开始为项目做出贡献。如果您已经对scikit-learn做出了贡献,则应该查看Easy issue。

  • Easy tag

    如果您已经对scikit-learn做出了贡献,则对scikit-learn做出贡献的另一种好方法是从列表中选择一个项目 Easy issues 在问题跟踪器中。经验丰富的开发人员将非常感谢您在这方面的帮助,因为这有助于腾出时间来专注于其他问题。

  • Help wanted tag

    我们经常使用“需要帮助”标签来标记问题,无论难度如何。此外,我们使用“需要帮助”标签来标记已被原始贡献者放弃的拉取请求,并可供某人继续原始贡献者停止的地方。可以找到“需要帮助”标签的问题列表 here .请注意,并非所有需要贡献者的问题都会有此标签。

文件#

我们很高兴接受任何形式的文件:

  • Function/method/class docstrings: 它们也称为“API文档”,描述对象的功能并详细说明任何参数、属性和方法。文档字符串与代码一起存在 sklearn/ ,并根据 doc/api_reference.py .要添加、更新、删除或弃用中列出的公共API,请执行以下操作: API参考 ,这就是值得一看的地方。

  • User guide: 这些提供了有关scikit-learn中实现的算法的更详细信息,并且通常位于根目录中 doc/ 目录和 doc/modules/ .

  • Examples: 这些提供了完整的代码示例,可以演示scikit-learn模块的使用、比较不同的算法或讨论其解释等。示例位于 examples/ .

  • Other reStructuredText documents: 这些提供了各种其他有用的信息(例如,的 贡献 指南)并居住在 doc/ .

文档字符串编写指南#
  • 您可以使用 pytest 测试文档字符串,例如假设 RandomForestClassifier doc字符串已被修改,以下命令将测试其doc字符串合规性:

    pytest --doctest-modules sklearn/ensemble/_forest.py -k RandomForestClassifier
    
  • 部分的正确顺序是:参数、返回、另请参阅、注释、示例。看到 numpydoc documentation 有关其他可能部分的信息。

  • 在记录参数和属性时,这里列出了一些格式良好的示例

    n_clusters : int, default=3
        The number of clusters detected by the algorithm.
    
    some_param : {"hello", "goodbye"}, bool or int, default=True
        The parameter description goes here, which can be either a string
        literal (either `hello` or `goodbye`), a bool, or an int. The default
        value is True.
    
    array_parameter : {array-like, sparse matrix} of shape (n_samples, n_features) \
        or (n_samples,)
        This parameter accepts data in either of the mentioned forms, with one
        of the mentioned shapes. The default value is `np.ones(shape=(n_samples,))`.
    
    list_param : list of int
    
    typed_ndarray : ndarray of shape (n_samples,), dtype=np.int32
    
    sample_weight : array-like of shape (n_samples,), default=None
    
    multioutput_array : ndarray of shape (n_samples, n_classes) or list of such arrays
    

    一般来说,请记住以下几点:

    • Use Python basic types. (bool instead of boolean)

    • 使用括号定义形状: array-like of shape (n_samples,)array-like of shape (n_samples, n_features)

    • 对于具有多个选项的字符串,请使用括号: input: {'log', 'squared', 'multinomial'}

    • 1D or 2D data can be a subset of {array-like, ndarray, sparse matrix, dataframe}. Note that array-like can also be a list, while ndarray is explicitly only a numpy.ndarray.

    • 指定 dataframe 当使用“类似框架”的功能时,例如列名。

    • 指定列表的数据类型时,请使用 of 作为收件箱: list of int .当参数支持提供有关形状和/或数据类型的详细信息的数组以及此类数组列表时,您可以使用以下之一 array-like of shape (n_samples,) or list of such arrays .

    • 当指定ndarray的dtype时,使用例如 dtype=np.int32 定义形状后: ndarray of shape (n_samples,), dtype=np.int32 .您可以将多个dype指定为一个集合: array-like of shape (n_samples,), dtype={np.float64, np.float32} .如果想提及任意精确度,请使用 integralfloating 而不是Python dtype intfloat .当两 intfloating 都支持,无需指定dype。

    • 当默认为 None , None 只需在结尾处指定 default=None .请确保在文档字符串中包含参数或属性的含义 None .

  • 在相关类/函数的文档字符串中添加“另请参阅”。

  • 文档字符串中的“See Also”应该是每个引用一行,加上冒号和解释,例如:

    See Also
    --------
    SelectKBest : Select features based on the k highest scores.
    SelectFpr : Select features based on a false positive rate test.
    
  • “注释”部分是可选的。它旨在提供有关函数/类/类方法/方法的特定行为的信息。

  • A Note 也可以添加到属性,但在这种情况下需要使用 .. rubric:: Note 指令。

  • 增加一两 snippets “示例”部分中的代码以展示如何使用它。代码应该可以按原样运行,即它应该包括所有所需的导入。本节尽可能简短。

编写用户指南和其他reStructured文本文档的指南#

重要的是要在数学和算法细节之间保持良好的妥协,并让读者直观地了解算法的作用。

  • 首先简要地解释算法/代码对数据的作用。

  • Highlight the usefulness of the feature and its recommended application. Consider including the algorithm's complexity (\(O\left(g\left(n\right)\right)\)) if available, as "rules of thumb" can be very machine-dependent. Only if those complexities are not available, then rules of thumb may be provided instead.

  • 合并相关的数字(从示例中生成)以提供直觉。

  • 包括一两个简短的代码示例来演示该功能的使用。

  • 引入任何必要的数学方程,然后是参考文献。通过推迟数学方面,主要对了解该功能的实际含义而不是其基本机制感兴趣的用户更容易访问该文档。

  • 编辑reStructured文本时 (.rst )文件,尽可能将行长度保持在88个字符以下(例外包括链接和表格)。

  • 在scikit-learn reStructuredText文件中,文本周围的单引号和双引号都将呈现为内联文字(通常用于代码,例如, list ).这是由于我们设置了特定的配置造成的。现在应该使用单回勾。

  • 过多的信息使用户难以访问他们感兴趣的内容。使用以下语法使用下拉列表对其进行因子分解

    .. dropdown:: Dropdown title
    
      Dropdown content.
    

    上面的片段将产生以下收件箱:

    下拉标题#

    下拉内容。

  • 默认情况下可以使用下拉列表隐藏的信息是:

    • 低层次部分,例如 References , Properties 等(例如,请参阅中的小节 检测错误权衡(DET) );

    • 深入的数学细节;

    • 特定于用例的叙述;

    • 一般来说,叙事可能只会让那些想要超越特定工具的实用性的用户感兴趣。

  • 不要在低级别部分使用下拉列表 Examples ,因为它应该对所有用户保持可见。请确保 Examples 部分正好在主要讨论之后,中间是可能折叠最少的部分。

  • 请注意,下拉列表会打破交叉引用。如果这有意义,请将引用与提及它的文本一起隐藏。否则,不要使用收件箱。

参考文献撰写指南#
  • 当有参考书目时 arxivDigital Object Identifier 识别号,使用phinx指令 :arxiv::doi: .例如,请参阅中的参考文献 Spectral Clustering Graphs .

  • 有关文档字符串中的“引用”部分,请参阅 sklearn.metrics.silhouette_score 作为一个例子。

  • 要交叉引用scikit-learn文档中的其他页面,请使用reStructuredtext交叉引用语法:

    • Section: 要链接到文档中的任意部分,请使用参考标签(请参阅 Sphinx docs ).例如:

      .. _my-section:
      
      My section
      ----------
      
      This is the text of the section.
      
      To refer to itself use :ref:`my-section`.
      

      您不应该修改现有的sphinx参考标签,因为这会破坏现有的交叉引用和指向scikit-learn文档中特定章节的外部链接。

    • Glossary: 链接到中的术语 常用术语和API元素词汇表 :

      :term:`cross_validation`
      
    • Function: 要链接到函数的文档,请使用该函数的完整导入路径:

      :func:`~sklearn.model_selection.cross_val_score`
      

      但如果出现 .. currentmodule:: 如果您在文档中上方的指令,则您只需使用指定的当前模块后面的函数的路径。例如:

      .. currentmodule:: sklearn.model_selection
      
      :func:`cross_val_score`
      
    • Class: 要链接到类的文档,请使用该类的完整导入路径,除非有 .. currentmodule:: 上述文件中的指令(见上文):

      :class:`~sklearn.preprocessing.StandardScaler`
      

您可以使用任何文本编辑器编辑文档,然后通过以下操作生成HTML输出 构建文档 .生成的HTML文件将被放置在 _build/html/ 并且例如通过打开本地 _build/html/index.html 文件或通过运行本地服务器

python -m http.server -d _build/html

构建文档#

Before submitting a pull request check if your modifications have introduced new sphinx warnings by building the documentation locally and try to fix them.

首先,确保您有 properly installed 开发版本。最重要的是,构建文档需要安装一些额外的软件包:

pip install sphinx sphinx-gallery numpydoc matplotlib Pillow pandas \
            polars scikit-image packaging seaborn sphinx-prompt \
            sphinxext-opengraph sphinx-copybutton plotly pooch \
            pydata-sphinx-theme sphinxcontrib-sass sphinx-design \
            sphinx-remove-toctrees

要构建文档,您需要在 doc 文件夹:

cd doc

在绝大多数情况下,您只需生成不包含示例库的网站:

make

该文档将在 _build/html/stable 目录并可在Web浏览器中查看,例如通过打开本地 _build/html/stable/index.html 文件.要生成示例库,您可以用途:

make html

这将运行所有示例,这需要一段时间。您还可以根据几个示例的文件名仅运行它们。以下是一种运行所有示例的方法,文件名包含 plot_calibration :

EXAMPLES_PATTERN="plot_calibration" make html

您可以将正规表达用于更高级的用例。

设置环境变量 NO_MATHJAX=1 如果您打算在离线设置中查看文档。要构建PDF手册,请运行:

make latexpdf

斯芬克斯版本

虽然我们尽最大努力在尽可能多的Sphinx版本下构建文档,但不同版本的行为往往略有不同。为了获得最佳结果,您应该使用与我们在CircleCI上使用的版本相同的版本。看看这个 GitHub search 要知道确切的版本。

生成有关GitHub Action的文档#

当您更改拉取请求中的文档时,GitHub Operations会自动构建它。要查看GitHub Operations生成的文档,只需转到PR页面的底部,查找“Check the rendering docs here!”并点击旁边的“详情”:

../_images/generated-doc-ci.png

测试和提高测试覆盖率#

高质量 unit testing 是scikit-learn开发过程的基石。为此目的,我们使用 pytest 包.这些测试是命名适当的函数,位于 tests 子目录,检查算法的有效性和代码的不同选项。

运行 pytest 将运行相应子包的所有测试。为了更详细地 pytest 工作流程,请参阅 拉取请求清单 .

我们希望新功能的代码覆盖率至少在90%左右。

编写matplotlib相关测试#

测试固定装置确保通过适当的初始化和清理执行一组测试。scikit-learn测试套件实现了 pyplot 可配合使用的固定装置 matplotlib .

pyplot 当测试功能处理时应使用固定装置 matplotlib . matplotlib 是一种软依赖,不需要。如果出现以下情况,该装置负责跳过测试 matplotlib 未安装。此外,一旦执行测试功能,测试期间创建的图形将自动关闭。

要在测试函数中使用此fixture,需要将其作为参数传递:

def test_requiring_mpl_fixture(pyplot):
    # you can now safely use matplotlib
提高测试覆盖率的工作流程#

要测试代码覆盖率,您需要安装 coverage 除了 pytest .

  1. 运行 pytest --cov sklearn /path/to/tests .输出列出了每个文件未测试的行号。

  2. 找到一个低挂的水果,看看哪些行没有测试,专门针对这些行编写或调整测试。

  3. 循环.

监测业绩#

This section is heavily inspired from the pandas documentation .

当提议对现有代码库进行更改时,确保它们不会引入性能回归非常重要。Scikit-learn使用 asv benchmarks 监控选定的常用估计器和函数的性能。您可以在 scikit-learn benchmark page .相应的基准套件可以在 asv_benchmarks/ 目录.

要使用asv的所有功能,您需要之一 conda or virtualenv. For more details please check the asv installation webpage .

首先您需要安装asv的开发版本:

pip install git+https://github.com/airspeed-velocity/asv

并将目录更改为 asv_benchmarks/ :

cd asv_benchmarks

基准套件配置为针对您本地的scikit-learn克隆运行。确保它是最新的:

git fetch upstream

在基准套件中,基准的组织结构与scikit-learn相同。例如,您可以比较特定估计器之间的性能 upstream/main 以及您正在工作的分支机构:

asv continuous -b LogisticRegression upstream/main HEAD

该命令默认使用conda来创建基准环境。如果您想使用virtualLev,请使用 -E 旗帜:

asv continuous -E virtualenv -b LogisticRegression upstream/main HEAD

您还可以指定整个模块进行基准测试:

asv continuous -b linear_model upstream/main HEAD

您可以替换 HEAD 由任何当地分支机构提供。默认情况下,它只会报告已更改至少10%的基准。您可以使用控制此比例 -f

要运行完整的基准测试套件,只需删除 -b 旗帜:

asv continuous upstream/main HEAD

然而,这可能需要长达两个小时的时间。的 -b tag还接受一个规则表达,以便运行更复杂的基准子集。

要在不与其他分支进行比较的情况下运行基准,请使用 run 命令:

asv run -b linear_model HEAD^!

您还可以使用当前Python环境中已安装的scikit-learn版本运行基准套件:

asv run --python=same

当您以可编辑模式安装scikit-learn时,它特别有用,以避免每次运行基准测试时创建新环境。默认情况下,使用现有安装时不会保存结果。要保存结果,您必须指定提交哈希:

asv run --python=same --set-commit-hash=<commit hash>

基准按机器、环境和提交保存和组织。要查看所有保存的基准的列表:

asv show

并查看特定运行的报告:

asv show <commit hash>

当为您正在处理的拉取请求运行基准时,请在github上报告结果。

基准套件支持额外的可配置选项,这些选项可以在 benchmarks/config.json 配置文件例如,基准测试可以针对所提供的 n_jobs 参数.

有关如何编写基准测试和如何使用asv的更多信息,请参阅 asv documentation .

问题追踪标签#

所有问题和拉取请求 GitHub issue tracker 应该(至少)具有以下标签之一:

Bug:

一些显然不应该发生的事情正在发生。错误的结果以及来自估计器的意外错误都出现在这里。

增强:

提高性能、可用性和一致性。

文件:

缺少、不正确或不符合标准的文档和示例。

新功能:

实现新功能的功能请求和拉取请求。

还有四个其他标签可以帮助新贡献者:

第一期不错:

本期非常适合对scikit-learn的首次贡献。如果配方不清楚,请寻求帮助。如果您已经对scikit-learn做出了贡献,请查看Easy issue。

容易:

这个问题可以在没有太多经验的情况下解决。

中度:

可能需要一些机器学习或包的知识,但对于项目新手来说仍然平易近人。

帮助通缉:

此标签标志着目前缺乏贡献者或公关的问题,需要另一位贡献者来接管工作。这些问题的难度可能各不相同,并且对于新贡献者来说可能无法解决。请注意,并非所有需要贡献者的问题都会有此标签。

保持向后兼容性#

弃用#

如果任何公开访问的类、函数、方法、属性或参数被重命名,我们仍然支持两个版本的旧类、函数、方法、属性或参数,并在调用、传递或访问它时发出弃用警告。

废弃类或函数

假设函数 zero_one 被重命名为 zero_one_loss ,我们添加了装饰师 utils.deprecatedzero_one 和呼叫 zero_one_loss 从该函数::

from ..utils import deprecated

def zero_one_loss(y_true, y_pred, normalize=True):
    # actual implementation
    pass

@deprecated(
    "Function `zero_one` was renamed to `zero_one_loss` in 0.13 and will be "
    "removed in 0.15. Default behavior is changed from `normalize=False` to "
    "`normalize=True`"
)
def zero_one(y_true, y_pred, normalize=False):
    return zero_one_loss(y_true, y_pred, normalize)

还需要搬家 zero_oneAPI_REFERENCEDEPRECATED_API_REFERENCE 并添加 zero_one_lossAPI_REFERENCEdoc/api_reference.py 文件以反映 API参考 .

废弃属性或方法

如果要废弃某个属性或方法,请使用装饰器 deprecated 在财产上。请注意 deprecated 装饰工应放置在 property 装饰器(如果有),以便可以正确呈现文档字符串。例如,重命名属性 labels_classes_ 可以这样做::

@deprecated(
    "Attribute `labels_` was deprecated in 0.13 and will be removed in 0.15. Use "
    "`classes_` instead"
)
@property
def labels_(self):
    return self.classes_

废弃参数

如果必须弃用参数,则 FutureWarning 必须手动发出警告。在下面的例子中, k 已废弃并重命名为n_clusters::

import warnings

def example_function(n_clusters=8, k="deprecated"):
    if k != "deprecated":
        warnings.warn(
            "`k` was renamed to `n_clusters` in 0.13 and will be removed in 0.15",
            FutureWarning,
        )
        n_clusters = k

When the change is in a class, we validate and raise warning in fit:

import warnings

class ExampleEstimator(BaseEstimator):
    def __init__(self, n_clusters=8, k='deprecated'):
        self.n_clusters = n_clusters
        self.k = k

    def fit(self, X, y):
        if self.k != "deprecated":
            warnings.warn(
                "`k` was renamed to `n_clusters` in 0.13 and will be removed in 0.15.",
                FutureWarning,
            )
            self._n_clusters = self.k
        else:
            self._n_clusters = self.n_clusters

与这些示例中一样,警告消息应该始终提供发生弃用的版本和将删除旧行为的版本。如果弃用发生在版本0.x-dev中,则消息应该表明弃用发生在版本0.x中,并且删除将发生在0中。(x+2),以便用户有足够的时间调整他们的代码以适应新行为。例如,如果弃用发生在0.18-dev版本中,则消息应该表明它发生在0.18版本中,并且旧行为将在0.20版本中删除。

警告消息还应包括更改的简短解释,并为用户指明替代方案。

此外,还应在文档字符串中添加一个弃用注释,回忆与上面解释的弃用警告相同的信息。使用 .. deprecated:: 指令:

.. deprecated:: 0.13
   ``k`` was renamed to ``n_clusters`` in version 0.13 and will be removed
   in 0.15.

更重要的是,弃用需要进行测试,以确保在相关情况下发出警告,但在其他情况下不会发出警告。该警告应在所有其他测试中捕捉到(使用例如, @pytest.mark.filterwarnings ),并且示例中不应该有警告。

更改参数的默认值#

如果需要更改参数的默认值,请将默认值替换为特定值(例如, "warn" )并提高 FutureWarning 当用户使用默认值时。下面的示例假设当前版本为0.20,并且我们更改的默认值 n_clusters 从5(旧默认值为0.20)到10(新默认值为0.22)::

import warnings

def example_function(n_clusters="warn"):
    if n_clusters == "warn":
        warnings.warn(
            "The default value of `n_clusters` will change from 5 to 10 in 0.22.",
            FutureWarning,
        )
        n_clusters = 5

When the change is in a class, we validate and raise warning in fit:

import warnings

class ExampleEstimator:
    def __init__(self, n_clusters="warn"):
        self.n_clusters = n_clusters

    def fit(self, X, y):
        if self.n_clusters == "warn":
            warnings.warn(
                "The default value of `n_clusters` will change from 5 to 10 in 0.22.",
                FutureWarning,
            )
            self._n_clusters = 5

与弃用类似,警告消息应该始终提供发生更改的版本和将删除旧行为的版本。

需要通过添加 versionchanged 具有新旧默认值的指令,指向更改生效时的版本:

.. versionchanged:: 0.22
   The default value for `n_clusters` will change from 5 to 10 in version 0.22.

最后,我们需要一个测试,以确保在相关情况下发出警告,但在其他情况下不会发出警告。该警告应在所有其他测试中捕捉到(使用例如, @pytest.mark.filterwarnings ),并且示例中不应该有警告。

代码审查指南#

审查为项目贡献的代码,因为PR是scikit-learn开发的重要组成部分。我们鼓励任何人开始审查其他开发人员的代码。代码审查过程对于每个参与者来说通常都具有很高的教育意义。如果它是您想要使用的功能,那么这就特别合适,因此可以批判性地回应公关是否满足您的需求。虽然每个拉取请求都需要由两名核心开发人员签署,但您可以通过提供反馈来加快此过程。

备注

客观改进和主观改进之间的区别并不总是很清楚。评审员应该记住,代码评审主要是为了降低项目中的风险。在审查代码时,应该旨在防止可能需要修复错误、弃用或撤回的情况。关于文档:拼写错误、语法问题和歧义消除最好立即解决。

任何代码审查都应涵盖的重要方面#

以下是任何代码审查中都需要涵盖的几个重要方面,从高级问题到更详细的检查列表。

  • 我们希望这个在图书馆吗?有可能被使用吗?作为scikit-learn用户,您喜欢此更改并打算使用它吗?它是否属于scikit-learn的范围?维护新功能的成本值得其收益吗?

  • 代码是否与scikit-learn的API一致?公共函数/类/参数是否命名良好且设计直观?

  • 是否所有的公共函数/类及其参数、返回类型和存储的属性都根据scikit-learn约定命名,并有清晰的文档记录?

  • 用户指南中是否描述了任何新功能并通过示例进行说明?

  • 每个公共功能/类别都经过测试吗?是否测试了一组合理的参数、其值、值类型和组合?测试是否验证代码是否正确,即按照文档所说的那样做?如果更改是错误修复,是否包括非回归测试?看看 this 开始使用Python进行测试。

  • 持续集成构建中的测试是否通过?如果合适,帮助贡献者了解测试失败的原因。

  • 测试是否覆盖了每一行代码(请参阅构建日志中的覆盖率报告)?如果不是,缺失覆盖范围的线路是好的例外吗?

  • 代码易于阅读并且冗余度低吗?是否应该为了清晰或一致性而改进变量名称?是否应该添加评论?是否应该将评论视为无益或无关内容而删除?

  • 是否可以轻松重写代码,以便在相关设置中更有效地运行?

  • 代码向后兼容之前的版本吗?(or有必要进行弃用周期吗?)

  • 新代码会添加对其他库的依赖吗?(this不太可能被接受)

  • 文档是否正确呈现(参见 文件 部分了解更多细节),情节是否有启发性?

审核标准回复 包括审阅者可能经常发表的一些评论。

传播指导方针#

审查打开拉取请求(PR)有助于推进项目。这是熟悉代码库的好方法,并且应该激励贡献者继续参与项目。 [1]

  • 每一个公关,无论好坏,都是一种慷慨的行为。以积极的评论开头会帮助作者感到得到回报,并且您随后的言论可能会被更清楚地听到。你可能也感觉很好。

  • 如果可能的话,从大问题开始,以便作者知道它们已经被理解。抵制立即逐行讨论或以普遍存在的小问题开始的诱惑。

  • 不要让完美成为美好的敌人。如果你发现自己提出了很多不属于的小建议, 代码审查指南 ,考虑以下方法:

    • 不要提交这些;

    • 将它们作为“Nit”的前置,以便贡献者知道可以不提及;

    • 在随后的公关中跟进,出于礼貌,您可能想让原始贡献者知道。

  • 不要着急,花点时间让您的评论清楚并证明您的建议是合理的。

  • 您是该项目的代言人。每个人都会遇到糟糕的日子,在这种情况下,你应该休息一下:尽量慢慢来并保持离线状态。

读取现有代码库#

阅读和消化现有的代码库始终是一项困难的练习,需要时间和经验来掌握。尽管我们总体上尝试编写简单的代码,但考虑到项目的庞大规模,理解代码一开始似乎是压倒性的。以下是可能有助于使这项任务更容易、更快(没有特定顺序)的提示列表。

  • 熟悉的 scikit-learn对象的API :了解什么 fit , predict , transform 等用于。

  • 在开始阅读函数/类的代码之前,首先查看文档字符串,并尝试了解每个参数/属性的作用。停下来思考一下也可能有帮助 how would I do this myself if I had to?

  • 最棘手的事情通常是识别代码的哪些部分相关,哪些部分不相关。在scikit-learn中 a lot 执行输入检查,尤其是在 fit 方法.有时,只有非常小的一部分代码在执行实际工作。例如,看看 fit 方法 LinearRegression ,您正在寻找的可能就是 scipy.linalg.lstsq ,但它被隐藏在多行输入检查和不同类型参数的处理中。

  • 由于使用 Inheritance ,某些方法可以在父类中实现。所有估计器至少继承自 BaseEstimator ,并且来自 Mixin 类(例如 ClassifierMixin ),它根据估计器的性质(分类器、回归器、Transformer等)启用默认行为。

  • 有时,阅读给定函数的测试会让您了解其预期目的是什么。您可以使用 git grep (see下面)查找为函数编写的所有测试。针对特定功能/类的大多数测试都放在 tests/ 模块的文件夹

  • 您经常会看到这样的代码: out = Parallel(...)(delayed(some_function)(param) for param in some_iterable) .这运行 some_function 并行使用 Joblib . out 那么是一个包含由返回的值的可迭代对象 some_function 每次通话。

  • 我们使用 Cython 编写快速代码。Cython代码位于 .pyx.pxd 文件. Cython代码更像C:我们使用指针、执行手动内存分配等。在C / C++方面拥有一些最低限度的经验在这里几乎是强制性的。更多信息请参阅 Cython最佳实践、惯例和知识 .

  • 掌握你的工具。

    • 对于这样一个大的项目,高效地使用您最喜欢的编辑器或IDE对于消化代码库大有裨益。能够快速跳跃(或 peek )函数/类/属性定义有很大帮助。能够快速查看给定名称在文件中的位置也是如此。

    • Git also has some built-in killer features. It is often useful to understand how a file changed over time, using e.g. git blame (manual). This can also be done directly on GitHub. git grep (examples) is also extremely useful to see every occurrence of a pattern (e.g. a function call or a variable) in the code base.

  • 配置 git blame 忽略将代码风格迁移到的提交 black 然后 ruff .

    git config blame.ignoreRevsFile .git-blame-ignore-revs
    

    了解更多黑色信息 documentation for avoiding ruining git blame .