メインコンテンツへスキップ
DataFit には 2 つの関連する要素があります。
  • 目的関数 (iws.objectives.*) — どの実験でモデル出力と比較するか。
  • コスト (iws.costs.*) — 点ごとの差をどう 1 つのスカラに集約するか。
各コストの数学的背景は 目的関数 (英語ガイド) を参照してください。

利用可能なコスト関数

最尤推定には iws.costs.GaussianLogLikelihood を使用してください — 変数ごとのノイズ標準偏差を受け取るか、フィッティングパラメータと併せて推定することもできます。ベイズ推定や MAP 推定に適したガウス負対数尤度を生成します。

コストをフィットに組み込む

cost を省略すると、オプティマイザのデフォルトコスト関数(通常は最小二乗形式)が使われます。
cost はコストスキーマのインスタンス (例: iws.costs.RMSE()) または type キーを明示した設定 dict (例: {"type": "RMSE"}) を受け付けます。cost="RMSE" のような名前だけの文字列は検証エラーで拒否されます — 代わりに {"type": "RMSE"} のようにラップしてください。

Wasserstein 重み付き点群モード

iws.costs.Wasserstein() はデフォルトでは目的変数ごとにモデルとデータのサンプルを比較します(ソート点ごとの比較、均一な重み)。position_variableweight_variable を両方指定すると 重み付き点群モード に切り替わり、一方が位置を、もう一方が(符号を除去・再正規化した)重みを供給して、目的ごとに 1 回 Wasserstein-1 距離を計算します。 dQ/dV のピークを電圧上で揃えるなど、サンプル単位の値ではなく 位置で密度を一致させたい 場合に使います。 iws.objectives.MSMRFullCelliws.objectives.ElectrodeBalancing の両方が、対応する Differential capacity [Ah/V] 値とその Voltage [V] (dQdU) マスク済み軸の兄弟キーを出力するため、いずれも重み付き点群フィットに利用できます:
position_variableweight_variable は同時に指定する必要があります — 片方だけ指定すると検証エラーになります。重みは絶対値が取られ内部で再正規化されるため、dQ/dV の符号規則は問題になりません。このモードでは残差配列出力は利用できません。

OCV フィットのための ElectrodeBalancing オプション

ElectrodeBalancing は、目的関数を評価する前のフルセル OCV 処理を制御するために、options 辞書で次のキーを受け付けます。これらは、フィットで使用するコスト関数(重み付き Wasserstein に限らない)に関係なく適用されます:

calculation_structure でコストをスコープする

デフォルトでは DataFit 上の各コストは、出力に存在するすべての目的関数とすべての目的変数を消費します。コストに calculation_structure を設定すると明示的にスコープを指定できます — 目的関数名から、そのコストが計算する変数名のリスト(または None でその目的関数の全変数、空リストで何も計算しない)へのマッピングです。 マッピングから外した目的関数は除外されません。DataFit の内部では、スコープされていない各目的関数はその全変数(None を指定した場合と同じ)にバインドされます。そのため、"cc" という目的関数も存在する状態で一方だけをスコープしても(例: {"ocp": ["Voltage [V]"]})、"cc" は引き続き全変数で計算されます。 1 つのコストが変数のサブセットだけを見るようにしたい場合に使います。最も一般的なのは、変数ごとのコスト(例: SSE)と重み付き Wasserstein を併用するケースです。Wasserstein 側が dQ/dV 変数(モデル側とデータ側で長さが構造的に異なる)を担当し、SSE 側はスコープでそれらを除外するため、長さが衝突することはありません。
calculation_structure は非推奨となった objective_names(目的関数名のフラットリストで、変数単位の制御がない)の置き換えです。同じコストに両方を指定すると検証エラーになります。

長さ不一致の警告

要素ごとのコスト(SSEMSERMSEMAEMax)はモデル配列とデータ配列を点ごとに結合するため、モデル側とデータ側の長さが異なる変数では意味のあるスコアになりません。DataFit はフィット設定時に、各コストがスコアリングする全変数の形状を確認し、不一致があるごとに UserWarning を発行します。例:
このチェックはフィット設定時に一度だけ実行され(目的関数評価ごとではない)、フィット性能に影響しません。この警告が出たら、calculation_structure を使ってモデル側とデータ側の長さが一致する変数のみコストが見るようにスコープし、モデル軸変数は Wasserstein(または他の分布メトリック)に振り分けてください。Wasserstein のような分布コストは長さの異なるサンプル集合を想定しているため、チェックの対象外です。

モデル電圧軸で dQ/dV ピークを揃える

