Parameters and priors#
The parameters of a model are described with Parameters.
It holds two kinds of things:
free parameters, which are estimated from the data. Each is a
Valuewith a starting value, lower and upper bounds, and a prior distribution.everything else the model needs to start, such as the initial values of the stimuli. These are plain numbers or arrays, without a prior.
import numpy as np
from cpm.generators import Parameters, Value
parameters = Parameters(
alpha=Value(
value=0.5,
lower=1e-10,
upper=1,
prior="truncated_normal",
args={"mean": 0.5, "sd": 0.25},
),
temperature=Value(
value=1,
lower=0,
upper=10,
prior="truncated_normal",
args={"mean": 5, "sd": 2.5},
),
values=np.array([0.25, 0.25, 0.25, 0.25]),
)
A parameter is free if, and only if, it has a prior.
free() lists the free parameters, and bounds() their bounds, which the optimisers use:
parameters.free()
['alpha', 'temperature']
parameters.bounds()
(array([1.e-10, 0.e+00]), array([ 1, 10]))
Inside a model function, parameters behave like numbers:
parameters.alpha * 2
1.0
Priors#
prior is the name of a distribution, and args its arguments.
The distributions are those of scipy.stats:
|
|
|---|---|
|
none: uniform between |
|
|
|
|
|
|
|
|
|
|
You can also pass a scipy.stats distribution itself, such as scipy.stats.multivariate_normal: cpm calls it with args as keyword arguments.
The priors are used in three places:
when fitting with
prior=True, the optimisers maximise the posterior instead of the likelihood,sample()draws parameters from their priors, for example to simulate data,hierarchical methods (
cpm.hierarchical) update the priors to the estimated group distribution.
parameters.sample(size=3)
[{'alpha': np.float64(0.31009860467551054),
'temperature': np.float64(8.333882539594498)},
{'alpha': np.float64(0.6145645170274359),
'temperature': np.float64(3.1935234940021315)},
{'alpha': np.float64(0.603999424362693),
'temperature': np.float64(6.788947830551595)}]
PDF() gives the joint prior density of the current values, or its logarithm with log=True:
parameters.PDF(log=True)
np.float64(-2.5547376125562042)
A density can be larger than 1: unlike a probability, it is only bounded by the requirement that it integrates to 1 over the whole range of the parameter.
Updating priors#
update_prior() changes the arguments of the priors, one keyword argument per parameter:
parameters.update_prior(alpha={"mean": 0.3, "sd": 0.1})
parameters.alpha.prior.mean()
np.float64(0.3004437839046317)
Parameters on a transformed scale#
Some optimisers work better on an unbounded scale.
LogParameters stores the parameters on a logit scale within their bounds, and transforms them back for the model.
Next: Models.