SKIP 3 — scikit-image 1.0への移行#

著者:

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

ステータス:

最終版

タイプ:

標準トラック

作成日:

2021-07-15

解決日:

2021-09-13

解決策:

拒否

有効バージョン:

なし

概要#

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

ベータ版であり、0.xシリーズのリリースであるにもかかわらず、scikit-imageは非常に広く使用されており、下位互換性のない変更は混乱を招く可能性が高いです。このSKIPは、コミュニティが今後の変更を認識し、ライブラリまたは宣言されたscikit-imageのバージョンの依存関係をそれに応じて調整できるようにするためのプロセスを提案しています。

動機と範囲#

scikit-imageは過去12年間にわたって有機的に成長しており、さまざまな背景を持つ幅広いコミュニティの貢献者によって機能が追加されてきました。このため、APIのさまざまな部分が不整合になっています。たとえば、skimage.transform.warpは座標の順序を反転するため、(45, 32)の平行移動は、NumPy配列の値を0番目の軸に沿って32、1番目の軸に沿って45移動しますが、2Dの場合のみです。

さらに、ユーザーベースの拡大に伴い、初期のAPIの選択の中には、役に立つよりも混乱を招くものもあったことが明らかになりました。たとえば、scikit-imageは画像をさまざまなデータ型に自動的に変換し、その過程でサイズ変更します。[0, 255]の範囲のuint8画像は、[0, 1]のfloat64画像に自動的に変換されます。これは一見妥当に思えるかもしれませんが、一貫性を保つため、[0, 65535]の範囲のuint16画像は[0, 1]のfloatに、顕微鏡で一般的に使用される[0, 4095]の12ビット範囲のuint16画像は[0, 0.0625]にサイズ変更されます。これらのサイレント変換は、多くのユーザーの混乱を招いてきました。

この規則を変更するには、ほとんどすべてのscikit-image関数にpreserve_range=キーワード引数を追加する必要があります。このキーワード引数のデフォルト値は、4つのバージョンにわたってFalseからTrueに変更されます。最終的には、どれだけ緩やかな廃止予定の期間を設定しても、変更は下位互換性がなくなります。

主に、同じ入力に対する関数の出力を変更することを含むため、標準的な廃止予定サイクルでは修正するには負担が大きすぎ、ノイズが多すぎるということが判明した、潜在的なAPI変更の蓄積を考えると、バージョン1.0への移行ですべての変更を行うことが理にかなっています。私たちが使用しているセマンティックバージョニングは、メジャーバージョンのアップデートでAPIの破壊的変更を明示的に許可しています[6]。しかし、(1) 膨大な数のプロジェクトがscikit-imageに依存しており、下位互換性のない変更の影響を受け、(2) 科学的Pythonコミュニティでは、依存関係に上限バージョンを設定することがまだ一般的ではないため、ほとんど誰もscikit-image<1.*を依存関係リストで使用していない(ただし、これは徐々に変化しています[5])ことを認めなければなりません。

上記を踏まえ、この変更が迫っていることをすべてのユーザーに通知し、注意喚起が一度行われたら警告を抑制できるようにする方法を考案する必要があります。

詳細な説明#

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

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

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

  • numpy.asarrayでNumPyに変換できる限り、非NumPy型の自動的な戻りを許可します。

  • さまざまな関数で同様のパラメーターを同じ名前に統一します。たとえば、現在、さまざまな関数でrandom_seedrandom_stateseedsample_seedなど、すべて同じ意味を持つものが存在します。

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

  • watershedslicfelzenschwalbなど、同じ目的を持つ関数を共通の名前空間に統合します。これにより、新しいユーザーが特定のタスクにどの関数を使用すべきかを簡単に確認できるようになります。

問題は、できるだけ混乱を招くことなく、どのようにこの移行を行うかということです。

このドキュメントでは、0.19を最後の真の0.xリリースとしてリリースし、その後すぐに、インポート時にユーザーに破壊的変更について警告するほぼ同一の0.20リリースをすぐにリリースすることを提案しています。これにより、ユーザーはscikit-imageの依存関係を0.19.xに固定することができます。警告には、コードを1.0に対応させるための移行ガイドへのリンクと、condaおよびpip環境での依存関係の管理方法も含まれています。実装を参照してください。

このアプローチにより、すべてのユーザーが十分な警告を受け、1.0がリリースされた後もスクリプトとライブラリが引き続き機能することを確認する機会が得られます。移行する時間や意欲がないユーザーは、依存関係を正しく固定することができます。最先端の技術を使用したいユーザーも、1.0リリースに合わせて計画を立て、scikit-imageに合わせてコードを正しく更新することができます。

