SKIP 4 — scikit-image 2.0への移行#

著者:

Juan Nunez-Iglesias <juan.nunez-iglesias@monash.edu>

著者:

Lars Grüter

ステータス:

ドラフト

タイプ:

標準トラック

作成日:

2022-04-08

解決日:

<null>

解決策:

<null>

有効バージョン:

なし

概要#

scikit-imageはバージョン1.0のリリースの準備をしています。これは見られましたAPIを整理する機会として、後方互換性のない変更を含みます。これらの変更の中には、関数シグネチャを変更せずに戻り値を変更するものが含まれており、通常は(new_return_style=Trueなど)役に立たないキーワード引数を追加する以外に方法がありません。このキーワード引数のデフォルト値は、いくつかのリリースにわたって変更されます。その結果、依然として後方互換性のない変更になりますが、より長い期間にわたって行われます。

ベータ版であり、0.xシリーズのリリースであるにもかかわらず、scikit-imageは非常に広く使用されており、後方互換性のない変更は混乱を招く可能性があります。SKIP-3の拒否を踏まえ、この文書では新しいAPIを作成するための代替パスを提案します。新しいパスには次の手順が含まれます。

  • v0.20とv0.21で予定されていた保留中の非推奨化は最終的に完了します(v0.19の非推奨化メッセージで提案された新しいAPIが唯一のAPIになります)。

  • これは1.0としてリリースされます。

  • この時点で、ブランチmainはパッケージ名とインポート名をskimage2に変更し、APIは自由に進化できます。

API変更のさらなる動機については以下で説明し、大部分はSKIP-3から複製されています。

動機と範囲#

scikit-imageは過去12年以上、さまざまなバックグラウンドを持つ幅広いコミュニティの貢献者によって機能が追加されて有機的に成長してきました。これにより、APIのさまざまな部分が矛盾するようになりました。たとえば、skimage.transform.warpは座標の順序を反転するため、(45, 32)の並進は実際にはNumPy配列の値を0番目の軸に沿って32、1番目の軸に沿って45移動しますが、2Dの場合のみです。3Dでは、(45, 32, 77)の並進は、各軸の値を対応する位置の数だけ移動します。

さらに、ユーザーベースの増加に伴い、初期のAPI選択の一部が有益であるよりも混乱を招くことが明らかになりました。たとえば、scikit-imageは画像をさまざまなデータ型に自動的に変換し、その過程でリサイズします。[0, 255]の範囲のuint8画像は、[0, 1]のfloat64画像に自動的に変換されます。これは最初は妥当に見えるかもしれませんが、一貫性のために、[0, 65535]の範囲のuint16画像は[0, 1]の浮動小数点数値にリサイズされ、顕微鏡で一般的な[0, 4095]の12ビット範囲のuint16画像は[0, 0.0625]にリサイズされます。これらのサイレント変換により、多くのユーザーが混乱しました。

この規則を変更するには、ほとんどすべてのscikit-image関数にpreserve_range=キーワード引数を追加する必要があり、そのデフォルト値は4つのバージョンにわたってFalseからTrueに変更されます。最終的に、どんなに緩やかな非推奨化カーブにしても、変更は後方互換性のないものになります。

skimage.measure.regionpropsなどの他の主要な関数は、リストではなく、ラベルをプロパティにマッピングする辞書を返すなど、API調整を使用できます。

主に、同じ入力に対して関数出力を変更することに関連しているため、標準的な非推奨化サイクルで修正するには負担が大きすぎ、ノイズが多すぎるということが判明した可能性のあるAPI変更の蓄積を考えると、バージョン2.0への移行ですべての変更を行うことが理にかなっています。

セマンティックバージョニング[6]は、メジャーバージョンの増加に伴ってAPIの変更を技術的に許可していますが、(1)非常に多くのプロジェクトがscikit-imageに依存しており、後方互換性のない変更の影響を受ける可能性があり、(2)科学的Pythonコミュニティで依存関係の上限バージョンを設定することはまだ一般的ではないため、scikit-image<1.*またはscikit-image<2.*を依存関係リストで使用した人はほとんどいないと推測できます。これは、破壊的なAPI変更を含むscikit-imageのバージョン2.0をリリースすると、多くのユーザーに支障をきたすことを意味します。さらに、そのような広範囲にわたる変更により、StackOverflowやその他のユーザーガイドの多くが無効になります。最後に、多数の変更を加えた新しいバージョンをリリースすると、ユーザーが新しいAPIに段階的に移行できなくなります。古いコードベースは、両方のバージョンのAPIに依存することが不可能なため、一括で移行する必要があります。これは、多くのユーザーにとって大きな参入障壁となります。