iws.objectives.ElectrodeBalancing は、データ電圧グリッドに加えて(あるいは代わりに) モデル自身の全窓電圧軸 で dQ/dV を出力できます。optionsdQdU model axis: True を指定し、objective variables にモデル軸版の 2 つの変数 — "Differential capacity [Ah/V] (model axis)""Voltage [V] (model axis)" — を追加してください。 重み付きコスト(典型的には点群モードWasserstein)に 位置シフト を行わせたい — つまりデータグリッド上の残差ごとではなく電圧上で dQ/dV ピークを揃えたい — 場合に使います。モデル側とデータ側は長さが構造的に異なるため、これらを消費できるのは重み付きコストだけです。フィット全体の整合性を保つため、上記の calculation_structure でスコープした変数ごとのコストと組み合わせて使ってください。 既存のデータ軸変数("Differential capacity [Ah/V]" と、マスク軸の兄弟変数 "Voltage [V] (dQdU)" / "Capacity [A.h] (dQdU)")も引き続き利用できます — 両方の軸を同時にリクエストできます。

利用可能な目的関数

複数を組み合わせるには DataFit.objectivesdict[str, objective] を渡します。

GITTModel: GITT・パルスフィット用の拡散のみモデル

GITTModel は GITT やパルス緩和測定から固相拡散係数(および単一の集中定数オーミック抵抗)を抽出するためのフィッティング専用モデルです。各電極の x 平均された球状粒子拡散を解き、表面フラックスは印加電流から決定されます。セル電圧は粒子表面ストイキオメトリで評価した開回路電位から、集中定数 "Ohmic resistance [Ohm]" パラメータによるオーミック降下を引いて計算します。 反応速度論(Butler-Volmer)、電解液動力学、熱効果はいずれも含まれません — OCP を除くすべてのパラメータは定数として扱われます。GITT やパルスデータの拡散律速領域に対して高速かつ良条件のフィットを行いたい場合に使用してください。完全な物理シミュレーションが必要な場合は SPM / SPMe / DFN を選択してください。 "working electrode" オプションでセル構成を選択します。 各計算対象電極は、標準的なフルセルのパラメータ名(厚み、活物質体積分率、粒子半径、拡散係数、OCP、最大濃度・初期濃度)に加えて、電流関数、電極断面積、初期温度、"Ohmic resistance [Ohm]" でパラメータ化されます。

フルセル GITT 測定へのフィット

ハーフセルパルス測定へのフィット

リチウム金属対極に対する片側電極のみをモデル化するには "working electrode": "positive" を指定します。必要なのは作用電極側のパラメータだけです。
"working electrode" が受け付ける値は "both" または "positive" のみで、それ以外はスキーマ検証で失敗します。options のその他のキーはパラメータ管理用に内部の電池モデルオプションへ転送されますが、拡散のみという物理には影響しません。

data_input の指定方法

各 objective の data_input(および calculation や interpolant の data フィールド)は、以下のいずれの形式も受け付けます:
  • 参照文字列: アップロード済みの測定データを参照するには "db:<id>" を使います。"file:...""folder:..." はローカルマシンから読み取られ、送信時に API クライアントによって config へインライン化されます。そのため、ローカル実行でも Ionworks にフィットを送信する場合でも動作します。ただし裸の DataFrame と同じ 1,000 行のインライン上限が適用されます。より大きなデータセットは測定としてアップロードしてから "db:<id>" で参照してください。
  • ionworksdata.DataLoader(ローカル、または DataLoader.from_db(...) で取得したもの)。
  • 事前に読み込み済みの pandas または polars の DataFrame
裸の DataFrame を渡した場合、シリアライズ時にパーサーが期待する {"data": <columns>} の形に自動的にラップされます — つまり data_input=dfdata_input={"data": df} は等価です。文字列パスや、すでにラップ済みの dict はそのまま渡されます。
インラインで渡す DataFrame は 1 回あたり 1,000 行までです。それより大きなデータセットは事前に measurement としてアップロードし、ID で参照してください。インライン時系列のサイズ制限を参照してください。

CycleAgeing の実験をデータから生成する

iws.objectives.CycleAgeing は通常、サイクルプロトコルを表す pybamm.Experiment を明示的に指定する必要があります。プロトコルがすでにデータに付随するサイクラーのステップ情報に含まれている場合は、experiment="from data" を指定することで、実験を手作業で組み立て直す手間を省けます。実験はフィット開始時に DataLoader.generate_experiment() を呼び出して遅延生成されます。 次のような場合に使用します:
  • フィット対象のデータが独自のステップ情報を持つ場合 (ローカルの ionworksdata.DataLoader、または DataLoader.from_db(...) で取得したもの)。
  • シミュレーションのプロトコルを測定プロトコルに正確に合わせたい場合 — サイクラーが記録した各ステップの電流、電圧の上下限、継続時間も含めて。
