tknlsq.py 技術ドキュメント

このドキュメントは、Pythonライブラリ tknlsq.py の技術的な側面を解説します。

ライブラリの機能や目的

tknlsq.py は、非線形最小二乗問題を解決するための汎用的なラッパーライブラリです。 主な目的は、アプリケーション固有の物理モデルとは独立して、残差ベクトル residual_func(params) -> residual vector を最小化する共通のフレームワークを提供することにあります。

このライブラリは以下の設計方針に基づいています:

  • アプリケーション固有の物理モデルは外部に配置します。

  • ここでは、residual_func(params) から返される残差ベクトルを最小化します。

  • 数値ヤコビアンと、パラメータの共分散行列を近似する \(s^2 (J^T J)^{-1}\) を共通化します。

  • 固定パラメータを扱いやすくするための機能を提供します。

基盤となる最適化ソルバーとして scipy.optimize.least_squares を使用しており、SciPy が利用できない環境では ImportError を発生させます。

importする方法

このライブラリを他のPythonプログラムから利用するには、以下のように import 文を使用します。

import numpy as np
from tknlsq import nonlinear_lsq, NonlinearLSQResult, delta_method_band

# または特定の関数のみをインポート
# from tknlsq import nonlinear_lsq

必要な非標準ライブラリとインストール方法

tknlsq.py は以下の非標準ライブラリに依存しています。

  • NumPy: 数値計算の基盤として利用されます。

  • SciPy: 非線形最小二乗法の中核となる scipy.optimize.least_squares を提供します。

これらのライブラリは pip コマンドを使用してインストールできます。

pip install numpy scipy

importできる変数と関数

tknlsq.py から import できる主要な変数(型エイリアスやデータクラス)と関数を以下に示します。

変数(型エイリアスとデータクラス)

  • ArrayLike:

    • 説明: Sequence[float] または np.ndarray のいずれかを表す型エイリアスです。配列のような浮動小数点数のコレクションを受け入れることを示します。

  • ParamsLike:

    • 説明: Sequence[float] または Mapping[str, float] のいずれかを表す型エイリアスです。パラメータがリストやNumPy配列のようなシーケンス形式、または名前と値の辞書形式で提供されることを示します。

  • NonlinearLSQResult:

    • 説明: 非線形最小二乗の結果を格納するためのデータクラスです。最適化の終了状態、計算されたパラメータ、残差、ヤコビアン、共分散などの詳細な情報を含みます。

    • フィールド:

      • params: np.ndarray または Dict[str, float]。最適化された全パラメータの値。p0 が辞書で与えられた場合は辞書形式で、それ以外はNumPy配列で返されます。

      • params_free: np.ndarray。最適化された自由パラメータの値。

      • names: List[str]。全パラメータの名前のリスト。

      • free_names: List[str]。自由パラメータの名前のリスト。

      • fixed_names: List[str]。固定パラメータの名前のリスト。

      • residuals: np.ndarray。最適化後の残差ベクトル。

      • jacobian: Optional[np.ndarray]。残差のヤコビアン行列。

      • cov_free: Optional[np.ndarray]。自由パラメータの共分散行列。

      • stderr_free: Optional[np.ndarray]。自由パラメータの標準誤差。

      • stderr: Union[Optional[np.ndarray], Dict[str, Optional[float]]]。全パラメータの標準誤差。固定パラメータの標準誤差は 0.0 となります。

      • sigma2_resid: Optional[float]。残差の分散 \(\sigma^2 = RSS / \text{dof}\)

      • dof: int。残差の自由度 (N - p_free)。

      • N: int。残差の数 (データポイント数)。

      • p_free: int。自由パラメータの数。

      • RSS: float。残差平方和 (Residual Sum of Squares)。

      • cost: floatscipy.optimize.least_squares の出力 0.5 * RSS

      • success: bool。最適化が成功したかどうか。

      • message: str。最適化の終了メッセージ。

      • nfev: Optional[int]。関数評価回数。

      • njev: Optional[int]。ヤコビアン評価回数。

      • status: Optional[int]。最適化の終了ステータスコード。

      • warning: str。警告メッセージ(例: 共分散計算時の特異行列に関する警告)。

      • raw_result: objectscipy.optimize.least_squares の生の結果オブジェクト。

    • プロパティ:

      • sigma_resid -> Optional[float]: 残差の標準偏差 \(\sigma = \sqrt{\max(\sigma^2, 0.0)}\)

