<a id="skfolio-linear-model-cslinearregressorwrapper"></a>

# skfolio.linear_model.CSLinearRegressorWrapper

<a id="skfolio.linear_model.CSLinearRegressorWrapper"></a>

### *class* skfolio.linear_model.CSLinearRegressorWrapper(regressor, n_jobs=1)

Cross-sectional regression based on a scikit-learn regressor.

This estimator wraps a scikit-learn regressor and fits one independent regression
across assets for each observation. These independent observation-level regressions
can be fitted in parallel by setting `n_jobs`. The wrapped regressor must define
`fit_intercept`, implement `fit`, accept a `sample_weight` argument, and expose
fitted `coef_` and `intercept_` attributes.

Missing-value handling is driven by `cs_weights` on each `(observation, asset)`
pair:

- If `cs_weights > 0`, all features in `X` and `y` must be finite.
- If `cs_weights == 0`, the pair is excluded from estimation and `X` and `y` may be
  finite or missing.
- Each observation must retain at least one valid asset after applying `cs_weights`.

* **Parameters:**
  **regressor** *BaseEstimator*
  : Scikit-learn regressor used at each observation.

  **n_jobs** *int, default=1*
  : Number of parallel jobs used to fit the observation-level regressions.
* **Attributes:**
  **coef_** *ndarray of shape (n_observations, n_features)*
  : Estimated coefficients for each observation.

  **intercept_** *ndarray of shape (n_observations,)*
  : Intercept for each observation. Set to zeros if `fit_intercept=False`.

  **n_features_in_** *int*
  : Number of features seen during `fit`.

  **n_valid_assets_** *ndarray of shape (n_observations,)*
  : Number of assets that participated in estimation (those with positive weight)
    for each observation.

### Methods

