TermBuilder.tx()

Contents

TermBuilder.tx()#

TermBuilder.tx(*marginals, common_scale=None, inference='default', scales_inference=MCMCSpec(<class 'liesel.goose.hmc.HMCKernel'>, self.kernel_group=None), prefix='', name=None)[source]#

General anisotropic tensor product interaction term without main effects.

Includes only the tensor product interaction. Corresponds to mgcv::ti.

Warning

This method removes any default gibbs samplers and replaces them with scales_inference on log level, since the full conditional for the variance parameters is not known in closed form for an anisotropic tensor product.

Parameters:
  • *marginals (StrctTerm) – Marginal terms, subclasses of StrctTerm.

  • common_scale (ScaleIG | Var | float | VarIGPrior | Literal['default'] | None, default: None) – A single, common scale to cover all marginal dimensions, resulting in an isotropic tensor product. This mean setting \(\tau^2_1 = \dots = \tau^2_M = \tau^2\) for all marginal dimensions of this interaction in the notation used in StrctInteractionTerm. This does not affect the scales of the supplied marginals (main effects).

  • inference (Any | None | Literal['default'], default: 'default') – Inference specification for this term’s coefficient. The default ("default") uses the TermBuilder’s default inference specification defined during initialization. Please refer to the TermBuilder documentation for more information.

  • scales_inference (Any | None | Literal['default'], default: MCMCSpec(<class 'liesel.goose.hmc.HMCKernel'>, self.kernel_group=None)) – If "default", uses the default inference passed to the TermBuilder upon initialization.

  • prefix (str, default: '') – A string prefix to be added to the returned term’s name.

  • name (str | None, default: None) – Manually defined name of the term. If a prefix is specified, the prefix will be added to this name.

Return type:

StrctInteractionTerm

Notes

Note

The methods tf() and tx() are closely related. The former loosely corresponds to mgcv::ti, and the latter loosely corresponds to mgcv::te, meaning that, when you supply centered marginals, tx will only include the highest-order interaction of the supplied marginals, while tf will include the highest-order interaction and all lower-order interactions, including the main effects.

See also

StrctInteractionTerm

The term class returned by this method; includes further details.

tf

Full tensor product, including main effects.

Examples

Using only the interaction term:

>>> import liesel_gam as gam
>>> df = gam.demo_data(100)
>>> tb = gam.TermBuilder.from_df(df)
>>> pred = gam.AdditivePredictor(name="loc")
>>> ps1 = tb.ps("x_nonlin", k=7)
>>> ps2 = tb.ps("x_lin", k=7)
>>> pred += tb.tx(ps1, ps2)
>>> pred.terms
{'tx(x_nonlin,x_lin)': StrctInteractionTerm(name="tx(x_nonlin,x_lin)")}

Anova decomposition

Including the main effects (this corresponds to tf()):

>>> import liesel_gam as gam
>>> df = gam.demo_data(100)
>>> tb = gam.TermBuilder.from_df(df)
>>> pred = gam.AdditivePredictor(name="loc")
>>> ps1 = tb.ps("x_nonlin", k=7)
>>> ps2 = tb.ps("x_lin", k=7)
>>> pred += ps1, ps2, tb.tx(ps1, ps2)
>>> len(pred.terms)
3

Isotropic tensor product interaction

>>> import liesel_gam as gam
>>> import tensorflow_probability.substrates.jax.bijectors as tfb
>>> import tensorflow_probability.substrates.jax.distributions as tfd
>>> df = gam.demo_data(100)
>>> tb = gam.TermBuilder.from_df(df)
>>> pred = gam.AdditivePredictor(name="loc")

Marginal smooths:

>>> ps1 = tb.ps("x_nonlin", k=7)
>>> ps2 = tb.ps("x_lin", k=7)

Initializing the scale variable:

>>> scale = lsl.Var.new_param(
...     1.0,
...     distribution=lsl.Dist(tfd.HalfNormal, scale=20.0),
...     name="{x}",
... )
>>> log_scale = scale.transform(
...     tfb.Exp(),
...     inference=gs.MCMCSpec(gs.HMCKernel),
...     name="ln({x})",
... )

Initializing the interaction term:

>>> tx1 = tb.tx(ps1, ps2, common_scale=scale)

The StrctTensorProdTerm.scales list now contains the same scale twice, leading to an isotropic tensor product.

>>> tx1.scales[0]
Var(name="$\tau_{tx(x_nonlin,x_lin)}$")
>>> tx1.scales[1]
Var(name="$\tau_{tx(x_nonlin,x_lin)}$")

Marginals with different dimensions

In the Anova decomposition of a tensor product, you can supply marginals with more bases than the marginals used in the interaction term. This can be helpful for managing the curse of dimensionality, as the parameter count in the interaction term grows rapidly.

>>> import liesel_gam as gam
>>> df = gam.demo_data(100)
>>> tb = gam.TermBuilder.from_df(df)
>>> pred = gam.AdditivePredictor(name="loc")

Independent marginal terms:

>>> ps1 = tb.ps("x_nonlin", k=20)
>>> ps2 = tb.ps("x_lin", k=20)
>>> pred += ps1, ps2

Adding an interaction term using marginals with fewer bases:

>>> pred += tb.tx(
...     tb.ps("x_nonlin", k=7),
...     tb.ps("x_lin", k=7),
... )
>>> len(pred.terms)
3

Note that this term has four variance parameters: Four of them govern the independent marginals, and the other two govern the interaction, because we initialize new marginals with new variance parameters for the interaction term.

This added flexibility when using tx() is a further difference to tf().

Three-dimensional interaction

Note that this term has six variance parameters: Three of them govern the independent marginals, and the other three are used in the interaction terms, because we initialize new marginals with new variance parameters for the interaction terms.

This added flexibility when using tx() is a further difference to tf().

>>> import liesel_gam as gam
>>> df = gam.demo_data(100)
>>> tb = gam.TermBuilder.from_df(df)
>>> pred = gam.AdditivePredictor(name="loc")
>>> ps1 = tb.ps("x_nonlin", k=20)
>>> ps2 = tb.ps("x_lin", k=20)
>>> ps3 = tb.ps("x", k=20)

We first add the main effects:

>>> pred += ps1, ps2, ps3

Then we initialize a second set of marginals:

>>> ps1x = tb.ps("x_nonlin", k=7)
>>> ps2x = tb.ps("x_lin", k=7)
>>> ps3x = tb.ps("x", k=7)

Then the three bivariate interactions:

>>> pred += tb.tx(ps1x, ps2x)
>>> pred += tb.tx(ps1x, ps3x)
>>> pred += tb.tx(ps2x, ps3x)

And finally the trivariate interaction:

>>> pred += tb.tx(ps1x, ps2x, ps3x)
>>> len(pred.terms)
7