.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/numerical_analysis/regression/plot_01_polynomial_regression.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_numerical_analysis_regression_plot_01_polynomial_regression.py: Least-squares polynomial regression and its conditioning ============================================================= :class:`~mathematicskit.numerical_analysis.systems.regression.PolynomialRegression` fits a degree-``d`` polynomial by solving the normal equations :math:`V^T V c = V^T y`. This script fits noisy cubic data, checks the :math:`R^2` and residuals, and then shows the fit's condition number (estimated via power iteration on the normal-equations matrix) growing sharply with degree -- squaring the design matrix's own condition number is exactly why the normal-equations approach is eventually replaced by a QR-based least-squares solve in :mod:`mathematicskit.linalg`. .. GENERATED FROM PYTHON SOURCE LINES 16-21 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from mathematicskit.numerical_analysis import PolynomialRegression .. GENERATED FROM PYTHON SOURCE LINES 22-24 Fit noisy cubic data ----------------------- .. GENERATED FROM PYTHON SOURCE LINES 24-44 .. code-block:: Python rng = np.random.default_rng(0) x = np.linspace(-1.0, 1.0, 60) y_true = 2.0 * x**3 - x + 0.5 y = y_true + rng.normal(0.0, 0.05, x.shape) model = PolynomialRegression(x, y, degree=3) result = model.fit() print(f"coefficients (highest power first): {result.coefficients}") print(f"R^2 = {result.r_squared:.5f}, adjusted R^2 = {result.adjusted_r_squared:.5f}") x_fine = np.linspace(-1.0, 1.0, 300) fig1, ax1 = plt.subplots(figsize=(6, 4)) ax1.scatter(x, y, s=12, color="gray", label="noisy data") ax1.plot(x_fine, model.predict(x_fine), color="firebrick", label="degree-3 fit") ax1.plot(x_fine, 2.0 * x_fine**3 - x_fine + 0.5, "--", color="black", label="true cubic") ax1.legend() ax1.set_title("Least-squares polynomial fit") fig1.tight_layout() .. image-sg:: /api/gallery/numerical_analysis/regression/images/sphx_glr_plot_01_polynomial_regression_001.png :alt: Least-squares polynomial fit :srcset: /api/gallery/numerical_analysis/regression/images/sphx_glr_plot_01_polynomial_regression_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none coefficients (highest power first): [ 1.90017422 -0.00562603 -0.92442784 0.50580371] R^2 = 0.98524, adjusted R^2 = 0.98445 .. GENERATED FROM PYTHON SOURCE LINES 45-49 Conditioning worsens with degree ------------------------------------ Fitting increasingly high-degree polynomials to the same data makes the Vandermonde normal-equations matrix more ill-conditioned. .. GENERATED FROM PYTHON SOURCE LINES 49-63 .. code-block:: Python degrees = [1, 2, 4, 6, 8, 10] conditions = [PolynomialRegression(x, y, degree=d).fit().condition_number for d in degrees] for d, c in zip(degrees, conditions): print(f"degree={d:2d} condition number~{c:.3e}") fig2, ax2 = plt.subplots(figsize=(6, 4)) ax2.semilogy(degrees, conditions, "o-", color="steelblue") ax2.set_xlabel("polynomial degree") ax2.set_ylabel("condition number of V^T V") ax2.set_title("Normal-equations conditioning worsens with degree") fig2.tight_layout() plt.show() .. image-sg:: /api/gallery/numerical_analysis/regression/images/sphx_glr_plot_01_polynomial_regression_002.png :alt: Normal-equations conditioning worsens with degree :srcset: /api/gallery/numerical_analysis/regression/images/sphx_glr_plot_01_polynomial_regression_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none degree= 1 condition number~1.703e+00 degree= 2 condition number~3.666e+00 degree= 4 condition number~1.817e+01 degree= 6 condition number~9.583e+01 degree= 8 condition number~5.204e+02 degree=10 condition number~2.884e+03 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.087 seconds) .. _sphx_glr_download_api_gallery_numerical_analysis_regression_plot_01_polynomial_regression.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_polynomial_regression.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_polynomial_regression.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_polynomial_regression.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_