| [`fit`](#skfolio.linear_model.CSLinearRegressorWrapper.fit)(X, y[, cs_weights])             | Fit one wrapped regressor per observation.                                         |
|--------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|
| [`get_metadata_routing`](#skfolio.linear_model.CSLinearRegressorWrapper.get_metadata_routing)()              | Get metadata routing of this object.                                               |
| [`get_params`](#skfolio.linear_model.CSLinearRegressorWrapper.get_params)([deep])                  | Get parameters for this estimator.                                                 |
| [`predict`](#skfolio.linear_model.CSLinearRegressorWrapper.predict)(X)                          | Predict using the cross-sectional linear model.                                    |
| [`score`](#skfolio.linear_model.CSLinearRegressorWrapper.score)(X, y[, cs_weights])           | Return the mean coefficient of determination across observations.                  |
| [`set_fit_request`](#skfolio.linear_model.CSLinearRegressorWrapper.set_fit_request)(\*[, cs_weights])   | Configure whether metadata should be requested to be passed to the `fit` method.   |
| [`set_params`](#skfolio.linear_model.CSLinearRegressorWrapper.set_params)(\*\*params)              | Set the parameters of this estimator.                                              |
| [`set_score_request`](#skfolio.linear_model.CSLinearRegressorWrapper.set_score_request)(\*[, cs_weights]) | Configure whether metadata should be requested to be passed to the `score` method. |

#### SEE ALSO
[`CSLinearRegression`](https://skfolio.org/generated/skfolio.linear_model.CSLinearRegression.html.md#skfolio.linear_model.CSLinearRegression)

### Examples

```pycon
>>> import numpy as np
>>> from sklearn.linear_model import HuberRegressor
>>> from skfolio.linear_model import CSLinearRegressorWrapper
>>>
>>> rng = np.random.default_rng(42)
>>> X = rng.normal(size=(3, 5, 2))
>>> y = rng.normal(size=(3, 5))
>>> cs_weights = 1.0 + rng.random(size=(3, 5))
>>>
>>> model = CSLinearRegressorWrapper(
...     regressor=HuberRegressor(fit_intercept=True, max_iter=200)
... )
>>> model.fit(X, y, cs_weights=cs_weights)
CSLinearRegressorWrapper(...)
>>>
>>> model.intercept_.shape
(3,)
>>> model.coef_.shape
(3, 2)
>>> model.predict(X).shape
(3, 5)
>>> model.score(X, y)
0.4901...
```

<a id="skfolio.linear_model.CSLinearRegressorWrapper.fit"></a>

#### fit(X, y, cs_weights=None)

Fit one wrapped regressor per observation.

Each observation must contain at least one asset with positive weight
and finite `X` and `y` values.

* **Parameters:**
  **X** *array-like of shape (n_observations, n_assets, n_features)*
  : Input feature tensor.

  **y** *array-like of shape (n_observations, n_assets)*
  : Target values.

  **cs_weights** *array-like of shape (n_observations, n_assets), optional*
  : Cross-sectional weights passed to the wrapped regressor as `sample_weight`.
    If None, all assets receive unit weight.
* **Returns:**
  **self** *CSLinearRegressorWrapper*
  : Fitted estimator.

<a id="skfolio.linear_model.CSLinearRegressorWrapper.get_metadata_routing"></a>

#### get_metadata_routing()

Get metadata routing of this object.

Please check [User Guide](https://skfolio.org/user_guide/metadata_routing.html.md#metadata-routing) on how the routing
mechanism works.

* **Returns:**
  **routing** *MetadataRequest*
  : A `MetadataRequest` encapsulating
    routing information.

<a id="skfolio.linear_model.CSLinearRegressorWrapper.get_params"></a>

#### get_params(deep=True)

Get parameters for this estimator.

* **Parameters:**
  **deep** *bool, default=True*
  : If True, will return the parameters for this estimator and
    contained subobjects that are estimators.
* **Returns:**
  **params** *dict*
  : Parameter names mapped to their values.

<a id="skfolio.linear_model.CSLinearRegressorWrapper.predict"></a>

#### predict(X)

Predict using the cross-sectional linear model.

For each observation $t$ and asset $i$, the prediction is
the systematic part; realized outcomes satisfy
$y_{ti} = \hat{y}_{ti} + \epsilon_{ti}$ with residual
$\epsilon_{ti}$. The prediction is

$$
\hat{y}_{ti} = X_{ti}^{T} \beta_t + \beta_{t,0}
$$

* **Parameters:**
  **X** *array-like of shape (n_observations, n_assets, n_features)*
  : Feature tensor used for prediction.
    The observation and feature axes must match those seen during
    `fit`. The asset axis may differ.
* **Returns:**
  **y_pred** *ndarray of shape (n_observations, n_assets)*
  : Predicted values.

<a id="skfolio.linear_model.CSLinearRegressorWrapper.score"></a>

#### score(X, y, cs_weights=None)

Return the mean coefficient of determination across observations.

The coefficient of determination $R^2$ is computed independently
for each observation and then averaged. For observation $t$:

$$
R^2_t = 1 - \frac{\sum_i w_{ti}(y_{ti} - \hat{y}_{ti})^2}
                 {\sum_i w_{ti}(y_{ti} - \bar{y}_t)^2}
$$

where $\bar{y}_t$ is the weighted mean of $y$ for
observation $t$.

* **Parameters:**
  **X** *array-like of shape (n_observations, n_assets, n_features)*
  : Feature tensor on which to evaluate the model.

  **y** *array-like of shape (n_observations, n_assets)*
  : Target values aligned with `X`.

  **cs_weights** *array-like of shape (n_observations, n_assets), optional*
  : Asset weights for computing weighted $R^2$ scores.
    If None, all assets are given equal weight. Pairs with zero weight
    are excluded from the score. Pairs with positive weight must have
    finite `X` and finite `y`.
* **Returns:**
  **score** *float*
  : Mean $R^2$ across all observations with finite values.
    Returns NaN if no observations have valid $R^2$ values.

<a id="skfolio.linear_model.CSLinearRegressorWrapper.set_fit_request"></a>

#### set_fit_request(\*, cs_weights='$UNCHANGED$')

Configure whether metadata should be requested to be passed to the `fit` method.

Note that this method is only relevant when this estimator is used as a
sub-estimator within a meta-estimator and metadata routing is enabled
with `enable_metadata_routing=True` (see `sklearn.set_config`).
Please check the [User Guide](https://skfolio.org/user_guide/metadata_routing.html.md#metadata-routing) on how the routing
mechanism works.

The options for each parameter are:

- `True`: metadata is requested, and passed to `fit` if provided. The request is ignored if metadata is not provided.
- `False`: metadata is not requested and the meta-estimator will not pass it to `fit`.
- `None`: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
- `str`: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (`sklearn.utils.metadata_routing.UNCHANGED`) retains the
existing request. This allows you to change the request for some
parameters and not others.

#### Versionadded
Added in version 1.3.

* **Parameters:**
  **cs_weights** *str, True, False, or None,                     default=sklearn.utils.metadata_routing.UNCHANGED*
  : Metadata routing for `cs_weights` parameter in `fit`.
* **Returns:**
  **self** *object*
  : The updated object.

<a id="skfolio.linear_model.CSLinearRegressorWrapper.set_params"></a>

#### set_params(\*\*params)

Set the parameters of this estimator.

The method works on simple estimators as well as on nested objects
(such as `Pipeline`). The latter have
parameters of the form `<component>__<parameter>` so that it’s
possible to update each component of a nested object.

* **Parameters:**
  **\*\*params** *dict*
  : Estimator parameters.
* **Returns:**
  **self** *estimator instance*
  : Estimator instance.

<a id="skfolio.linear_model.CSLinearRegressorWrapper.set_score_request"></a>

#### set_score_request(\*, cs_weights='$UNCHANGED$')

Configure whether metadata should be requested to be passed to the `score` method.

Note that this method is only relevant when this estimator is used as a
sub-estimator within a meta-estimator and metadata routing is enabled
with `enable_metadata_routing=True` (see `sklearn.set_config`).
Please check the [User Guide](https://skfolio.org/user_guide/metadata_routing.html.md#metadata-routing) on how the routing
mechanism works.

The options for each parameter are:

- `True`: metadata is requested, and passed to `score` if provided. The request is ignored if metadata is not provided.
- `False`: metadata is not requested and the meta-estimator will not pass it to `score`.
- `None`: metadata is not requested, and the meta-estimator will raise an error if the user provides it.
- `str`: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (`sklearn.utils.metadata_routing.UNCHANGED`) retains the
existing request. This allows you to change the request for some
parameters and not others.

#### Versionadded
Added in version 1.3.

* **Parameters:**
  **cs_weights** *str, True, False, or None,                     default=sklearn.utils.metadata_routing.UNCHANGED*
  : Metadata routing for `cs_weights` parameter in `score`.
* **Returns:**
  **self** *object*
  : The updated object.

