Skip to content

Provide a way to make a copy of a model with different parameter values, or be more flexible with parameter shape #16593

@astrofrog

Description

@astrofrog

GIven a model with scalar or array parameters, I would like to be able to easily make another model which has different parameter values (either scalar or array), while preserving other things (e.g. constraints, polynomial degree, etc). One can try the naive approach of making a copy of the model and then changing the parameters, but this doesn't always work:

Common imports

from astropy.modeling.models import Polynomial1D

import numpy as np

Scalar ▶️ Scalar

This case works fine:

poly = Polynomial1D(2, c0=1, c1=3, c2=5)
poly.c0.fixed = True
poly.c1.bounds = [0, 10]

poly2 = poly.copy()
poly2.c0=1.5
poly2.c1=3.2
poly2.c2 = 5.5

Array ▶️ scalar

poly = Polynomial1D(2, c0=np.ones((10, 10)), c1=np.ones((10, 10)) * 3, c2=np.ones((10, 10)) * 5)
poly.c0.fixed = True
poly.c1.bounds = [0, 10]

poly2 = poly.copy()
poly2.c0=1.5
poly2.c1=3.2
poly2.c2 = 5.5

This works ok because scalars are broadcastable to arrays. This is not ideal though as one temporarily has a copy of all the arrays in memory, and if the arrays are big it might be annoying.

Array ▶️ array

This does not work if the new array shape is not broadcastable to the old one:

poly = Polynomial1D(2, c0=np.ones((10, 10)), c1=np.ones((10, 10)) * 3, c2=np.ones((10, 10)) * 5)
poly.c0.fixed = True
poly.c1.bounds = [0, 10]

poly2 = poly.copy()
poly2.c0=np.arange(5)

The error is:

InputParameterError: Value for parameter c0 does not match shape or size
expected by model ((5,), 5) vs ((10, 10), 100)

Scalar ▶️ Array

This does not work at all:

poly = Polynomial1D(2, c0=1, c1=3, c2=5)
poly.c0.fixed = True
poly.c1.bounds = [0, 10]

poly2 = poly.copy()
poly2.c0=np.arange(5)

the error is:

InputParameterError: Value for parameter c0 does not match shape or size
expected by model ((5,), 5) vs ((1,), 1)

Possible solutions

One option would not be to check the dimensions whenever parameters are set, but to instead validate them at the point where the model is called - otherwise it is not possible to change the parameters to have a shape that is not broadcastable to the current one.

Another option would be to have a way to do e.g. poly.copy_with_new_parameters(c0=np.arange(5), ...) or similar, that is, do a copy but replace the parameter value with the ones provided in the method call.

I'm open to other ideas though!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions