# Beta


Beta regression family with logit link.


Usage

``` python
Beta(phi=None)
```


The Beta family models a continuous response strictly between 0 and 1 -- for example rates, fractions, or proportions that are not simply the ratio of successes to a known number of trials (in which case [Binomial](Binomial.md#whittaker.Binomial) is usually more appropriate). It parameterizes the Beta distribution by its mean `mu` and a precision parameter `phi`, so that larger `phi` yields a tighter distribution around `mu` for fixed mean, analogous to the role `theta` plays in [NegativeBinomial](NegativeBinomial.md#whittaker.NegativeBinomial). The logit link keeps the fitted mean within `(0, 1)` and gives coefficients the same log-odds interpretation as in [Binomial](Binomial.md#whittaker.Binomial) regression.


## Parameters


`phi: float or None = None`  
Fixed precision parameter, must be positive if provided. If `None` (the default), precision is treated as unknown and estimated from the data via the scale parameter (`phi = 1 / scale`); in that case `scale_known` is `False`. Passing a fixed `phi` is useful when the precision is known a priori or should not be re-estimated.


## Notes

The link is the logit function:

 g(\mu) = \log\\\left(\frac{\mu}{1-\mu}\right) 

The variance function is

 V(\mu) = \frac{\mu(1-\mu)}{1+\phi}, 

so larger `phi` (higher precision) shrinks the variance for a given mean. The deviance is twice the difference between the saturated and fitted log-likelihoods,

 D(y, \hat\mu) = 2 \sum_i \left\[ \ell(y_i; y_i) - \ell(y_i; \hat\mu_i) \right\], 

where \ell is the Beta log-density parameterized by (a, b) = (\mu \phi, (1-\mu)\phi).


## Examples

Fit a GAM to a proportion response with a smooth mean trend:


``` python
import numpy as np
import whittaker as wk
from scipy.special import expit

rng = np.random.default_rng(0)
n = 200
x = np.linspace(0, 2 * np.pi, n)
mu = expit(np.sin(x))
phi = 20.0
y = rng.beta(mu * phi, (1 - mu) * phi)

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

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


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

    Parametric coefficients:
      Term                       Estimate    Std.Err    t value    p-value
      ------------------------ ---------- ---------- ---------- ----------
      (Intercept)                  0.0188     0.0323      0.583     0.5603

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

    Total EDF:  7.22
    Scale est:  0.047158
    Deviance:   9.0913
    Null dev:   27.9173
    Dev. expl:  67.4%
    GCV score:  0.048923
    AIC:        -338.54
    BIC:        -314.74


## Attributes

| Name | Description |
|----|----|
| [scale_known](#scale_known) | Whether the precision parameter `phi` is fixed rather than estimated. |

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


### scale_known


Whether the precision parameter `phi` is fixed rather than estimated.


`scale_known: bool`


Returns `True` when a fixed `phi` was supplied at construction, and `False` when `phi` is `None` and must be estimated from the data during fitting. This determines whether [GAM.fit()](GAM.md#whittaker.GAM.fit) treats `phi` as a nuisance parameter to be estimated.


## Methods

| Name | Description |
|----|----|
| [deviance()](#deviance) | Total Beta deviance, the (weighted) sum of `unit_deviance`. |
| [initialize()](#initialize) | Starting values for `mu`: `y` clipped strictly inside `(0, 1)`. |
| [link()](#link) | Apply the logit link: \eta = \log(\mu / (1-\mu)). |
| [link_derivative()](#link_derivative) | Derivative of the logit link: g'(\mu) = 1 / (\mu(1-\mu)). |
| [link_inverse()](#link_inverse) | Apply the inverse logit link (logistic sigmoid): \mu = 1 / (1 + e^{-\eta}). |
| [log_likelihood()](#log_likelihood) | Beta log-likelihood parameterized by mean `mu` and precision `phi`. |
| [simulate()](#simulate) | Simulate Beta-distributed response values with mean `mu` and precision `phi`. |
| [unit_deviance()](#unit_deviance) | Per-observation Beta deviance contributions. |
| [variance()](#variance) | Beta variance function: V(\mu) = \mu(1-\mu) / (1+\phi) up to the `1+phi` scaling. |

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


### deviance()


Total Beta deviance, the (weighted) sum of `unit_deviance`.


Usage

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


#### Parameters


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

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

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


#### Returns


`float`  
The total (weighted) deviance.


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


### initialize()


Starting values for `mu`: `y` clipped strictly inside `(0, 1)`.


Usage

``` python
initialize(y)
```


Since the logit link is undefined at `0` and `1`, values are clipped to `[0.01, 0.99]` to avoid infinite linear predictors on the first P-IRLS iteration.


#### Parameters


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


#### Returns


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


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


### link()


Apply the logit link: \eta = \log(\mu / (1-\mu)).


Usage

``` python
link(mu)
```


#### Parameters


`mu: NDArray`  
Conditional mean values, shape `(n,)`; clipped to `(0, 1)` before transforming.


#### Returns


`NDArray`  
Linear predictor (log-odds) values, shape `(n,)`.


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


### link_derivative()


Derivative of the logit link: g'(\mu) = 1 / (\mu(1-\mu)).


Usage

``` python
link_derivative(mu)
```


#### Parameters


`mu: NDArray`  
Conditional mean values, shape `(n,)`; clipped away from `0` and `1`.


#### Returns


`NDArray`  
Derivative values, shape `(n,)`.


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


### link_inverse()


Apply the inverse logit link (logistic sigmoid): \mu = 1 / (1 + e^{-\eta}).


Usage

``` python
link_inverse(eta)
```


#### Parameters


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


#### Returns


`NDArray`  
Conditional mean values, shape `(n,)`, always in `(0, 1)`.


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


### log_likelihood()


Beta log-likelihood parameterized by mean `mu` and precision `phi`.


Usage

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


The precision used is the fixed `phi` supplied at construction if set, otherwise `1 / scale`. Each observation's log-density is evaluated using shape parameters (a, b) = (\mu \phi, (1-\mu)\phi).


#### Parameters


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

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

`scale: float`  
Used to derive `phi = 1/scale` when no fixed `phi` was supplied at construction.

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


#### Returns


`float`  
The total log-likelihood.


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


### simulate()


Simulate Beta-distributed response values with mean `mu` and precision `phi`.


Usage

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


#### Parameters


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

`scale: float`  
Used to derive `phi = 1/scale` when no fixed `phi` was supplied at construction.

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


#### Returns


`NDArray`  
Simulated response values in `(0, 1)`, shape `(n,)`.


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


### unit_deviance()


Per-observation Beta deviance contributions.


Usage

``` python
unit_deviance(
    y,
    mu,
)
```


Computes a Binomial-like deviance form d_i = 2 \left\[ y_i \log(y_i/\hat\mu_i) + (1-y_i)\log((1-y_i)/(1-\hat\mu_i)) \right\], used as a convenient goodness-of-fit measure on the `(0, 1)` scale.


#### Parameters


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

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


#### Returns


`NDArray`  
Per-observation deviance contributions, shape `(n,)`.


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


### variance()


Beta variance function: V(\mu) = \mu(1-\mu) / (1+\phi) up to the `1+phi` scaling.


Usage

``` python
variance(mu)
```


This method returns the mean-dependent part \mu(1-\mu); the precision-dependent scaling by `1/(1+phi)` is folded into the working weights elsewhere in the fitting loop.


#### Parameters


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


#### Returns


`NDArray`  
Variance values \mu(1-\mu), shape `(n,)`.
