2017-08-04 125 views
5

我想在astropy.modelling中使用Model.tied(或Parameter.tied)屬性,但似乎無法弄清楚它是如何工作的。例如,假設我想創建具有兩個參數的複合模型:flux_0flux_1。但是,我只想在配件中使用flux_0flux_1應始終攜帶值1 - flux_0。 (最後,我需要擴展該功能使得flux_0 + flux_1 + ... + flux_n = 1。)在astropy.modeling中綁定參數

我定義模型類和「可調用」爲tied屬性像這樣:

>>> from astropy.modeling import Fittable1DModel, Parameter 
>>> 
>>> class MyModel(Fittable1DModel): 
...  flux = Parameter() 
...  @staticmethod 
...  def evaluate(x, flux): 
...   return flux 
... 
>>> def tie_fluxes(model): 
...  flux_1 = 1 - model.flux_0 
...  return flux_1 
... 
>>> TwoModel = MyModel + MyModel 
>>> 
>>> TwoModel 
<class '__main__.CompoundModel0'> 
Name: CompoundModel0 
Inputs: ('x',) 
Outputs: ('y',) 
Fittable parameters: ('flux_0', 'flux_1') 
Expression: [0] + [1] 
Components: 
    [0]: <class '__main__.MyModel'> 
    Name: MyModel 
    Inputs: ('x',) 
    Outputs: ('y',) 
    Fittable parameters: ('flux',) 

    [1]: <class '__main__.MyModel'> 
    Name: MyModel 
    Inputs: ('x',) 
    Outputs: ('y',) 
    Fittable parameters: ('flux',) 

然後我檢查tied屬性。我的理解是,這應該是一個字典(見注),但它不是:

>>> TwoModel.tied 
<property object at 0x109523958> 
>>> 
>>> TwoModel.tied['flux_1'] = tie_fluxes 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
TypeError: 'property' object does not support item assignment 

如果我嘗試設置它作爲一個字典,它不會更新相應的Parameter

>>> TwoModel.tied = {'flux_1': tie_fluxes} 
>>> 
>>> TwoModel.flux_1.tied 
False 

但是,當我嘗試創建一個對象而不是複合模型類(這不是我想要做的最後)時,對象的tied屬性是一個字典。不幸的是,設置這個字典仍然沒有產生預期的效果:

>>> TwoSetModel = MyModel(0.2) + MyModel(0.3) 
>>> 
>>> TwoSetModel 
<CompoundModel1(flux_0=0.2, flux_1=0.3)> 
>>> 
>>> TwoSetModel.tied 
{'flux_1': False, 'flux_0': False} 
>>> 
>>> TwoSetModel.tied['flux_1'] = tie_fluxes 
>>> 
>>> TwoSetModel 
<CompoundModel1(flux_0=0.2, flux_1=0.3)> 
>>> 
>>> TwoSetModel.flux_1.tied 
<function tie_fluxes at 0x102987730> 

所以在這個例子中,tied屬性確實保持正確的功能,但參數的value沒有相應的更新。

我在這裏做錯了什麼?我完全誤解了tied屬性?

(我在上面的例子中使用Python 3.5.2與1.3.3 Astropy)


腳註:

運行help(TwoModel),我得到以下信息:

⁝ 
| tied : dict, optional 
|  Dictionary ``{parameter_name: callable}`` of parameters which are 
|  linked to some other parameter. The dictionary values are callables 
|  providing the linking relationship. 
| 
|  Alternatively the `~astropy.modeling.Parameter.tied` property of a 
|  parameter may be used to set the ``tied`` constraint on individual 
|  parameters. 
⁝ 
| Examples 
| -------- 
| >>> from astropy.modeling import models 
| >>> def tie_center(model): 
| ...   mean = 50 * model.stddev 
| ...   return mean 
| >>> tied_parameters = {'mean': tie_center} 
| 
| Specify that ``'mean'`` is a tied parameter in one of two ways: 
| 
| >>> g1 = models.Gaussian1D(amplitude=10, mean=5, stddev=.3, 
| ...      tied=tied_parameters) 
| 
| or 
| 
| >>> g1 = models.Gaussian1D(amplitude=10, mean=5, stddev=.3) 
| >>> g1.mean.tied 
| False 
| >>> g1.mean.tied = tie_center 
| >>> g1.mean.tied 
| <function tie_center at 0x...> 
⁝ 
+0

