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:float。scipy.optimize.least_squaresの出力0.5 * RSS。success:bool。最適化が成功したかどうか。message:str。最適化の終了メッセージ。nfev:Optional[int]。関数評価回数。njev:Optional[int]。ヤコビアン評価回数。status:Optional[int]。最適化の終了ステータスコード。warning:str。警告メッセージ(例: 共分散計算時の特異行列に関する警告)。raw_result:object。scipy.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_squaresのloss引数。デフォルトは "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 されることを前提として設計されています。