# tklsq マニュアル

## 1. 役割

`tklsq` は、科学データ向けの線形・非線形最小二乗、共分散、予測誤差、モデル選択、パラメータ診断、パラメータ表入出力を責務別モジュールに分離したパッケージです。

| モジュール | 主な責務 |
|---|---|
| `tklsq.tklsq` | 線形最小二乗、予測誤差、AIC/BIC/AICc、Bayesian linear model |
| `tklsq.tknlsq` | `scipy.optimize.least_squares` による非線形最小二乗 |
| `tklsq.tkminfit` | `scipy.optimize.minimize` ベース、penalty、variable projection |
| `tklsq.tkfitdiag` | 共分散・相関・固有値診断、固定候補提案 |
| `tklsq.tkparamio` | CSVパラメータ表、固定/自由/線形/非線形parameter管理 |
| `tklsq.tkdataio` | CSV/Excel/JSON入出力 |
| `tklsq.tkplot` | fit前後・誤差band・進捗plot |
| `tklsq.tksynthetic` | 合成データ生成 |

## 2. トップレベル公開API

線形最小二乗のコアはトップレベルから利用できます。

```python
from tklsq import (
    polynomial_lsq,
    predict_polynomial,
    information_criteria,
)
```

非線形、診断、parameter I/Oは責務別moduleからimportします。

```python
from tklsq.tknlsq import nonlinear_lsq
from tklsq.tkfitdiag import diagnose_covariance
from tklsq.tkparamio import read_param_csv
```

## 3. 線形・多項式最小二乗

```python
import numpy as np
from tklsq import polynomial_lsq, predict_polynomial

x = np.linspace(0.0, 5.0, 30)
y = 1.5 - 0.7 * x + 0.2 * x**2

result = polynomial_lsq(x, y, order=2)
pred = predict_polynomial(x, result, order=2)

print(result.beta)
print(result.beta_std)
print(result.condition_number)
print(pred.sigma_param)  # parameter uncertainty only
print(pred.sigma_pred)   # parameter + residual noise
```

`linear_lsq(X, y)` では、`X` は `(N, p)` の設計行列です。切片は自動追加されないので、必要なら `add_intercept(X)` を使います。

## 4. 重みと既知分散

```python
weights = 1.0 / sigma_y**2
result = linear_lsq(X, y, weights=weights, known_sigma=True)
```

- `known_sigma=False`: 残差から分散を推定し、`(X^T W X)^-1` に掛けます。
- `known_sigma=True`: `weights=1/sigma_y^2` を絶対分散として扱います。

rank不足または `N-p <= 0` でも係数は返りますが、共分散と誤差bandは `None` になり、`warning` に理由が入ります。

## 5. 非線形最小二乗

```python
import numpy as np
from tklsq.tknlsq import nonlinear_lsq

x = np.linspace(0.0, 5.0, 50)
y = 2.0 * np.exp(-x / 1.5) + 0.1


def residual(params):
    a, tau, c = params
    return a * np.exp(-x / tau) + c - y

result = nonlinear_lsq(
    residual,
    p0=[1.0, 1.0, 0.0],
    bounds=([0.0, 0.01, -np.inf], [np.inf, np.inf, np.inf]),
)
```

辞書parameterと固定parameterにも対応します。`residual_func` は「モデル値−観測値」またはその逆のどちらでもRSSは同じですが、Jacobianや後処理との整合のためプロジェクト内で符号を統一してください。

## 6. `minimize` ベースfit

`tkminfit.minimize_lsq()` は、Nelder–Mead等の一般目的最適化器で残差平方和を最小化します。パラメータCSVの `min/max/dp/scale/fix/linear` 等と組み合わせる設計です。

```python
from tklsq.tkminfit import minimize_lsq

params = {
    "a": {"value": 1.0, "min": 0.0, "max": 10.0, "fix": 0},
    "tau": {"value": 1.0, "min": 0.01, "max": 100.0, "fix": 0},
}


def residual(p):
    return p["a"] * np.exp(-x / p["tau"]) - y

result = minimize_lsq(residual, params, method="Nelder-Mead")
```

`callback` には `scipy.optimize.minimize` 内部の最適化vector `q` が渡されます。log変換parameterを使う場合、callback側でinverse transformしてください。

## 7. variable projection

モデルが「一部parameterには線形、残りには非線形」の場合、`variable_projection_lsq()` で各非線形stepごとに線形blockを厳密に解けます。振幅・offsetが線形、peak位置・幅が非線形、といった問題に有効です。

## 8. 診断

```python
from tklsq.tkfitdiag import (
    diagnose_covariance,
    propose_fix_candidates_from_diagnostics,
    format_fix_candidates,
)

diag = diagnose_covariance(names, values, covariance, jacobian=jacobian)
candidates = propose_fix_candidates_from_diagnostics(diag)
print(format_fix_candidates(candidates))
```

診断は、相対誤差、強相関、共分散固有vector、`J^T J` 条件数を使います。固定候補は自動決定ではなく、モデル再設計・追加データ・parameter固定を検討するための提案です。

## 9. モデル選択

- `information_criteria()`: AIC, BIC, AICc
- `select_models_by_ic()`: 複数設計行列の比較
- `bayesian_log_evidence()` / `select_models_by_evidence()`
- `empirical_bayes_linear()`
- `ard_select()`: sklearn ARDRegressionを使うoptional機能

AICcは標本数がparameter数に近い場合に特に重要です。比較するモデルは同じ観測データと尤度仮定を使ってください。

## 10. parameter CSV

```python
from tklsq.tkparamio import read_param_csv, write_param_csv

params = read_param_csv("params.csv", defaults=defaults, create_if_missing=True)
values = {name: row["value"] for name, row in params.items()}
```

parameterの変換には `scale` として通常値またはlog値を扱う関数があります。最適化vectorと物理parameterを混同しないでください。

## 11. 依存関係

- コア: `numpy`
- 非線形fit・minimize: `scipy`
- 表入出力: `pandas`, `openpyxl`
- plot: `matplotlib`
- ARD: `scikit-learn`

## 12. 生成AI向けコード生成ルール

1. 線形モデルは可能な限り `linear_lsq()` / `polynomial_lsq()` を使い、非線形optimizerに不要に渡さない。
2. `X` に切片列が必要かを明示する。`linear_lsq()` は自動で切片を追加しない。
3. measurement uncertaintyを重みにする場合は `weights=1/sigma^2` を使う。
4. `beta_std` や共分散が `None` になり得るため、rankとdofを確認する。
5. confidence band（平均推定誤差）とprediction band（新規観測誤差）を区別する。
6. 非線形fitのresidual関数は1次元数値配列を返す。
7. parameter辞書を使うfitでは `tkparamio` の名前・scale・fix規則を尊重する。
8. `callback` の引数を物理parameter辞書だと仮定しない。
9. 診断の固定候補を無条件で自動固定せず、物理的意味を確認する。
10. top-level `tklsq` と責務別moduleのAPIを混同しない。