好問題 - 我寫了大部分代碼,所以我應該能夠回答你的問題。我即將出發的一天,但我會盡快找回。不幸的是,IIRC處理複合模型的約束仍然有點棘手。 – Iguananaut

+1

我現在可以告訴你的一件事 - 你似乎陷入了一個常見的誤解,即在手動更新參數值時應用模型約束。不是這種情況。約束條件*只適用於擬合模型的擬合者,以便對參數設置約束條件。不符合擬合約束條件。我曾考慮過改變它,以便它能像你期望的那樣工作。有一個問題在某一點上公開,但我現在似乎無法找到它...... – Iguananaut

+0

我認爲https://github.com/astropy/astropy/issues/2265提供了一些參考。 – Iguananaut

回答

0

下面的例子與在astropy文檔中給出的例子類似。

複合模型=兩個1D高斯函數的和。

約束:mean_1 = 2個* mean_0

import numpy as np 
import matplotlib.pyplot as plt 
from astropy.modeling import models, fitting 


def tie_center(model): 
    mean = 2* model.mean_0 
    return mean 

tied_parameters = {'mean_1': tie_center} 
np.random.seed(42) 
g1 = models.Gaussian1D(2, 0.4, 0.3) 
g2 = models.Gaussian1D(2.5, 0.2, 0.2) 
TwoGaussians = (models.Gaussian1D + 
models.Gaussian1D).rename('TwoGaussians') 
x = np.linspace(-1, 1, 200) 
y = g1(x) + g2(x) + np.random.normal(0., 0.2, x.shape) 

gg_init = TwoGaussians(amplitude_0=1.4, mean_0=1.2, stddev_0=0.1,\ 
amplitude_1=1.0,stddev_1=0.2, tied=tied_parameters) 
fitter = fitting.SLSQPLSQFitter() 
gg_fit = fitter(gg_init, x, y) 


plt.figure(figsize=(8,5)) 
plt.plot(x, y, 'ko') 
plt.plot(x, gg_fit(x)) 
plt.xlabel('Position') 
plt.ylabel('Flux') 
plt.show() 
print(gg_fit.mean_0,gg_fit.mean_1) 

搭售在astropy參數時Compund_model =三個1D高斯函數 約束總和:所有三種手段的總和應始終等於一。

def tie_center(model): 
    mean = 1-(model.mean_0+ model.mean_1) 
    return mean 
tied_parameters = {'mean_2': tie_center} 

np.random.seed(42) 
g1 = models.Gaussian1D(2, 0.4, 0.3) 
g2 = models.Gaussian1D(2.5, 0.2, 0.2) 
g3 = models.Gaussian1D(1.5, 0.4, 0.1) 
ThreeGaussians = (models.Gaussian1D + models.Gaussian1D + 
models.Gaussian1D).rename('ThreeGaussians') 
x = np.linspace(-1, 1, 200) 
y = g1(x) + g2(x) + g3(x) + np.random.normal(0., 0.2, x.shape) 

gg_init = ThreeGaussians(amplitude_0=1.4, mean_0=0.3, stddev_0=0.1, 
amplitude_1=1.0, mean_1=0.3,stddev_1=0.2, \ 
amplitude_2=1.5,stddev_2=0.1,tied=tied_parameters) 
fitter = fitting.SLSQPLSQFitter() 
gg_fit = fitter(gg_init, x, y) 
plt.figure(figsize=(8,5)) 
plt.plot(x, y, 'ko') 
plt.plot(x, gg_fit(x)) 
plt.xlabel('Position') 
plt.ylabel('Flux') 
plt.show() 
print(gg_fit.mean_0,gg_fit.mean_1, gg_fit.mean_2)