2017-08-04 19 views
5

Astropy.modelling içinde Model.tied (veya Parameter.tied) özniteliğini kullanmaya çalışıyorum, ancak nasıl çalıştığını anlayamıyorum. flux_0 ve flux_1: Örneğin, iki parametrelerle bir bileşik model oluşturmak istedik diyelim. flux_1 daima değerini 1 - flux_0 taşımalıdır: Ancak, ben sadece flux_0 uydurma kullanılacak istiyoruz. (Sonunda, bu flux_0 + flux_1 + ... + flux_n = 1 için bu işlevselliğini gerekir.) Parametreleri astropy.modeling içinde

çok gibi örnek bir sınıfı ve tied özelliği için bir "çağrılabilir" tanımlar:
>>> 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',) 

Sonra tied özelliği kontrol edin. uygun Parameter güncelleme yok,

>>> 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 

Ben bir sözlük olarak ayarlamak çalışırsanız:

>>> TwoModel.tied = {'flux_1': tie_fluxes} 
>>> 
>>> TwoModel.flux_1.tied 
False 
Benim anlayış bu bir sözlük (dipnot bakınız) olmasıdır, ama değil Ben (bu Eninde sonunda yapmak istediğim değildir) sağ yarasa yerine bileşik modeli sınıfında kapalı bir nesne oluştururken çalıştığınızda

Fakat, nesnenin tied nitelik bir sözlük olduğunu. Ne yazık ki, istenen etkiyi üretmez hala bu sözlüğü ayarı: Bu örnekteki Yani

>>> 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 özellik düzgün bir şekilde çalışıp tutun, ama parametre en value buna göre güncellemek etmez.

yanlış burada ne yapıyorum? tied özniteliğini tamamen yanlış anlamış mıyım?

(yukarıdaki örneklerde Astropy 1.3.3 ile Python 3.5.2 kullanıyorum)


Dipnot:

help(TwoModel) Koşu, ben şu bilgileri almak:

⁝ 
| 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

İyi soru - Bu kodun çoğunu yazdım, böylece sorunuzu yanıtlayabilmem gerekir. Gün için yola çıkmak üzereyim ama ASAP'a geri dönmeyi deneyeceğim. IIRC, bileşik modellerle kısıtlamalarla uğraşırken, maalesef hala biraz zor olabilir. Ben şimdi söyleyebilirim – Iguananaut

+1

Bir şey - görüntülenmesini elle parametrelerin değerlerini güncellerken modeli kısıtlamaları uygulanır bir Sanıldığının düşmekten edilecek. Durum bu değil.Kısıtlamalar * sadece * modelleri takarken fitters tarafından kullanılır, parametreler üzerinde kısıtlamalar koymak için. Uydurma kısıtlamaları dışında zorlanmaz. Bunu daha önce değiştirmeyi düşündüm, böylece beklediğiniz gibi çalışıyor. Bir noktada bunun için bir sorun vardı ama şimdi onu bulmak için görünmüyor olabilir ... – Iguananaut

+0

Sanırım https://github.com/astropy/astropy/issues/2265 bunun için biraz referans yapar. – Iguananaut

cevap

0

Aşağıdaki örnek, astropi belgelerinde verilene benzer. İki 1D Gauss fonksiyonları

Bileşik Model = toplamıdır. Üç araçlarının toplamı her zaman bir eşit olmalıdır:

Koru: Compund_model = üç 1D Gauss fonksiyonları Koru toplamı astropy içinde 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) 

Bağlama parametreleri.

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)