# GAMClassifier


Scikit-learn compatible GAM classifier (binary).


Usage

``` python
GAMClassifier(
    formula=None,
    *,
    method="GCV",
    select=False,
)
```


[GAMClassifier](GAMClassifier.md#whittaker.GAMClassifier) wraps [whittaker.gam.GAM](GAM.md#whittaker.GAM) behind the scikit-learn `BaseEstimator` / `ClassifierMixin` interface for binary classification. It always fits a `whittaker.families.binomial.Binomial(link="logit")` family internally -- i.e. a logistic GAM -- so the linear predictor is related to the class-1 probability `\mu` by the logit link, `\eta = \log(\mu / (1 - \mu))`. Only two-class problems are supported: `fit()` raises a `ValueError` if `y` does not contain exactly two distinct labels. The formula-building behavior (synthetic feature names, default `s(xi)`-per-feature formula, or an explicit `formula`) is identical to [GAMRegressor](GAMRegressor.md#whittaker.GAMRegressor); see that class for details.

Fitted attributes follow the scikit-learn classifier convention: `self.classes_` holds the two observed labels sorted ascending (as returned by `numpy.unique`), and [predict_proba](GAMClassifier.md#whittaker.GAMClassifier.predict_proba) returns probability columns ordered to match `self.classes_` (column 0 is `P(y = classes_[0])`, column 1 is `P(y = classes_[1])`). This makes [GAMClassifier](GAMClassifier.md#whittaker.GAMClassifier) compatible with `Pipeline`, `GridSearchCV`/`RandomizedSearchCV` (scored via `"accuracy"`, `"roc_auc"`, or a custom scorer), and any tooling that consumes [predict_proba](GAMClassifier.md#whittaker.GAMClassifier.predict_proba), such as `sklearn.calibration.CalibratedClassifierCV` or manual decision-threshold tuning on the predicted probabilities.


## Parameters


`formula: str = None`  
GAM formula for the right-hand side (e.g. `"s(x0) + s(x1)"`), or a complete formula containing `"~"`. If it contains `"~"` it is used verbatim; otherwise the response `"y"` is prepended. If `None` (the default), a formula with one `s(xi)` smooth per input feature is generated automatically.

`method: str = ``"GCV"`  
Smoothing parameter selection criterion forwarded to [GAM.fit](GAM.md#whittaker.GAM.fit): `"GCV"` (default), `"REML"`, or `"ML"`. See [whittaker.gam.GAM.fit](GAM.md#whittaker.GAM.fit) for the meaning of each option.

`select: bool = ``False`  
If `True`, enable double-penalty smooth selection, forwarded to [GAM.fit](GAM.md#whittaker.GAM.fit). Defaults to `False`.


## Notes

As with [GAMRegressor](GAMRegressor.md#whittaker.GAMRegressor), the hyperparameters exposed to `GridSearchCV`/`RandomizedSearchCV` via `get_params()` are the constructor arguments -- `formula`, [method](CausalGAM.md#whittaker.CausalGAM.method), and `select` -- since scikit-learn's `get_params` introspects `__init__`. There is no `family` parameter here because the family is fixed to `Binomial(link="logit")`. The smoothing parameters `\lambda_j` are always selected internally by [method](CausalGAM.md#whittaker.CausalGAM.method) during `fit()` rather than being directly tunable.


## Examples


``` python
import numpy as np
from whittaker.sklearn import GAMClassifier

rng = np.random.default_rng(0)
X = rng.uniform(-2, 2, size=(300, 2))
logit = 1.5 * np.sin(X[:, 0]) - X[:, 1]
p = 1 / (1 + np.exp(-logit))
y = rng.binomial(1, p)

clf = GAMClassifier(formula="s(x0) + s(x1)")
clf.fit(X, y)
clf.predict_proba(X[:5])
```


    array([[0.13026716, 0.86973284],
           [0.74973502, 0.25026498],
           [0.57189211, 0.42810789],
           [0.46846977, 0.53153023],
           [0.82997728, 0.17002272]])


``` python
clf.predict(X[:5])
```


    array([1, 0, 0, 1, 0])


## Methods

| Name | Description |
|----|----|
| [fit()](#fit) | Fit the GAM classifier. |
| [predict()](#predict) | Predict class labels for X. |
| [predict_proba()](#predict_proba) | Predict class probabilities for X. |

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


### fit()


Fit the GAM classifier.


Usage

``` python
fit(
    X,
    y,
    **fit_params,
)
```


Validates `X` and `y` with `check_X_y`, records the two observed class labels in `self.classes_`, assigns synthetic feature names, builds the model formula, and fits an internal `Binomial(link="logit")` [whittaker.gam.GAM](GAM.md#whittaker.GAM) to the resulting data dictionary using [method](CausalGAM.md#whittaker.CausalGAM.method) and `select`.


#### Parameters


`X: numpy.ndarray`  
Feature matrix, shape `(n_samples, n_features)`. Coerced to `float64` and validated by `sklearn.utils.validation.check_X_y`.

`y: numpy.ndarray`  
Class labels, shape `(n_samples,)`. Must contain exactly two distinct values (e.g. `0`/`1`, or any two comparable labels); coerced to `float64` alongside `X`.


#### Returns


`GAMClassifier`  
Returns `self`, with fitted attributes `classes_` (the two sorted class labels seen in `y`), `n_features_in_`, `feature_names_`, and `gam_` (the underlying fitted [Binomial](Binomial.md#whittaker.Binomial)-family [whittaker.gam.GAM](GAM.md#whittaker.GAM)).


#### Raises


`ValueError`  
If `y` contains fewer or more than two distinct values, since [GAMClassifier](GAMClassifier.md#whittaker.GAMClassifier) supports binary classification only.


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


### predict()


Predict class labels for X.


Usage

``` python
predict(X)
```


Calls [predict_proba()](GAMClassifier.md#whittaker.GAMClassifier.predict_proba) and, for each sample, returns the label in `self.classes_` corresponding to the higher predicted probability (i.e. thresholding at `0.5` on the positive-class probability).


#### Parameters


`X: numpy.ndarray`  
Feature matrix, shape `(n_samples, n_features_in_)`.


#### Returns


`NDArray`  
Predicted class labels, shape `(n_samples,)`, drawn from `self.classes_`.


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


### predict_proba()


Predict class probabilities for X.


Usage

``` python
predict_proba(X)
```


Requires `fit()` to have been called first. Converts `X` into the internal data dictionary and calls the fitted [Binomial](Binomial.md#whittaker.Binomial)-family [GAM](GAM.md#whittaker.GAM)'s `predict()` to obtain the probability of the positive class (`self.classes_[1]`), then derives the probability of the negative class as its complement.


#### Parameters


`X: numpy.ndarray`  
Feature matrix, shape `(n_samples, n_features_in_)`. Coerced to `float64` and validated by `sklearn.utils.validation.check_array`.


#### Returns


`NDArray`  
Predicted probabilities, shape `(n_samples, 2)`. Column `0` is `P(y == self.classes_[0])` and column `1` is `P(y == self.classes_[1])`, matching the scikit-learn convention that [predict_proba](GAMClassifier.md#whittaker.GAMClassifier.predict_proba) columns are ordered by `self.classes_`.
