Files
FYS-STK4155/doc/pub/week36/html/week36.html
T
Morten Hjorth-Jensen eb12e84cf6 update
2021-09-09 07:27:17 +02:00

2252 lines
134 KiB
HTML

<!--
Automatically generated HTML file from DocOnce source
(https://github.com/doconce/doconce/)
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="DocOnce: https://github.com/doconce/doconce/" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Week 36: Statistical interpretation of Linear Regression and Resampling techniques">
<title>Week 36: Statistical interpretation of Linear Regression and Resampling techniques</title>
<style type="text/css">
/* bloodish style */
body {
font-family: Helvetica, Verdana, Arial, Sans-serif;
color: #404040;
background: #ffffff;
}
h1 { font-size: 1.8em; color: #8A0808; }
h2 { font-size: 1.6em; color: #8A0808; }
h3 { font-size: 1.4em; color: #8A0808; }
h4 { color: #8A0808; }
a { color: #8A0808; text-decoration:none; }
tt { font-family: "Courier New", Courier; }
/* pre style removed because it will interfer with pygments */
p { text-indent: 0px; }
hr { border: 0; width: 80%; border-bottom: 1px solid #aaa}
p.caption { width: 80%; font-style: normal; text-align: left; }
hr.figure { border: 0; width: 80%; border-bottom: 1px solid #aaa}
.alert-text-small { font-size: 80%; }
.alert-text-large { font-size: 130%; }
.alert-text-normal { font-size: 90%; }
.alert {
padding:8px 35px 8px 14px; margin-bottom:18px;
text-shadow:0 1px 0 rgba(255,255,255,0.5);
border:1px solid #bababa;
border-radius: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
color: #555;
background-color: #f8f8f8;
background-position: 10px 5px;
background-repeat: no-repeat;
background-size: 38px;
padding-left: 55px;
width: 75%;
}
.alert-block {padding-top:14px; padding-bottom:14px}
.alert-block > p, .alert-block > ul {margin-bottom:1em}
.alert li {margin-top: 1em}
.alert-block p+p {margin-top:5px}
.alert-notice { background-image: url(https://cdn.rawgit.com/doconce/doconce/master/bundled/html_images/small_gray_notice.png); }
.alert-summary { background-image:url(https://cdn.rawgit.com/doconce/doconce/master/bundled/html_images/small_gray_summary.png); }
.alert-warning { background-image: url(https://cdn.rawgit.com/doconce/doconce/master/bundled/html_images/small_gray_warning.png); }
.alert-question {background-image:url(https://cdn.rawgit.com/doconce/doconce/master/bundled/html_images/small_gray_question.png); }
div { text-align: justify; text-justify: inter-word; }
</style>
</head>
<!-- tocinfo
{'highest level': 2,
'sections': [('Plans for week 36', 2, None, 'plans-for-week-36'),
('Thursday September 9', 2, None, 'thursday-september-9'),
('Summary from last Week and Examples',
2,
None,
'summary-from-last-week-and-examples'),
('Linear Regression and the SVD',
2,
None,
'linear-regression-and-the-svd'),
('What does it mean?', 2, None, 'what-does-it-mean'),
('And finally $\\boldsymbol{X}\\boldsymbol{X}^T$',
2,
None,
'and-finally-boldsymbol-x-boldsymbol-x-t'),
('Ridge and LASSO Regression',
2,
None,
'ridge-and-lasso-regression'),
('From OLS to Ridge and Lasso',
2,
None,
'from-ols-to-ridge-and-lasso'),
('Deriving the Ridge Regression Equations',
2,
None,
'deriving-the-ridge-regression-equations'),
('SVD analysis', 2, None, 'svd-analysis'),
('Interpreting the Ridge results',
2,
None,
'interpreting-the-ridge-results'),
('More interpretations', 2, None, 'more-interpretations'),
('Deriving the Lasso Regression Equations',
2,
None,
'deriving-the-lasso-regression-equations'),
('Simple example to illustrate Ordinary Least Squares, Ridge and '
'Lasso Regression',
2,
None,
'simple-example-to-illustrate-ordinary-least-squares-ridge-and-lasso-regression'),
('Ridge Regression', 2, None, 'ridge-regression'),
('Lasso Regression', 2, None, 'lasso-regression'),
('Yet another Example', 2, None, 'yet-another-example'),
('The OLS case', 2, None, 'the-ols-case'),
('The Ridge case', 2, None, 'the-ridge-case'),
('Writing the Cost Function',
2,
None,
'writing-the-cost-function'),
('Lasso case', 2, None, 'lasso-case'),
('The first Case', 2, None, 'the-first-case'),
('Simple code for solving the above problem',
2,
None,
'simple-code-for-solving-the-above-problem'),
('Linking the regression analysis with a statistical '
'interpretation',
2,
None,
'linking-the-regression-analysis-with-a-statistical-interpretation'),
('Assumptions made', 2, None, 'assumptions-made'),
('Expectation value and variance',
2,
None,
'expectation-value-and-variance'),
('Expectation value and variance for $\\boldsymbol{\\beta}$',
2,
None,
'expectation-value-and-variance-for-boldsymbol-beta'),
('Deriving OLS from a probability distribution',
2,
None,
'deriving-ols-from-a-probability-distribution'),
('Independent and Identically Distrubuted (iid)',
2,
None,
'independent-and-identically-distrubuted-iid'),
('Maximum Likelihood Estimation (MLE)',
2,
None,
'maximum-likelihood-estimation-mle'),
('A new Cost Function', 2, None, 'a-new-cost-function'),
('Friday September 10', 2, None, 'friday-september-10'),
('Why resampling methods', 2, None, 'why-resampling-methods'),
('Resampling methods', 2, None, 'resampling-methods'),
('Resampling approaches can be computationally expensive',
2,
None,
'resampling-approaches-can-be-computationally-expensive'),
('Why resampling methods ?', 2, None, 'why-resampling-methods'),
('Statistical analysis', 2, None, 'statistical-analysis'),
('Resampling methods', 2, None, 'resampling-methods'),
('Resampling methods: Jackknife and Bootstrap',
2,
None,
'resampling-methods-jackknife-and-bootstrap'),
('Resampling methods: Jackknife',
2,
None,
'resampling-methods-jackknife'),
('Jackknife code example', 2, None, 'jackknife-code-example'),
('Resampling methods: Bootstrap',
2,
None,
'resampling-methods-bootstrap'),
('Resampling methods: Bootstrap background',
2,
None,
'resampling-methods-bootstrap-background'),
('Resampling methods: More Bootstrap background',
2,
None,
'resampling-methods-more-bootstrap-background'),
('Resampling methods: Bootstrap approach',
2,
None,
'resampling-methods-bootstrap-approach'),
('Resampling methods: Bootstrap steps',
2,
None,
'resampling-methods-bootstrap-steps'),
('Code example for the Bootstrap method',
2,
None,
'code-example-for-the-bootstrap-method'),
('Various steps in cross-validation',
2,
None,
'various-steps-in-cross-validation'),
('How to set up the cross-validation for Ridge and/or Lasso',
2,
None,
'how-to-set-up-the-cross-validation-for-ridge-and-or-lasso'),
('Cross-validation in brief',
2,
None,
'cross-validation-in-brief'),
('Code Example for Cross-validation and $k$-fold '
'Cross-validation',
2,
None,
'code-example-for-cross-validation-and-k-fold-cross-validation'),
('The bias-variance tradeoff',
2,
None,
'the-bias-variance-tradeoff'),
('Example code for Bias-Variance tradeoff',
2,
None,
'example-code-for-bias-variance-tradeoff'),
('Understanding what happens',
2,
None,
'understanding-what-happens'),
('Summing up', 2, None, 'summing-up'),
("Another Example from Scikit-Learn's Repository",
2,
None,
'another-example-from-scikit-learn-s-repository'),
('More examples on bootstrap and cross-validation and errors',
2,
None,
'more-examples-on-bootstrap-and-cross-validation-and-errors'),
('The same example but now with cross-validation',
2,
None,
'the-same-example-but-now-with-cross-validation'),
('Cross-validation with Ridge',
2,
None,
'cross-validation-with-ridge')]}
end of tocinfo -->
<body>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
TeX: {
equationNumbers: { autoNumber: "AMS" },
extensions: ["AMSmath.js", "AMSsymbols.js", "autobold.js", "color.js"]
}
});
</script>
<script type="text/javascript" async
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<!-- ------------------- main content ---------------------- -->
<center><h1>Week 36: Statistical interpretation of Linear Regression and Resampling techniques</h1></center> <!-- document title -->
<p>
<!-- author(s): Morten Hjorth-Jensen -->
<center>
<b>Morten Hjorth-Jensen</b> [1, 2]
</center>
<p>
<!-- institution(s) -->
<center>[1] <b>Department of Physics, University of Oslo</b></center>
<center>[2] <b>Department of Physics and Astronomy and National Superconducting Cyclotron Laboratory, Michigan State University</b></center>
<br>
<p>
<center><h4>Sep 9, 2021</h4></center> <!-- date -->
<br>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="plans-for-week-36">Plans for week 36 </h2>
<ul>
<li> Thursday: Summary from last week on SVD, Statistics, probability theory and linear regression</li>
<li> Friday: Linear Regression and links with Statistics, Resampling methods and presentation of first project.</li>
</ul>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="thursday-september-9">Thursday September 9 </h2>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="summary-from-last-week-and-examples">Summary from last Week and Examples </h2>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="linear-regression-and-the-svd">Linear Regression and the SVD </h2>
<p>
We used the SVD to analyse the matrix to invert in ordinary lineat regression
$$
\boldsymbol{X}^T\boldsymbol{X}=\boldsymbol{V}\boldsymbol{\Sigma}^T\boldsymbol{U}^T\boldsymbol{U}\boldsymbol{\Sigma}\boldsymbol{V}^T=\boldsymbol{V}\boldsymbol{\Sigma}^T\boldsymbol{\Sigma}\boldsymbol{V}^T.
$$
Since the matrices here have dimension \( p\times p \), with \( p \) corresponding to the singular values, we defined last week the matrix
$$
\boldsymbol{\Sigma}^T\boldsymbol{\Sigma} = \begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \\ \boldsymbol{0}\\ \end{bmatrix},
$$
where the tilde-matrix \( \tilde{\boldsymbol{\Sigma}} \) is a matrix of dimension \( p\times p \) containing only the singular values \( \sigma_i \), that is
$$
\tilde{\boldsymbol{\Sigma}}=\begin{bmatrix} \sigma_0 & 0 & 0 & \dots & 0 & 0 \\
0 & \sigma_1 & 0 & \dots & 0 & 0 \\
0 & 0 & \sigma_2 & \dots & 0 & 0 \\
0 & 0 & 0 & \dots & \sigma_{p-2} & 0 \\
0 & 0 & 0 & \dots & 0 & \sigma_{p-1} \\
\end{bmatrix},
$$
meaning we can write
$$
\boldsymbol{X}^T\boldsymbol{X}=\boldsymbol{V}\tilde{\boldsymbol{\Sigma}}^2\boldsymbol{V}^T.
$$
Multiplying from the right with \( \boldsymbol{V} \) (using the orthogonality of \( \boldsymbol{V} \)) we get
$$
\left(\boldsymbol{X}^T\boldsymbol{X}\right)\boldsymbol{V}=\boldsymbol{V}\tilde{\boldsymbol{\Sigma}}^2.
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="what-does-it-mean">What does it mean? </h2>
<p>
This means the vectors \( \boldsymbol{v}_i \) of the orthogonal matrix \( \boldsymbol{V} \)
are the eigenvectors of the matrix \( \boldsymbol{X}^T\boldsymbol{X} \) with eigenvalues
given by the singular values squared, that is
$$
\left(\boldsymbol{X}^T\boldsymbol{X}\right)\boldsymbol{v}_i=\boldsymbol{v}_i\sigma_i^2.
$$
<p>
In other words, each non-zero singular value of \( \boldsymbol{X} \) is a positive
square root of an eigenvalue of \( \boldsymbol{X}^T\boldsymbol{X} \). It means also that
the columns of \( \boldsymbol{V} \) are the eigenvectors of
\( \boldsymbol{X}^T\boldsymbol{X} \). Since we have ordered the singular values of
\( \boldsymbol{X} \) in a descending order, it means that the column vectors
\( \boldsymbol{v}_i \) are hierarchically ordered by how much correlation they
encode from the columns of \( \boldsymbol{X} \).
<p>
Note that these are also the eigenvectors and eigenvalues of the
Hessian matrix.
<p>
If we now recall the definition of the covariance matrix (not using
Bessel's correction) we have
$$
\boldsymbol{C}[\boldsymbol{X}]=\frac{1}{n}\boldsymbol{X}^T\boldsymbol{X},
$$
<p>
meaning that every squared non-singular value of \( \boldsymbol{X} \) divided by \( n \) (
the number of samples) are the eigenvalues of the covariance
matrix. Every singular value of \( \boldsymbol{X} \) is thus a positive square
root of an eigenvalue of \( \boldsymbol{X}^T\boldsymbol{X} \). If the matrix \( \boldsymbol{X} \) is
self-adjoint, the singular values of \( \boldsymbol{X} \) are equal to the
absolute value of the eigenvalues of \( \boldsymbol{X} \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="and-finally-boldsymbol-x-boldsymbol-x-t">And finally \( \boldsymbol{X}\boldsymbol{X}^T \) </h2>
<p>
For \( \boldsymbol{X}\boldsymbol{X}^T \) we found
$$
\boldsymbol{X}\boldsymbol{X}^T=\boldsymbol{U}\boldsymbol{\Sigma}\boldsymbol{V}^T\boldsymbol{V}\boldsymbol{\Sigma}^T\boldsymbol{U}^T=\boldsymbol{U}\boldsymbol{\Sigma}^T\boldsymbol{\Sigma}\boldsymbol{U}^T.
$$
Since the matrices here have dimension \( n\times n \), we have
$$
\boldsymbol{\Sigma}\boldsymbol{\Sigma}^T = \begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \\ \boldsymbol{0}\\ \end{bmatrix}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} \boldsymbol{0}\\ \end{bmatrix}=\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0} \\ \boldsymbol{0} & \boldsymbol{0}\\ \end{bmatrix},
$$
leading to
$$
\boldsymbol{X}\boldsymbol{X}^T=\boldsymbol{U}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0} \\ \boldsymbol{0} & \boldsymbol{0}\\ \end{bmatrix}\boldsymbol{U}^T.
$$
<p>
Multiplying with \( \boldsymbol{U} \) from the right gives us the eigenvalue problem
$$
(\boldsymbol{X}\boldsymbol{X}^T)\boldsymbol{U}=\boldsymbol{U}\begin{bmatrix} \tilde{\boldsymbol{\Sigma}} & \boldsymbol{0} \\ \boldsymbol{0} & \boldsymbol{0}\\ \end{bmatrix}.
$$
<p>
It means that the eigenvalues of \( \boldsymbol{X}\boldsymbol{X}^T \) are again given by
the non-zero singular values plus now a series of zeros. The column
vectors of \( \boldsymbol{U} \) are the eigenvectors of \( \boldsymbol{X}\boldsymbol{X}^T \) and
measure how much correlations are contained in the rows of \( \boldsymbol{X} \).
<p>
Since we will mainly be interested in the correlations among the features
of our data (the columns of \( \boldsymbol{X} \), the quantity of interest for us are the non-zero singular
values and the column vectors of \( \boldsymbol{V} \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="ridge-and-lasso-regression">Ridge and LASSO Regression </h2>
<p>
Let us remind ourselves about the expression for the standard Mean Squared Error (MSE) which we used to define our cost function and the equations for the ordinary least squares (OLS) method, that is
our optimization problem is
$$
{\displaystyle \min_{\boldsymbol{\beta}\in {\mathbb{R}}^{p}}}\frac{1}{n}\left\{\left(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right)^T\left(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right)\right\}.
$$
or we can state it as
$$
{\displaystyle \min_{\boldsymbol{\beta}\in
{\mathbb{R}}^{p}}}\frac{1}{n}\sum_{i=0}^{n-1}\left(y_i-\tilde{y}_i\right)^2=\frac{1}{n}\vert\vert \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\vert\vert_2^2,
$$
where we have used the definition of a norm-2 vector, that is
$$
\vert\vert \boldsymbol{x}\vert\vert_2 = \sqrt{\sum_i x_i^2}.
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="from-ols-to-ridge-and-lasso">From OLS to Ridge and Lasso </h2>
<p>
By minimizing the above equation with respect to the parameters
\( \boldsymbol{\beta} \) we could then obtain an analytical expression for the
parameters \( \boldsymbol{\beta} \). We can add a regularization parameter \( \lambda \) by
defining a new cost function to be optimized, that is
$$
{\displaystyle \min_{\boldsymbol{\beta}\in
{\mathbb{R}}^{p}}}\frac{1}{n}\vert\vert \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\vert\vert_2^2+\lambda\vert\vert \boldsymbol{\beta}\vert\vert_2^2
$$
<p>
which leads to the Ridge regression minimization problem where we
require that \( \vert\vert \boldsymbol{\beta}\vert\vert_2^2\le t \), where \( t \) is
a finite number larger than zero. By defining
$$
C(\boldsymbol{X},\boldsymbol{\beta})=\frac{1}{n}\vert\vert \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\vert\vert_2^2+\lambda\vert\vert \boldsymbol{\beta}\vert\vert_1,
$$
<p>
we have a new optimization equation
$$
{\displaystyle \min_{\boldsymbol{\beta}\in
{\mathbb{R}}^{p}}}\frac{1}{n}\vert\vert \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\vert\vert_2^2+\lambda\vert\vert \boldsymbol{\beta}\vert\vert_1
$$
which leads to Lasso regression. Lasso stands for least absolute shrinkage and selection operator.
<p>
Here we have defined the norm-1 as
$$
\vert\vert \boldsymbol{x}\vert\vert_1 = \sum_i \vert x_i\vert.
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="deriving-the-ridge-regression-equations">Deriving the Ridge Regression Equations </h2>
<p>
Using the matrix-vector expression for Ridge regression and dropping the parameter \( 1/n \) in front of the standard means squared error equation, we have
$$
C(\boldsymbol{X},\boldsymbol{\beta})=\left\{(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta})^T(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta})\right\}+\lambda\boldsymbol{\beta}^T\boldsymbol{\beta},
$$
and
taking the derivatives with respect to \( \boldsymbol{\beta} \) we obtain then
a slightly modified matrix inversion problem which for finite values
of \( \lambda \) does not suffer from singularity problems. We obtain
the optimal parameters
$$
\hat{\boldsymbol{\beta}}_{\mathrm{Ridge}} = \left(\boldsymbol{X}^T\boldsymbol{X}+\lambda\boldsymbol{I}\right)^{-1}\boldsymbol{X}^T\boldsymbol{y},
$$
<p>
with \( \boldsymbol{I} \) being a \( p\times p \) identity matrix with the constraint that
$$
\sum_{i=0}^{p-1} \beta_i^2 \leq t,
$$
<p>
with \( t \) a finite positive number.
<p>
When we compare this with the ordinary least squares result we have
$$
\hat{\boldsymbol{\beta}}_{\mathrm{OLS}} = \left(\boldsymbol{X}^T\boldsymbol{X}\right)^{-1}\boldsymbol{X}^T\boldsymbol{y},
$$
which can lead to singular matrices. However, with the SVD, we can always compute the inverse of the matrix \( \boldsymbol{X}^T\boldsymbol{X} \).
<p>
We see that Ridge regression is nothing but the standard OLS with a
modified diagonal term added to \( \boldsymbol{X}^T\boldsymbol{X} \). The consequences, in
particular for our discussion of the bias-variance tradeoff are rather
interesting. We will see that for specific values of \( \lambda \), we may
even reduce the variance of the optimal parameters \( \boldsymbol{\beta} \). These topics and other related ones, will be discussed after the more linear algebra oriented analysis here.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="svd-analysis">SVD analysis </h2>
<p>
Using our insights about the SVD of the design matrix \( \boldsymbol{X} \)
We have already analyzed the OLS solutions in terms of the eigenvectors (the columns) of the right singular value matrix \( \boldsymbol{U} \) as
$$
\tilde{\boldsymbol{y}}_{\mathrm{OLS}}=\boldsymbol{X}\boldsymbol{\beta} =\boldsymbol{U}\boldsymbol{U}^T\boldsymbol{y}.
$$
<p>
For Ridge regression this becomes
$$
\tilde{\boldsymbol{y}}_{\mathrm{Ridge}}=\boldsymbol{X}\boldsymbol{\beta}_{\mathrm{Ridge}} = \boldsymbol{U\Sigma V^T}\left(\boldsymbol{V}\boldsymbol{\Sigma}^2\boldsymbol{V}^T+\lambda\boldsymbol{I} \right)^{-1}(\boldsymbol{U\Sigma V^T})^T\boldsymbol{y}=\sum_{j=0}^{p-1}\boldsymbol{u}_j\boldsymbol{u}_j^T\frac{\sigma_j^2}{\sigma_j^2+\lambda}\boldsymbol{y},
$$
<p>
with the vectors \( \boldsymbol{u}_j \) being the columns of \( \boldsymbol{U} \) from the SVD of the matrix \( \boldsymbol{X} \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="interpreting-the-ridge-results">Interpreting the Ridge results </h2>
<p>
Since \( \lambda \geq 0 \), it means that compared to OLS, we have
$$
\frac{\sigma_j^2}{\sigma_j^2+\lambda} \leq 1.
$$
<p>
Ridge regression finds the coordinates of \( \boldsymbol{y} \) with respect to the
orthonormal basis \( \boldsymbol{U} \), it then shrinks the coordinates by
\( \frac{\sigma_j^2}{\sigma_j^2+\lambda} \). Recall that the SVD has
eigenvalues ordered in a descending way, that is \( \sigma_i \geq
\sigma_{i+1} \).
<p>
For small eigenvalues \( \sigma_i \) it means that their contributions become less important, a fact which can be used to reduce the number of degrees of freedom. More about this when we have covered the material on a statistical interpretation of various linear regression methods.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="more-interpretations">More interpretations </h2>
<p>
For the sake of simplicity, let us assume that the design matrix is orthonormal, that is
$$
\boldsymbol{X}^T\boldsymbol{X}=(\boldsymbol{X}^T\boldsymbol{X})^{-1} =\boldsymbol{I}.
$$
<p>
In this case the standard OLS results in
$$
\boldsymbol{\beta}^{\mathrm{OLS}} = \boldsymbol{X}^T\boldsymbol{y}=\sum_{i=0}^{p-1}\boldsymbol{u}_j\boldsymbol{u}_j^T\boldsymbol{y},
$$
<p>
and
$$
\boldsymbol{\beta}^{\mathrm{Ridge}} = \left(\boldsymbol{I}+\lambda\boldsymbol{I}\right)^{-1}\boldsymbol{X}^T\boldsymbol{y}=\left(1+\lambda\right)^{-1}\boldsymbol{\beta}^{\mathrm{OLS}},
$$
<p>
that is the Ridge estimator scales the OLS estimator by the inverse of a factor \( 1+\lambda \), and
the Ridge estimator converges to zero when the hyperparameter goes to
infinity.
<p>
We will come back to more interpreations after we have gone through some of the statistical analysis part.
<p>
For more discussions of Ridge and Lasso regression, <a href="https://arxiv.org/abs/1509.09169" target="_blank">Wessel van Wieringen's</a> article is highly recommended.
Similarly, <a href="https://arxiv.org/abs/1803.08823" target="_blank">Mehta et al's article</a> is also recommended.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="deriving-the-lasso-regression-equations">Deriving the Lasso Regression Equations </h2>
<p>
Using the matrix-vector expression for Lasso regression and dropping the parameter \( 1/n \) in front of the standard mean squared error equation, we have the following <b>cost</b> function
$$
C(\boldsymbol{X},\boldsymbol{\beta})=\left\{(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta})^T(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta})\right\}+\lambda\vert\vert\boldsymbol{\beta}\vert\vert_1,
$$
<p>
Taking the derivative with respect to \( \boldsymbol{\beta} \) and recalling that the derivative of the absolute value is (we drop the boldfaced vector symbol for simplicty)
$$
\frac{d \vert \beta\vert}{d \boldsymbol{\beta}}=\mathrm{sgn}(\boldsymbol{\beta})=\left\{\begin{array}{cc} 1 & \beta > 0 \\ 0 & \beta =0\\-1 & \beta < 0, \end{array}\right.
$$
we have that the derivative of the cost function is
$$
\frac{\partial C(\boldsymbol{X},\boldsymbol{\beta})}{\partial \boldsymbol{\beta}}=-2\boldsymbol{X}^T(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta})+\lambda sgn(\boldsymbol{\beta})=0,
$$
and reordering we have
$$
\boldsymbol{X}^T\boldsymbol{X}\boldsymbol{\beta}+\lambda sgn(\boldsymbol{\beta})=2\boldsymbol{X}^T\boldsymbol{y}.
$$
This equation does not lead to a nice analytical equation as in Ridge regression or ordinary least squares. This equation can however be solved by using standard convex optimization algorithms using for example the Python package <a href="https://cvxopt.org/" target="_blank">CVXOPT</a>. We will discuss this later.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="simple-example-to-illustrate-ordinary-least-squares-ridge-and-lasso-regression">Simple example to illustrate Ordinary Least Squares, Ridge and Lasso Regression </h2>
<p>
Let us assume that our design matrix is given by unit (identity) matrix, that is a square diagonal matrix with ones only along the
diagonal. In this case we have an equal number of rows and columns \( n=p \).
<p>
Our model approximation is just \( \tilde{\boldsymbol{y}}=\boldsymbol{\beta} \) and the mean squared error and thereby the cost function for ordinary least sqquares (OLS) is then (we drop the term \( 1/n \))
$$
C(\boldsymbol{\beta})=\sum_{i=0}^{p-1}(y_i-\beta_i)^2,
$$
and minimizing we have that
$$
\hat{\beta}_i^{\mathrm{OLS}} = y_i.
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="ridge-regression">Ridge Regression </h2>
<p>
For Ridge regression our cost function is
$$
C(\boldsymbol{\beta})=\sum_{i=0}^{p-1}(y_i-\beta_i)^2+\lambda\sum_{i=0}^{p-1}\beta_i^2,
$$
and minimizing we have that
$$
\hat{\beta}_i^{\mathrm{Ridge}} = \frac{y_i}{1+\lambda}.
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="lasso-regression">Lasso Regression </h2>
<p>
For Lasso regression our cost function is
$$
C(\boldsymbol{\beta})=\sum_{i=0}^{p-1}(y_i-\beta_i)^2+\lambda\sum_{i=0}^{p-1}\vert\beta_i\vert=\sum_{i=0}^{p-1}(y_i-\beta_i)^2+\lambda\sum_{i=0}^{p-1}\sqrt{\beta_i^2},
$$
and minimizing we have that
$$
-2\sum_{i=0}^{p-1}(y_i-\beta_i)+\lambda \sum_{i=0}^{p-1}\frac{(\beta_i)}{\vert\beta_i\vert}=0,
$$
which leads to
$$
\hat{\boldsymbol{\beta}}_i^{\mathrm{Lasso}} = \left\{\begin{array}{ccc}y_i-\frac{\lambda}{2} &\mathrm{if} & y_i> \frac{\lambda}{2}\\
y_i+\frac{\lambda}{2} &\mathrm{if} & y_i < -\frac{\lambda}{2}\\
0 &\mathrm{if} & \vert y_i\vert\le \frac{\lambda}{2}\end{array}\right.\\.
$$
<p>
Plotting these results (figure in handwritten notes for week 36) shows clearly that Lasso regression suppresses (sets to zero) values of \( \beta_i \) for specific values of \( \lambda \). Ridge regression reduces on the other hand the values of \( \beta_i \) as function of \( \lambda \).
<p>
We will now couple the discussions of ordinary least squares, Ridge and Lasso regression with a statistical interpretation, that is we move from a linear algebra analysis to a statistical analysis. In particular, we will focus on what the regularization terms can result in.
We will amongst other things show that the regularization parameter can reduce considerably the variance of the parameters \( \beta \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="yet-another-example">Yet another Example </h2>
<p>
Let us assume we have a data set with outputs/targets given by the vector
$$
\boldsymbol{y}=\begin{bmatrix}4 \\ 2 \\3\end{bmatrix},
$$
and our inputs as a \( 3\times 2 \) design matrix
$$
\boldsymbol{X}=\begin{bmatrix}2 & 0\\ 0 & 1 \\ 0 & 0\end{bmatrix},
$$
meaning that we have two features and two unknown parameters \( \beta_0 \) and \( \beta_1 \) to be determined either by ordinary least squares, Ridge or Lasso regression.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="the-ols-case">The OLS case </h2>
<p>
For ordinary least squares (OLS) we know that the optimal solution is
$$
\hat{\boldsymbol{\beta}}^{\mathrm{OLS}}=\left( \boldsymbol{X}^T\boldsymbol{X}\right)^{-1}\boldsymbol{X}^T\boldsymbol{y}.
$$
Inserting the above values we obtain that
$$
\hat{\boldsymbol{\beta}}^{\mathrm{OLS}}=\begin{bmatrix}2 \\ 2\end{bmatrix},
$$
<p>
The code which implements this simpler case is presented after the discussion of Ridge and Lasso.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="the-ridge-case">The Ridge case </h2>
<p>
For Ridge regression we have
$$
\hat{\boldsymbol{\beta}}^{\mathrm{Ridge}}=\left( \boldsymbol{X}^T\boldsymbol{X}+\lambda\boldsymbol{I}\right)^{-1}\boldsymbol{X}^T\boldsymbol{y}.
$$
Inserting the above values we obtain that
$$
\hat{\boldsymbol{\beta}}^{\mathrm{Ridge}}=\begin{bmatrix}\frac{8}{4+\lambda} \\ \frac{2}{1+\lambda}\end{bmatrix},
$$
<p>
There is normally a constraint on the value of $\vert\vert \boldsymbol{\beta}\vert\vert_2 via the parameter \( \lambda \).
Let us for simplicity assume now that \( \beta_0^2+\beta_1^2=1 \) as constraint. This will allow us to find an expression with the optimal values of \( \beta \) and \( \lambda \).
<p>
To see this, let us write the cost function for Ridge regression.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="writing-the-cost-function">Writing the Cost Function </h2>
<p>
We define the MSE without the \( 1/n \) factor and have then, using that
$$
\boldsymbol{X}\boldsymbol{\beta}=\begin{bmatrix} 2\beta_0 \\ \beta_1 \\0 \end{bmatrix},
$$
$$
C(\boldsymbol{\beta})=(4-2\beta_0)^2+(2-\beta_1)^2+\lambda(\beta_0^2+\beta_1^2),
$$
and taking the derivative with respect to \( \beta_0 \) we get
$$
\beta_0=\frac{8}{4+\lambda},
$$
and for \( \beta_1 \) we obtain
$$
\beta_1=\frac{2}{1+\lambda},
$$
<p>
Using the constraint for \( \beta_0^2+\beta_1^2=1 \) we can constrain \( \lambda \) by solving
$$
\left(\frac{8}{4+\lambda}\right)^2+\left(\frac{2}{1+\lambda}\right)^2=1,
$$
which gives \( \lambda=4.571 \) and \( \beta_0=0.933 \) and \( \beta_1=0.359 \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="lasso-case">Lasso case </h2>
<p>
For Lasso we need now, keeping a constraint on \( \vert\beta_0\vert+\vert\beta_1\vert=1 \), to take the derivative of the absolute values of \( \beta_0 \)
and \( \beta_1 \). This gives us the following derivatives of the cost function
$$
C(\boldsymbol{\beta})=(4-2\beta_0)^2+(2-\beta_1)^2+\lambda(\vert\beta_0\vert+\vert\beta_1\vert),
$$
$$
\frac{\partial C(\boldsymbol{\beta})}{\partial \beta_0}=-4(4-2\beta_0)+\lambda\mathrm{sgn}(\beta_0)=0,
$$
and
$$
\frac{\partial C(\boldsymbol{\beta})}{\partial \beta_1}=-2(2-\beta_1)+\lambda\mathrm{sgn}(\beta_1)=0.
$$
We have now four cases to solve besides the trivial cases \( \beta_0 \) and/or \( \beta_1 \) are zero, namely
<ol>
<li> \( \beta_0 > 0 \) and \( \beta_1 > 0 \),</li>
<li> \( \beta_0 > 0 \) and \( \beta_1 < 0 \),</li>
<li> \( \beta_0 < 0 \) and \( \beta_1 > 0 \),</li>
<li> \( \beta_0 < 0 \) and \( \beta_1 < 0 \).</li>
</ol>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="the-first-case">The first Case </h2>
<p>
If we consider the first case, we have then
$$
-4(4-2\beta_0)+\lambda=0,
$$
and
$$
-2(2-\beta_1)+\lambda=0.
$$
which yields
$$
\beta_0=\frac{16+\lambda}{8},
$$
and
$$
\beta_1=\frac{4+\lambda}{2}.
$$
<p>
Using the constraint on \( \beta_0 \) and \( \beta_1 \) we can then find the optimal value of \( \lambda \) for the different cases. We leave this as an exercise to you.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="simple-code-for-solving-the-above-problem">Simple code for solving the above problem </h2>
<p>
Here we set up the OLS, Ridge and Lasso functionality in order to study the above example. Note that here we have opted for a set of values of \( \lambda \), meaning that we need to perform a search in order to find the optimal values.
<p>
First we study and compare the OLS and Ridge results. The next code compares all three methods.
<p>
<!-- !split -->
<h2 id="linking-the-regression-analysis-with-a-statistical-interpretation">Linking the regression analysis with a statistical interpretation </h2>
<p>
The
advantage of doing linear regression is that we actually end up with
analytical expressions for several statistical quantities.
Standard least squares and Ridge regression allow us to
derive quantities like the variance and other expectation values in a
rather straightforward way.
<p>
It is assumed that \( \varepsilon_i
\sim \mathcal{N}(0, \sigma^2) \) and the \( \varepsilon_{i} \) are
independent, i.e.:
$$
\begin{align*}
\mbox{Cov}(\varepsilon_{i_1},
\varepsilon_{i_2}) & = \left\{ \begin{array}{lcc} \sigma^2 & \mbox{if}
& i_1 = i_2, \\ 0 & \mbox{if} & i_1 \not= i_2. \end{array} \right.
\end{align*}
$$
The randomness of \( \varepsilon_i \) implies that
\( \mathbf{y}_i \) is also a random variable. In particular,
\( \mathbf{y}_i \) is normally distributed, because \( \varepsilon_i \sim
\mathcal{N}(0, \sigma^2) \) and \( \mathbf{X}_{i,\ast} \, \boldsymbol{\beta} \) is a
non-random scalar. To specify the parameters of the distribution of
\( \mathbf{y}_i \) we need to calculate its first two moments.
<p>
Recall that \( \boldsymbol{X} \) is a matrix of dimensionality \( n\times p \). The
notation above \( \mathbf{X}_{i,\ast} \) means that we are looking at the
row number \( i \) and perform a sum over all values \( p \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="assumptions-made">Assumptions made </h2>
<p>
The assumption we have made here can be summarized as (and this is going to be useful when we discuss the bias-variance trade off)
that there exists a function \( f(\boldsymbol{x}) \) and a normal distributed error \( \boldsymbol{\varepsilon}\sim \mathcal{N}(0, \sigma^2) \)
which describe our data
$$
\boldsymbol{y} = f(\boldsymbol{x})+\boldsymbol{\varepsilon}
$$
<p>
We approximate this function with our model from the solution of the linear regression equations, that is our
function \( f \) is approximated by \( \boldsymbol{\tilde{y}} \) where we want to minimize \( (\boldsymbol{y}-\boldsymbol{\tilde{y}})^2 \), our MSE, with
$$
\boldsymbol{\tilde{y}} = \boldsymbol{X}\boldsymbol{\beta}.
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="expectation-value-and-variance">Expectation value and variance </h2>
<p>
We can calculate the expectation value of \( \boldsymbol{y} \) for a given element \( i \)
$$
\begin{align*}
\mathbb{E}(y_i) & =
\mathbb{E}(\mathbf{X}_{i, \ast} \, \boldsymbol{\beta}) + \mathbb{E}(\varepsilon_i)
\, \, \, = \, \, \, \mathbf{X}_{i, \ast} \, \beta,
\end{align*}
$$
while
its variance is
$$
\begin{align*} \mbox{Var}(y_i) & = \mathbb{E} \{ [y_i
- \mathbb{E}(y_i)]^2 \} \, \, \, = \, \, \, \mathbb{E} ( y_i^2 ) -
[\mathbb{E}(y_i)]^2 \\ & = \mathbb{E} [ ( \mathbf{X}_{i, \ast} \,
\beta + \varepsilon_i )^2] - ( \mathbf{X}_{i, \ast} \, \boldsymbol{\beta})^2 \\ &
= \mathbb{E} [ ( \mathbf{X}_{i, \ast} \, \boldsymbol{\beta})^2 + 2 \varepsilon_i
\mathbf{X}_{i, \ast} \, \boldsymbol{\beta} + \varepsilon_i^2 ] - ( \mathbf{X}_{i,
\ast} \, \beta)^2 \\ & = ( \mathbf{X}_{i, \ast} \, \boldsymbol{\beta})^2 + 2
\mathbb{E}(\varepsilon_i) \mathbf{X}_{i, \ast} \, \boldsymbol{\beta} +
\mathbb{E}(\varepsilon_i^2 ) - ( \mathbf{X}_{i, \ast} \, \boldsymbol{\beta})^2
\\ & = \mathbb{E}(\varepsilon_i^2 ) \, \, \, = \, \, \,
\mbox{Var}(\varepsilon_i) \, \, \, = \, \, \, \sigma^2.
\end{align*}
$$
Hence, \( y_i \sim \mathcal{N}( \mathbf{X}_{i, \ast} \, \boldsymbol{\beta}, \sigma^2) \), that is \( \boldsymbol{y} \) follows a normal distribution with
mean value \( \boldsymbol{X}\boldsymbol{\beta} \) and variance \( \sigma^2 \) (not be confused with the singular values of the SVD).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="expectation-value-and-variance-for-boldsymbol-beta">Expectation value and variance for \( \boldsymbol{\beta} \) </h2>
<p>
With the OLS expressions for the parameters \( \boldsymbol{\beta} \) we can evaluate the expectation value
$$
\mathbb{E}(\boldsymbol{\beta}) = \mathbb{E}[ (\mathbf{X}^{\top} \mathbf{X})^{-1}\mathbf{X}^{T} \mathbf{Y}]=(\mathbf{X}^{T} \mathbf{X})^{-1}\mathbf{X}^{T} \mathbb{E}[ \mathbf{Y}]=(\mathbf{X}^{T} \mathbf{X})^{-1} \mathbf{X}^{T}\mathbf{X}\boldsymbol{\beta}=\boldsymbol{\beta}.
$$
This means that the estimator of the regression parameters is unbiased.
<p>
We can also calculate the variance
<p>
The variance of \( \boldsymbol{\beta} \) is
$$
\begin{eqnarray*}
\mbox{Var}(\boldsymbol{\beta}) & = & \mathbb{E} \{ [\boldsymbol{\beta} - \mathbb{E}(\boldsymbol{\beta})] [\boldsymbol{\beta} - \mathbb{E}(\boldsymbol{\beta})]^{T} \}
\\
& = & \mathbb{E} \{ [(\mathbf{X}^{T} \mathbf{X})^{-1} \, \mathbf{X}^{T} \mathbf{Y} - \boldsymbol{\beta}] \, [(\mathbf{X}^{T} \mathbf{X})^{-1} \, \mathbf{X}^{T} \mathbf{Y} - \boldsymbol{\beta}]^{T} \}
\\
% & = & \mathbb{E} \{ [(\mathbf{X}^{T} \mathbf{X})^{-1} \, \mathbf{X}^{T} \mathbf{Y}] \, [(\mathbf{X}^{T} \mathbf{X})^{-1} \, \mathbf{X}^{T} \mathbf{Y}]^{T} \} - \boldsymbol{\beta} \, \boldsymbol{\beta}^{T}
% \\
% & = & \mathbb{E} \{ (\mathbf{X}^{T} \mathbf{X})^{-1} \, \mathbf{X}^{T} \mathbf{Y} \, \mathbf{Y}^{T} \, \mathbf{X} \, (\mathbf{X}^{T} \mathbf{X})^{-1} \} - \boldsymbol{\beta} \, \boldsymbol{\beta}^{T}
% \\
& = & (\mathbf{X}^{T} \mathbf{X})^{-1} \, \mathbf{X}^{T} \, \mathbb{E} \{ \mathbf{Y} \, \mathbf{Y}^{T} \} \, \mathbf{X} \, (\mathbf{X}^{T} \mathbf{X})^{-1} - \boldsymbol{\beta} \, \boldsymbol{\beta}^{T}
\\
& = & (\mathbf{X}^{T} \mathbf{X})^{-1} \, \mathbf{X}^{T} \, \{ \mathbf{X} \, \boldsymbol{\beta} \, \boldsymbol{\beta}^{T} \, \mathbf{X}^{T} + \sigma^2 \} \, \mathbf{X} \, (\mathbf{X}^{T} \mathbf{X})^{-1} - \boldsymbol{\beta} \, \boldsymbol{\beta}^{T}
% \\
% & = & (\mathbf{X}^T \mathbf{X})^{-1} \, \mathbf{X}^T \, \mathbf{X} \, \boldsymbol{\beta} \, \boldsymbol{\beta}^T \, \mathbf{X}^T \, \mathbf{X} \, (\mathbf{X}^T % \mathbf{X})^{-1}
% \\
% & & + \, \, \sigma^2 \, (\mathbf{X}^T \mathbf{X})^{-1} \, \mathbf{X}^T \, \mathbf{X} \, (\mathbf{X}^T \mathbf{X})^{-1} - \boldsymbol{\beta} \boldsymbol{\beta}^T
\\
& = & \boldsymbol{\beta} \, \boldsymbol{\beta}^{T} + \sigma^2 \, (\mathbf{X}^{T} \mathbf{X})^{-1} - \boldsymbol{\beta} \, \boldsymbol{\beta}^{T}
\, \, \, = \, \, \, \sigma^2 \, (\mathbf{X}^{T} \mathbf{X})^{-1},
\end{eqnarray*}
$$
<p>
where we have used that \( \mathbb{E} (\mathbf{Y} \mathbf{Y}^{T}) =
\mathbf{X} \, \boldsymbol{\beta} \, \boldsymbol{\beta}^{T} \, \mathbf{X}^{T} +
\sigma^2 \, \mathbf{I}_{nn} \). From \( \mbox{Var}(\boldsymbol{\beta}) = \sigma^2
\, (\mathbf{X}^{T} \mathbf{X})^{-1} \), one obtains an estimate of the
variance of the estimate of the \( j \)-th regression coefficient:
\( \boldsymbol{\sigma}^2 (\boldsymbol{\beta}_j ) = \boldsymbol{\sigma}^2 \sqrt{
[(\mathbf{X}^{T} \mathbf{X})^{-1}]_{jj} } \). This may be used to
construct a confidence interval for the estimates.
<p>
In a similar way, we can obtain analytical expressions for say the
expectation values of the parameters \( \boldsymbol{\beta} \) and their variance
when we employ Ridge regression, allowing us again to define a confidence interval.
<p>
It is rather straightforward to show that
$$
\mathbb{E} \big[ \boldsymbol{\beta}^{\mathrm{Ridge}} \big]=(\mathbf{X}^{T} \mathbf{X} + \lambda \mathbf{I}_{pp})^{-1} (\mathbf{X}^{\top} \mathbf{X})\boldsymbol{\beta}^{\mathrm{OLS}}.
$$
We see clearly that
\( \mathbb{E} \big[ \boldsymbol{\beta}^{\mathrm{Ridge}} \big] \not= \boldsymbol{\beta}^{\mathrm{OLS}} \) for any \( \lambda > 0 \). We say then that the ridge estimator is biased.
<p>
We can also compute the variance as
$$
\mbox{Var}[\boldsymbol{\beta}^{\mathrm{Ridge}}]=\sigma^2[ \mathbf{X}^{T} \mathbf{X} + \lambda \mathbf{I} ]^{-1} \mathbf{X}^{T} \mathbf{X} \{ [ \mathbf{X}^{\top} \mathbf{X} + \lambda \mathbf{I} ]^{-1}\}^{T},
$$
and it is easy to see that if the parameter \( \lambda \) goes to infinity then the variance of Ridge parameters \( \boldsymbol{\beta} \) goes to zero.
<p>
With this, we can compute the difference
$$
\mbox{Var}[\boldsymbol{\beta}^{\mathrm{OLS}}]-\mbox{Var}(\boldsymbol{\beta}^{\mathrm{Ridge}})=\sigma^2 [ \mathbf{X}^{T} \mathbf{X} + \lambda \mathbf{I} ]^{-1}[ 2\lambda\mathbf{I} + \lambda^2 (\mathbf{X}^{T} \mathbf{X})^{-1} ] \{ [ \mathbf{X}^{T} \mathbf{X} + \lambda \mathbf{I} ]^{-1}\}^{T}.
$$
The difference is non-negative definite since each component of the
matrix product is non-negative definite.
This means the variance we obtain with the standard OLS will always for \( \lambda > 0 \) be larger than the variance of \( \boldsymbol{\beta} \) obtained with the Ridge estimator. This has interesting consequences when we discuss the so-called bias-variance trade-off below.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="deriving-ols-from-a-probability-distribution">Deriving OLS from a probability distribution </h2>
<p>
Our basic assumption when we derived the OLS equations was to assume
that our output is determined by a given continuous function
\( f(\boldsymbol{x}) \) and a random noise \( \boldsymbol{\epsilon} \) given by the normal
distribution with zero mean value and an undetermined variance
\( \sigma^2 \).
<p>
We found above that the outputs \( \boldsymbol{y} \) have a mean value given by
\( \boldsymbol{X}\hat{\boldsymbol{\beta}} \) and variance \( \sigma^2 \). Since the entries to
the design matrix are not stochastic variables, we can assume that the
probability distribution of our targets is also a normal distribution
but now with mean value \( \boldsymbol{X}\hat{\boldsymbol{\beta}} \). This means that a
single output \( y_i \) is given by the Gaussian distribution
$$
y_i\sim \mathcal{N}(\boldsymbol{X}_{i,*}\boldsymbol{\beta}, \sigma^2)=\frac{1}{\sqrt{2\pi\sigma^2}}\exp{\left[-\frac{(y_i-\boldsymbol{X}_{i,*}\boldsymbol{\beta})^2}{2\sigma^2}\right]}.
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="independent-and-identically-distrubuted-iid">Independent and Identically Distrubuted (iid) </h2>
<p>
We assume now that the various \( y_i \) values are stochastically distributed according to the above Gaussian distribution.
We define this distribution as
$$
p(y_i\vert \boldsymbol{X};\boldsymbol{\beta})=\frac{1}{\sqrt{2\pi\sigma^2}}\exp{\left[-\frac{(y_i-\boldsymbol{X}_{i,*}\boldsymbol{\beta})^2}{2\sigma^2}\right]},
$$
which reads as finding the likelihood of an event \( y_i \) given the input variables \( \boldsymbol{X} \) and the parameters (to be determined) \( \boldsymbol{\beta} \).
<p>
Since these events are assumed to be independent and identicall distributed we can build the probability distribution function (PDF) for all possible event \( \boldsymbol{y} \) as the product of the single events, that is we have
$$
p(\boldsymbol{y}\vert \boldsymbol{X};\boldsymbol{\beta})=\prod_{i=0}^{n-1}\frac{1}{\sqrt{2\pi\sigma^2}}\exp{\left[-\frac{(y_i-\boldsymbol{X}_{i,*}\boldsymbol{\beta})^2}{2\sigma^2}\right]}=\prod_{i=0}^{n-1}p(y_i\vert \boldsymbol{X};\boldsymbol{\beta}).
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="maximum-likelihood-estimation-mle">Maximum Likelihood Estimation (MLE) </h2>
<p>
In statistics, maximum likelihood estimation (MLE) is a method of
estimating the parameters of an assumed probability distribution,
given some observed data. This is achieved by maximizing a likelihood
function so that, under the assumed statistical model, the observed
data is the most probable.
<p>
We will assume here that our events are given by the above Gaussian
distribution and we will determine the optimal parameters \( \beta \) by
maximizing the above PDF. However, computing the derivatives of a
product function is cumbersome and can easily lead to overflow and/or
underflowproblems, with potentials for loss of numerical precision.
<p>
In practice, it is more convenient to maximize the logarithm of the
PDF because it is a monotonically increasing function of the argument.
Alternatively, and this will be our option, we will minimize the
negative of the logarithm since this is a monotonically decreasing
function.
<p>
Note also that maximization/minimization of the logarithm of the PDF
is equivalent to the maximization/minimization of the function itself.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="a-new-cost-function">A new Cost Function </h2>
<p>
We could now define a new cost function to minimize, namely the negative logarithm of the above PDF
$$
C(\boldsymbol{\beta}=-\log{\prod_{i=0}^{n-1}p(y_i\vert \boldsymbol{X};\boldsymbol{\beta})}=-\sum_{i=0}^{n-1}\log{p(y_i\vert \boldsymbol{X};\boldsymbol{\beta})},
$$
which becomes
$$
C(\boldsymbol{\beta}=\frac{n}{2}\log{2\pi\sigma^2}+\frac{\vert\vert (\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta})\vert\vert_2^2}{2\sigma^2}.
$$
<p>
Taking the derivative of the <em>new</em> cost function with respect to the parameters \( \beta \) we recognize our familiar OLS equation, namely
$$
\boldsymbol{X}^T\left(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right) =0,
$$
which leads to
$$
\hat{\boldsymbol{\beta}}_{\mathrm{OLS}}=\left(\boldsymbol{X}^T\boldsymbol{X}\right)^{-1}\boldsymbol{X}^T\boldsymbol{y}!
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="friday-september-10">Friday September 10 </h2>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="why-resampling-methods">Why resampling methods </h2>
<p>
Before we proceed, we need to rethink what we have been doing. In our
eager to fit the data, we have omitted several important elements in
our regression analysis. In what follows we will
<ol>
<li> look at statistical properties, including a discussion of mean values, variance and the so-called bias-variance tradeoff</li>
<li> introduce resampling techniques like cross-validation, bootstrapping and jackknife and more</li>
</ol>
This will allow us to link the standard linear algebra methods we have discussed above to a statistical interpretation of the methods.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods">Resampling methods </h2>
<div class="alert alert-block alert-block alert-text-normal">
<b></b>
<p>
Resampling methods are an indispensable tool in modern
statistics. They involve repeatedly drawing samples from a training
set and refitting a model of interest on each sample in order to
obtain additional information about the fitted model. For example, in
order to estimate the variability of a linear regression fit, we can
repeatedly draw different samples from the training data, fit a linear
regression to each new sample, and then examine the extent to which
the resulting fits differ. Such an approach may allow us to obtain
information that would not be available from fitting the model only
once using the original training sample.
<p>
Two resampling methods are often used in Machine Learning analyses,
<ol>
<li> The <b>bootstrap method</b></li>
<li> and <b>Cross-Validation</b></li>
</ol>
In addition there are several other methods such as the Jackknife and the Blocking methods. We will discuss in particular
cross-validation and the bootstrap method.
</div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-approaches-can-be-computationally-expensive">Resampling approaches can be computationally expensive </h2>
<div class="alert alert-block alert-block alert-text-normal">
<b></b>
<p>
<p>
Resampling approaches can be computationally expensive, because they
involve fitting the same statistical method multiple times using
different subsets of the training data. However, due to recent
advances in computing power, the computational requirements of
resampling methods generally are not prohibitive. In this chapter, we
discuss two of the most commonly used resampling methods,
cross-validation and the bootstrap. Both methods are important tools
in the practical application of many statistical learning
procedures. For example, cross-validation can be used to estimate the
test error associated with a given statistical learning method in
order to evaluate its performance, or to select the appropriate level
of flexibility. The process of evaluating a model&#8217;s performance is
known as model assessment, whereas the process of selecting the proper
level of flexibility for a model is known as model selection. The
bootstrap is widely used.
</div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="why-resampling-methods">Why resampling methods ? </h2>
<div class="alert alert-block alert-block alert-text-normal">
<b>Statistical analysis</b>
<p>
<ul>
<li> Our simulations can be treated as <em>computer experiments</em>. This is particularly the case for Monte Carlo methods</li>
<li> The results can be analysed with the same statistical tools as we would use analysing experimental data.</li>
<li> As in all experiments, we are looking for expectation values and an estimate of how accurate they are, i.e., possible sources for errors.</li>
</ul>
</div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="statistical-analysis">Statistical analysis </h2>
<div class="alert alert-block alert-block alert-text-normal">
<b></b>
<p>
<ul>
<li> As in other experiments, many numerical experiments have two classes of errors:</li>
<ul>
<li> Statistical errors</li>
<li> Systematical errors</li>
</ul>
<li> Statistical errors can be estimated using standard tools from statistics</li>
<li> Systematical errors are method specific and must be treated differently from case to case.</li>
</ul>
</div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods">Resampling methods </h2>
<p>
With all these analytical equations for both the OLS and Ridge
regression, we will now outline how to assess a given model. This will
lead us to a discussion of the so-called bias-variance tradeoff (see
below) and so-called resampling methods.
<p>
One of the quantities we have discussed as a way to measure errors is
the mean-squared error (MSE), mainly used for fitting of continuous
functions. Another choice is the absolute error.
<p>
In the discussions below we will focus on the MSE and in particular since we will split the data into test and training data,
we discuss the
<ol>
<li> prediction error or simply the <b>test error</b> \( \mathrm{Err_{Test}} \), where we have a fixed training set and the test error is the MSE arising from the data reserved for testing. We discuss also the</li>
<li> training error \( \mathrm{Err_{Train}} \), which is the average loss over the training data.</li>
</ol>
As our model becomes more and more complex, more of the training data tends to used. The training may thence adapt to more complicated structures in the data. This may lead to a decrease in the bias (see below for code example) and a slight increase of the variance for the test error.
For a certain level of complexity the test error will reach minimum, before starting to increase again. The
training error reaches a saturation.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods-jackknife-and-bootstrap">Resampling methods: Jackknife and Bootstrap </h2>
<p>
Two famous
resampling methods are the <b>independent bootstrap</b> and <b>the jackknife</b>.
<p>
The jackknife is a special case of the independent bootstrap. Still, the jackknife was made
popular prior to the independent bootstrap. And as the popularity of
the independent bootstrap soared, new variants, such as <b>the dependent bootstrap</b>.
<p>
The Jackknife and independent bootstrap work for
independent, identically distributed random variables.
If these conditions are not
satisfied, the methods will fail. Yet, it should be said that if the data are
independent, identically distributed, and we only want to estimate the
variance of \( \overline{X} \) (which often is the case), then there is no
need for bootstrapping.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods-jackknife">Resampling methods: Jackknife </h2>
<p>
The Jackknife works by making many replicas of the estimator \( \widehat{\theta} \).
The jackknife is a resampling method where we systematically leave out one observation from the vector of observed values \( \boldsymbol{x} = (x_1,x_2,\cdots,X_n) \).
Let \( \boldsymbol{x}_i \) denote the vector
$$
\boldsymbol{x}_i = (x_1,x_2,\cdots,x_{i-1},x_{i+1},\cdots,x_n),
$$
<p>
which equals the vector \( \boldsymbol{x} \) with the exception that observation
number \( i \) is left out. Using this notation, define
\( \widehat{\theta}_i \) to be the estimator
\( \widehat{\theta} \) computed using \( \vec{X}_i \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="jackknife-code-example">Jackknife code example </h2>
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">import</span> <span style="color: #666666">*</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">numpy.random</span> <span style="color: #008000; font-weight: bold">import</span> randint, randn
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">time</span> <span style="color: #008000; font-weight: bold">import</span> time
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">jackknife</span>(data, stat):
n <span style="color: #666666">=</span> <span style="color: #008000">len</span>(data);t <span style="color: #666666">=</span> zeros(n); inds <span style="color: #666666">=</span> arange(n); t0 <span style="color: #666666">=</span> time()
<span style="color: #408080; font-style: italic">## &#39;jackknifing&#39; by leaving out an observation for each i </span>
<span style="color: #008000; font-weight: bold">for</span> i <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(n):
t[i] <span style="color: #666666">=</span> stat(delete(data,i) )
<span style="color: #408080; font-style: italic"># analysis </span>
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;Runtime: </span><span style="color: #BB6688; font-weight: bold">%g</span><span style="color: #BA2121"> sec&quot;</span> <span style="color: #666666">%</span> (time()<span style="color: #666666">-</span>t0)); <span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;Jackknife Statistics :&quot;</span>)
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;original bias std. error&quot;</span>)
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;</span><span style="color: #BB6688; font-weight: bold">%8g</span><span style="color: #BA2121"> </span><span style="color: #BB6688; font-weight: bold">%14g</span><span style="color: #BA2121"> </span><span style="color: #BB6688; font-weight: bold">%15g</span><span style="color: #BA2121">&quot;</span> <span style="color: #666666">%</span> (stat(data),(n<span style="color: #666666">-1</span>)<span style="color: #666666">*</span>mean(t)<span style="color: #666666">/</span>n, (n<span style="color: #666666">*</span>var(t))<span style="color: #666666">**.5</span>))
<span style="color: #008000; font-weight: bold">return</span> t
<span style="color: #408080; font-style: italic"># Returns mean of data samples </span>
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">stat</span>(data):
<span style="color: #008000; font-weight: bold">return</span> mean(data)
mu, sigma <span style="color: #666666">=</span> <span style="color: #666666">100</span>, <span style="color: #666666">15</span>
datapoints <span style="color: #666666">=</span> <span style="color: #666666">10000</span>
x <span style="color: #666666">=</span> mu <span style="color: #666666">+</span> sigma<span style="color: #666666">*</span>random<span style="color: #666666">.</span>randn(datapoints)
<span style="color: #408080; font-style: italic"># jackknife returns the data sample </span>
t <span style="color: #666666">=</span> jackknife(x, stat)
</pre></div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods-bootstrap">Resampling methods: Bootstrap </h2>
<div class="alert alert-block alert-block alert-text-normal">
<b></b>
<p>
Bootstrapping is a nonparametric approach to statistical inference
that substitutes computation for more traditional distributional
assumptions and asymptotic results. Bootstrapping offers a number of
advantages:
<ol>
<li> The bootstrap is quite general, although there are some cases in which it fails.</li>
<li> Because it does not require distributional assumptions (such as normally distributed errors), the bootstrap can provide more accurate inferences when the data are not well behaved or when the sample size is small.</li>
<li> It is possible to apply the bootstrap to statistics with sampling distributions that are difficult to derive, even asymptotically.</li>
<li> It is relatively simple to apply the bootstrap to complex data-collection plans (such as stratified and clustered samples).</li>
</ol>
</div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods-bootstrap-background">Resampling methods: Bootstrap background </h2>
<p>
Since \( \widehat{\theta} = \widehat{\theta}(\boldsymbol{X}) \) is a function of random variables,
\( \widehat{\theta} \) itself must be a random variable. Thus it has
a pdf, call this function \( p(\boldsymbol{t}) \). The aim of the bootstrap is to
estimate \( p(\boldsymbol{t}) \) by the relative frequency of
\( \widehat{\theta} \). You can think of this as using a histogram
in the place of \( p(\boldsymbol{t}) \). If the relative frequency closely
resembles \( p(\vec{t}) \), then using numerics, it is straight forward to
estimate all the interesting parameters of \( p(\boldsymbol{t}) \) using point
estimators.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods-more-bootstrap-background">Resampling methods: More Bootstrap background </h2>
<p>
In the case that \( \widehat{\theta} \) has
more than one component, and the components are independent, we use the
same estimator on each component separately. If the probability
density function of \( X_i \), \( p(x) \), had been known, then it would have
been straight forward to do this by:
<ol>
<li> Drawing lots of numbers from \( p(x) \), suppose we call one such set of numbers \( (X_1^*, X_2^*, \cdots, X_n^*) \).</li>
<li> Then using these numbers, we could compute a replica of \( \widehat{\theta} \) called \( \widehat{\theta}^* \).</li>
</ol>
By repeated use of (1) and (2), many
estimates of \( \widehat{\theta} \) could have been obtained. The
idea is to use the relative frequency of \( \widehat{\theta}^* \)
(think of a histogram) as an estimate of \( p(\boldsymbol{t}) \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods-bootstrap-approach">Resampling methods: Bootstrap approach </h2>
<p>
But
unless there is enough information available about the process that
generated \( X_1,X_2,\cdots,X_n \), \( p(x) \) is in general
unknown. Therefore, <a href="https://projecteuclid.org/euclid.aos/1176344552" target="_blank">Efron in 1979</a> asked the
question: What if we replace \( p(x) \) by the relative frequency
of the observation \( X_i \); if we draw observations in accordance with
the relative frequency of the observations, will we obtain the same
result in some asymptotic sense? The answer is yes.
<p>
Instead of generating the histogram for the relative
frequency of the observation \( X_i \), just draw the values
\( (X_1^*,X_2^*,\cdots,X_n^*) \) with replacement from the vector
\( \boldsymbol{X} \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="resampling-methods-bootstrap-steps">Resampling methods: Bootstrap steps </h2>
<p>
The independent bootstrap works like this:
<ol>
<li> Draw with replacement \( n \) numbers for the observed variables \( \boldsymbol{x} = (x_1,x_2,\cdots,x_n) \).</li>
<li> Define a vector \( \boldsymbol{x}^* \) containing the values which were drawn from \( \boldsymbol{x} \).</li>
<li> Using the vector \( \boldsymbol{x}^* \) compute \( \widehat{\theta}^* \) by evaluating \( \widehat \theta \) under the observations \( \boldsymbol{x}^* \).</li>
<li> Repeat this process \( k \) times.</li>
</ol>
When you are done, you can draw a histogram of the relative frequency
of \( \widehat \theta^* \). This is your estimate of the probability
distribution \( p(t) \). Using this probability distribution you can
estimate any statistics thereof. In principle you never draw the
histogram of the relative frequency of \( \widehat{\theta}^* \). Instead
you use the estimators corresponding to the statistic of interest. For
example, if you are interested in estimating the variance of \( \widehat
\theta \), apply the etsimator \( \widehat \sigma^2 \) to the values
\( \widehat \theta ^* \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="code-example-for-the-bootstrap-method">Code example for the Bootstrap method </h2>
<p>
The following code starts with a Gaussian distribution with mean value
\( \mu =100 \) and variance \( \sigma=15 \). We use this to generate the data
used in the bootstrap analysis. The bootstrap analysis returns a data
set after a given number of bootstrap operations (as many as we have
data points). This data set consists of estimated mean values for each
bootstrap operation. The histogram generated by the bootstrap method
shows that the distribution for these mean values is also a Gaussian,
centered around the mean value \( \mu=100 \) but with standard deviation
\( \sigma/\sqrt{n} \), where \( n \) is the number of bootstrap samples (in
this case the same as the number of original data points). The value
of the standard deviation is what we expect from the central limit
theorem.
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">import</span> <span style="color: #666666">*</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">numpy.random</span> <span style="color: #008000; font-weight: bold">import</span> randint, randn
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">time</span> <span style="color: #008000; font-weight: bold">import</span> time
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.mlab</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">mlab</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.pyplot</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">plt</span>
<span style="color: #408080; font-style: italic"># Returns mean of bootstrap samples </span>
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">stat</span>(data):
<span style="color: #008000; font-weight: bold">return</span> mean(data)
<span style="color: #408080; font-style: italic"># Bootstrap algorithm</span>
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">bootstrap</span>(data, statistic, R):
t <span style="color: #666666">=</span> zeros(R); n <span style="color: #666666">=</span> <span style="color: #008000">len</span>(data); inds <span style="color: #666666">=</span> arange(n); t0 <span style="color: #666666">=</span> time()
<span style="color: #408080; font-style: italic"># non-parametric bootstrap </span>
<span style="color: #008000; font-weight: bold">for</span> i <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(R):
t[i] <span style="color: #666666">=</span> statistic(data[randint(<span style="color: #666666">0</span>,n,n)])
<span style="color: #408080; font-style: italic"># analysis </span>
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;Runtime: </span><span style="color: #BB6688; font-weight: bold">%g</span><span style="color: #BA2121"> sec&quot;</span> <span style="color: #666666">%</span> (time()<span style="color: #666666">-</span>t0)); <span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;Bootstrap Statistics :&quot;</span>)
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;original bias std. error&quot;</span>)
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;</span><span style="color: #BB6688; font-weight: bold">%8g</span><span style="color: #BA2121"> </span><span style="color: #BB6688; font-weight: bold">%8g</span><span style="color: #BA2121"> </span><span style="color: #BB6688; font-weight: bold">%14g</span><span style="color: #BA2121"> </span><span style="color: #BB6688; font-weight: bold">%15g</span><span style="color: #BA2121">&quot;</span> <span style="color: #666666">%</span> (statistic(data), std(data),mean(t),std(t)))
<span style="color: #008000; font-weight: bold">return</span> t
mu, sigma <span style="color: #666666">=</span> <span style="color: #666666">100</span>, <span style="color: #666666">15</span>
datapoints <span style="color: #666666">=</span> <span style="color: #666666">10000</span>
x <span style="color: #666666">=</span> mu <span style="color: #666666">+</span> sigma<span style="color: #666666">*</span>random<span style="color: #666666">.</span>randn(datapoints)
<span style="color: #408080; font-style: italic"># bootstrap returns the data sample </span>
t <span style="color: #666666">=</span> bootstrap(x, stat, datapoints)
<span style="color: #408080; font-style: italic"># the histogram of the bootstrapped data </span>
n, binsboot, patches <span style="color: #666666">=</span> plt<span style="color: #666666">.</span>hist(t, <span style="color: #666666">50</span>, normed<span style="color: #666666">=1</span>, facecolor<span style="color: #666666">=</span><span style="color: #BA2121">&#39;red&#39;</span>, alpha<span style="color: #666666">=0.75</span>)
<span style="color: #408080; font-style: italic"># add a &#39;best fit&#39; line </span>
y <span style="color: #666666">=</span> mlab<span style="color: #666666">.</span>normpdf( binsboot, mean(t), std(t))
lt <span style="color: #666666">=</span> plt<span style="color: #666666">.</span>plot(binsboot, y, <span style="color: #BA2121">&#39;r--&#39;</span>, linewidth<span style="color: #666666">=1</span>)
plt<span style="color: #666666">.</span>xlabel(<span style="color: #BA2121">&#39;Smarts&#39;</span>)
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">&#39;Probability&#39;</span>)
plt<span style="color: #666666">.</span>axis([<span style="color: #666666">99.5</span>, <span style="color: #666666">100.6</span>, <span style="color: #666666">0</span>, <span style="color: #666666">3.0</span>])
plt<span style="color: #666666">.</span>grid(<span style="color: #008000; font-weight: bold">True</span>)
plt<span style="color: #666666">.</span>show()
</pre></div>
<p>
<!-- !split -->
<h2 id="various-steps-in-cross-validation">Various steps in cross-validation </h2>
<p>
When the repetitive splitting of the data set is done randomly,
samples may accidently end up in a fast majority of the splits in
either training or test set. Such samples may have an unbalanced
influence on either model building or prediction evaluation. To avoid
this \( k \)-fold cross-validation structures the data splitting. The
samples are divided into \( k \) more or less equally sized exhaustive and
mutually exclusive subsets. In turn (at each split) one of these
subsets plays the role of the test set while the union of the
remaining subsets constitutes the training set. Such a splitting
warrants a balanced representation of each sample in both training and
test set over the splits. Still the division into the \( k \) subsets
involves a degree of randomness. This may be fully excluded when
choosing \( k=n \). This particular case is referred to as leave-one-out
cross-validation (LOOCV).
<p>
<!-- !split -->
<h2 id="how-to-set-up-the-cross-validation-for-ridge-and-or-lasso">How to set up the cross-validation for Ridge and/or Lasso </h2>
<ul>
<li> Define a range of interest for the penalty parameter.</li>
<li> Divide the data set into training and test set comprising samples \( \{1, \ldots, n\} \setminus i \) and \( \{ i \} \), respectively.</li>
<li> Fit the linear regression model by means of ridge estimation for each \( \lambda \) in the grid using the training set, and the corresponding estimate of the error variance \( \boldsymbol{\sigma}_{-i}^2(\lambda) \), as</li>
</ul>
$$
\begin{align*}
\boldsymbol{\beta}_{-i}(\lambda) & = ( \boldsymbol{X}_{-i, \ast}^{T}
\boldsymbol{X}_{-i, \ast} + \lambda \boldsymbol{I}_{pp})^{-1}
\boldsymbol{X}_{-i, \ast}^{T} \boldsymbol{y}_{-i}
\end{align*}
$$
<ul>
<li> Evaluate the prediction performance of these models on the test set by \( \log\{L[y_i, \boldsymbol{X}_{i, \ast}; \boldsymbol{\beta}_{-i}(\lambda), \boldsymbol{\sigma}_{-i}^2(\lambda)]\} \). Or, by the prediction error \( |y_i - \boldsymbol{X}_{i, \ast} \boldsymbol{\beta}_{-i}(\lambda)| \), the relative error, the error squared or the R2 score function.</li>
<li> Repeat the first three steps such that each sample plays the role of the test set once.</li>
<li> Average the prediction performances of the test sets at each grid point of the penalty bias/parameter. It is an estimate of the prediction performance of the model corresponding to this value of the penalty parameter on novel data. It is defined as</li>
</ul>
$$
\begin{align*}
\frac{1}{n} \sum_{i = 1}^n \log\{L[y_i, \mathbf{X}_{i, \ast}; \boldsymbol{\beta}_{-i}(\lambda), \boldsymbol{\sigma}_{-i}^2(\lambda)]\}.
\end{align*}
$$
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="cross-validation-in-brief">Cross-validation in brief </h2>
<p>
For the various values of \( k \)
<ol>
<li> shuffle the dataset randomly.</li>
<li> Split the dataset into \( k \) groups.</li>
<li> For each unique group:
<ol type="a"></li>
<li> Decide which group to use as set for test data</li>
<li> Take the remaining groups as a training data set</li>
<li> Fit a model on the training set and evaluate it on the test set</li>
<li> Retain the evaluation score and discard the model</li>
</ol>
<li> Summarize the model using the sample of model evaluation scores</li>
</ol>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="code-example-for-cross-validation-and-k-fold-cross-validation">Code Example for Cross-validation and \( k \)-fold Cross-validation </h2>
<p>
The code here uses Ridge regression with cross-validation (CV) resampling and \( k \)-fold CV in order to fit a specific polynomial.
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.pyplot</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">plt</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> KFold
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">import</span> Ridge
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> cross_val_score
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.preprocessing</span> <span style="color: #008000; font-weight: bold">import</span> PolynomialFeatures
<span style="color: #408080; font-style: italic"># A seed just to ensure that the random numbers are the same for every run.</span>
<span style="color: #408080; font-style: italic"># Useful for eventual debugging.</span>
np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>seed(<span style="color: #666666">3155</span>)
<span style="color: #408080; font-style: italic"># Generate the data.</span>
nsamples <span style="color: #666666">=</span> <span style="color: #666666">100</span>
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>randn(nsamples)
y <span style="color: #666666">=</span> <span style="color: #666666">3*</span>x<span style="color: #666666">**2</span> <span style="color: #666666">+</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>randn(nsamples)
<span style="color: #408080; font-style: italic">## Cross-validation on Ridge regression using KFold only</span>
<span style="color: #408080; font-style: italic"># Decide degree on polynomial to fit</span>
poly <span style="color: #666666">=</span> PolynomialFeatures(degree <span style="color: #666666">=</span> <span style="color: #666666">6</span>)
<span style="color: #408080; font-style: italic"># Decide which values of lambda to use</span>
nlambdas <span style="color: #666666">=</span> <span style="color: #666666">500</span>
lambdas <span style="color: #666666">=</span> np<span style="color: #666666">.</span>logspace(<span style="color: #666666">-3</span>, <span style="color: #666666">5</span>, nlambdas)
<span style="color: #408080; font-style: italic"># Initialize a KFold instance</span>
k <span style="color: #666666">=</span> <span style="color: #666666">5</span>
kfold <span style="color: #666666">=</span> KFold(n_splits <span style="color: #666666">=</span> k)
<span style="color: #408080; font-style: italic"># Perform the cross-validation to estimate MSE</span>
scores_KFold <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros((nlambdas, k))
i <span style="color: #666666">=</span> <span style="color: #666666">0</span>
<span style="color: #008000; font-weight: bold">for</span> lmb <span style="color: #AA22FF; font-weight: bold">in</span> lambdas:
ridge <span style="color: #666666">=</span> Ridge(alpha <span style="color: #666666">=</span> lmb)
j <span style="color: #666666">=</span> <span style="color: #666666">0</span>
<span style="color: #008000; font-weight: bold">for</span> train_inds, test_inds <span style="color: #AA22FF; font-weight: bold">in</span> kfold<span style="color: #666666">.</span>split(x):
xtrain <span style="color: #666666">=</span> x[train_inds]
ytrain <span style="color: #666666">=</span> y[train_inds]
xtest <span style="color: #666666">=</span> x[test_inds]
ytest <span style="color: #666666">=</span> y[test_inds]
Xtrain <span style="color: #666666">=</span> poly<span style="color: #666666">.</span>fit_transform(xtrain[:, np<span style="color: #666666">.</span>newaxis])
ridge<span style="color: #666666">.</span>fit(Xtrain, ytrain[:, np<span style="color: #666666">.</span>newaxis])
Xtest <span style="color: #666666">=</span> poly<span style="color: #666666">.</span>fit_transform(xtest[:, np<span style="color: #666666">.</span>newaxis])
ypred <span style="color: #666666">=</span> ridge<span style="color: #666666">.</span>predict(Xtest)
scores_KFold[i,j] <span style="color: #666666">=</span> np<span style="color: #666666">.</span>sum((ypred <span style="color: #666666">-</span> ytest[:, np<span style="color: #666666">.</span>newaxis])<span style="color: #666666">**2</span>)<span style="color: #666666">/</span>np<span style="color: #666666">.</span>size(ypred)
j <span style="color: #666666">+=</span> <span style="color: #666666">1</span>
i <span style="color: #666666">+=</span> <span style="color: #666666">1</span>
estimated_mse_KFold <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean(scores_KFold, axis <span style="color: #666666">=</span> <span style="color: #666666">1</span>)
<span style="color: #408080; font-style: italic">## Cross-validation using cross_val_score from sklearn along with KFold</span>
<span style="color: #408080; font-style: italic"># kfold is an instance initialized above as:</span>
<span style="color: #408080; font-style: italic"># kfold = KFold(n_splits = k)</span>
estimated_mse_sklearn <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(nlambdas)
i <span style="color: #666666">=</span> <span style="color: #666666">0</span>
<span style="color: #008000; font-weight: bold">for</span> lmb <span style="color: #AA22FF; font-weight: bold">in</span> lambdas:
ridge <span style="color: #666666">=</span> Ridge(alpha <span style="color: #666666">=</span> lmb)
X <span style="color: #666666">=</span> poly<span style="color: #666666">.</span>fit_transform(x[:, np<span style="color: #666666">.</span>newaxis])
estimated_mse_folds <span style="color: #666666">=</span> cross_val_score(ridge, X, y[:, np<span style="color: #666666">.</span>newaxis], scoring<span style="color: #666666">=</span><span style="color: #BA2121">&#39;neg_mean_squared_error&#39;</span>, cv<span style="color: #666666">=</span>kfold)
<span style="color: #408080; font-style: italic"># cross_val_score return an array containing the estimated negative mse for every fold.</span>
<span style="color: #408080; font-style: italic"># we have to the the mean of every array in order to get an estimate of the mse of the model</span>
estimated_mse_sklearn[i] <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean(<span style="color: #666666">-</span>estimated_mse_folds)
i <span style="color: #666666">+=</span> <span style="color: #666666">1</span>
<span style="color: #408080; font-style: italic">## Plot and compare the slightly different ways to perform cross-validation</span>
plt<span style="color: #666666">.</span>figure()
plt<span style="color: #666666">.</span>plot(np<span style="color: #666666">.</span>log10(lambdas), estimated_mse_sklearn, label <span style="color: #666666">=</span> <span style="color: #BA2121">&#39;cross_val_score&#39;</span>)
plt<span style="color: #666666">.</span>plot(np<span style="color: #666666">.</span>log10(lambdas), estimated_mse_KFold, <span style="color: #BA2121">&#39;r--&#39;</span>, label <span style="color: #666666">=</span> <span style="color: #BA2121">&#39;KFold&#39;</span>)
plt<span style="color: #666666">.</span>xlabel(<span style="color: #BA2121">&#39;log10(lambda)&#39;</span>)
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">&#39;mse&#39;</span>)
plt<span style="color: #666666">.</span>legend()
plt<span style="color: #666666">.</span>show()
</pre></div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="the-bias-variance-tradeoff">The bias-variance tradeoff </h2>
<p>
We will discuss the bias-variance tradeoff in the context of
continuous predictions such as regression. However, many of the
intuitions and ideas discussed here also carry over to classification
tasks. Consider a dataset \( \mathcal{L} \) consisting of the data
\( \mathbf{X}_\mathcal{L}=\{(y_j, \boldsymbol{x}_j), j=0\ldots n-1\} \).
<p>
Let us assume that the true data is generated from a noisy model
$$
\boldsymbol{y}=f(\boldsymbol{x}) + \boldsymbol{\epsilon}
$$
<p>
where \( \epsilon \) is normally distributed with mean zero and standard deviation \( \sigma^2 \).
<p>
In our derivation of the ordinary least squares method we defined then
an approximation to the function \( f \) in terms of the parameters
\( \boldsymbol{\beta} \) and the design matrix \( \boldsymbol{X} \) which embody our model,
that is \( \boldsymbol{\tilde{y}}=\boldsymbol{X}\boldsymbol{\beta} \).
<p>
Thereafter we found the parameters \( \boldsymbol{\beta} \) by optimizing the means squared error via the so-called cost function
$$
C(\boldsymbol{X},\boldsymbol{\beta}) =\frac{1}{n}\sum_{i=0}^{n-1}(y_i-\tilde{y}_i)^2=\mathbb{E}\left[(\boldsymbol{y}-\boldsymbol{\tilde{y}})^2\right].
$$
<p>
We can rewrite this as
$$
\mathbb{E}\left[(\boldsymbol{y}-\boldsymbol{\tilde{y}})^2\right]=\frac{1}{n}\sum_i(f_i-\mathbb{E}\left[\boldsymbol{\tilde{y}}\right])^2+\frac{1}{n}\sum_i(\tilde{y}_i-\mathbb{E}\left[\boldsymbol{\tilde{y}}\right])^2+\sigma^2.
$$
<p>
The three terms represent the square of the bias of the learning
method, which can be thought of as the error caused by the simplifying
assumptions built into the method. The second term represents the
variance of the chosen model and finally the last terms is variance of
the error \( \boldsymbol{\epsilon} \).
<p>
To derive this equation, we need to recall that the variance of \( \boldsymbol{y} \) and \( \boldsymbol{\epsilon} \) are both equal to \( \sigma^2 \). The mean value of \( \boldsymbol{\epsilon} \) is by definition equal to zero. Furthermore, the function \( f \) is not a stochastics variable, idem for \( \boldsymbol{\tilde{y}} \).
We use a more compact notation in terms of the expectation value
$$
\mathbb{E}\left[(\boldsymbol{y}-\boldsymbol{\tilde{y}})^2\right]=\mathbb{E}\left[(\boldsymbol{f}+\boldsymbol{\epsilon}-\boldsymbol{\tilde{y}})^2\right],
$$
and adding and subtracting \( \mathbb{E}\left[\boldsymbol{\tilde{y}}\right] \) we get
$$
\mathbb{E}\left[(\boldsymbol{y}-\boldsymbol{\tilde{y}})^2\right]=\mathbb{E}\left[(\boldsymbol{f}+\boldsymbol{\epsilon}-\boldsymbol{\tilde{y}}+\mathbb{E}\left[\boldsymbol{\tilde{y}}\right]-\mathbb{E}\left[\boldsymbol{\tilde{y}}\right])^2\right],
$$
which, using the abovementioned expectation values can be rewritten as
$$
\mathbb{E}\left[(\boldsymbol{y}-\boldsymbol{\tilde{y}})^2\right]=\mathbb{E}\left[(\boldsymbol{y}-\mathbb{E}\left[\boldsymbol{\tilde{y}}\right])^2\right]+\mathrm{Var}\left[\boldsymbol{\tilde{y}}\right]+\sigma^2,
$$
that is the rewriting in terms of the so-called bias, the variance of the model \( \boldsymbol{\tilde{y}} \) and the variance of \( \boldsymbol{\epsilon} \).
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="example-code-for-bias-variance-tradeoff">Example code for Bias-Variance tradeoff </h2>
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.pyplot</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">plt</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">import</span> LinearRegression, Ridge, Lasso
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.preprocessing</span> <span style="color: #008000; font-weight: bold">import</span> PolynomialFeatures
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> train_test_split
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.pipeline</span> <span style="color: #008000; font-weight: bold">import</span> make_pipeline
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.utils</span> <span style="color: #008000; font-weight: bold">import</span> resample
np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>seed(<span style="color: #666666">2018</span>)
n <span style="color: #666666">=</span> <span style="color: #666666">500</span>
n_boostraps <span style="color: #666666">=</span> <span style="color: #666666">100</span>
degree <span style="color: #666666">=</span> <span style="color: #666666">18</span> <span style="color: #408080; font-style: italic"># A quite high value, just to show.</span>
noise <span style="color: #666666">=</span> <span style="color: #666666">0.1</span>
<span style="color: #408080; font-style: italic"># Make data set.</span>
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linspace(<span style="color: #666666">-1</span>, <span style="color: #666666">3</span>, n)<span style="color: #666666">.</span>reshape(<span style="color: #666666">-1</span>, <span style="color: #666666">1</span>)
y <span style="color: #666666">=</span> np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>x<span style="color: #666666">**2</span>) <span style="color: #666666">+</span> <span style="color: #666666">1.5</span> <span style="color: #666666">*</span> np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>(x<span style="color: #666666">-2</span>)<span style="color: #666666">**2</span>) <span style="color: #666666">+</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>normal(<span style="color: #666666">0</span>, <span style="color: #666666">0.1</span>, x<span style="color: #666666">.</span>shape)
<span style="color: #408080; font-style: italic"># Hold out some test data that is never used in training.</span>
x_train, x_test, y_train, y_test <span style="color: #666666">=</span> train_test_split(x, y, test_size<span style="color: #666666">=0.2</span>)
<span style="color: #408080; font-style: italic"># Combine x transformation and model into one operation.</span>
<span style="color: #408080; font-style: italic"># Not neccesary, but convenient.</span>
model <span style="color: #666666">=</span> make_pipeline(PolynomialFeatures(degree<span style="color: #666666">=</span>degree), LinearRegression(fit_intercept<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">False</span>))
<span style="color: #408080; font-style: italic"># The following (m x n_bootstraps) matrix holds the column vectors y_pred</span>
<span style="color: #408080; font-style: italic"># for each bootstrap iteration.</span>
y_pred <span style="color: #666666">=</span> np<span style="color: #666666">.</span>empty((y_test<span style="color: #666666">.</span>shape[<span style="color: #666666">0</span>], n_boostraps))
<span style="color: #008000; font-weight: bold">for</span> i <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(n_boostraps):
x_, y_ <span style="color: #666666">=</span> resample(x_train, y_train)
<span style="color: #408080; font-style: italic"># Evaluate the new model on the same test data each time.</span>
y_pred[:, i] <span style="color: #666666">=</span> model<span style="color: #666666">.</span>fit(x_, y_)<span style="color: #666666">.</span>predict(x_test)<span style="color: #666666">.</span>ravel()
<span style="color: #408080; font-style: italic"># Note: Expectations and variances taken w.r.t. different training</span>
<span style="color: #408080; font-style: italic"># data sets, hence the axis=1. Subsequent means are taken across the test data</span>
<span style="color: #408080; font-style: italic"># set in order to obtain a total value, but before this we have error/bias/variance</span>
<span style="color: #408080; font-style: italic"># calculated per data point in the test set.</span>
<span style="color: #408080; font-style: italic"># Note 2: The use of keepdims=True is important in the calculation of bias as this </span>
<span style="color: #408080; font-style: italic"># maintains the column vector form. Dropping this yields very unexpected results.</span>
error <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean( np<span style="color: #666666">.</span>mean((y_test <span style="color: #666666">-</span> y_pred)<span style="color: #666666">**2</span>, axis<span style="color: #666666">=1</span>, keepdims<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">True</span>) )
bias <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean( (y_test <span style="color: #666666">-</span> np<span style="color: #666666">.</span>mean(y_pred, axis<span style="color: #666666">=1</span>, keepdims<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">True</span>))<span style="color: #666666">**2</span> )
variance <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean( np<span style="color: #666666">.</span>var(y_pred, axis<span style="color: #666666">=1</span>, keepdims<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">True</span>) )
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;Error:&#39;</span>, error)
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;Bias^2:&#39;</span>, bias)
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;Var:&#39;</span>, variance)
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;</span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BA2121"> &gt;= </span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BA2121"> + </span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BA2121"> = </span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BA2121">&#39;</span><span style="color: #666666">.</span>format(error, bias, variance, bias<span style="color: #666666">+</span>variance))
plt<span style="color: #666666">.</span>plot(x[::<span style="color: #666666">5</span>, :], y[::<span style="color: #666666">5</span>, :], label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;f(x)&#39;</span>)
plt<span style="color: #666666">.</span>scatter(x_test, y_test, label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;Data points&#39;</span>)
plt<span style="color: #666666">.</span>scatter(x_test, np<span style="color: #666666">.</span>mean(y_pred, axis<span style="color: #666666">=1</span>), label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;Pred&#39;</span>)
plt<span style="color: #666666">.</span>legend()
plt<span style="color: #666666">.</span>show()
</pre></div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="understanding-what-happens">Understanding what happens </h2>
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.pyplot</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">plt</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">import</span> LinearRegression, Ridge, Lasso
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.preprocessing</span> <span style="color: #008000; font-weight: bold">import</span> PolynomialFeatures
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> train_test_split
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.pipeline</span> <span style="color: #008000; font-weight: bold">import</span> make_pipeline
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.utils</span> <span style="color: #008000; font-weight: bold">import</span> resample
np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>seed(<span style="color: #666666">2018</span>)
n <span style="color: #666666">=</span> <span style="color: #666666">40</span>
n_boostraps <span style="color: #666666">=</span> <span style="color: #666666">100</span>
maxdegree <span style="color: #666666">=</span> <span style="color: #666666">14</span>
<span style="color: #408080; font-style: italic"># Make data set.</span>
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linspace(<span style="color: #666666">-3</span>, <span style="color: #666666">3</span>, n)<span style="color: #666666">.</span>reshape(<span style="color: #666666">-1</span>, <span style="color: #666666">1</span>)
y <span style="color: #666666">=</span> np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>x<span style="color: #666666">**2</span>) <span style="color: #666666">+</span> <span style="color: #666666">1.5</span> <span style="color: #666666">*</span> np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>(x<span style="color: #666666">-2</span>)<span style="color: #666666">**2</span>)<span style="color: #666666">+</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>normal(<span style="color: #666666">0</span>, <span style="color: #666666">0.1</span>, x<span style="color: #666666">.</span>shape)
error <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(maxdegree)
bias <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(maxdegree)
variance <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(maxdegree)
polydegree <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(maxdegree)
x_train, x_test, y_train, y_test <span style="color: #666666">=</span> train_test_split(x, y, test_size<span style="color: #666666">=0.2</span>)
<span style="color: #008000; font-weight: bold">for</span> degree <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(maxdegree):
model <span style="color: #666666">=</span> make_pipeline(PolynomialFeatures(degree<span style="color: #666666">=</span>degree), LinearRegression(fit_intercept<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">False</span>))
y_pred <span style="color: #666666">=</span> np<span style="color: #666666">.</span>empty((y_test<span style="color: #666666">.</span>shape[<span style="color: #666666">0</span>], n_boostraps))
<span style="color: #008000; font-weight: bold">for</span> i <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(n_boostraps):
x_, y_ <span style="color: #666666">=</span> resample(x_train, y_train)
y_pred[:, i] <span style="color: #666666">=</span> model<span style="color: #666666">.</span>fit(x_, y_)<span style="color: #666666">.</span>predict(x_test)<span style="color: #666666">.</span>ravel()
polydegree[degree] <span style="color: #666666">=</span> degree
error[degree] <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean( np<span style="color: #666666">.</span>mean((y_test <span style="color: #666666">-</span> y_pred)<span style="color: #666666">**2</span>, axis<span style="color: #666666">=1</span>, keepdims<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">True</span>) )
bias[degree] <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean( (y_test <span style="color: #666666">-</span> np<span style="color: #666666">.</span>mean(y_pred, axis<span style="color: #666666">=1</span>, keepdims<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">True</span>))<span style="color: #666666">**2</span> )
variance[degree] <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean( np<span style="color: #666666">.</span>var(y_pred, axis<span style="color: #666666">=1</span>, keepdims<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">True</span>) )
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;Polynomial degree:&#39;</span>, degree)
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;Error:&#39;</span>, error[degree])
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;Bias^2:&#39;</span>, bias[degree])
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;Var:&#39;</span>, variance[degree])
<span style="color: #008000">print</span>(<span style="color: #BA2121">&#39;</span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BA2121"> &gt;= </span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BA2121"> + </span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BA2121"> = </span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BA2121">&#39;</span><span style="color: #666666">.</span>format(error[degree], bias[degree], variance[degree], bias[degree]<span style="color: #666666">+</span>variance[degree]))
plt<span style="color: #666666">.</span>plot(polydegree, error, label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;Error&#39;</span>)
plt<span style="color: #666666">.</span>plot(polydegree, bias, label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;bias&#39;</span>)
plt<span style="color: #666666">.</span>plot(polydegree, variance, label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;Variance&#39;</span>)
plt<span style="color: #666666">.</span>legend()
plt<span style="color: #666666">.</span>show()
</pre></div>
<p>
<!-- !split -->
<h2 id="summing-up">Summing up </h2>
<p>
The bias-variance tradeoff summarizes the fundamental tension in
machine learning, particularly supervised learning, between the
complexity of a model and the amount of training data needed to train
it. Since data is often limited, in practice it is often useful to
use a less-complex model with higher bias, that is a model whose asymptotic
performance is worse than another model because it is easier to
train and less sensitive to sampling noise arising from having a
finite-sized training dataset (smaller variance).
<p>
The above equations tell us that in
order to minimize the expected test error, we need to select a
statistical learning method that simultaneously achieves low variance
and low bias. Note that variance is inherently a nonnegative quantity,
and squared bias is also nonnegative. Hence, we see that the expected
test MSE can never lie below \( Var(\epsilon) \), the irreducible error.
<p>
What do we mean by the variance and bias of a statistical learning
method? The variance refers to the amount by which our model would change if we
estimated it using a different training data set. Since the training
data are used to fit the statistical learning method, different
training data sets will result in a different estimate. But ideally the
estimate for our model should not vary too much between training
sets. However, if a method has high variance then small changes in
the training data can result in large changes in the model. In general, more
flexible statistical methods have higher variance.
<p>
You may also find this recent <a href="https://www.pnas.org/content/116/32/15849" target="_blank">article</a> of interest.
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="another-example-from-scikit-learn-s-repository">Another Example from Scikit-Learn's Repository </h2>
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #BA2121; font-style: italic">&quot;&quot;&quot;</span>
<span style="color: #BA2121; font-style: italic">============================</span>
<span style="color: #BA2121; font-style: italic">Underfitting vs. Overfitting</span>
<span style="color: #BA2121; font-style: italic">============================</span>
<span style="color: #BA2121; font-style: italic">This example demonstrates the problems of underfitting and overfitting and</span>
<span style="color: #BA2121; font-style: italic">how we can use linear regression with polynomial features to approximate</span>
<span style="color: #BA2121; font-style: italic">nonlinear functions. The plot shows the function that we want to approximate,</span>
<span style="color: #BA2121; font-style: italic">which is a part of the cosine function. In addition, the samples from the</span>
<span style="color: #BA2121; font-style: italic">real function and the approximations of different models are displayed. The</span>
<span style="color: #BA2121; font-style: italic">models have polynomial features of different degrees. We can see that a</span>
<span style="color: #BA2121; font-style: italic">linear function (polynomial with degree 1) is not sufficient to fit the</span>
<span style="color: #BA2121; font-style: italic">training samples. This is called **underfitting**. A polynomial of degree 4</span>
<span style="color: #BA2121; font-style: italic">approximates the true function almost perfectly. However, for higher degrees</span>
<span style="color: #BA2121; font-style: italic">the model will **overfit** the training data, i.e. it learns the noise of the</span>
<span style="color: #BA2121; font-style: italic">training data.</span>
<span style="color: #BA2121; font-style: italic">We evaluate quantitatively **overfitting** / **underfitting** by using</span>
<span style="color: #BA2121; font-style: italic">cross-validation. We calculate the mean squared error (MSE) on the validation</span>
<span style="color: #BA2121; font-style: italic">set, the higher, the less likely the model generalizes correctly from the</span>
<span style="color: #BA2121; font-style: italic">training data.</span>
<span style="color: #BA2121; font-style: italic">&quot;&quot;&quot;</span>
<span style="color: #008000">print</span>(<span style="color: #19177C">__doc__</span>)
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.pyplot</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">plt</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.pipeline</span> <span style="color: #008000; font-weight: bold">import</span> Pipeline
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.preprocessing</span> <span style="color: #008000; font-weight: bold">import</span> PolynomialFeatures
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">import</span> LinearRegression
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> cross_val_score
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">true_fun</span>(X):
<span style="color: #008000; font-weight: bold">return</span> np<span style="color: #666666">.</span>cos(<span style="color: #666666">1.5</span> <span style="color: #666666">*</span> np<span style="color: #666666">.</span>pi <span style="color: #666666">*</span> X)
np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>seed(<span style="color: #666666">0</span>)
n_samples <span style="color: #666666">=</span> <span style="color: #666666">30</span>
degrees <span style="color: #666666">=</span> [<span style="color: #666666">1</span>, <span style="color: #666666">4</span>, <span style="color: #666666">15</span>]
X <span style="color: #666666">=</span> np<span style="color: #666666">.</span>sort(np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>rand(n_samples))
y <span style="color: #666666">=</span> true_fun(X) <span style="color: #666666">+</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>randn(n_samples) <span style="color: #666666">*</span> <span style="color: #666666">0.1</span>
plt<span style="color: #666666">.</span>figure(figsize<span style="color: #666666">=</span>(<span style="color: #666666">14</span>, <span style="color: #666666">5</span>))
<span style="color: #008000; font-weight: bold">for</span> i <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(<span style="color: #008000">len</span>(degrees)):
ax <span style="color: #666666">=</span> plt<span style="color: #666666">.</span>subplot(<span style="color: #666666">1</span>, <span style="color: #008000">len</span>(degrees), i <span style="color: #666666">+</span> <span style="color: #666666">1</span>)
plt<span style="color: #666666">.</span>setp(ax, xticks<span style="color: #666666">=</span>(), yticks<span style="color: #666666">=</span>())
polynomial_features <span style="color: #666666">=</span> PolynomialFeatures(degree<span style="color: #666666">=</span>degrees[i],
include_bias<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">False</span>)
linear_regression <span style="color: #666666">=</span> LinearRegression()
pipeline <span style="color: #666666">=</span> Pipeline([(<span style="color: #BA2121">&quot;polynomial_features&quot;</span>, polynomial_features),
(<span style="color: #BA2121">&quot;linear_regression&quot;</span>, linear_regression)])
pipeline<span style="color: #666666">.</span>fit(X[:, np<span style="color: #666666">.</span>newaxis], y)
<span style="color: #408080; font-style: italic"># Evaluate the models using crossvalidation</span>
scores <span style="color: #666666">=</span> cross_val_score(pipeline, X[:, np<span style="color: #666666">.</span>newaxis], y,
scoring<span style="color: #666666">=</span><span style="color: #BA2121">&quot;neg_mean_squared_error&quot;</span>, cv<span style="color: #666666">=10</span>)
X_test <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linspace(<span style="color: #666666">0</span>, <span style="color: #666666">1</span>, <span style="color: #666666">100</span>)
plt<span style="color: #666666">.</span>plot(X_test, pipeline<span style="color: #666666">.</span>predict(X_test[:, np<span style="color: #666666">.</span>newaxis]), label<span style="color: #666666">=</span><span style="color: #BA2121">&quot;Model&quot;</span>)
plt<span style="color: #666666">.</span>plot(X_test, true_fun(X_test), label<span style="color: #666666">=</span><span style="color: #BA2121">&quot;True function&quot;</span>)
plt<span style="color: #666666">.</span>scatter(X, y, edgecolor<span style="color: #666666">=</span><span style="color: #BA2121">&#39;b&#39;</span>, s<span style="color: #666666">=20</span>, label<span style="color: #666666">=</span><span style="color: #BA2121">&quot;Samples&quot;</span>)
plt<span style="color: #666666">.</span>xlabel(<span style="color: #BA2121">&quot;x&quot;</span>)
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">&quot;y&quot;</span>)
plt<span style="color: #666666">.</span>xlim((<span style="color: #666666">0</span>, <span style="color: #666666">1</span>))
plt<span style="color: #666666">.</span>ylim((<span style="color: #666666">-2</span>, <span style="color: #666666">2</span>))
plt<span style="color: #666666">.</span>legend(loc<span style="color: #666666">=</span><span style="color: #BA2121">&quot;best&quot;</span>)
plt<span style="color: #666666">.</span>title(<span style="color: #BA2121">&quot;Degree </span><span style="color: #BB6688; font-weight: bold">{}</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121">MSE = </span><span style="color: #BB6688; font-weight: bold">{:.2e}</span><span style="color: #BA2121">(+/- </span><span style="color: #BB6688; font-weight: bold">{:.2e}</span><span style="color: #BA2121">)&quot;</span><span style="color: #666666">.</span>format(
degrees[i], <span style="color: #666666">-</span>scores<span style="color: #666666">.</span>mean(), scores<span style="color: #666666">.</span>std()))
plt<span style="color: #666666">.</span>show()
</pre></div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="more-examples-on-bootstrap-and-cross-validation-and-errors">More examples on bootstrap and cross-validation and errors </h2>
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #408080; font-style: italic"># Common imports</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">os</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">pandas</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">pd</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.pyplot</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">plt</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">import</span> LinearRegression, Ridge, Lasso
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> train_test_split
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.utils</span> <span style="color: #008000; font-weight: bold">import</span> resample
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.metrics</span> <span style="color: #008000; font-weight: bold">import</span> mean_squared_error
<span style="color: #408080; font-style: italic"># Where to save the figures and data files</span>
PROJECT_ROOT_DIR <span style="color: #666666">=</span> <span style="color: #BA2121">&quot;Results&quot;</span>
FIGURE_ID <span style="color: #666666">=</span> <span style="color: #BA2121">&quot;Results/FigureFiles&quot;</span>
DATA_ID <span style="color: #666666">=</span> <span style="color: #BA2121">&quot;DataFiles/&quot;</span>
<span style="color: #008000; font-weight: bold">if</span> <span style="color: #AA22FF; font-weight: bold">not</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>exists(PROJECT_ROOT_DIR):
os<span style="color: #666666">.</span>mkdir(PROJECT_ROOT_DIR)
<span style="color: #008000; font-weight: bold">if</span> <span style="color: #AA22FF; font-weight: bold">not</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>exists(FIGURE_ID):
os<span style="color: #666666">.</span>makedirs(FIGURE_ID)
<span style="color: #008000; font-weight: bold">if</span> <span style="color: #AA22FF; font-weight: bold">not</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>exists(DATA_ID):
os<span style="color: #666666">.</span>makedirs(DATA_ID)
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">image_path</span>(fig_id):
<span style="color: #008000; font-weight: bold">return</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>join(FIGURE_ID, fig_id)
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">data_path</span>(dat_id):
<span style="color: #008000; font-weight: bold">return</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>join(DATA_ID, dat_id)
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">save_fig</span>(fig_id):
plt<span style="color: #666666">.</span>savefig(image_path(fig_id) <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;.png&quot;</span>, <span style="color: #008000">format</span><span style="color: #666666">=</span><span style="color: #BA2121">&#39;png&#39;</span>)
infile <span style="color: #666666">=</span> <span style="color: #008000">open</span>(data_path(<span style="color: #BA2121">&quot;EoS.csv&quot;</span>),<span style="color: #BA2121">&#39;r&#39;</span>)
<span style="color: #408080; font-style: italic"># Read the EoS data as csv file and organize the data into two arrays with density and energies</span>
EoS <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>read_csv(infile, names<span style="color: #666666">=</span>(<span style="color: #BA2121">&#39;Density&#39;</span>, <span style="color: #BA2121">&#39;Energy&#39;</span>))
EoS[<span style="color: #BA2121">&#39;Energy&#39;</span>] <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>to_numeric(EoS[<span style="color: #BA2121">&#39;Energy&#39;</span>], errors<span style="color: #666666">=</span><span style="color: #BA2121">&#39;coerce&#39;</span>)
EoS <span style="color: #666666">=</span> EoS<span style="color: #666666">.</span>dropna()
Energies <span style="color: #666666">=</span> EoS[<span style="color: #BA2121">&#39;Energy&#39;</span>]
Density <span style="color: #666666">=</span> EoS[<span style="color: #BA2121">&#39;Density&#39;</span>]
<span style="color: #408080; font-style: italic"># The design matrix now as function of various polytrops</span>
Maxpolydegree <span style="color: #666666">=</span> <span style="color: #666666">30</span>
X <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros((<span style="color: #008000">len</span>(Density),Maxpolydegree))
X[:,<span style="color: #666666">0</span>] <span style="color: #666666">=</span> <span style="color: #666666">1.0</span>
testerror <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(Maxpolydegree)
trainingerror <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(Maxpolydegree)
polynomial <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(Maxpolydegree)
trials <span style="color: #666666">=</span> <span style="color: #666666">100</span>
<span style="color: #008000; font-weight: bold">for</span> polydegree <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(<span style="color: #666666">1</span>, Maxpolydegree):
polynomial[polydegree] <span style="color: #666666">=</span> polydegree
<span style="color: #008000; font-weight: bold">for</span> degree <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(polydegree):
X[:,degree] <span style="color: #666666">=</span> Density<span style="color: #666666">**</span>(degree<span style="color: #666666">/3.0</span>)
<span style="color: #408080; font-style: italic"># loop over trials in order to estimate the expectation value of the MSE</span>
testerror[polydegree] <span style="color: #666666">=</span> <span style="color: #666666">0.0</span>
trainingerror[polydegree] <span style="color: #666666">=</span> <span style="color: #666666">0.0</span>
<span style="color: #008000; font-weight: bold">for</span> samples <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(trials):
x_train, x_test, y_train, y_test <span style="color: #666666">=</span> train_test_split(X, Energies, test_size<span style="color: #666666">=0.2</span>)
model <span style="color: #666666">=</span> LinearRegression(fit_intercept<span style="color: #666666">=</span><span style="color: #008000; font-weight: bold">True</span>)<span style="color: #666666">.</span>fit(x_train, y_train)
ypred <span style="color: #666666">=</span> model<span style="color: #666666">.</span>predict(x_train)
ytilde <span style="color: #666666">=</span> model<span style="color: #666666">.</span>predict(x_test)
testerror[polydegree] <span style="color: #666666">+=</span> mean_squared_error(y_test, ytilde)
trainingerror[polydegree] <span style="color: #666666">+=</span> mean_squared_error(y_train, ypred)
testerror[polydegree] <span style="color: #666666">/=</span> trials
trainingerror[polydegree] <span style="color: #666666">/=</span> trials
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;Degree of polynomial: </span><span style="color: #BB6688; font-weight: bold">%3d</span><span style="color: #BA2121">&quot;</span><span style="color: #666666">%</span> polynomial[polydegree])
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;Mean squared error on training data: </span><span style="color: #BB6688; font-weight: bold">%.8f</span><span style="color: #BA2121">&quot;</span> <span style="color: #666666">%</span> trainingerror[polydegree])
<span style="color: #008000">print</span>(<span style="color: #BA2121">&quot;Mean squared error on test data: </span><span style="color: #BB6688; font-weight: bold">%.8f</span><span style="color: #BA2121">&quot;</span> <span style="color: #666666">%</span> testerror[polydegree])
plt<span style="color: #666666">.</span>plot(polynomial, np<span style="color: #666666">.</span>log10(trainingerror), label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;Training Error&#39;</span>)
plt<span style="color: #666666">.</span>plot(polynomial, np<span style="color: #666666">.</span>log10(testerror), label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;Test Error&#39;</span>)
plt<span style="color: #666666">.</span>xlabel(<span style="color: #BA2121">&#39;Polynomial degree&#39;</span>)
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">&#39;log10[MSE]&#39;</span>)
plt<span style="color: #666666">.</span>legend()
plt<span style="color: #666666">.</span>show()
</pre></div>
<p>
<!-- !split -->
<h2 id="the-same-example-but-now-with-cross-validation">The same example but now with cross-validation </h2>
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #408080; font-style: italic"># Common imports</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">os</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">pandas</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">pd</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.pyplot</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">plt</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">import</span> LinearRegression, Ridge, Lasso
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.metrics</span> <span style="color: #008000; font-weight: bold">import</span> mean_squared_error
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> KFold
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> cross_val_score
<span style="color: #408080; font-style: italic"># Where to save the figures and data files</span>
PROJECT_ROOT_DIR <span style="color: #666666">=</span> <span style="color: #BA2121">&quot;Results&quot;</span>
FIGURE_ID <span style="color: #666666">=</span> <span style="color: #BA2121">&quot;Results/FigureFiles&quot;</span>
DATA_ID <span style="color: #666666">=</span> <span style="color: #BA2121">&quot;DataFiles/&quot;</span>
<span style="color: #008000; font-weight: bold">if</span> <span style="color: #AA22FF; font-weight: bold">not</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>exists(PROJECT_ROOT_DIR):
os<span style="color: #666666">.</span>mkdir(PROJECT_ROOT_DIR)
<span style="color: #008000; font-weight: bold">if</span> <span style="color: #AA22FF; font-weight: bold">not</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>exists(FIGURE_ID):
os<span style="color: #666666">.</span>makedirs(FIGURE_ID)
<span style="color: #008000; font-weight: bold">if</span> <span style="color: #AA22FF; font-weight: bold">not</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>exists(DATA_ID):
os<span style="color: #666666">.</span>makedirs(DATA_ID)
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">image_path</span>(fig_id):
<span style="color: #008000; font-weight: bold">return</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>join(FIGURE_ID, fig_id)
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">data_path</span>(dat_id):
<span style="color: #008000; font-weight: bold">return</span> os<span style="color: #666666">.</span>path<span style="color: #666666">.</span>join(DATA_ID, dat_id)
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">save_fig</span>(fig_id):
plt<span style="color: #666666">.</span>savefig(image_path(fig_id) <span style="color: #666666">+</span> <span style="color: #BA2121">&quot;.png&quot;</span>, <span style="color: #008000">format</span><span style="color: #666666">=</span><span style="color: #BA2121">&#39;png&#39;</span>)
infile <span style="color: #666666">=</span> <span style="color: #008000">open</span>(data_path(<span style="color: #BA2121">&quot;EoS.csv&quot;</span>),<span style="color: #BA2121">&#39;r&#39;</span>)
<span style="color: #408080; font-style: italic"># Read the EoS data as csv file and organize the data into two arrays with density and energies</span>
EoS <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>read_csv(infile, names<span style="color: #666666">=</span>(<span style="color: #BA2121">&#39;Density&#39;</span>, <span style="color: #BA2121">&#39;Energy&#39;</span>))
EoS[<span style="color: #BA2121">&#39;Energy&#39;</span>] <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>to_numeric(EoS[<span style="color: #BA2121">&#39;Energy&#39;</span>], errors<span style="color: #666666">=</span><span style="color: #BA2121">&#39;coerce&#39;</span>)
EoS <span style="color: #666666">=</span> EoS<span style="color: #666666">.</span>dropna()
Energies <span style="color: #666666">=</span> EoS[<span style="color: #BA2121">&#39;Energy&#39;</span>]
Density <span style="color: #666666">=</span> EoS[<span style="color: #BA2121">&#39;Density&#39;</span>]
<span style="color: #408080; font-style: italic"># The design matrix now as function of various polytrops</span>
Maxpolydegree <span style="color: #666666">=</span> <span style="color: #666666">30</span>
X <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros((<span style="color: #008000">len</span>(Density),Maxpolydegree))
X[:,<span style="color: #666666">0</span>] <span style="color: #666666">=</span> <span style="color: #666666">1.0</span>
estimated_mse_sklearn <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(Maxpolydegree)
polynomial <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(Maxpolydegree)
k <span style="color: #666666">=5</span>
kfold <span style="color: #666666">=</span> KFold(n_splits <span style="color: #666666">=</span> k)
<span style="color: #008000; font-weight: bold">for</span> polydegree <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(<span style="color: #666666">1</span>, Maxpolydegree):
polynomial[polydegree] <span style="color: #666666">=</span> polydegree
<span style="color: #008000; font-weight: bold">for</span> degree <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(polydegree):
X[:,degree] <span style="color: #666666">=</span> Density<span style="color: #666666">**</span>(degree<span style="color: #666666">/3.0</span>)
OLS <span style="color: #666666">=</span> LinearRegression()
<span style="color: #408080; font-style: italic"># loop over trials in order to estimate the expectation value of the MSE</span>
estimated_mse_folds <span style="color: #666666">=</span> cross_val_score(OLS, X, Energies, scoring<span style="color: #666666">=</span><span style="color: #BA2121">&#39;neg_mean_squared_error&#39;</span>, cv<span style="color: #666666">=</span>kfold)
<span style="color: #408080; font-style: italic">#[:, np.newaxis]</span>
estimated_mse_sklearn[polydegree] <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean(<span style="color: #666666">-</span>estimated_mse_folds)
plt<span style="color: #666666">.</span>plot(polynomial, np<span style="color: #666666">.</span>log10(estimated_mse_sklearn), label<span style="color: #666666">=</span><span style="color: #BA2121">&#39;Test Error&#39;</span>)
plt<span style="color: #666666">.</span>xlabel(<span style="color: #BA2121">&#39;Polynomial degree&#39;</span>)
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">&#39;log10[MSE]&#39;</span>)
plt<span style="color: #666666">.</span>legend()
plt<span style="color: #666666">.</span>show()
</pre></div>
<p>
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
<h2 id="cross-validation-with-ridge">Cross-validation with Ridge </h2>
<p>
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">matplotlib.pyplot</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">plt</span>
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> KFold
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">import</span> Ridge
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> cross_val_score
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">sklearn.preprocessing</span> <span style="color: #008000; font-weight: bold">import</span> PolynomialFeatures
<span style="color: #408080; font-style: italic"># A seed just to ensure that the random numbers are the same for every run.</span>
np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>seed(<span style="color: #666666">3155</span>)
<span style="color: #408080; font-style: italic"># Generate the data.</span>
n <span style="color: #666666">=</span> <span style="color: #666666">100</span>
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linspace(<span style="color: #666666">-3</span>, <span style="color: #666666">3</span>, n)<span style="color: #666666">.</span>reshape(<span style="color: #666666">-1</span>, <span style="color: #666666">1</span>)
y <span style="color: #666666">=</span> np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>x<span style="color: #666666">**2</span>) <span style="color: #666666">+</span> <span style="color: #666666">1.5</span> <span style="color: #666666">*</span> np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>(x<span style="color: #666666">-2</span>)<span style="color: #666666">**2</span>)<span style="color: #666666">+</span> np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>normal(<span style="color: #666666">0</span>, <span style="color: #666666">0.1</span>, x<span style="color: #666666">.</span>shape)
<span style="color: #408080; font-style: italic"># Decide degree on polynomial to fit</span>
poly <span style="color: #666666">=</span> PolynomialFeatures(degree <span style="color: #666666">=</span> <span style="color: #666666">10</span>)
<span style="color: #408080; font-style: italic"># Decide which values of lambda to use</span>
nlambdas <span style="color: #666666">=</span> <span style="color: #666666">500</span>
lambdas <span style="color: #666666">=</span> np<span style="color: #666666">.</span>logspace(<span style="color: #666666">-3</span>, <span style="color: #666666">5</span>, nlambdas)
<span style="color: #408080; font-style: italic"># Initialize a KFold instance</span>
k <span style="color: #666666">=</span> <span style="color: #666666">5</span>
kfold <span style="color: #666666">=</span> KFold(n_splits <span style="color: #666666">=</span> k)
estimated_mse_sklearn <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros(nlambdas)
i <span style="color: #666666">=</span> <span style="color: #666666">0</span>
<span style="color: #008000; font-weight: bold">for</span> lmb <span style="color: #AA22FF; font-weight: bold">in</span> lambdas:
ridge <span style="color: #666666">=</span> Ridge(alpha <span style="color: #666666">=</span> lmb)
estimated_mse_folds <span style="color: #666666">=</span> cross_val_score(ridge, x, y, scoring<span style="color: #666666">=</span><span style="color: #BA2121">&#39;neg_mean_squared_error&#39;</span>, cv<span style="color: #666666">=</span>kfold)
estimated_mse_sklearn[i] <span style="color: #666666">=</span> np<span style="color: #666666">.</span>mean(<span style="color: #666666">-</span>estimated_mse_folds)
i <span style="color: #666666">+=</span> <span style="color: #666666">1</span>
plt<span style="color: #666666">.</span>figure()
plt<span style="color: #666666">.</span>plot(np<span style="color: #666666">.</span>log10(lambdas), estimated_mse_sklearn, label <span style="color: #666666">=</span> <span style="color: #BA2121">&#39;cross_val_score&#39;</span>)
plt<span style="color: #666666">.</span>xlabel(<span style="color: #BA2121">&#39;log10(lambda)&#39;</span>)
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">&#39;MSE&#39;</span>)
plt<span style="color: #666666">.</span>legend()
plt<span style="color: #666666">.</span>show()
</pre></div>
<p>
<!-- ------------------- end of main content --------------- -->
<center style="font-size:80%">
<!-- copyright --> &copy; 1999-2021, Morten Hjorth-Jensen. Released under CC Attribution-NonCommercial 4.0 license
</center>
</body>
</html>