{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Fitting an Elastic Net with a precomputed Gram Matrix and Weighted Samples\n\nThe following example shows how to precompute the gram matrix\nwhile using weighted samples with an :class:`~sklearn.linear_model.ElasticNet`.\n\nIf weighted samples are used, the design matrix must be centered and then\nrescaled by the square root of the weight vector before the gram matrix\nis computed.\n\n<div class=\"alert alert-info\"><h4>Note</h4><p>`sample_weight` vector is also rescaled to sum to `n_samples`, see the\n   documentation for the `sample_weight` parameter to\n   :meth:`~sklearn.linear_model.ElasticNet.fit`.</p></div>\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Authors: The scikit-learn developers\n# SPDX-License-Identifier: BSD-3-Clause"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's start by loading the dataset and creating some sample weights.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import numpy as np\n\nfrom sklearn.datasets import make_regression\n\nrng = np.random.RandomState(0)\n\nn_samples = int(1e5)\nX, y = make_regression(n_samples=n_samples, noise=0.5, random_state=rng)\n\nsample_weight = rng.lognormal(size=n_samples)\n# normalize the sample weights\nnormalized_weights = sample_weight * (n_samples / (sample_weight.sum()))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "To fit the elastic net using the `precompute` option together with the sample\nweights, we must first center the design matrix,  and rescale it by the\nnormalized weights prior to computing the gram matrix.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "X_offset = np.average(X, axis=0, weights=normalized_weights)\nX_centered = X - np.average(X, axis=0, weights=normalized_weights)\nX_scaled = X_centered * np.sqrt(normalized_weights)[:, np.newaxis]\ngram = np.dot(X_scaled.T, X_scaled)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We can now proceed with fitting. We must passed the centered design matrix to\n`fit` otherwise the elastic net estimator will detect that it is uncentered\nand discard the gram matrix we passed. However, if we pass the scaled design\nmatrix, the preprocessing code will incorrectly rescale it a second time.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from sklearn.linear_model import ElasticNet\n\nlm = ElasticNet(alpha=0.01, precompute=gram)\nlm.fit(X_centered, y, sample_weight=normalized_weights)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.11.14"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}