Experimentにデータを添付する#

入力JSON、モデル、評価結果、ログや画像を、Experiment全体または特定のRun(一回の試行)に添付できます。まず標準の型付きメソッドかファイル添付を使います。基本的な記録と保存の流れは二つの試行を記録するTutorialを参照してください。

SDKのインストールに従って実行環境を用意してください。この例にはAdapterやソルバーは不要です。

標準のデータとファイルを保存する#

次の例は、小さな入力ファイルを作り、共有の問題・JSON・ファイルと、Runの評価結果を保存します。attachment-example/notes.txtはこの例で作成・更新するファイルです。

from pathlib import Path

from ommx import Instance
from ommx.experiment import Experiment

data_dir = Path("attachment-example")
data_dir.mkdir(exist_ok=True)
input_file = data_dir / "notes.txt"
input_file.write_bytes(b"candidate evaluated locally\n")

instance = Instance.minimize()
x = instance.new_binary("x")
instance.objective = x

with Experiment() as experiment:
    experiment.log_json("source-data", {"description": "one binary variable"})
    experiment.log_instance("problem", instance)
    experiment.log_file("notes", input_file, media_type="text/plain")
    with experiment.run() as run:
        run.log_solution("evaluation", instance.evaluate({x.id: 0}))

experiment.save(data_dir / "attachments.ommx")

log_fileは、その時点のファイル内容を取り込みます。元のファイルへのリンクではありません。後から元ファイルを編集しても、保存済み添付データは変わりません。saveは同名ファイルを上書きしないので、再実行時は新しい保存先を選び、後の読込パスも合わせてください。

名前を確認して取り出す#

型が分かっているときは型別の取得メソッドを使います。間違った種類のデータを指定した場合、暗黙に別の型へ変換せずエラーになります。

from ommx.experiment import Experiment

loaded = Experiment.import_archive("attachment-example/attachments.ommx")
print(sorted(loaded.attachment_names))
source_data = loaded.get_json("source-data")
problem = loaded.get_instance("problem")
evaluation = loaded.runs[0].get_solution("evaluation")
assert source_data["description"] == "one binary variable"
assert problem.evaluate(evaluation.state).objective == evaluation.objective
assert loaded.get_blob("notes") == b"candidate evaluated locally\n"

get_attachment(name)はMedia Type(保存データの種類)を見て標準型を読み分けます。get_blob(name)はbytesが必要なときに使います。元のファイルとして書き出す場合は、保存先を指定します。

from pathlib import Path

destination = Path("attachment-example/restored-notes.txt")
loaded.write_attachment("notes", destination, overwrite=True)
assert destination.read_bytes() == b"candidate evaluated locally\n"

ここでは例を再実行できるようoverwrite=Trueで指定先ファイルを更新します。既存ファイルを置き換えたくない場合はこの引数を省略し、新しいパスを指定してください。

どこに置き、何を明示するか#

全Runで共通の入力はExperiment、試行ごとに異なるデータはRunに置くと、後で対応を辿りやすくなります。添付名はそのスコープ内で取り出すための名前です。Runごとに同じ名前を使っても、別のRunの添付データです。

比較表の列にしたいスカラー値はrun.log_parameterに記録します。添付JSON内の数値やAdapterに渡したオプションが、自動的にRun parameterへ展開されるわけではありません。

大きなJSONやファイルなどはcompression="zstd"を指定できます。取得メソッドは展開された内容を返すので、読み手の操作は変わりません。対応するメソッドと厳密な制限はExperimentとRunを参照してください。

独自型を保存する場合だけCodecを使う#

標準型でもファイルでも扱えないPythonオブジェクトには、media_type、encode(value) -> bytes、decode(bytes) -> valueを持つCodecをlog_with_codec / get_with_codecに渡せます。具体的なCodecは、原則としてその型を所有するパッケージ側が提供します。読み手にも対応するパッケージとCodecが必要です。

OMMXは外部型の意味やバージョン互換性を自動的に決めません。外部パッケージの公開Codecやシリアライズ仕様を確認してください。Protocolの呼び出し方とMedia Typeの検証はlog_with_codec()とget_with_codec()を参照してください。

記録の確定・再開はExperimentのGuide、階層を使わないデータ交換はArtifactのTutorialに分けています。