HN 日本語サマリー

← 一覧へ戻る
プログラミング

PythonとJuliaにおけるシンボリック学習

Symbolic Learning in Python and Julia (github.com)

59 pointsby alex_hirner11 コメント

要約

PySRは、PythonとJuliaで利用できるオープンソースのシンボリック回帰ツールです。このツールは、目的関数を最適化する解釈可能なシンボリック式を見つけることを目指しており、高性能、高設定可能性、使いやすさを重視して設計されています。ニューラルネットワークの解釈や、低次元データセットでの複雑な関係性の発見に役立ちます。

全文翻訳

[画像]PySR

シンボリック回帰 PythonとJuliaで
ドキュメント  ×  例  ×  API  ×  フォーラム  ×  エージェント
[画像: PyPI] [画像: conda-forge] [画像: arXiv]

pip install pysr

PySRが役立つと感じた場合は、論文 arXiv:2305.01582 を引用してください。PySRでプロジェクトを完了した場合は、リサーチショーケースページであなたの作品を紹介するPRを提出してください!

目次:

PySRを選ぶ理由

PySRは、シンボリック回帰のためのオープンソースツールです。これは、目的関数を最適化する解釈可能なシンボリック式を見つけることを目標とする機械学習タスクです。

数年かけて、PySRは(1)可能な限り高性能、(2)可能な限り設定可能、(3)使いやすいようにゼロから設計されてきました。PySRは、Juliaライブラリ SymbolicRegression.jl と共に開発されており、これがPySRの強力な検索エンジンを形成しています。これらのアルゴリズムの詳細は、PySR論文で説明されています。

シンボリック回帰は低次元データセットで最も効果を発揮しますが、ニューラルネットワークの「シンボリック蒸留」を使用して高次元空間に拡張することも可能です。これは、2006.11287で説明されており、N体問題に適用されています。ここでは、シンボリック回帰を使用してニューラルネットを解析方程式に変換します。したがって、これらのツールは、ディープニューラルネットワークを解釈するための明示的かつ強力な方法を同時に提供します。

インストール

pipまたはcondaでPySRをインストールできます。

pip install pysr
conda install -c conda-forge pysr

Juliaの依存関係は、最初のインポート時にインストールされます。

AIエージェントスキル

PySRスキルをインストールして、より大きなエージェントループの一部としてPySRを使用する際のコーディングエージェントにガイダンスを提供します。

npx skills add astroautomata/PySR

スキルをグローバルにインストールするには --global を追加してください。

Docker

Dockerを使用してPySRをインストールすることもできます。

  1. このリポジトリをクローンします。
  2. リポジトリのディレクトリ内で、Dockerコンテナをビルドします。
docker build -t pysr .
  1. IPython実行でコンテナを開始できます。
docker run -it --rm pysr ipython

詳細については、Dockerセクションを参照してください。

Apptainer

ルートアクセスが許可されていないクラスターでPySRを使用している場合は、Dockerの代わりにApptainerを使用してコンテナをビルドできます。Apptainer.defファイルはDockerfileに類似しており、次のようにビルドできます。

apptainer build --notest pysr.sif Apptainer.def

そして、次のように起動します。

apptainer run pysr.sif
トラブルシューティング

発生する可能性のある問題の1つは、GLIBCXX_...が見つからないというメッセージでハードクラッシュすることです。これは、他のPython依存関係が間違ったlibstdc++ライブラリをロードしていることが原因です。これを修正するには、Juliaライブラリを参照するようにLD_LIBRARY_PATH変数を変更する必要があります。たとえば、libstdc++.soのJuliaバージョンが$HOME/.julia/juliaup/julia-1.10.0+0.x64.linux.gnu/lib/julia/(システムによって異なる可能性が高い!)にある場合、次を追加できます。

export LD_LIBRARY_PATH=$HOME/.julia/juliaup/julia-1.10.0+0.x64.linux.gnu/lib/julia/:$LD_LIBRARY_PATH

.bashrcまたは.zshrcファイルに。

クイックスタート

インタラクティブチュートリアルをこちらで試すことができます。これは、examples/pysr_demo.ipynbのノートブックを使用しています。