上記の点を考慮して、このSKIPでは、既存のユーザーベースに支障をきたすことなく、10年以上にわたる開発から得られた教訓をすべて適用できる新しいパッケージをリリースすることを提案します。

詳細な説明#

このドキュメントでは、skimage2の提案されたAPI変更をすべてリストすることは範囲外です。それらの多くはまだ決定されていません。実際、このSKIPが承認された場合、2.0移行の範囲と野心は大きくなる可能性があります。このSKIPは、ユーザーのコードを壊すことなく移行を管理するためのメカニズムを提案します。提案された変更を追跡するメタ問題は、GitHubのscikit-image/scikit-image#5439にあります[7]。例として、いくつかの例を以下に示します。

  • dtypeをfloatに強制する必要がある場合に入力配列のリサイズを停止します。

  • 描画やワープなど、さまざまなコンテキストで座標軸の順序の入れ替えを停止します。

  • numpy.asarrayでNumPyに変換できる限り、NumPy以外の型の自動返却を許可します。

  • さまざまな関数で同様のパラメーターを同じ名前で統一します。たとえば、現在、random_seedrandom_stateseed、またはsample_seedをさまざまな関数で使用しており、すべて同じ意味です。

  • measure.regionpropsをリストではなく辞書を返すように変更します。

  • watershedslic、またはfelzenschwalbなど、目的が同じ関数を共通の名前空間に結合します。これにより、新しいユーザーが特定のタスクにどの関数を使用するかを簡単に確認できます。また、現在scikit-image APIは関数ごとに固有であるため、共通のAPIを中心にコミュニティを成長させるのにも役立ちます。

この移行を最小限のユーザーへの影響で実現するために、このSKIPでは、既存のライブラリを置き換える新しいライブラリ、skimage2をリリースすることを提案します。ただし、ユーザーが明示的にオプトインした場合のみです。さらに、新しいライブラリをリリースすることで、ユーザーはscikit-image(1.0)とskimage2の両方に依存できるため、ユーザーはコードを段階的に移行できます。

実装#

提案の詳細を以下に示します。

  • scikit-image 0.19 の次は scikit-image 1.0 となります。1.0 ではすべての非推奨メッセージが削除され、API は scikit-image 1.0 API とみなされます。

  • 1.0 以降、メインブランチは、(a) インポート名を skimage2 に変更する、(b) パッケージ名を skimage2 に変更する、(c) バージョン番号を 2.0-dev に変更する、という変更が行われます。

  • バージョン 2.0 の「scikit-image」パッケージは PyPI には存在しません。pip install scikit-image を実行したユーザーには常に 1.x バージョンのパッケージがインストールされます。scikit-image 2.0 をインストールするには、ユーザーは pip install skimage2conda install skimage2 または同様のコマンドを実行する必要があります。

  • 新しいAPIについて合意が得られた後、skimage2 がリリースされます。

  • skimage2 のリリース後、scikit-image 1.1 がリリースされます。このリリースは 1.0 と同一です(バグ修正を含む)。ただし、ユーザーに対して (a) skimage2 にアップグレードするか、(b)警告を回避するためにパッケージを scikit-image<1.1 に固定するかのいずれかを行うように促します。

  • scikit-image 1.0.x および 1.1.x は、バグの深刻さと必要な労力に応じて、一定期間、重大なバグ修正を受け続けます。

後方互換性#

この提案は、ライブラリの多くの場所で後方互換性を損なっています。しかし、これは新しい名前空間で行われるため、この提案はユーザーにとって後方互換性の問題を引き起こすことはありません。とはいえ、作成者は、後方互換性のない変更を、全体的なユーザーエクスペリエンスを大幅に向上させる可能性のあるものだけに制限しようとします。skimage コードを skimage2 に移植することは容易なプロセスになると予想され、skimage2 のリリースまでに、移行のためのユーザーガイドを公開します。ユーザーは、scikit-image 1.1 の警告などを通じて、これらのリソースについて通知されます。

代替案#

