新しいクランプの種類を定義する

本節では,このソフトウェアパッケージに新しい非線形適合アルゴリズムを追加したり,ユーザ定義の部品を作成したりする方法について述べる.簡単に言うと誤差関数と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