新しいクランプの種類を定義する¶
本節では,このソフトウェアパッケージに新しい非線形適合アルゴリズムを追加したり,ユーザ定義の部品を作成したりする方法について述べる.簡単に言うと誤差関数と1つを定義する必要があります __call__
方法は、クランプと一緒に動作する制約タイプ(ある場合)を定義する。
以下、ScipyのSLSQPアルゴリズムを例に詳細に説明する。全ての組み立て工の基礎は Fitter
**
class SLSQPFitter(Fitter):
supported_constraints = ['bounds', 'eqcons', 'ineqcons', 'fixed',
'tied']
def __init__(self):
# Most currently defined fitters take no arguments in their
# __init__, but the option certainly exists for custom fitters
super().__init__()
すべてのクランプ工はモデルを持っています __call__
メソッド修正モデルのパラメータ)をそれらの第1のパラメータとする.
次に,ERROR関数は,適合アルゴリズムが戻ってきたパラメータリストと入力座標を繰り返し取得し,それらを用いてモデルを評価し,あるタイプの適合メトリックを返す.本例では、残差二乗和は、適合のメトリックとして使用される。
def objective_function(self, fps, *args):
model = args[0]
meas = args[-1]
model.fitparams(fps)
res = self.model(*args[1:-1]) - meas
return np.sum(res**2)
♪the __call__
方法はフィッティングを実行する。少なくとも,すべての座標を単独のパラメータとする.必要に応じて他のパラメータを伝達する:
def __call__(self, model, x, y , maxiter=MAXITER, epsilon=EPS):
if model.linear:
raise ModelLinearityException(
'Model is linear in parameters; '
'non-linear fitting methods should not be used.')
model_copy = model.copy()
init_values, _ = _model_to_fit_params(model_copy)
self.fitparams = optimize.fmin_slsqp(self.errorfunc, p0=init_values,
args=(y, x),
bounds=self.bounds,
eqcons=self.eqcons,
ineqcons=self.ineqcons)
return model_copy
プラグイン·ローダの定義¶
astropy.modeling
Asterpyコア以外の組立作業の挿入を可能にするプラグイン機構を含む astropy.modeling.fitting
namespace through the use of entry points. Entry points are references to importable objects. A tutorial on defining entry points can be found in setuptools' documentation それがそうです。プラグインの組み立て者は Fitter
基本類です。クランプが発見され挿入されます astropy.modeling.fitting
入り口に挿入しなければなりません astropy.modeling
入口点編成
setup(
# ...
entry_points = {'astropy.modeling': 'PluginFitterName = fitter_module:PlugFitterClass'}
)
これによりユーザーの導入が可能になります PlugFitterName
通り抜ける astropy.modeling.fitting
vt.から.
from astropy.modeling.fitting import PlugFitterName
この機能を使ったプロジェクトの1つは Saba ご参考までに。
カスタム統計関数を用いる¶
本節では,ユーザ定義の統計関数を持つ新しいクランプをどのように作成するかについて述べる.以下の例は,2つの変数が不確実性を持つ直線に適合する特殊なクラスを示す.
以下のIMPORT文が必要である:
import numpy as np
from astropy.modeling.fitting import (_validate_model,
_fitter_to_model_params,
_model_to_fit_params, Fitter,
_convert_input)
from astropy.modeling.optimizers import Simplex
まず統計データを定義する必要がある.これは関数であってもよいし、呼び出し可能なクラスであってもよい。:
def chi_line(measured_vals, updated_model, x_sigma, y_sigma, x):
"""
Chi^2 statistic for fitting a straight line with uncertainties in x and
y.
Parameters
----------
measured_vals : array
updated_model : `~astropy.modeling.ParametricModel`
model with parameters set by the current iteration of the optimizer
x_sigma : array
uncertainties in x
y_sigma : array
uncertainties in y
"""
model_vals = updated_model(x)
if x_sigma is None and y_sigma is None:
return np.sum((model_vals - measured_vals) ** 2)
elif x_sigma is not None and y_sigma is not None:
weights = 1 / (y_sigma ** 2 + updated_model.parameters[1] ** 2 *
x_sigma ** 2)
return np.sum((weights * (model_vals - measured_vals)) ** 2)
else:
if x_sigma is not None:
weights = 1 / x_sigma ** 2
else:
weights = 1 / y_sigma ** 2
return np.sum((weights * (model_vals - measured_vals)) ** 2)
一般に、新たなクランプを定義するためには、統計関数とオプティマイザを提供するだけでよい。本例では,オプティマイザをFitterのオプションパラメータに設定し,統計情報を設定した. chi_line
上の図::
class LineFitter(Fitter):
"""
Fit a straight line with uncertainties in both variables
Parameters
----------
optimizer : class or callable
one of the classes in optimizers.py (default: Simplex)
"""
def __init__(self, optimizer=Simplex):
self.statistic = chi_line
super().__init__(optimizer, statistic=self.statistic)
最後に定義するのは __call__
方法:
def __call__(self, model, x, y, x_sigma=None, y_sigma=None, **kwargs):
"""
Fit data to this model.
Parameters
----------
model : `~astropy.modeling.core.ParametricModel`
model to fit to x, y
x : array
input coordinates
y : array
input coordinates
x_sigma : array
uncertainties in x
y_sigma : array
uncertainties in y
kwargs : dict
optional keyword arguments to be passed to the optimizer
Returns
------
model_copy : `~astropy.modeling.core.ParametricModel`
a copy of the input model with parameters set by the fitter
"""
model_copy = _validate_model(model,
self._opt_method.supported_constraints)
farg = _convert_input(x, y)
farg = (model_copy, x_sigma, y_sigma) + farg
p0, _ = _model_to_fit_params(model_copy)
fitparams, self.fit_info = self._opt_method(
self.objective_function, p0, farg, **kwargs)
_fitter_to_model_params(model_copy, fitparams)
return model_copy