# Gaussian


Gaussian (Normal) family with identity link.


Usage

``` python
Gaussian()
```


The Gaussian family models a continuous, unbounded response with constant variance. It is the default family in Whittaker and corresponds to classical (penalized) least-squares regression: with the identity link, P-IRLS converges in a single step since the working response and weights do not depend on the current fit. Use it whenever the response is real-valued, approximately symmetric, and its spread does not depend systematically on its mean -- for example, physical measurements, log-transformed sizes, or residual-like quantities. If the variance grows with the mean, or the response is a count, proportion, or strictly positive quantity, consider [Poisson](Poisson.md#whittaker.Poisson), [Binomial](Binomial.md#whittaker.Binomial), [Gamma](Gamma.md#whittaker.Gamma), or another family instead.


## Notes

The canonical (and only supported) link is the identity function:

 g(\mu) = \mu 

so the linear predictor `eta` is directly on the response scale and no back-transformation is needed for predictions. The variance function is constant in the mean,

 V(\mu) = 1, \qquad \operatorname{Var}(Y) = \phi \\ V(\mu) = \sigma^2, 

which is what makes the Gaussian family the special case in which ordinary least squares and maximum-likelihood estimation coincide. The deviance is the residual sum of squares:

 D(y, \hat\mu) = \sum_i (y_i - \hat\mu_i)^2 . 


## Examples

Fit a GAM with a smooth term to noisy sine-wave data using the (default) Gaussian family:


``` python
import numpy as np
import whittaker as wk

rng = np.random.default_rng(0)
n = 200
x = np.linspace(0, 2 * np.pi, n)
y = np.sin(x) + rng.normal(0, 0.3, n)

data = {"x": x, "y": y}

model = wk.GAM("y ~ s(x)", family=wk.Gaussian())
model.fit(data, method="REML")
print(model.summary())
```


    GAM fit summary
    ============================================================
    Formula:    y ~ s(x)
    Family:     Gaussian(link='identity')
    Inference:  REML
    Observations: 200
    Coefficients: 10

    Parametric coefficients:
      Term                       Estimate    Std.Err    t value    p-value
      ------------------------ ---------- ---------- ---------- ----------
      (Intercept)                  0.0046     0.0205      0.224     0.8233

    Approximate significance of smooth terms:
      Term                        EDF Ref.df     Chi.sq    p-value
      ------------------------ ------ ------ ---------- ----------
      s(x)                       7.31      8   1279.244    < 1e-16

    Total EDF:  8.31
    Scale est:  0.083835
    Deviance:   16.0702
    Null dev:   123.9418
    Dev. expl:  87.0%
    GCV score:  0.087470
    AIC:        80.11
    BIC:        107.52


## Methods

| Name | Description |
|----|----|
| [deviance()](#deviance) | Total deviance: the (weighted) residual sum of squares \sum_i (y_i - \hat\mu_i)^2. |
| [initialize()](#initialize) | Starting values for `mu`: a copy of the observed response `y`. |
| [link()](#link) | Apply the identity link: \eta = \mu. |
| [link_derivative()](#link_derivative) | Derivative of the identity link: g'(\mu) = 1. |
| [link_inverse()](#link_inverse) | Apply the inverse identity link: \mu = \eta. |
| [log_likelihood()](#log_likelihood) | Gaussian log-likelihood evaluated at variance `scale`. |
| [simulate()](#simulate) | Simulate Gaussian response values `N(mu, scale)`. |
| [variance()](#variance) | Constant variance function: V(\mu) = 1. |

------------------------------------------------------------------------


### deviance()


Total deviance: the (weighted) residual sum of squares \sum_i (y_i - \hat\mu_i)^2.


Usage

``` python
deviance(
    y,
    mu,
    *,
    weights=None,
)
```


#### Parameters


`y: NDArray`  
Observed response values, shape `(n,)`.

`mu: NDArray`  
Fitted conditional mean values, shape `(n,)`.

`weights: NDArray | None = None`  
Optional prior weights, shape `(n,)`.


#### Returns


`float`  
The total (weighted) residual sum of squares.


------------------------------------------------------------------------


### initialize()


Starting values for `mu`: a copy of the observed response `y`.


Usage

``` python
initialize(y)
```


Appropriate for the Gaussian family since the identity link places no constraint on the valid range of `mu`.


#### Parameters


`y: NDArray`  
Observed response values, shape `(n,)`.


#### Returns


`NDArray`  
Starting values for `mu`, shape `(n,)`.


------------------------------------------------------------------------


### link()


Apply the identity link: \eta = \mu.


Usage

``` python
link(mu)
```


The Gaussian family uses the identity link, so this is a no-op that returns `mu` unchanged.


#### Parameters


`mu: NDArray`  
Conditional mean values, shape `(n,)`.


#### Returns


`NDArray`  
Linear predictor values \eta = \mu, shape `(n,)`.


------------------------------------------------------------------------


### link_derivative()


Derivative of the identity link: g'(\mu) = 1.


Usage

``` python
link_derivative(mu)
```


#### Parameters


`mu: NDArray`  
Conditional mean values, shape `(n,)`.


#### Returns


`NDArray`  
An array of ones, shape `(n,)`.


------------------------------------------------------------------------


### link_inverse()


Apply the inverse identity link: \mu = \eta.


Usage

``` python
link_inverse(eta)
```


Returns `eta` unchanged, since the identity link is self-inverse.


#### Parameters


`eta: NDArray`  
Linear predictor values, shape `(n,)`.


#### Returns


`NDArray`  
Conditional mean values \mu = \eta, shape `(n,)`.


------------------------------------------------------------------------


### log_likelihood()


Gaussian log-likelihood evaluated at variance `scale`.


Usage

``` python
log_likelihood(
    y,
    mu,
    scale,
    *,
    weights=None,
)
```


Computes \ell_i = -\tfrac{1}{2}\log(2\pi\phi) - \tfrac{(y_i - \mu_i)^2}{2\phi} for each observation, where \phi is `scale`, and sums (optionally weighted) over observations.


#### Parameters


`y: NDArray`  
Observed response values, shape `(n,)`.

`mu: NDArray`  
Fitted conditional mean values, shape `(n,)`.

`scale: float`  
Residual variance \phi = \sigma^2.

`weights: NDArray | None = None`  
Optional prior weights, shape `(n,)`.


#### Returns


`float`  
The total log-likelihood.


------------------------------------------------------------------------


### simulate()


Simulate Gaussian response values `N(mu, scale)`.


Usage

``` python
simulate(
    mu,
    scale,
    rng,
)
```


#### Parameters


`mu: NDArray`  
Mean (fitted values), shape `(n,)`.

`scale: float`  
Residual variance `sigma^2`.

`rng: np.random.Generator`  
A `numpy.random.Generator` instance.


#### Returns


`NDArray`  
Simulated response values, shape `(n,)`.


------------------------------------------------------------------------


### variance()


Constant variance function: V(\mu) = 1.


Usage

``` python
variance(mu)
```


The Gaussian variance does not depend on the mean, so `Var(Y) = phi * V(mu) = phi` (the residual variance `sigma^2`).


#### Parameters


`mu: NDArray`  
Conditional mean values, shape `(n,)`.


#### Returns


`NDArray`  
An array of ones, shape `(n,)`.