実際には、印刷がはるかに見やすいため、JupyterよりもIPythonの使用を強くお勧めします。以下は、Pythonランタイムに貼り付けることができる簡単なデモです。まず、テストデータを生成するためにnumpyをインポートしましょう。

import numpy as np

X = 2 * np.random.randn(100, 5)
y = 2.5382 * np.cos(X[:, 3]) + X[:, 0] ** 2 - 0.5

5つの特徴を持つ100個のデータポイントを持つデータセットを作成しました。モデル化したい関係は、$2.5382 \cos(x_3) + x_0^2 - 0.5$です。

次に、PySRモデルを作成してトレーニングします。PySRの主なインターフェースはscikit-learnのスタイルです。

from pysr import PySRRegressor

model = PySRRegressor(
    maxsize=20,
    niterations=40,  # < 結果を良くするために増やしてください
    binary_operators=["+", "*"]
    unary_operators=[
        "cos",
        "exp",
        "sin",
        "inv(x) = 1/x",
        # ^ カスタムオペレーター (julia構文)
    ],
    extra_sympy_mappings={"inv": lambda x: 1 / x},
    # ^ SymPyでもオペレーターを定義
    elementwise_loss="loss(prediction, target) = (prediction - target)^2",
    # ^ カスタム損失関数 (julia構文)
)

これにより、数百千もの突然変異と方程式評価を含む検索コードの40回の反復のためにモデルが設定されます。

このモデルをデータセットでトレーニングしましょう。

model.fit(X, y)

内部的には、これはデータセットに適合する方程式を検索するマルチスレッド検索を実行するJuliaプロセスを起動します。

トレーニング中に方程式が出力され、満足したら、「q」を押してから<enter>を押すことで早期に終了できます。

モデルがフィットした後、model.predict(X)を実行して、自動選択された式を使用するデータセットでの予測を表示できます。または、たとえばmodel.predict(X, 3)を実行して、3番目の式の予測を表示できます。

次を実行できます。

print(model)

学習された方程式を出力します。