実装#

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

  • scikit-image 0.19は、最後の真の0.xリリースになります。いくつかの新機能、バグ修正、0.17で廃止予定となったものを引き継いだいくつかのAPI変更が含まれています。

  • 0.19の直後に、インポート時に警告を出す点を除いて同一の0.20をリリースします。警告の内容は以下のようになります。「scikit-image 1.0は今年後半にリリースされ、破壊的変更が含まれます。コードが引き続き動作するようにするには、scikit-image<=0.19.*をインストールしてください。この警告を抑制し、1.0がリリースされた後もscikit-imageに依存するには、scikit-image!=0.20.*をインストールしてください。」警告には、詳細とcondaおよびpip環境での依存関係の管理方法に関する手順へのリンクも含まれています。

  • 0.20以降、廃止予定サイクルなしですべて必要なAPI変更を行います。重要なのは、すべてのAPI変更について、ドキュメントの「scikit-image 1.0移行ガイド」に1行を追加することです。このガイドは、ライブラリの変更された機能を古い形式から新しい形式にマッピングします。これらの変更は、GitHubの問題[7]および1.0のマイルストーン[8]で追跡されます。

  • リポジトリでの移行が完了したら、グローバルな警告と共に移行ガイドへのリンクを含むアルファ版である1.0.0a0をリリースします。新機能もすべて含まれています。また、同じ警告を含む0.21もリリースしますが、機能的には0.19と同一です。これにより、scikit-image!=0.20.*を指定して固定していた開発者は、1.0への移行を行うことができます。

  • 少なくとも1ヶ月後には、1.0をリリースします。

  • ユーザーが新しいAPIに移行する時間を与えるため、1年間、バグ修正を含む0.19.xブランチを維持します。

下位互換性#

この提案は、ライブラリの多くの場所で下位互換性を破ります。

代替案#

新しいパッケージ名#

scikit-imageパッケージで互換性を壊す代わりに、そのパッケージを0.19のままにして、新しいパッケージ(例:scikit-image1)をリリースし、1.0から開始し、skimage1としてインポートすることができます。これにより、ユーザーがscikit-imageのバージョンを固定する必要がなくなります。skimage 0.xに依存するユーザーは、そのライブラリを「永久的に」使用できます。

最終的に、コア開発者は、このアプローチによって、0.19を引き続き使用するユーザーと1.0に移行するユーザーとの間でコミュニティが不必要に分裂する可能性があると判断しました。最終的には、ダウンストリームコードを1.0に移行することは、提案されたアプローチと同じくらい困難ですが、scikit-imageをインストールするすべての人が古いバージョンを取得するため、切り替える圧力は減少します。

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

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

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

最終的に、コアチームは、このアプローチは、scikit-imageの開発者とダウンストリームライブラリの開発者の両方に、疑わしいメリットのためにより多くの作業を生み出すと判断しました。最終的には、scikit-imageの新しいバージョンは、古いバージョンと互換性がなくなるものの、より長い時間スケールになります。

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

別の可能性として、極端な場合を除いて、下位互換性のないAPI変更を完全に拒否することもあります。コアチームは、これは基本的にライブラリを0.19に固定することと同等だと考えています。

議論#

2021年7月上旬、コアチームは一連の会議を開き、このアプローチについて議論しました。この会議の議事録は、scikit-imageの会議ノートリポジトリにあります。[9]

継続的な議論は、ユーザーフォーラム[10]、開発者フォーラム[11]、およびGitHubのディスカッション[7]で行われます。関連する投稿への具体的なリンクは、承認前にこのドキュメントに追加されます。

結論#

このSKIPは、2021年7月のメーリングリストのスレッドで最も広く議論されました。[12] 最終的に、多くのコア開発者は、この計画がコードの動作を無音で変更するか、コミュニティの善意を損なうか、あるいはその両方を行う大きなリスクがあると判断しました。Matthew Brettは[13]で記述しました。

1.0のオプションが、私が「Konrad Hinsenルール」と呼ぶ科学ソフトウェアのルールを破るかどうか、完全に確信が持てませんでした。

“””事実上、いかなる状況下でも、科学パッケージの新しいバージョンは、以前のバージョンからの同じ関数/メソッド呼び出しに対して、大幅に異なる結果を無音で返すべきではありません。“””

Matthewはさらに[14]で、Hinsenルールを破らない代わりに、ユーザーの固定されていないスクリプトを破ってしまうと、コミュニティの善意を大きく失うだろうと記述しています。

これらの変更がすべて壊れてしまう(幸運な場合)か、完全に間違った結果を返す場合、メーリングリストに登録されていない他の多くのユーザーに大きな損害を与えることは想像に難くありません。

コア開発者の1人であるRiadh Fezzaniは、SemVer[6]はユーザーを保護するのに十分であると強く主張しました。[15]

scikit-imageでは、エンジニアリングコミュニティで広く採用されているセマンティックバージョニングを採用しました。この規約はAPIの破壊を管理し、v1.0をリリースすることで、まさにそれを行っています。

しかし、この見解を採用しても、Josh Warner[16]が指摘したように、10年分の蓄積されたStackOverflowの回答など、破壊的な1.0リリースによって時代遅れになる外部のscikit-image「ドキュメント」の問題に対処することはできません。

また、相当量のscikit-imageの教育資料が存在することも考慮する価値があります。その大部分は私たちが管理できないため、更新または編集できません。YouTubeでチュートリアルの最初のヒットは、最新のものではなく、多くのビューを持つ古いものです。

Tom Caswell[17]が指摘したように、古いAPIから新しいAPIへのコードベースの段階的な移行の問題にも対処できません。

言い換えれば、大学院生に「新しいAPIを使いたいのですが、古いAPIを使用する1万行の継承コードがあります…」と言わせるような状況に陥らせたくありません。

最終的に、これらの懸念事項はすべて、SKIPを拒否するという説得力のある理由となります。Juan Nunez-Iglesiasはメーリングリストに[18]で記述しました。

今後の提案は、SKIP-3を拒否し、skimage2パッケージを提案するSKIP-4を作成することです。

したがって、SKIPは拒否されます。

参考文献と脚注#

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