フィット対象のデータ (例えばサイクルごとの集計テーブル) が、プロトコルを定義する測定とは別のオブジェクトの場合は、experiment に別の DataLoader を渡します — ステップ情報はその DataLoader から取得され、残差は引き続き data_input に対して計算されます:
experiment="from data" は、data_input がステップ情報を持つ DataLoader (またはその "data" エントリが DataLoader である dict) に解決される必要があります。experiment に別の DataLoader を渡す場合は、ステップ情報はその DataLoader に含まれている必要があります。いずれの場合も、ステップ情報を欠いた構成は、シミュレーションが走る前に目的関数の構築時点で明確なエラーとともに即座に失敗します。

自動構築されるソルバーのチューニング

シミュレーションを伴う目的関数 (CurrentDrivenPulseCalendarAgeingCycleAgeingMSMRFullCell など) は、明示的な solver が指定されていない場合に IonworksSolver を自動構築します。チューニング済みのデフォルトをすべて書き直すことなく一部だけを上書きしたい場合は、simulation_kwargs の中で solver_kwargs を渡します:
  • ネストされた options はデフォルトの IDAKLU オプションにマージされます。例えば {"options": {"compile": True}} はモデルコンパイルだけを有効化し、他のチューニング済みオプションはそのまま維持します。
  • その他のトップレベルキー (atolrtolon_extrapolation など) は、対応するデフォルトのソルバー kwargs を上書きします。
solver_kwargs は、明示的な solver が指定された場合は警告とともに無視されます — その場合はソルバーインスタンス上で直接設定してください。また、モデルのデフォルトソルバーが IDAKLU ベースでない場合も無視されます。
事前に compile を有効化する ({"options": {"compile": True}}) と、一度きりのコンパイルコストと引き換えに繰り返しの評価が高速になります — 同じ目的関数をフィットやスイープ中に何度も解くようなケースで有効です。

実行時の solve への kwargs の転送

simulation_kwargssolve_kwargs も受け付けます。これは、目的関数の評価ごとに実行される sim.solve(...) 呼び出しへ転送される dict です。ソルバ本体ではなく solve 呼び出し自体に渡すべき引数 — 例えば直前の解からウォームスタートするための starting_solution や、その他の pybamm.Simulation.solve 引数 — に使用します。
  • solve_kwargs は、目的関数がソルバを自動構築した場合でも、明示的な solver を指定した場合でも常に適用されます。どのソルバとも互換のある、solve 時の引数を渡す推奨方法です。
  • 上で説明した solver_kwargs は自動構築されたソルバを 構築時 にチューニングします。一方 solve_kwargs は各 solve 呼び出し を設定します。両者は独立しており、組み合わせて使えます。
  • 目的関数が直接制御するキー — inputsinitial_soct_evalt_interpfrequencies — は予約されており、solve_kwargs で渡すと ValueError が発生します。
  • CycleAgeing では save_at_cycles はメトリックから自動的に導出されます。solve_kwargs で値を渡しても、メトリックに必要なサイクルが保持されるよう警告とともに無視されます。

CycleAgeing: first/last のみの metrics に対する store_first_last の自動有効化

CycleAgeing では、各目的変数を .by_cycle() のメトリックにマッピングする metrics を指定できます。"LLI [%]""LAM_ne [%]""LAM_pe [%]" にはデフォルトが用意されており、いずれもステップごとに 1 サンプルだけを読み取ります。 metrics のすべてのメトリックがステップの最初または最後のサンプルのみを読み取る場合(デフォルト、または任意の First / Last.by_cycle() メトリック)、CycleAgeingsolver_kwargs["store_first_last"] を自動で True に設定します。これによりソルバは各ステップの端点のみを保存するため、長期サイクル解析でメモリ使用量を大幅に削減でき、これらのメトリックの結果は変わりません。 このフラグは安全な場合にのみ自動で設定されます:
  • 内部点を読み取るメトリック(例: Mean(...).by_cycle())ではデフォルトは無効のままで、サンプルは間引かれません。
  • 合成メトリック(First/Last を含む演算)は安全側に倒して自動有効化されません。
  • solver_kwargsstore_first_last が明示指定されている場合は常にそれが優先されます。
  • 独自の solver を指定した場合は、他と同様に solver_kwargs の注入自体がスキップされます。
ほとんどのオプティマイザでは SSE が最も無難です — 残差配列形式とスカラ形式の両方を持つため、すべてのアルゴリズムと互換性があります。スケール非依存の報告が必要な場合は MSE / RMSE を使用してください。

目的関数 (理論)

残差形式と正準形式、MLE の解釈 (英語ガイド)。

データフィッティング概要

目的関数・パラメータ・オプティマイザの組み合わせ方。