セマンティックバージョニングを使用して同じパッケージで新しいAPIをリリースする#

これはSKIP-3であり、コミュニティとの議論の後、却下されました。

複数のバージョンにわたる継続的な非推奨化#

この移行は、多くのバージョンにわたって段階的に行うことができます。例えば、浮動小数点入力の自動変換とリスケーリングを行う関数の場合、最初はFalseをデフォルトとするpreserve_rangeキーワード引数を追加し、Falseのデフォルト値を非推奨とし、ユーザーにTrueに切り替えるよう警告を出すことができます。切り替え後、引数を非推奨にすることができ(オプション)、さらに2回のリリース後、同じ状態になります。つまり、scikit-imageはデータの自動リスケールを行わず、API全体に不要なキーワード引数が残っていません。

もちろん、この種の操作は、上記のすべての提案された変更と同時に実行する必要があります。

最終的に、コアチームは、このアプローチは、scikit-imageの開発者と下流ライブラリの開発者の両方に、疑わしい利点のためにより多くの作業を生み出すと感じました。最終的には、scikit-imageの新しいバージョンは、以前のバージョンと互換性がなくなりますが、より長い時間をかけてになります。

両方のバージョンを含む単一のパッケージ#

インポート名が変更されるため、少なくともしばらくの間、skimageskimage2の両方の名前空間を含む単一のパッケージを作成することが可能です。このオプションは魅力的ですが、1.0の名前空間の長期的なメンテナンス(メンテナンス担当者の時間が不足する可能性があります)、または1.0の名前空間の長い非推奨化サイクル(最終的には、scikit-imageの使用から非推奨化メッセージを受け取る多くの不満なユーザーにつながる可能性があります)を意味します。

提案されたAPIの変更を行わない#

もう1つの可能性は、極端な場合を除いて、後方互換性のないAPIの変更を完全に拒否することです。コアチームは、これは本質的にライブラリを0.19に固定することと同等であると考えています。

新しいパッケージ名として「scikit-image2」を使用する#

作成者は、scikit-imageのユーザーベースとコミュニティへの混乱を最小限に抑えるために、新しい名前を慎重に選択する必要があることを認識しています。しかし、上位バージョンの制約がないユーザーが誤って新しいAPIにアップグレードするのを防ぐために、パッケージ名scikit-imageを変更する必要があります。インポート名skimageを変更することも同様に有利です。なぜなら、同じ環境で両方のAPIを使用できるようになるからです。

このドキュメントでは、scikit-imageのAPIバージョン2.0の新しい名前としてskimage2を提案しています。これはインポート名とPyPI、conda-forgeなどでの名前の両方に当てはまります。これには次の理由があります。

  • プロジェクトに新しい名前が1つしか導入されないため、関連する名前の数を最小限に抑えることができます。

  • この変更により、インポート名とパッケージ名が一致するようになります。

  • ユーザーはscikit-image2scikit-image-2のどちらをインストールすべきか混乱する可能性があります。skimage2はこの混乱を回避すると考えられました。

  • skimageを知っていて、インストール手順でskimage2を見れば、それがパッケージの新しいバージョンであると推測できる可能性が高いです。

  • 新しいAPI 2.0を知っていても新しいパッケージ名を知らないユーザーは少ないでしょう。scikit-image 1.1の提案されたリリースでは、インストールと更新プロセス中にユーザーにskimage2を指示し、後継者の名前を明確に伝えることができます。

パッケージ名をskimage2にすることに対する反対意見は以下の通りです。

  • 「最小限の驚き」の原則によれば、scikit-image2はパッケージ名の最も驚くべき進化ではないとみなされる可能性があります。

  • scikit-imageを含む他のscikitに従われている規則を破っています。(この規則はしばらくの間真実ではなかったこと、そして名前の中にバージョン番号を導入することはいずれにしても前例であることが指摘されました。)

前のセクション「関連作業」では、他のプロジェクトが同様の問題をどのように処理したかが説明されています。

議論#

このSKIPは、SKIP-3の議論の結果です。このSKIPの動機に関する詳細については、そのドキュメントの「解決策」セクションを参照してください。

解決策#

参考文献と脚注#

すべてのSKIPは、Copyrightのように、CC0ライセンス[1]でパブリックドメインに専念するものとして宣言する必要があります。CC0+BY[2]で帰属を推奨します。