関数

  • numerical_jacobian(fun_vec, p, *, rel_step=1e-6, abs_step=1e-12)

    • 動作: 中心差分を用いてベクトル関数のヤコビアン行列を計算します。ヤコビアン \(J\)\(J_{ij} = \frac{\partial \text{residual}_i}{\partial p_j}\) と定義されます。

    • 引数:

      • fun_vec: Callable[[np.ndarray], ArrayLike]。パラメータベクトル p を受け取り、残差ベクトルを返す関数。

      • p: ArrayLike。ヤコビアンを計算する点のパラメータベクトル。

      • rel_step: float (オプション)。相対ステップサイズ。

      • abs_step: float (オプション)。絶対ステップサイズ。

    • 戻り値: np.ndarray。計算されたヤコビアン行列。

  • covariance_from_jacobian(residuals, J, *, dof=None, rcond=1e-12)

    • 動作: 残差ベクトルとヤコビアン行列から、パラメータの共分散行列を近似します。共分散は以下の式で近似されます。

      \[\text{cov} \approx s^2 (J^T J)^{-1}, \quad s^2 = \frac{\text{RSS}}{\text{dof}}\]

      dof <= 0 の場合、共分散と標準誤差は None を返します。

    • 引数:

      • residuals: ArrayLike。残差ベクトル。

      • J: np.ndarray。ヤコビアン行列。

      • dof: Optional[int] (オプション)。残差の自由度。指定しない場合、residuals.size - J.shape[1] から計算されます。

      • rcond: float (オプション)。特異値分解に基づく擬似逆行列の計算で使用される小さい特異値のしきい値。

    • 戻り値: Tuple[Optional[np.ndarray], Optional[np.ndarray], Optional[float], str]

      • cov: 共分散行列。

      • stderr: 標準誤差ベクトル。

      • sigma2_resid: 残差の分散 \(s^2\)

      • warning: 警告メッセージ。

  • nonlinear_lsq(residual_func, p0, *, names=None, fixed=None, bounds=None, loss="linear", max_nfev=None, rel_step=1e-6, abs_step=1e-12, use_result_jac=True, scipy_kwargs=None)

    • 動作: 非線形最小二乗問題を解決するメイン関数です。scipy.optimize.least_squares を内部で利用します。 residual_func はパラメータ params を受け取り、1次元の残差ベクトルを返す関数です。 p0 が辞書形式で与えられた場合、residual_func には辞書が渡されます。 p0 がリストまたは配列の場合、residual_func には np.ndarray が渡されます。

    • 引数:

      • residual_func: Callable[[Union[np.ndarray, Dict[str, float]]], ArrayLike]。残差を計算する関数。

      • p0: ParamsLike。初期パラメータ。

      • names: Optional[Sequence[str]] (オプション)。パラメータ名のリスト。p0 が辞書形式でない場合に必要。

      • fixed: Optional[Union[Sequence[str], Mapping[str, float]]] (オプション)。固定パラメータの名前のリスト、または {name: value} の辞書。

      • bounds: Optional[Union[Tuple[ArrayLike, ArrayLike], Mapping[str, Tuple[float, float]]]] (オプション)。パラメータの境界。タプル (lb, ub) または {name: (lb, ub)} の辞書形式で指定。

      • loss: str (オプション)。scipy.optimize.least_squaresloss 引数。デフォルトは "linear"。

      • max_nfev: Optional[int] (オプション)。最大関数評価回数。

      • rel_step: float (オプション)。数値ヤコビアン計算の相対ステップサイズ。

      • abs_step: float (オプション)。数値ヤコビアン計算の絶対ステップサイズ。

      • use_result_jac: bool (オプション)。scipy.optimize.least_squares が計算したヤコビアンを利用するかどうか。False の場合、常に数値ヤコビアンを再計算します。

      • scipy_kwargs: Optional[dict] (オプション)。scipy.optimize.least_squares に渡す追加のキーワード引数。

    • 戻り値: NonlinearLSQResult。最適化の結果を格納したオブジェクト。

  • delta_method_variance(output_func, p, cov, *, rel_step=1e-6, abs_step=1e-12)

    • 動作: 出力量 \(y=f(p)\) の分散をデルタ法で計算します。入力パラメータ \(p\) の共分散行列 cov を用いて、出力 \(y\) の分散 var_y を計算します。 出力 \(y\) の各要素 \(y_n\) の分散は、入力パラメータ \(p\) の各要素 \(p_i, p_j\) についての勾配 \(G_{ni} = \frac{\partial y_n}{\partial p_i}\) を用いて以下のように計算されます。

      \[ \text{var}_y[n] = \sum_{i} \sum_{j} G_{ni} \text{cov}_{ij} G_{nj} \]
    • 引数:

      • output_func: Callable[[np.ndarray], ArrayLike]。パラメータ p を受け取り、出力ベクトルを返す関数。

      • p: ArrayLike。パラメータベクトル。

      • cov: np.ndarray。パラメータ p の共分散行列。

      • rel_step: float (オプション)。数値ヤコビアン計算の相対ステップサイズ。

      • abs_step: float (オプション)。数値ヤコビアン計算の絶対ステップサイズ。

    • 戻り値: Tuple[np.ndarray, np.ndarray, np.ndarray]

      • y0: np.ndarray。評価点 p での output_func の出力。

      • var_y: np.ndarray。出力 y の各要素の分散。

      • grads: np.ndarray。出力関数 output_func のヤコビアン行列(勾配)。

  • delta_method_band(output_func, p, cov, *, nsigma=1.0, rel_step=1e-6, abs_step=1e-12)

    • 動作: デルタ法を用いて、出力 \(y\) とその信頼区間(\(y \pm n\sigma_y\))を計算します。

    • 引数:

      • output_func: Callable[[np.ndarray], ArrayLike]。パラメータ p を受け取り、出力ベクトルを返す関数。

      • p: ArrayLike。パラメータベクトル。

      • cov: np.ndarray。パラメータ p の共分散行列。

      • nsigma: float (オプション)。信頼区間を計算するための標準偏差の倍数。デフォルトは 1.0

      • rel_step: float (オプション)。数値ヤコビアン計算の相対ステップサイズ。

      • abs_step: float (オプション)。数値ヤコビアン計算の絶対ステップサイズ。

    • 戻り値: Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]

      • y0: np.ndarray。評価点 p での output_func の出力。

      • y_low: np.ndarray\(y_0 - \text{nsigma} \cdot \sigma_y\)

      • y_high: np.ndarray\(y_0 + \text{nsigma} \cdot \sigma_y\)

      • sigma_y: np.ndarray。出力 y の各要素の標準偏差。

  • result_free_values(result)

    • 動作: NonlinearLSQResult オブジェクトから自由パラメータの値の配列を抽出して返します。

    • 引数:

      • result: NonlinearLSQResult

    • 戻り値: np.ndarray。自由パラメータの値。

  • result_free_cov(result)

    • 動作: NonlinearLSQResult オブジェクトから自由パラメータの共分散行列を抽出して返します。

    • 引数:

      • result: NonlinearLSQResult

    • 戻り値: Optional[np.ndarray]。自由パラメータの共分散行列。

main scriptとして実行したときの動作

tknlsq.py は、自身が main script として直接実行された場合に特別な動作をするための if __name__ == "__main__": ブロックを含んでいません。そのため、このファイルを直接実行しても、何も出力されず、特定の処理も行われません。ライブラリとして他のプログラムから import されることを前提として設計されています。