PySRRegressor.equations_ = [
	   pick     score                                           equation       loss  complexity
	0        0.000000                                          4.4324794  42.354317           1
	1        1.255691                                          (x0 * x0)   3.437307           3
	2        0.011629                          ((x0 * x0) + -0.28087974)   3.358285           5
	3        0.897855                              ((x0 * x0) + cos(x3))   1.368308           6
	4        0.857018                ((x0 * x0) + (cos(x3) * 2.4566472))   0.246483           8
	5  >>>>       inf  (((cos(x3) + -0.19699033) * 2.5382123) + (x0 *...   0.000000          10
]

pick列のこの矢印は、予測のためにmodel_selection戦略によって現在選択されている方程式を示しています。(model_selectionは.fit(X, y)の後でも変更できます。)

model.equations_は、呼び出し可能な形式(lambda_format)、SymPy形式(sympy_format - model.sympy()でも取得できます)、さらにはJAXおよびPyTorch形式(どちらも微分可能 - model.jax()およびmodel.pytorch()で取得できます)を含むすべての方程式を含むpandas DataFrameです。

PySRRegressorは最後の検索の状態を保存し、warm_start=Trueが設定されていると仮定して、次に.fit()を呼び出すときに途中から再開することに注意してください。検索パラメータ(オペレーターの変更など)に大きな変更が加えられた場合、これは問題を引き起こします。状態をリセットするにはmodel.reset()を実行できます。

PySRは2つのファイルを保存することに気づくでしょう:hall_of_fame...csvとhall_of_fame...pkl。csvファイルは方程式とその損失のリストであり、pklファイルはモデルの保存された状態です。次のようにpklファイルからモデルをロードできます。

model = PySRRegressor.from_file("hall_of_fame.2022-08-10_100832.281.pkl")

デノイジング(例:denoise=True)、特徴選択(例:select_k_features=3)など、他にも多くの便利な機能があります。これらの機能やその他の機能の例については、例ページを参照してください。より多くのオプションの詳細については、オプションページを参照してください。API全体はこのページで確認できます。PySRのチューニングに関するヒントもこのページにあります。

詳細な例

以下のコードは、可能な限り多くのPySR機能を使用しています。これは機能のデモンストレーションであり、この例をそのまま使用しないでください。各パラメータの詳細については、APIページを確認してください。

model = PySRRegressor(
    populations=8,
    # ^ 4コアがあると仮定すると、コアあたり2つのポピュレーションがあるため、常に1つが実行されています。
    population_size=50,
    # ^ より多様性のために、やや大きなポピュレーション。
    ncycles_per_iteration=500,
    # ^ マイグレーション間の世代。
    niterations=10000000,  # 無限に実行
    early_stop_condition=(
        "stop_if(loss, complexity) = loss < 1e-6 && complexity < 10"
        # 良い単純な式が見つかったら早期停止
    ),
    timeout_in_seconds=60 * 60 * 24,
    # ^ または、24時間後に停止。
    maxsize=50,
    # ^ より大きな複雑性を許可。
    maxdepth=10,
    # ^ ただし、深いネストは避ける。
    binary_operators=["*", "+", "-", "/"]
    unary_operators=["square", "cube", "exp", "cos2(x)=cos(x)^2"],
    constraints={
        "/": (-1, 9),
        "square": 9,
        "cube": 9,
        "exp": 9,
    },
    # ^ 各引数内の複雑性を制限。
    # "inv": (-1, 9) は、分子に制約がなく、分母の最大複雑性が9であることを示します。
    # "exp": 9 は、`exp`が入力として複雑性9の式のみを持つことができることを単に示します。
    nested_constraints={
        "square": {"square": 1, "cube": 1, "exp": 0},
        "cube": {"square": 1, "cube": 1, "exp": 0},
        "exp": {"square": 1, "cube": 1, "exp": 0},
    },
    # ^ オペレーターのネスト制約。たとえば、
    # "square(exp(x))" は許可されません。なぜなら "square": {"exp": 0} だからです。
    complexity_of_operators={"/": 2, "exp": 3},
    # ^ 特定のオペレーターのカスタム複雑性。
    complexity_of_constants=2,
    # ^ 定数を変数よりも多く罰する
    select_k_features=4,
    # ^ 最も重要な4つの特徴のみでトレーニング
    progress=True,
    # ^ ファイルへの書き込み時にfalseに設定できます。
    weight_randomize=0.1,
    # ^ ツリーをより頻繁にランダム化
    cluster_manager=None,
    # ^ "slurm"などに設定して、スラムクラスターを実行できます。
    # ヘッドノードから1つのスクリプトを起動するだけです。
    precision=64,
    # ^ より高い精度の計算。
    warm_start=True,
    # ^ 途中から開始。
    turbo=True,
    # ^ より高速な評価(実験的)
    extra_sympy_mappings={"cos2": lambda x: sympy.cos(x)**2},
    # extra_torch_mappings={sympy.cos: torch.cos},
    # ^ cosは既に定義されているため不要ですが、カスタムtorchオペレーターは次のように定義します。
    # extra_jax_mappings={sympy.cos: "jnp.cos"},
    # ^ JAXの場合、文字列を渡します。
)
Docker

このリポジトリのルートディレクトリで次のコマンドを実行して、DockerでPySRをローカルにインストールせずにテストすることもできます。

docker build -t pysr .

これにより、システムアーキテクチャ用のpysrというイメージがビルドされ、IPythonも含まれます。次を使用して、特定のPythonおよびJuliaバージョンを選択できます。

docker build -t pysr --build-arg JLVERSION=1.10.0 --build-arg PYVERSION=3.11.6 .

次に、このDockerファイルを使用して次のように実行できます。

docker run -it --rm -v "$PWD:/data" pysr ipython

これにより、現在のディレクトリがコンテナの/dataディレクトリにリンクされ、IPythonが起動します。

システムアーキテクチャのビルドに問題がある場合は、buildおよびrunコマンドの前に--platform linux/amd64を含めることで、別のアーキテクチャをエミュレートできます。

私たちは新しい貢献者を歓迎することに熱心です!ヒントについては、貢献者ガイドをご覧ください🚀。新しい機能のアイデアがある場合は、イシューまたはディスカッションページで共有することをためらわないでください。

[画像: Adil] Adil[画像: Christopher Rowley] Christopher Rowley[画像: Mark Kittisopikul] Mark Kittisopikul[画像: T Coxon] T Coxon[画像: Dhananjay Ashok] Dhananjay Ashok[画像: Johan Blåbäck] Johan Blåbäck[画像: JuliusMartensen] JuliusMartensen[画像: ngam] ngam
[画像: Kaze Wong] Kaze Wong[画像: Christopher Rackauckas] Christopher Rackauckas[画像: Patrick Kidger] Patrick Kidger[画像: Okon Samuel] Okon Samuel[画像: William Booth-Clibborn] William Booth-Clibborn[画像: Aya Ghaleb] Aya Ghaleb[画像: gca30] gca30[画像: Niklas Heim] Niklas Heim
[画像: Atharva Sehgal] Atharva Sehgal[画像: wkharold] wkharold[画像: William Moses] William Moses[画像: Ardeleanu Cristian] Ardeleanu Cristian[画像: gm89uk] gm89uk[画像: Pablo Lemos] Pablo Lemos[画像: Jerry Ling] Jerry Ling[画像: Charles Fox] Charles Fox
[画像: Johann Brehmer] Johann Brehmer[画像: Marius Millea] Marius Millea[画像: Coba] Coba[画像: foxtran] foxtran[画像: Shah Mahdi Hasan] Shah Mahdi Hasan[画像: Dilum Aluthge] Dilum Aluthge[画像: Sebastian Micluța-Câmpeanu] Sebastian Micluța-Câmpeanu[画像: Tim Holy] Tim Holy
[画像: BrotherHa] BrotherHa[画像: William Thompson] William Thompson[画像: Tom Jelen] Tom Jelen[画像: Miguel Crispim Romao] Miguel Crispim Romao[画像: Andy Dienes] Andy Dienes[画像: Harsh Singh] Harsh Singh[画像: Pietro Monticone] Pietro Monticone[画像: Mateusz Kubica] Mateusz Kubica
[画像: William Booth-Clibborn] William Booth-Clibborn[画像: Raúl Peralta Lozada] Raúl Peralta Lozada[画像: Roy Hvaara] Roy Hvaara[画像: Vishal Jain] Vishal Jain[画像: spaette] spaette[画像: Yi-Xin Liu] Yi-Xin Liu[画像: spinnau] spinnau[画像: Xianda Sun] Xianda Sun
[画像: Jay Wadekar] Jay Wadekar[画像: Anthony Blaom, PhD] Anthony Blaom, PhD[画像: Jgmedina95] Jgmedina95[画像: Michael Abbott] Michael Abbott[画像: Oscar Smith] Oscar Smith[画像: Eric Hanson] Eric Hanson[画像: Henrique Becker] Henrique Becker[画像: qwertyjl] qwertyjl
[画像: Rik Huijzer] Rik Huijzer[画像: Hongyu Wang] Hongyu Wang[画像: Zehao Jin] Zehao Jin[画像: Tanner Mengel] Tanner Mengel[画像: Arthur Grundner] Arthur Grundner[画像: sjwetzel] sjwetzel[画像: Saurav Maheshkar] Saurav Maheshkar[画像: chris-soelistyo] chris-soelistyo
[画像: Ilya Orson] Ilya Orson[画像: Ho Fung Tsoi] Ho Fung Tsoi[画像: LionessOfCintra] LionessOfCintra[画像: Manuel Morales] Manuel Morales[画像: Paulo Montero Camacho] Paulo Montero Camacho[画像: Writu Dasgupta] Writu Dasgupta[画像: Anubhav Kamal] Anubhav Kamal[画像: anthony-sun] anthony-sun
[画像: Hao Guo] Hao Guo[画像: Trailblazer] Trailblazer[画像: Christos Pliakos] Christos Pliakos[画像: Sousa Neto] Sousa Neto[画像: Leonardo Voltolini] Leonardo Voltolini[画像: Daniel Eduardo Conde Villatoro] Daniel Eduardo Conde Villatoro[画像: Sam Beckers] Sam Beckers