1674 lines
102 KiB
HTML
1674 lines
102 KiB
HTML
<!--
|
|
Automatically generated HTML file from DocOnce source
|
|
(https://github.com/hplgit/doconce/)
|
|
-->
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<meta name="generator" content="DocOnce: https://github.com/hplgit/doconce/" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="description" content="Week 35: Linear Regression and Review of Statistical Analysis and Probability Theory">
|
|
|
|
<title>Week 35: Linear Regression and Review of Statistical Analysis and Probability Theory</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/hplgit/doconce/master/bundled/html_images/small_gray_notice.png); }
|
|
.alert-summary { background-image:url(https://cdn.rawgit.com/hplgit/doconce/master/bundled/html_images/small_gray_summary.png); }
|
|
.alert-warning { background-image: url(https://cdn.rawgit.com/hplgit/doconce/master/bundled/html_images/small_gray_warning.png); }
|
|
.alert-question {background-image:url(https://cdn.rawgit.com/hplgit/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 35, August 24-28', 2, None, '___sec0'),
|
|
('Thursday August 27', 2, None, '___sec1'),
|
|
('Why Linear Regression (aka Ordinary Least Squares and family)',
|
|
2,
|
|
None,
|
|
'___sec2'),
|
|
('Regression analysis, overarching aims', 2, None, '___sec3'),
|
|
('Regression analysis, overarching aims II', 2, None, '___sec4'),
|
|
('Examples', 2, None, '___sec5'),
|
|
('General linear models', 2, None, '___sec6'),
|
|
('Rewriting the fitting procedure as a linear algebra problem',
|
|
2,
|
|
None,
|
|
'___sec7'),
|
|
('Rewriting the fitting procedure as a linear algebra problem, '
|
|
'more details',
|
|
2,
|
|
None,
|
|
'___sec8'),
|
|
('Generalizing the fitting procedure as a linear algebra problem',
|
|
2,
|
|
None,
|
|
'___sec9'),
|
|
('Generalizing the fitting procedure as a linear algebra problem',
|
|
2,
|
|
None,
|
|
'___sec10'),
|
|
('Optimizing our parameters', 2, None, '___sec11'),
|
|
('Our model for the nuclear binding energies',
|
|
2,
|
|
None,
|
|
'___sec12'),
|
|
('Optimizing our parameters, more details', 2, None, '___sec13'),
|
|
('Interpretations and optimizing our parameters',
|
|
2,
|
|
None,
|
|
'___sec14'),
|
|
('Interpretations and optimizing our parameters',
|
|
2,
|
|
None,
|
|
'___sec15'),
|
|
('Some useful matrix and vector expressions',
|
|
2,
|
|
None,
|
|
'___sec16'),
|
|
('Interpretations and optimizing our parameters',
|
|
2,
|
|
None,
|
|
'___sec17'),
|
|
('Own code for Ordinary Least Squares', 2, None, '___sec18'),
|
|
('Adding error analysis and training set up',
|
|
2,
|
|
None,
|
|
'___sec19'),
|
|
('The $\\chi^2$ function', 2, None, '___sec20'),
|
|
('The $\\chi^2$ function', 2, None, '___sec21'),
|
|
('The $\\chi^2$ function', 2, None, '___sec22'),
|
|
('The $\\chi^2$ function', 2, None, '___sec23'),
|
|
('The $\\chi^2$ function', 2, None, '___sec24'),
|
|
('The $\\chi^2$ function', 2, None, '___sec25'),
|
|
('Fitting an Equation of State for Dense Nuclear Matter',
|
|
2,
|
|
None,
|
|
'___sec26'),
|
|
('The code', 2, None, '___sec27'),
|
|
('Splitting our Data in Training and Test data',
|
|
2,
|
|
None,
|
|
'___sec28'),
|
|
('The Boston housing data example', 2, None, '___sec29'),
|
|
('Housing data, the code', 2, None, '___sec30'),
|
|
('Reducing the number of degrees of freedom, overarching view',
|
|
2,
|
|
None,
|
|
'___sec31'),
|
|
('Preprocessing our data', 2, None, '___sec32'),
|
|
('More preprocessing', 2, None, '___sec33'),
|
|
('Simple preprocessing examples, Franke function and regression',
|
|
2,
|
|
None,
|
|
'___sec34'),
|
|
('Friday August 28', 2, None, '___sec35')]}
|
|
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 35: Linear Regression and Review of Statistical Analysis and Probability Theory</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 16, 2020</h4></center> <!-- date -->
|
|
<br>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec0">Plans for week 35, August 24-28 </h2>
|
|
|
|
<ul>
|
|
<li> Thursday: Introduction to ordinary Least Squares and derivation of basic equation</li>
|
|
<li> Friday: Linear regression and statistical analysis and probability theory</li>
|
|
</ul>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec1">Thursday August 27 </h2>
|
|
|
|
<p>
|
|
<a href="https://www.uio.no/studier/emner/matnat/fys/FYS-STK4155/h20/forelesningsvideoer/LectureAug27.mp4?vrtx=view-as-webpage" target="_blank">Video of Lecture</a>.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec2">Why Linear Regression (aka Ordinary Least Squares and family) </h2>
|
|
|
|
<p>
|
|
Fitting a continuous function with linear parameterization in terms of the parameters \( \boldsymbol{\beta} \).
|
|
|
|
<ul>
|
|
<li> Method of choice for fitting a continuous function!</li>
|
|
<li> Gives an excellent introduction to central Machine Learning features with <b>understandable pedagogical</b> links to other methods like <b>Neural Networks</b>, <b>Support Vector Machines</b> etc</li>
|
|
<li> Analytical expression for the fitting parameters \( \boldsymbol{\beta} \)</li>
|
|
<li> Analytical expressions for statistical propertiers like mean values, variances, confidence intervals and more</li>
|
|
<li> Analytical relation with probabilistic interpretations</li>
|
|
<li> Easy to introduce basic concepts like bias-variance tradeoff, cross-validation, resampling and regularization techniques and many other ML topics</li>
|
|
<li> Easy to code! And links well with classification problems and logistic regression and neural networks</li>
|
|
<li> Allows for <b>easy</b> hands-on understanding of gradient descent methods</li>
|
|
<li> and many more features</li>
|
|
</ul>
|
|
|
|
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="___sec3">Regression analysis, overarching aims </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
Regression modeling deals with the description of the sampling distribution of a given random variable \( y \) and how it varies as function of another variable or a set of such variables \( \boldsymbol{x} =[x_0, x_1,\dots, x_{n-1}]^T \).
|
|
The first variable is called the <b>dependent</b>, the <b>outcome</b> or the <b>response</b> variable while the set of variables \( \boldsymbol{x} \) is called the independent variable, or the predictor variable or the explanatory variable.
|
|
|
|
<p>
|
|
A regression model aims at finding a likelihood function \( p(\boldsymbol{y}\vert \boldsymbol{x}) \), that is the conditional distribution for \( \boldsymbol{y} \) with a given \( \boldsymbol{x} \). The estimation of \( p(\boldsymbol{y}\vert \boldsymbol{x}) \) is made using a data set with
|
|
|
|
<ul>
|
|
<li> \( n \) cases \( i = 0, 1, 2, \dots, n-1 \)</li>
|
|
<li> Response (target, dependent or outcome) variable \( y_i \) with \( i = 0, 1, 2, \dots, n-1 \)</li>
|
|
<li> \( p \) so-called explanatory (independent or predictor) variables \( \boldsymbol{x}_i=[x_{i0}, x_{i1}, \dots, x_{ip-1}] \) with \( i = 0, 1, 2, \dots, n-1 \) and explanatory variables running from \( 0 \) to \( p-1 \). See below for more explicit examples.</li>
|
|
</ul>
|
|
|
|
The goal of the regression analysis is to extract/exploit relationship between \( \boldsymbol{y} \) and \( \boldsymbol{x} \) in or to infer causal dependencies, approximations to the likelihood functions, functional relationships and to make predictions, making fits and many other things.
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec4">Regression analysis, overarching aims II </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
Consider an experiment in which \( p \) characteristics of \( n \) samples are
|
|
measured. The data from this experiment, for various explanatory variables \( p \) are normally represented by a matrix
|
|
\( \mathbf{X} \).
|
|
|
|
<p>
|
|
The matrix \( \mathbf{X} \) is called the <em>design
|
|
matrix</em>. Additional information of the samples is available in the
|
|
form of \( \boldsymbol{y} \) (also as above). The variable \( \boldsymbol{y} \) is
|
|
generally referred to as the <em>response variable</em>. The aim of
|
|
regression analysis is to explain \( \boldsymbol{y} \) in terms of
|
|
\( \boldsymbol{X} \) through a functional relationship like \( y_i =
|
|
f(\mathbf{X}_{i,\ast}) \). When no prior knowledge on the form of
|
|
\( f(\cdot) \) is available, it is common to assume a linear relationship
|
|
between \( \boldsymbol{X} \) and \( \boldsymbol{y} \). This assumption gives rise to
|
|
the <em>linear regression model</em> where \( \boldsymbol{\beta} = [\beta_0, \ldots,
|
|
\beta_{p-1}]^{T} \) are the <em>regression parameters</em>.
|
|
|
|
<p>
|
|
Linear regression gives us a set of analytical equations for the parameters \( \beta_j \).
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec5">Examples </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
In order to understand the relation among the predictors \( p \), the set of data \( n \) and the target (outcome, output etc) \( \boldsymbol{y} \),
|
|
consider the model we discussed for describing nuclear binding energies.
|
|
|
|
<p>
|
|
There we assumed that we could parametrize the data using a polynomial approximation based on the liquid drop model.
|
|
Assuming
|
|
$$
|
|
BE(A) = a_0+a_1A+a_2A^{2/3}+a_3A^{-1/3}+a_4A^{-1},
|
|
$$
|
|
|
|
we have five predictors, that is the intercept, the \( A \) dependent term, the \( A^{2/3} \) term and the \( A^{-1/3} \) and \( A^{-1} \) terms.
|
|
This gives \( p=0,1,2,3,4 \). Furthermore we have \( n \) entries for each predictor. It means that our design matrix is a
|
|
\( p\times n \) matrix \( \boldsymbol{X} \).
|
|
|
|
<p>
|
|
Here the predictors are based on a model we have made. A popular data set which is widely encountered in ML applications is the
|
|
so-called <a href="https://www.sciencedirect.com/science/article/pii/S0957417407006719?via%3Dihub" target="_blank">credit card default data from Taiwan</a>. The data set contains data on \( n=30000 \) credit card holders with predictors like gender, marital status, age, profession, education, etc. In total there are \( 24 \) such predictors or attributes leading to a design matrix of dimensionality \( 24 \times 30000 \). This is however a classification problem and we will come back to it when we discuss Logistic Regression.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec6">General linear models </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
Before we proceed let us study a case from linear algebra where we aim at fitting a set of data \( \boldsymbol{y}=[y_0,y_1,\dots,y_{n-1}] \). We could think of these data as a result of an experiment or a complicated numerical experiment. These data are functions of a series of variables \( \boldsymbol{x}=[x_0,x_1,\dots,x_{n-1}] \), that is \( y_i = y(x_i) \) with \( i=0,1,2,\dots,n-1 \). The variables \( x_i \) could represent physical quantities like time, temperature, position etc. We assume that \( y(x) \) is a smooth function.
|
|
|
|
<p>
|
|
Since obtaining these data points may not be trivial, we want to use these data to fit a function which can allow us to make predictions for values of \( y \) which are not in the present set. The perhaps simplest approach is to assume we can parametrize our function in terms of a polynomial of degree \( n-1 \) with \( n \) points, that is
|
|
$$
|
|
y=y(x) \rightarrow y(x_i)=\tilde{y}_i+\epsilon_i=\sum_{j=0}^{n-1} \beta_j x_i^j+\epsilon_i,
|
|
$$
|
|
|
|
where \( \epsilon_i \) is the error in our approximation.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec7">Rewriting the fitting procedure as a linear algebra problem </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
For every set of values \( y_i,x_i \) we have thus the corresponding set of equations
|
|
$$
|
|
\begin{align*}
|
|
y_0&=\beta_0+\beta_1x_0^1+\beta_2x_0^2+\dots+\beta_{n-1}x_0^{n-1}+\epsilon_0\\
|
|
y_1&=\beta_0+\beta_1x_1^1+\beta_2x_1^2+\dots+\beta_{n-1}x_1^{n-1}+\epsilon_1\\
|
|
y_2&=\beta_0+\beta_1x_2^1+\beta_2x_2^2+\dots+\beta_{n-1}x_2^{n-1}+\epsilon_2\\
|
|
\dots & \dots \\
|
|
y_{n-1}&=\beta_0+\beta_1x_{n-1}^1+\beta_2x_{n-1}^2+\dots+\beta_{n-1}x_{n-1}^{n-1}+\epsilon_{n-1}.\\
|
|
\end{align*}
|
|
$$
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec8">Rewriting the fitting procedure as a linear algebra problem, more details </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
Defining the vectors
|
|
$$
|
|
\boldsymbol{y} = [y_0,y_1, y_2,\dots, y_{n-1}]^T,
|
|
$$
|
|
|
|
and
|
|
$$
|
|
\boldsymbol{\beta} = [\beta_0,\beta_1, \beta_2,\dots, \beta_{n-1}]^T,
|
|
$$
|
|
|
|
and
|
|
$$
|
|
\boldsymbol{\epsilon} = [\epsilon_0,\epsilon_1, \epsilon_2,\dots, \epsilon_{n-1}]^T,
|
|
$$
|
|
|
|
and the design matrix
|
|
$$
|
|
\boldsymbol{X}=
|
|
\begin{bmatrix}
|
|
1& x_{0}^1 &x_{0}^2& \dots & \dots &x_{0}^{n-1}\\
|
|
1& x_{1}^1 &x_{1}^2& \dots & \dots &x_{1}^{n-1}\\
|
|
1& x_{2}^1 &x_{2}^2& \dots & \dots &x_{2}^{n-1}\\
|
|
\dots& \dots &\dots& \dots & \dots &\dots\\
|
|
1& x_{n-1}^1 &x_{n-1}^2& \dots & \dots &x_{n-1}^{n-1}\\
|
|
\end{bmatrix}
|
|
$$
|
|
|
|
we can rewrite our equations as
|
|
$$
|
|
\boldsymbol{y} = \boldsymbol{X}\boldsymbol{\beta}+\boldsymbol{\epsilon}.
|
|
$$
|
|
|
|
The above design matrix is called a <a href="https://en.wikipedia.org/wiki/Vandermonde_matrix" target="_blank">Vandermonde matrix</a>.
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec9">Generalizing the fitting procedure as a linear algebra problem </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
We are obviously not limited to the above polynomial expansions. We
|
|
could replace the various powers of \( x \) with elements of Fourier
|
|
series or instead of \( x_i^j \) we could have \( \cos{(j x_i)} \) or \( \sin{(j
|
|
x_i)} \), or time series or other orthogonal functions. For every set
|
|
of values \( y_i,x_i \) we can then generalize the equations to
|
|
|
|
$$
|
|
\begin{align*}
|
|
y_0&=\beta_0x_{00}+\beta_1x_{01}+\beta_2x_{02}+\dots+\beta_{n-1}x_{0n-1}+\epsilon_0\\
|
|
y_1&=\beta_0x_{10}+\beta_1x_{11}+\beta_2x_{12}+\dots+\beta_{n-1}x_{1n-1}+\epsilon_1\\
|
|
y_2&=\beta_0x_{20}+\beta_1x_{21}+\beta_2x_{22}+\dots+\beta_{n-1}x_{2n-1}+\epsilon_2\\
|
|
\dots & \dots \\
|
|
y_{i}&=\beta_0x_{i0}+\beta_1x_{i1}+\beta_2x_{i2}+\dots+\beta_{n-1}x_{in-1}+\epsilon_i\\
|
|
\dots & \dots \\
|
|
y_{n-1}&=\beta_0x_{n-1,0}+\beta_1x_{n-1,2}+\beta_2x_{n-1,2}+\dots+\beta_{n-1}x_{n-1,n-1}+\epsilon_{n-1}.\\
|
|
\end{align*}
|
|
$$
|
|
|
|
<p>
|
|
<b>Note that we have \( p=n \) here. The matrix is symmetric. This is generally not the case!</b>
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec10">Generalizing the fitting procedure as a linear algebra problem </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
We redefine in turn the matrix \( \boldsymbol{X} \) as
|
|
$$
|
|
\boldsymbol{X}=
|
|
\begin{bmatrix}
|
|
x_{00}& x_{01} &x_{02}& \dots & \dots &x_{0,n-1}\\
|
|
x_{10}& x_{11} &x_{12}& \dots & \dots &x_{1,n-1}\\
|
|
x_{20}& x_{21} &x_{22}& \dots & \dots &x_{2,n-1}\\
|
|
\dots& \dots &\dots& \dots & \dots &\dots\\
|
|
x_{n-1,0}& x_{n-1,1} &x_{n-1,2}& \dots & \dots &x_{n-1,n-1}\\
|
|
\end{bmatrix}
|
|
$$
|
|
|
|
and without loss of generality we rewrite again our equations as
|
|
$$
|
|
\boldsymbol{y} = \boldsymbol{X}\boldsymbol{\beta}+\boldsymbol{\epsilon}.
|
|
$$
|
|
|
|
The left-hand side of this equation is kwown. Our error vector \( \boldsymbol{\epsilon} \) and the parameter vector \( \boldsymbol{\beta} \) are our unknow quantities. How can we obtain the optimal set of \( \beta_i \) values?
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec11">Optimizing our parameters </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
We have defined the matrix \( \boldsymbol{X} \) via the equations
|
|
$$
|
|
\begin{align*}
|
|
y_0&=\beta_0x_{00}+\beta_1x_{01}+\beta_2x_{02}+\dots+\beta_{n-1}x_{0n-1}+\epsilon_0\\
|
|
y_1&=\beta_0x_{10}+\beta_1x_{11}+\beta_2x_{12}+\dots+\beta_{n-1}x_{1n-1}+\epsilon_1\\
|
|
y_2&=\beta_0x_{20}+\beta_1x_{21}+\beta_2x_{22}+\dots+\beta_{n-1}x_{2n-1}+\epsilon_1\\
|
|
\dots & \dots \\
|
|
y_{i}&=\beta_0x_{i0}+\beta_1x_{i1}+\beta_2x_{i2}+\dots+\beta_{n-1}x_{in-1}+\epsilon_1\\
|
|
\dots & \dots \\
|
|
y_{n-1}&=\beta_0x_{n-1,0}+\beta_1x_{n-1,2}+\beta_2x_{n-1,2}+\dots+\beta_{n-1}x_{n-1,n-1}+\epsilon_{n-1}.\\
|
|
\end{align*}
|
|
$$
|
|
|
|
<p>
|
|
As we noted above, we stayed with a system with the design matrix
|
|
\( \boldsymbol{X}\in {\mathbb{R}}^{n\times n} \), that is we have \( p=n \). For reasons to come later (algorithmic arguments) we will hereafter define
|
|
our matrix as \( \boldsymbol{X}\in {\mathbb{R}}^{n\times p} \), with the predictors refering to the column numbers and the entries \( n \) being the row elements.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec12">Our model for the nuclear binding energies </h2>
|
|
|
|
<p>
|
|
In our <a href="https://compphysics.github.io/MachineLearning/doc/pub/How2ReadData/html/How2ReadData.html" target="_blank">introductory notes</a> we looked at the so-called <a href="https://en.wikipedia.org/wiki/Semi-empirical_mass_formula" target="_blank">liquid drop model</a>. Let us remind ourselves about what we did by looking at the code.
|
|
|
|
<p>
|
|
We restate the parts of the code we are most interested in.
|
|
<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">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">IPython.display</span> <span style="color: #008000; font-weight: bold">import</span> display
|
|
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">os</span>
|
|
|
|
<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">"Results"</span>
|
|
FIGURE_ID <span style="color: #666666">=</span> <span style="color: #BA2121">"Results/FigureFiles"</span>
|
|
DATA_ID <span style="color: #666666">=</span> <span style="color: #BA2121">"DataFiles/"</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">".png"</span>, format<span style="color: #666666">=</span><span style="color: #BA2121">'png'</span>)
|
|
|
|
infile <span style="color: #666666">=</span> <span style="color: #008000">open</span>(data_path(<span style="color: #BA2121">"MassEval2016.dat"</span>),<span style="color: #BA2121">'r'</span>)
|
|
|
|
|
|
<span style="color: #408080; font-style: italic"># Read the experimental data with Pandas</span>
|
|
Masses <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>read_fwf(infile, usecols<span style="color: #666666">=</span>(<span style="color: #666666">2</span>,<span style="color: #666666">3</span>,<span style="color: #666666">4</span>,<span style="color: #666666">6</span>,<span style="color: #666666">11</span>),
|
|
names<span style="color: #666666">=</span>(<span style="color: #BA2121">'N'</span>, <span style="color: #BA2121">'Z'</span>, <span style="color: #BA2121">'A'</span>, <span style="color: #BA2121">'Element'</span>, <span style="color: #BA2121">'Ebinding'</span>),
|
|
widths<span style="color: #666666">=</span>(<span style="color: #666666">1</span>,<span style="color: #666666">3</span>,<span style="color: #666666">5</span>,<span style="color: #666666">5</span>,<span style="color: #666666">5</span>,<span style="color: #666666">1</span>,<span style="color: #666666">3</span>,<span style="color: #666666">4</span>,<span style="color: #666666">1</span>,<span style="color: #666666">13</span>,<span style="color: #666666">11</span>,<span style="color: #666666">11</span>,<span style="color: #666666">9</span>,<span style="color: #666666">1</span>,<span style="color: #666666">2</span>,<span style="color: #666666">11</span>,<span style="color: #666666">9</span>,<span style="color: #666666">1</span>,<span style="color: #666666">3</span>,<span style="color: #666666">1</span>,<span style="color: #666666">12</span>,<span style="color: #666666">11</span>,<span style="color: #666666">1</span>),
|
|
header<span style="color: #666666">=39</span>,
|
|
index_col<span style="color: #666666">=</span><span style="color: #008000">False</span>)
|
|
|
|
<span style="color: #408080; font-style: italic"># Extrapolated values are indicated by '#' in place of the decimal place, so</span>
|
|
<span style="color: #408080; font-style: italic"># the Ebinding column won't be numeric. Coerce to float and drop these entries.</span>
|
|
Masses[<span style="color: #BA2121">'Ebinding'</span>] <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>to_numeric(Masses[<span style="color: #BA2121">'Ebinding'</span>], errors<span style="color: #666666">=</span><span style="color: #BA2121">'coerce'</span>)
|
|
Masses <span style="color: #666666">=</span> Masses<span style="color: #666666">.</span>dropna()
|
|
<span style="color: #408080; font-style: italic"># Convert from keV to MeV.</span>
|
|
Masses[<span style="color: #BA2121">'Ebinding'</span>] <span style="color: #666666">/=</span> <span style="color: #666666">1000</span>
|
|
|
|
<span style="color: #408080; font-style: italic"># Group the DataFrame by nucleon number, A.</span>
|
|
Masses <span style="color: #666666">=</span> Masses<span style="color: #666666">.</span>groupby(<span style="color: #BA2121">'A'</span>)
|
|
<span style="color: #408080; font-style: italic"># Find the rows of the grouped DataFrame with the maximum binding energy.</span>
|
|
Masses <span style="color: #666666">=</span> Masses<span style="color: #666666">.</span>apply(<span style="color: #008000; font-weight: bold">lambda</span> t: t[t<span style="color: #666666">.</span>Ebinding<span style="color: #666666">==</span>t<span style="color: #666666">.</span>Ebinding<span style="color: #666666">.</span>max()])
|
|
A <span style="color: #666666">=</span> Masses[<span style="color: #BA2121">'A'</span>]
|
|
Z <span style="color: #666666">=</span> Masses[<span style="color: #BA2121">'Z'</span>]
|
|
N <span style="color: #666666">=</span> Masses[<span style="color: #BA2121">'N'</span>]
|
|
Element <span style="color: #666666">=</span> Masses[<span style="color: #BA2121">'Element'</span>]
|
|
Energies <span style="color: #666666">=</span> Masses[<span style="color: #BA2121">'Ebinding'</span>]
|
|
|
|
<span style="color: #408080; font-style: italic"># Now we set up the design matrix X</span>
|
|
X <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros((<span style="color: #008000">len</span>(A),<span style="color: #666666">5</span>))
|
|
X[:,<span style="color: #666666">0</span>] <span style="color: #666666">=</span> <span style="color: #666666">1</span>
|
|
X[:,<span style="color: #666666">1</span>] <span style="color: #666666">=</span> A
|
|
X[:,<span style="color: #666666">2</span>] <span style="color: #666666">=</span> A<span style="color: #666666">**</span>(<span style="color: #666666">2.0/3.0</span>)
|
|
X[:,<span style="color: #666666">3</span>] <span style="color: #666666">=</span> A<span style="color: #666666">**</span>(<span style="color: #666666">-1.0/3.0</span>)
|
|
X[:,<span style="color: #666666">4</span>] <span style="color: #666666">=</span> A<span style="color: #666666">**</span>(<span style="color: #666666">-1.0</span>)
|
|
<span style="color: #408080; font-style: italic"># Then nice printout using pandas</span>
|
|
DesignMatrix <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>DataFrame(X)
|
|
DesignMatrix<span style="color: #666666">.</span>index <span style="color: #666666">=</span> A
|
|
DesignMatrix<span style="color: #666666">.</span>columns <span style="color: #666666">=</span> [<span style="color: #BA2121">'1'</span>, <span style="color: #BA2121">'A'</span>, <span style="color: #BA2121">'A^(2/3)'</span>, <span style="color: #BA2121">'A^(-1/3)'</span>, <span style="color: #BA2121">'1/A'</span>]
|
|
display(DesignMatrix)
|
|
</pre></div>
|
|
<p>
|
|
With \( \boldsymbol{\beta}\in {\mathbb{R}}^{p\times 1} \), it means that we will hereafter write our equations for the approximation as
|
|
$$
|
|
\boldsymbol{\tilde{y}}= \boldsymbol{X}\boldsymbol{\beta},
|
|
$$
|
|
|
|
throughout these lectures.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec13">Optimizing our parameters, more details </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
With the above we use the design matrix to define the approximation \( \boldsymbol{\tilde{y}} \) via the unknown quantity \( \boldsymbol{\beta} \) as
|
|
$$
|
|
\boldsymbol{\tilde{y}}= \boldsymbol{X}\boldsymbol{\beta},
|
|
$$
|
|
|
|
and in order to find the optimal parameters \( \beta_i \) instead of solving the above linear algebra problem, we define a function which gives a measure of the spread between the values \( y_i \) (which represent hopefully the exact values) and the parameterized values \( \tilde{y}_i \), namely
|
|
$$
|
|
C(\boldsymbol{\beta})=\frac{1}{n}\sum_{i=0}^{n-1}\left(y_i-\tilde{y}_i\right)^2=\frac{1}{n}\left\{\left(\boldsymbol{y}-\boldsymbol{\tilde{y}}\right)^T\left(\boldsymbol{y}-\boldsymbol{\tilde{y}}\right)\right\},
|
|
$$
|
|
|
|
or using the matrix \( \boldsymbol{X} \) and in a more compact matrix-vector notation as
|
|
$$
|
|
C(\boldsymbol{\beta})=\frac{1}{n}\left\{\left(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right)^T\left(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right)\right\}.
|
|
$$
|
|
|
|
This function is one possible way to define the so-called cost function.
|
|
|
|
<p>
|
|
It is also common to define
|
|
the function \( C \) as
|
|
|
|
$$
|
|
C(\boldsymbol{\beta})=\frac{1}{2n}\sum_{i=0}^{n-1}\left(y_i-\tilde{y}_i\right)^2,
|
|
$$
|
|
|
|
since when taking the first derivative with respect to the unknown parameters \( \beta \), the factor of \( 2 \) cancels out.
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec14">Interpretations and optimizing our parameters </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
The function
|
|
$$
|
|
C(\boldsymbol{\beta})=\frac{1}{n}\left\{\left(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right)^T\left(\boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right)\right\},
|
|
$$
|
|
|
|
can be linked to the variance of the quantity \( y_i \) if we interpret the latter as the mean value.
|
|
When linking (see the discussion below) with the maximum likelihood approach below, we will indeed interpret \( y_i \) as a mean value
|
|
$$
|
|
y_{i}=\langle y_i \rangle = \beta_0x_{i,0}+\beta_1x_{i,1}+\beta_2x_{i,2}+\dots+\beta_{n-1}x_{i,n-1}+\epsilon_i,
|
|
$$
|
|
|
|
<p>
|
|
where \( \langle y_i \rangle \) is the mean value. Keep in mind also that
|
|
till now we have treated \( y_i \) as the exact value. Normally, the
|
|
response (dependent or outcome) variable \( y_i \) the outcome of a
|
|
numerical experiment or another type of experiment and is thus only an
|
|
approximation to the true value. It is then always accompanied by an
|
|
error estimate, often limited to a statistical error estimate given by
|
|
the standard deviation discussed earlier. In the discussion here we
|
|
will treat \( y_i \) as our exact value for the response variable.
|
|
|
|
<p>
|
|
In order to find the parameters \( \beta_i \) we will then minimize the spread of \( C(\boldsymbol{\beta}) \), that is we are going to solve the problem
|
|
$$
|
|
{\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\}.
|
|
$$
|
|
|
|
In practical terms it means we will require
|
|
$$
|
|
\frac{\partial C(\boldsymbol{\beta})}{\partial \beta_j} = \frac{\partial }{\partial \beta_j}\left[ \frac{1}{n}\sum_{i=0}^{n-1}\left(y_i-\beta_0x_{i,0}-\beta_1x_{i,1}-\beta_2x_{i,2}-\dots-\beta_{n-1}x_{i,n-1}\right)^2\right]=0,
|
|
$$
|
|
|
|
which results in
|
|
$$
|
|
\frac{\partial C(\boldsymbol{\beta})}{\partial \beta_j} = -\frac{2}{n}\left[ \sum_{i=0}^{n-1}x_{ij}\left(y_i-\beta_0x_{i,0}-\beta_1x_{i,1}-\beta_2x_{i,2}-\dots-\beta_{n-1}x_{i,n-1}\right)\right]=0,
|
|
$$
|
|
|
|
or in a matrix-vector form as
|
|
$$
|
|
\frac{\partial C(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} = 0 = \boldsymbol{X}^T\left( \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right).
|
|
$$
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec15">Interpretations and optimizing our parameters </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
We can rewrite
|
|
$$
|
|
\frac{\partial C(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} = 0 = \boldsymbol{X}^T\left( \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right),
|
|
$$
|
|
|
|
as
|
|
$$
|
|
\boldsymbol{X}^T\boldsymbol{y} = \boldsymbol{X}^T\boldsymbol{X}\boldsymbol{\beta},
|
|
$$
|
|
|
|
and if the matrix \( \boldsymbol{X}^T\boldsymbol{X} \) is invertible we have the solution
|
|
$$
|
|
\boldsymbol{\beta} =\left(\boldsymbol{X}^T\boldsymbol{X}\right)^{-1}\boldsymbol{X}^T\boldsymbol{y}.
|
|
$$
|
|
|
|
<p>
|
|
We note also that since our design matrix is defined as \( \boldsymbol{X}\in
|
|
{\mathbb{R}}^{n\times p} \), the product \( \boldsymbol{X}^T\boldsymbol{X} \in
|
|
{\mathbb{R}}^{p\times p} \). In the above case we have that \( p \ll n \),
|
|
in our case \( p=5 \) meaning that we end up with inverting a small
|
|
\( 5\times 5 \) matrix. This is a rather common situation, in many cases we end up with low-dimensional
|
|
matrices to invert. The methods discussed here and for many other
|
|
supervised learning algorithms like classification with logistic
|
|
regression or support vector machines, exhibit dimensionalities which
|
|
allow for the usage of direct linear algebra methods such as <b>LU</b> decomposition or <b>Singular Value Decomposition</b> (SVD) for finding the inverse of the matrix
|
|
\( \boldsymbol{X}^T\boldsymbol{X} \).
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
<b>Small question</b>: Do you think the example we have at hand here (the nuclear binding energies) can lead to problems in inverting the matrix \( \boldsymbol{X}^T\boldsymbol{X} \)? What kind of problems can we expect?
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec16">Some useful matrix and vector expressions </h2>
|
|
|
|
<p>
|
|
The following matrix and vector relation will be useful here and for the rest of the course. Vectors are always written as boldfaced lower case letters and
|
|
matrices as upper case boldfaced letters.
|
|
|
|
$$
|
|
\frac{\partial (\boldsymbol{b}^T\boldsymbol{a})}{\partial \boldsymbol{a}} = \boldsymbol{b},
|
|
$$
|
|
|
|
$$
|
|
\frac{\partial (\boldsymbol{a}^T\boldsymbol{A}\boldsymbol{a})}{\partial \boldsymbol{a}} = (\boldsymbol{A}+\boldsymbol{A}^T)\boldsymbol{a},
|
|
$$
|
|
|
|
$$
|
|
\frac{\partial tr(\boldsymbol{B}\boldsymbol{A})}{\partial \boldsymbol{A}} = \boldsymbol{B}^T,
|
|
$$
|
|
|
|
$$
|
|
\frac{\partial \log{\vert\boldsymbol{A}\vert}}{\partial \boldsymbol{A}} = (\boldsymbol{A}^{-1})^T.
|
|
$$
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec17">Interpretations and optimizing our parameters </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
The residuals \( \boldsymbol{\epsilon} \) are in turn given by
|
|
$$
|
|
\boldsymbol{\epsilon} = \boldsymbol{y}-\boldsymbol{\tilde{y}} = \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta},
|
|
$$
|
|
|
|
and with
|
|
$$
|
|
\boldsymbol{X}^T\left( \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right)= 0,
|
|
$$
|
|
|
|
we have
|
|
$$
|
|
\boldsymbol{X}^T\boldsymbol{\epsilon}=\boldsymbol{X}^T\left( \boldsymbol{y}-\boldsymbol{X}\boldsymbol{\beta}\right)= 0,
|
|
$$
|
|
|
|
meaning that the solution for \( \boldsymbol{\beta} \) is the one which minimizes the residuals. Later we will link this with the maximum likelihood approach.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
Let us now return to our nuclear binding energies and simply code the above equations.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec18">Own code for Ordinary Least Squares </h2>
|
|
|
|
<p>
|
|
It is rather straightforward to implement the matrix inversion and obtain the parameters \( \boldsymbol{\beta} \). After having defined the matrix \( \boldsymbol{X} \) we simply need to
|
|
write
|
|
<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"># matrix inversion to find beta</span>
|
|
beta <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linalg<span style="color: #666666">.</span>inv(X<span style="color: #666666">.</span>T<span style="color: #666666">.</span>dot(X))<span style="color: #666666">.</span>dot(X<span style="color: #666666">.</span>T)<span style="color: #666666">.</span>dot(Energies)
|
|
<span style="color: #408080; font-style: italic"># and then make the prediction</span>
|
|
ytilde <span style="color: #666666">=</span> X @ beta
|
|
</pre></div>
|
|
<p>
|
|
Alternatively, you can use the least squares functionality in <b>Numpy</b> as
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>fit <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linalg<span style="color: #666666">.</span>lstsq(X, Energies, rcond <span style="color: #666666">=</span><span style="color: #008000">None</span>)[<span style="color: #666666">0</span>]
|
|
ytildenp <span style="color: #666666">=</span> np<span style="color: #666666">.</span>dot(fit,X<span style="color: #666666">.</span>T)
|
|
</pre></div>
|
|
<p>
|
|
And finally we plot our fit with and compare with data
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>Masses[<span style="color: #BA2121">'Eapprox'</span>] <span style="color: #666666">=</span> ytilde
|
|
<span style="color: #408080; font-style: italic"># Generate a plot comparing the experimental with the fitted values values.</span>
|
|
fig, ax <span style="color: #666666">=</span> plt<span style="color: #666666">.</span>subplots()
|
|
ax<span style="color: #666666">.</span>set_xlabel(<span style="color: #BA2121">r'$A = N + Z$'</span>)
|
|
ax<span style="color: #666666">.</span>set_ylabel(<span style="color: #BA2121">r'$E_\mathrm{bind}\,/\mathrm{MeV}$'</span>)
|
|
ax<span style="color: #666666">.</span>plot(Masses[<span style="color: #BA2121">'A'</span>], Masses[<span style="color: #BA2121">'Ebinding'</span>], alpha<span style="color: #666666">=0.7</span>, lw<span style="color: #666666">=2</span>,
|
|
label<span style="color: #666666">=</span><span style="color: #BA2121">'Ame2016'</span>)
|
|
ax<span style="color: #666666">.</span>plot(Masses[<span style="color: #BA2121">'A'</span>], Masses[<span style="color: #BA2121">'Eapprox'</span>], alpha<span style="color: #666666">=0.7</span>, lw<span style="color: #666666">=2</span>, c<span style="color: #666666">=</span><span style="color: #BA2121">'m'</span>,
|
|
label<span style="color: #666666">=</span><span style="color: #BA2121">'Fit'</span>)
|
|
ax<span style="color: #666666">.</span>legend()
|
|
save_fig(<span style="color: #BA2121">"Masses2016OLS"</span>)
|
|
plt<span style="color: #666666">.</span>show()
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec19">Adding error analysis and training set up </h2>
|
|
|
|
<p>
|
|
We can easily test our fit by computing the \( R2 \) score that we discussed in connection with the functionality of <b>Scikit-Learn</b> in the introductory slides.
|
|
Since we are not using <b>Scikit-Learn</b> here we can define our own \( R2 \) function as
|
|
<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">def</span> <span style="color: #0000FF">R2</span>(y_data, y_model):
|
|
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">1</span> <span style="color: #666666">-</span> np<span style="color: #666666">.</span>sum((y_data <span style="color: #666666">-</span> y_model) <span style="color: #666666">**</span> <span style="color: #666666">2</span>) <span style="color: #666666">/</span> np<span style="color: #666666">.</span>sum((y_data <span style="color: #666666">-</span> np<span style="color: #666666">.</span>mean(y_data)) <span style="color: #666666">**</span> <span style="color: #666666">2</span>)
|
|
</pre></div>
|
|
<p>
|
|
and we would be using it as
|
|
<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">print</span>(R2(Energies,ytilde))
|
|
</pre></div>
|
|
<p>
|
|
We can easily add our <b>MSE</b> score as
|
|
<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">def</span> <span style="color: #0000FF">MSE</span>(y_data,y_model):
|
|
n <span style="color: #666666">=</span> np<span style="color: #666666">.</span>size(y_model)
|
|
<span style="color: #008000; font-weight: bold">return</span> np<span style="color: #666666">.</span>sum((y_data<span style="color: #666666">-</span>y_model)<span style="color: #666666">**2</span>)<span style="color: #666666">/</span>n
|
|
|
|
<span style="color: #008000; font-weight: bold">print</span>(MSE(Energies,ytilde))
|
|
</pre></div>
|
|
<p>
|
|
and finally the relative error as
|
|
<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">def</span> <span style="color: #0000FF">RelativeError</span>(y_data,y_model):
|
|
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #008000">abs</span>((y_data<span style="color: #666666">-</span>y_model)<span style="color: #666666">/</span>y_data)
|
|
<span style="color: #008000; font-weight: bold">print</span>(RelativeError(Energies, ytilde))
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec20">The \( \chi^2 \) function </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
Normally, the response (dependent or outcome) variable \( y_i \) is the
|
|
outcome of a numerical experiment or another type of experiment and is
|
|
thus only an approximation to the true value. It is then always
|
|
accompanied by an error estimate, often limited to a statistical error
|
|
estimate given by the standard deviation discussed earlier. In the
|
|
discussion here we will treat \( y_i \) as our exact value for the
|
|
response variable.
|
|
|
|
<p>
|
|
Introducing the standard deviation \( \sigma_i \) for each measurement
|
|
\( y_i \), we define now the \( \chi^2 \) function (omitting the \( 1/n \) term)
|
|
as
|
|
|
|
$$
|
|
\chi^2(\boldsymbol{\beta})=\frac{1}{n}\sum_{i=0}^{n-1}\frac{\left(y_i-\tilde{y}_i\right)^2}{\sigma_i^2}=\frac{1}{n}\left\{\left(\boldsymbol{y}-\boldsymbol{\tilde{y}}\right)^T\frac{1}{\boldsymbol{\Sigma^2}}\left(\boldsymbol{y}-\boldsymbol{\tilde{y}}\right)\right\},
|
|
$$
|
|
|
|
where the matrix \( \boldsymbol{\Sigma} \) is a diagonal matrix with \( \sigma_i \) as matrix elements.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec21">The \( \chi^2 \) function </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
In order to find the parameters \( \beta_i \) we will then minimize the spread of \( \chi^2(\boldsymbol{\beta}) \) by requiring
|
|
$$
|
|
\frac{\partial \chi^2(\boldsymbol{\beta})}{\partial \beta_j} = \frac{\partial }{\partial \beta_j}\left[ \frac{1}{n}\sum_{i=0}^{n-1}\left(\frac{y_i-\beta_0x_{i,0}-\beta_1x_{i,1}-\beta_2x_{i,2}-\dots-\beta_{n-1}x_{i,n-1}}{\sigma_i}\right)^2\right]=0,
|
|
$$
|
|
|
|
which results in
|
|
$$
|
|
\frac{\partial \chi^2(\boldsymbol{\beta})}{\partial \beta_j} = -\frac{2}{n}\left[ \sum_{i=0}^{n-1}\frac{x_{ij}}{\sigma_i}\left(\frac{y_i-\beta_0x_{i,0}-\beta_1x_{i,1}-\beta_2x_{i,2}-\dots-\beta_{n-1}x_{i,n-1}}{\sigma_i}\right)\right]=0,
|
|
$$
|
|
|
|
or in a matrix-vector form as
|
|
$$
|
|
\frac{\partial \chi^2(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} = 0 = \boldsymbol{A}^T\left( \boldsymbol{b}-\boldsymbol{A}\boldsymbol{\beta}\right).
|
|
$$
|
|
|
|
where we have defined the matrix \( \boldsymbol{A} =\boldsymbol{X}/\boldsymbol{\Sigma} \) with matrix elements \( a_{ij} = x_{ij}/\sigma_i \) and the vector \( \boldsymbol{b} \) with elements \( b_i = y_i/\sigma_i \).
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec22">The \( \chi^2 \) function </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
We can rewrite
|
|
$$
|
|
\frac{\partial \chi^2(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} = 0 = \boldsymbol{A}^T\left( \boldsymbol{b}-\boldsymbol{A}\boldsymbol{\beta}\right),
|
|
$$
|
|
|
|
as
|
|
$$
|
|
\boldsymbol{A}^T\boldsymbol{b} = \boldsymbol{A}^T\boldsymbol{A}\boldsymbol{\beta},
|
|
$$
|
|
|
|
and if the matrix \( \boldsymbol{A}^T\boldsymbol{A} \) is invertible we have the solution
|
|
$$
|
|
\boldsymbol{\beta} =\left(\boldsymbol{A}^T\boldsymbol{A}\right)^{-1}\boldsymbol{A}^T\boldsymbol{b}.
|
|
$$
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec23">The \( \chi^2 \) function </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
If we then introduce the matrix
|
|
$$
|
|
\boldsymbol{H} = \left(\boldsymbol{A}^T\boldsymbol{A}\right)^{-1},
|
|
$$
|
|
|
|
we have then the following expression for the parameters \( \beta_j \) (the matrix elements of \( \boldsymbol{H} \) are \( h_{ij} \))
|
|
$$
|
|
\beta_j = \sum_{k=0}^{p-1}h_{jk}\sum_{i=0}^{n-1}\frac{y_i}{\sigma_i}\frac{x_{ik}}{\sigma_i} = \sum_{k=0}^{p-1}h_{jk}\sum_{i=0}^{n-1}b_ia_{ik}
|
|
$$
|
|
|
|
We state without proof the expression for the uncertainty in the parameters \( \beta_j \) as (we leave this as an exercise)
|
|
$$
|
|
\sigma^2(\beta_j) = \sum_{i=0}^{n-1}\sigma_i^2\left( \frac{\partial \beta_j}{\partial y_i}\right)^2,
|
|
$$
|
|
|
|
resulting in
|
|
$$
|
|
\sigma^2(\beta_j) = \left(\sum_{k=0}^{p-1}h_{jk}\sum_{i=0}^{n-1}a_{ik}\right)\left(\sum_{l=0}^{p-1}h_{jl}\sum_{m=0}^{n-1}a_{ml}\right) = h_{jj}!
|
|
$$
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec24">The \( \chi^2 \) function </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
The first step here is to approximate the function \( y \) with a first-order polynomial, that is we write
|
|
$$
|
|
y=y(x) \rightarrow y(x_i) \approx \beta_0+\beta_1 x_i.
|
|
$$
|
|
|
|
By computing the derivatives of \( \chi^2 \) with respect to \( \beta_0 \) and \( \beta_1 \) show that these are given by
|
|
$$
|
|
\frac{\partial \chi^2(\boldsymbol{\beta})}{\partial \beta_0} = -2\left[ \frac{1}{n}\sum_{i=0}^{n-1}\left(\frac{y_i-\beta_0-\beta_1x_{i}}{\sigma_i^2}\right)\right]=0,
|
|
$$
|
|
|
|
and
|
|
$$
|
|
\frac{\partial \chi^2(\boldsymbol{\beta})}{\partial \beta_1} = -\frac{2}{n}\left[ \sum_{i=0}^{n-1}x_i\left(\frac{y_i-\beta_0-\beta_1x_{i}}{\sigma_i^2}\right)\right]=0.
|
|
$$
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec25">The \( \chi^2 \) function </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
For a linear fit (a first-order polynomial) we don't need to invert a matrix!!
|
|
Defining
|
|
$$
|
|
\gamma = \sum_{i=0}^{n-1}\frac{1}{\sigma_i^2},
|
|
$$
|
|
|
|
|
|
$$
|
|
\gamma_x = \sum_{i=0}^{n-1}\frac{x_{i}}{\sigma_i^2},
|
|
$$
|
|
|
|
|
|
$$
|
|
\gamma_y = \sum_{i=0}^{n-1}\left(\frac{y_i}{\sigma_i^2}\right),
|
|
$$
|
|
|
|
|
|
$$
|
|
\gamma_{xx} = \sum_{i=0}^{n-1}\frac{x_ix_{i}}{\sigma_i^2},
|
|
$$
|
|
|
|
|
|
$$
|
|
\gamma_{xy} = \sum_{i=0}^{n-1}\frac{y_ix_{i}}{\sigma_i^2},
|
|
$$
|
|
|
|
<p>
|
|
we obtain
|
|
|
|
$$
|
|
\beta_0 = \frac{\gamma_{xx}\gamma_y-\gamma_x\gamma_y}{\gamma\gamma_{xx}-\gamma_x^2},
|
|
$$
|
|
|
|
|
|
$$
|
|
\beta_1 = \frac{\gamma_{xy}\gamma-\gamma_x\gamma_y}{\gamma\gamma_{xx}-\gamma_x^2}.
|
|
$$
|
|
|
|
<p>
|
|
This approach (different linear and non-linear regression) suffers
|
|
often from both being underdetermined and overdetermined in the
|
|
unknown coefficients \( \beta_i \). A better approach is to use the
|
|
Singular Value Decomposition (SVD) method discussed below. Or using
|
|
Lasso and Ridge regression. See below.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec26">Fitting an Equation of State for Dense Nuclear Matter </h2>
|
|
|
|
<p>
|
|
Before we continue, let us introduce yet another example. We are going to fit the
|
|
nuclear equation of state using results from many-body calculations.
|
|
The equation of state we have made available here, as function of
|
|
density, has been derived using modern nucleon-nucleon potentials with
|
|
<a href="https://www.sciencedirect.com/science/article/pii/S0370157399001106" target="_blank">the addition of three-body
|
|
forces</a>. This
|
|
time the file is presented as a standard <b>csv</b> file.
|
|
|
|
<p>
|
|
The beginning of the Python code here is similar to what you have seen
|
|
before, with the same initializations and declarations. We use also
|
|
<b>pandas</b> again, rather extensively in order to organize our data.
|
|
|
|
<p>
|
|
The difference now is that we use <b>Scikit-Learn's</b> regression tools
|
|
instead of our own matrix inversion implementation. Furthermore, we
|
|
sneak in <b>Ridge</b> regression (to be discussed below) which includes a
|
|
hyperparameter \( \lambda \), also to be explained below.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec27">The code </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">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">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">skl</span>
|
|
<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, r2_score, mean_absolute_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">"Results"</span>
|
|
FIGURE_ID <span style="color: #666666">=</span> <span style="color: #BA2121">"Results/FigureFiles"</span>
|
|
DATA_ID <span style="color: #666666">=</span> <span style="color: #BA2121">"DataFiles/"</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">".png"</span>, format<span style="color: #666666">=</span><span style="color: #BA2121">'png'</span>)
|
|
|
|
infile <span style="color: #666666">=</span> <span style="color: #008000">open</span>(data_path(<span style="color: #BA2121">"EoS.csv"</span>),<span style="color: #BA2121">'r'</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">'Density'</span>, <span style="color: #BA2121">'Energy'</span>))
|
|
EoS[<span style="color: #BA2121">'Energy'</span>] <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>to_numeric(EoS[<span style="color: #BA2121">'Energy'</span>], errors<span style="color: #666666">=</span><span style="color: #BA2121">'coerce'</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">'Energy'</span>]
|
|
Density <span style="color: #666666">=</span> EoS[<span style="color: #BA2121">'Density'</span>]
|
|
<span style="color: #408080; font-style: italic"># The design matrix now as function of various polytrops</span>
|
|
X <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros((<span style="color: #008000">len</span>(Density),<span style="color: #666666">4</span>))
|
|
X[:,<span style="color: #666666">3</span>] <span style="color: #666666">=</span> Density<span style="color: #666666">**</span>(<span style="color: #666666">4.0/3.0</span>)
|
|
X[:,<span style="color: #666666">2</span>] <span style="color: #666666">=</span> Density
|
|
X[:,<span style="color: #666666">1</span>] <span style="color: #666666">=</span> Density<span style="color: #666666">**</span>(<span style="color: #666666">2.0/3.0</span>)
|
|
X[:,<span style="color: #666666">0</span>] <span style="color: #666666">=</span> <span style="color: #666666">1</span>
|
|
|
|
<span style="color: #408080; font-style: italic"># We use now Scikit-Learn's linear regressor and ridge regressor</span>
|
|
<span style="color: #408080; font-style: italic"># OLS part</span>
|
|
clf <span style="color: #666666">=</span> skl<span style="color: #666666">.</span>LinearRegression()<span style="color: #666666">.</span>fit(X, Energies)
|
|
ytilde <span style="color: #666666">=</span> clf<span style="color: #666666">.</span>predict(X)
|
|
EoS[<span style="color: #BA2121">'Eols'</span>] <span style="color: #666666">=</span> ytilde
|
|
<span style="color: #408080; font-style: italic"># The mean squared error </span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Mean squared error: </span><span style="color: #BB6688; font-weight: bold">%.2f</span><span style="color: #BA2121">"</span> <span style="color: #666666">%</span> mean_squared_error(Energies, ytilde))
|
|
<span style="color: #408080; font-style: italic"># Explained variance score: 1 is perfect prediction </span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Variance score: </span><span style="color: #BB6688; font-weight: bold">%.2f</span><span style="color: #BA2121">'</span> <span style="color: #666666">%</span> r2_score(Energies, ytilde))
|
|
<span style="color: #408080; font-style: italic"># Mean absolute error </span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Mean absolute error: </span><span style="color: #BB6688; font-weight: bold">%.2f</span><span style="color: #BA2121">'</span> <span style="color: #666666">%</span> mean_absolute_error(Energies, ytilde))
|
|
<span style="color: #008000; font-weight: bold">print</span>(clf<span style="color: #666666">.</span>coef_, clf<span style="color: #666666">.</span>intercept_)
|
|
|
|
<span style="color: #408080; font-style: italic"># The Ridge regression with a hyperparameter lambda = 0.1</span>
|
|
_lambda <span style="color: #666666">=</span> <span style="color: #666666">0.1</span>
|
|
clf_ridge <span style="color: #666666">=</span> skl<span style="color: #666666">.</span>Ridge(alpha<span style="color: #666666">=</span>_lambda)<span style="color: #666666">.</span>fit(X, Energies)
|
|
yridge <span style="color: #666666">=</span> clf_ridge<span style="color: #666666">.</span>predict(X)
|
|
EoS[<span style="color: #BA2121">'Eridge'</span>] <span style="color: #666666">=</span> yridge
|
|
<span style="color: #408080; font-style: italic"># The mean squared error </span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Mean squared error: </span><span style="color: #BB6688; font-weight: bold">%.2f</span><span style="color: #BA2121">"</span> <span style="color: #666666">%</span> mean_squared_error(Energies, yridge))
|
|
<span style="color: #408080; font-style: italic"># Explained variance score: 1 is perfect prediction </span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Variance score: </span><span style="color: #BB6688; font-weight: bold">%.2f</span><span style="color: #BA2121">'</span> <span style="color: #666666">%</span> r2_score(Energies, yridge))
|
|
<span style="color: #408080; font-style: italic"># Mean absolute error </span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Mean absolute error: </span><span style="color: #BB6688; font-weight: bold">%.2f</span><span style="color: #BA2121">'</span> <span style="color: #666666">%</span> mean_absolute_error(Energies, yridge))
|
|
<span style="color: #008000; font-weight: bold">print</span>(clf_ridge<span style="color: #666666">.</span>coef_, clf_ridge<span style="color: #666666">.</span>intercept_)
|
|
|
|
fig, ax <span style="color: #666666">=</span> plt<span style="color: #666666">.</span>subplots()
|
|
ax<span style="color: #666666">.</span>set_xlabel(<span style="color: #BA2121">r'$\rho[\mathrm{fm}^{-3}]$'</span>)
|
|
ax<span style="color: #666666">.</span>set_ylabel(<span style="color: #BA2121">r'Energy per particle'</span>)
|
|
ax<span style="color: #666666">.</span>plot(EoS[<span style="color: #BA2121">'Density'</span>], EoS[<span style="color: #BA2121">'Energy'</span>], alpha<span style="color: #666666">=0.7</span>, lw<span style="color: #666666">=2</span>,
|
|
label<span style="color: #666666">=</span><span style="color: #BA2121">'Theoretical data'</span>)
|
|
ax<span style="color: #666666">.</span>plot(EoS[<span style="color: #BA2121">'Density'</span>], EoS[<span style="color: #BA2121">'Eols'</span>], alpha<span style="color: #666666">=0.7</span>, lw<span style="color: #666666">=2</span>, c<span style="color: #666666">=</span><span style="color: #BA2121">'m'</span>,
|
|
label<span style="color: #666666">=</span><span style="color: #BA2121">'OLS'</span>)
|
|
ax<span style="color: #666666">.</span>plot(EoS[<span style="color: #BA2121">'Density'</span>], EoS[<span style="color: #BA2121">'Eridge'</span>], alpha<span style="color: #666666">=0.7</span>, lw<span style="color: #666666">=2</span>, c<span style="color: #666666">=</span><span style="color: #BA2121">'g'</span>,
|
|
label<span style="color: #666666">=</span><span style="color: #BA2121">'Ridge $\lambda = 0.1$'</span>)
|
|
ax<span style="color: #666666">.</span>legend()
|
|
save_fig(<span style="color: #BA2121">"EoSfitting"</span>)
|
|
plt<span style="color: #666666">.</span>show()
|
|
</pre></div>
|
|
<p>
|
|
The above simple polynomial in density \( \rho \) gives an excellent fit
|
|
to the data.
|
|
|
|
<p>
|
|
We note also that there is a small deviation between the
|
|
standard OLS and the Ridge regression at higher densities. We discuss this in more detail
|
|
below.
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec28">Splitting our Data in Training and Test data </h2>
|
|
|
|
<p>
|
|
It is normal in essentially all Machine Learning studies to split the
|
|
data in a training set and a test set (sometimes also an additional
|
|
validation set). <b>Scikit-Learn</b> has an own function for this. There
|
|
is no explicit recipe for how much data should be included as training
|
|
data and say test data. An accepted rule of thumb is to use
|
|
approximately \( 2/3 \) to \( 4/5 \) of the data as training data. We will
|
|
postpone a discussion of this splitting to the end of these notes and
|
|
our discussion of the so-called <b>bias-variance</b> tradeoff. Here we
|
|
limit ourselves to repeat the above equation of state fitting example
|
|
but now splitting the data into a training set and a test set.
|
|
|
|
<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">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.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> train_test_split
|
|
<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">"Results"</span>
|
|
FIGURE_ID <span style="color: #666666">=</span> <span style="color: #BA2121">"Results/FigureFiles"</span>
|
|
DATA_ID <span style="color: #666666">=</span> <span style="color: #BA2121">"DataFiles/"</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">".png"</span>, format<span style="color: #666666">=</span><span style="color: #BA2121">'png'</span>)
|
|
|
|
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">R2</span>(y_data, y_model):
|
|
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">1</span> <span style="color: #666666">-</span> np<span style="color: #666666">.</span>sum((y_data <span style="color: #666666">-</span> y_model) <span style="color: #666666">**</span> <span style="color: #666666">2</span>) <span style="color: #666666">/</span> np<span style="color: #666666">.</span>sum((y_data <span style="color: #666666">-</span> np<span style="color: #666666">.</span>mean(y_data)) <span style="color: #666666">**</span> <span style="color: #666666">2</span>)
|
|
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">MSE</span>(y_data,y_model):
|
|
n <span style="color: #666666">=</span> np<span style="color: #666666">.</span>size(y_model)
|
|
<span style="color: #008000; font-weight: bold">return</span> np<span style="color: #666666">.</span>sum((y_data<span style="color: #666666">-</span>y_model)<span style="color: #666666">**2</span>)<span style="color: #666666">/</span>n
|
|
|
|
infile <span style="color: #666666">=</span> <span style="color: #008000">open</span>(data_path(<span style="color: #BA2121">"EoS.csv"</span>),<span style="color: #BA2121">'r'</span>)
|
|
|
|
<span style="color: #408080; font-style: italic"># Read the EoS data as csv file and organized 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">'Density'</span>, <span style="color: #BA2121">'Energy'</span>))
|
|
EoS[<span style="color: #BA2121">'Energy'</span>] <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>to_numeric(EoS[<span style="color: #BA2121">'Energy'</span>], errors<span style="color: #666666">=</span><span style="color: #BA2121">'coerce'</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">'Energy'</span>]
|
|
Density <span style="color: #666666">=</span> EoS[<span style="color: #BA2121">'Density'</span>]
|
|
<span style="color: #408080; font-style: italic"># The design matrix now as function of various polytrops</span>
|
|
X <span style="color: #666666">=</span> np<span style="color: #666666">.</span>zeros((<span style="color: #008000">len</span>(Density),<span style="color: #666666">5</span>))
|
|
X[:,<span style="color: #666666">0</span>] <span style="color: #666666">=</span> <span style="color: #666666">1</span>
|
|
X[:,<span style="color: #666666">1</span>] <span style="color: #666666">=</span> Density<span style="color: #666666">**</span>(<span style="color: #666666">2.0/3.0</span>)
|
|
X[:,<span style="color: #666666">2</span>] <span style="color: #666666">=</span> Density
|
|
X[:,<span style="color: #666666">3</span>] <span style="color: #666666">=</span> Density<span style="color: #666666">**</span>(<span style="color: #666666">4.0/3.0</span>)
|
|
X[:,<span style="color: #666666">4</span>] <span style="color: #666666">=</span> Density<span style="color: #666666">**</span>(<span style="color: #666666">5.0/3.0</span>)
|
|
<span style="color: #408080; font-style: italic"># We split the data in test and training data</span>
|
|
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>)
|
|
<span style="color: #408080; font-style: italic"># matrix inversion to find beta</span>
|
|
beta <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linalg<span style="color: #666666">.</span>inv(X_train<span style="color: #666666">.</span>T<span style="color: #666666">.</span>dot(X_train))<span style="color: #666666">.</span>dot(X_train<span style="color: #666666">.</span>T)<span style="color: #666666">.</span>dot(y_train)
|
|
<span style="color: #408080; font-style: italic"># and then make the prediction</span>
|
|
ytilde <span style="color: #666666">=</span> X_train @ beta
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Training R2"</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(R2(y_train,ytilde))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Training MSE"</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(MSE(y_train,ytilde))
|
|
ypredict <span style="color: #666666">=</span> X_test @ beta
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Test R2"</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(R2(y_test,ypredict))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Test MSE"</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(MSE(y_test,ypredict))
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split -->
|
|
|
|
<h2 id="___sec29">The Boston housing data example </h2>
|
|
|
|
<p>
|
|
The Boston housing
|
|
data set was originally a part of UCI Machine Learning Repository
|
|
and has been removed now. The data set is now included in <b>Scikit-Learn</b>'s
|
|
library. There are 506 samples and 13 feature (predictor) variables
|
|
in this data set. The objective is to predict the value of prices of
|
|
the house using the features (predictors) listed here.
|
|
|
|
<p>
|
|
The features/predictors are
|
|
|
|
<ol>
|
|
<li> CRIM: Per capita crime rate by town</li>
|
|
<li> ZN: Proportion of residential land zoned for lots over 25000 square feet</li>
|
|
<li> INDUS: Proportion of non-retail business acres per town</li>
|
|
<li> CHAS: Charles River dummy variable (= 1 if tract bounds river; 0 otherwise)</li>
|
|
<li> NOX: Nitric oxide concentration (parts per 10 million)</li>
|
|
<li> RM: Average number of rooms per dwelling</li>
|
|
<li> AGE: Proportion of owner-occupied units built prior to 1940</li>
|
|
<li> DIS: Weighted distances to five Boston employment centers</li>
|
|
<li> RAD: Index of accessibility to radial highways</li>
|
|
<li> TAX: Full-value property tax rate per USD10000</li>
|
|
<li> B: \( 1000(Bk - 0.63)^2 \), where \( Bk \) is the proportion of [people of African American descent] by town</li>
|
|
<li> LSTAT: Percentage of lower status of the population</li>
|
|
<li> MEDV: Median value of owner-occupied homes in USD 1000s</li>
|
|
</ol>
|
|
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec30">Housing data, the code </h2>
|
|
We start by importing the libraries
|
|
<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">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">seaborn</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">sns</span>
|
|
</pre></div>
|
|
<p>
|
|
and load the Boston Housing DataSet from <b>Scikit-Learn</b>
|
|
|
|
<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">sklearn.datasets</span> <span style="color: #008000; font-weight: bold">import</span> load_boston
|
|
|
|
boston_dataset <span style="color: #666666">=</span> load_boston()
|
|
|
|
<span style="color: #408080; font-style: italic"># boston_dataset is a dictionary</span>
|
|
<span style="color: #408080; font-style: italic"># let's check what it contains</span>
|
|
boston_dataset<span style="color: #666666">.</span>keys()
|
|
</pre></div>
|
|
<p>
|
|
Then we invoke Pandas
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>boston <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>DataFrame(boston_dataset<span style="color: #666666">.</span>data, columns<span style="color: #666666">=</span>boston_dataset<span style="color: #666666">.</span>feature_names)
|
|
boston<span style="color: #666666">.</span>head()
|
|
boston[<span style="color: #BA2121">'MEDV'</span>] <span style="color: #666666">=</span> boston_dataset<span style="color: #666666">.</span>target
|
|
</pre></div>
|
|
<p>
|
|
and preprocess the data
|
|
<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"># check for missing values in all the columns</span>
|
|
boston<span style="color: #666666">.</span>isnull()<span style="color: #666666">.</span>sum()
|
|
</pre></div>
|
|
<p>
|
|
We can then visualize the data
|
|
<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"># set the size of the figure</span>
|
|
sns<span style="color: #666666">.</span>set(rc<span style="color: #666666">=</span>{<span style="color: #BA2121">'figure.figsize'</span>:(<span style="color: #666666">11.7</span>,<span style="color: #666666">8.27</span>)})
|
|
|
|
<span style="color: #408080; font-style: italic"># plot a histogram showing the distribution of the target values</span>
|
|
sns<span style="color: #666666">.</span>distplot(boston[<span style="color: #BA2121">'MEDV'</span>], bins<span style="color: #666666">=30</span>)
|
|
plt<span style="color: #666666">.</span>show()
|
|
</pre></div>
|
|
<p>
|
|
It is now useful to look at the correlation matrix
|
|
<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"># compute the pair wise correlation for all columns </span>
|
|
correlation_matrix <span style="color: #666666">=</span> boston<span style="color: #666666">.</span>corr()<span style="color: #666666">.</span>round(<span style="color: #666666">2</span>)
|
|
<span style="color: #408080; font-style: italic"># use the heatmap function from seaborn to plot the correlation matrix</span>
|
|
<span style="color: #408080; font-style: italic"># annot = True to print the values inside the square</span>
|
|
sns<span style="color: #666666">.</span>heatmap(data<span style="color: #666666">=</span>correlation_matrix, annot<span style="color: #666666">=</span><span style="color: #008000">True</span>)
|
|
</pre></div>
|
|
<p>
|
|
From the above coorelation plot we can see that <b>MEDV</b> is strongly correlated to <b>LSTAT</b> and <b>RM</b>. We see also that <b>RAD</b> and <b>TAX</b> are stronly correlated, but we don't include this in our features together to avoid multi-colinearity
|
|
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>plt<span style="color: #666666">.</span>figure(figsize<span style="color: #666666">=</span>(<span style="color: #666666">20</span>, <span style="color: #666666">5</span>))
|
|
|
|
features <span style="color: #666666">=</span> [<span style="color: #BA2121">'LSTAT'</span>, <span style="color: #BA2121">'RM'</span>]
|
|
target <span style="color: #666666">=</span> boston[<span style="color: #BA2121">'MEDV'</span>]
|
|
|
|
<span style="color: #008000; font-weight: bold">for</span> i, col <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">enumerate</span>(features):
|
|
plt<span style="color: #666666">.</span>subplot(<span style="color: #666666">1</span>, <span style="color: #008000">len</span>(features) , i<span style="color: #666666">+1</span>)
|
|
x <span style="color: #666666">=</span> boston[col]
|
|
y <span style="color: #666666">=</span> target
|
|
plt<span style="color: #666666">.</span>scatter(x, y, marker<span style="color: #666666">=</span><span style="color: #BA2121">'o'</span>)
|
|
plt<span style="color: #666666">.</span>title(col)
|
|
plt<span style="color: #666666">.</span>xlabel(col)
|
|
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">'MEDV'</span>)
|
|
</pre></div>
|
|
<p>
|
|
Now we start training our model
|
|
<p>
|
|
|
|
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
|
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>X <span style="color: #666666">=</span> pd<span style="color: #666666">.</span>DataFrame(np<span style="color: #666666">.</span>c_[boston[<span style="color: #BA2121">'LSTAT'</span>], boston[<span style="color: #BA2121">'RM'</span>]], columns <span style="color: #666666">=</span> [<span style="color: #BA2121">'LSTAT'</span>,<span style="color: #BA2121">'RM'</span>])
|
|
Y <span style="color: #666666">=</span> boston[<span style="color: #BA2121">'MEDV'</span>]
|
|
</pre></div>
|
|
<p>
|
|
We split the data into training and test sets
|
|
|
|
<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">sklearn.model_selection</span> <span style="color: #008000; font-weight: bold">import</span> train_test_split
|
|
|
|
<span style="color: #408080; font-style: italic"># splits the training and test data set in 80% : 20%</span>
|
|
<span style="color: #408080; font-style: italic"># assign random_state to any value.This ensures consistency.</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">=</span> <span style="color: #666666">0.2</span>, random_state<span style="color: #666666">=5</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(X_train<span style="color: #666666">.</span>shape)
|
|
<span style="color: #008000; font-weight: bold">print</span>(X_test<span style="color: #666666">.</span>shape)
|
|
<span style="color: #008000; font-weight: bold">print</span>(Y_train<span style="color: #666666">.</span>shape)
|
|
<span style="color: #008000; font-weight: bold">print</span>(Y_test<span style="color: #666666">.</span>shape)
|
|
</pre></div>
|
|
<p>
|
|
Then we use the linear regression functionality from <b>Scikit-Learn</b>
|
|
<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">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.metrics</span> <span style="color: #008000; font-weight: bold">import</span> mean_squared_error, r2_score
|
|
|
|
lin_model <span style="color: #666666">=</span> LinearRegression()
|
|
lin_model<span style="color: #666666">.</span>fit(X_train, Y_train)
|
|
|
|
<span style="color: #408080; font-style: italic"># model evaluation for training set</span>
|
|
|
|
y_train_predict <span style="color: #666666">=</span> lin_model<span style="color: #666666">.</span>predict(X_train)
|
|
rmse <span style="color: #666666">=</span> (np<span style="color: #666666">.</span>sqrt(mean_squared_error(Y_train, y_train_predict)))
|
|
r2 <span style="color: #666666">=</span> r2_score(Y_train, y_train_predict)
|
|
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"The model performance for training set"</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"--------------------------------------"</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'RMSE is {}'</span><span style="color: #666666">.</span>format(rmse))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'R2 score is {}'</span><span style="color: #666666">.</span>format(r2))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121">"</span>)
|
|
|
|
<span style="color: #408080; font-style: italic"># model evaluation for testing set</span>
|
|
|
|
y_test_predict <span style="color: #666666">=</span> lin_model<span style="color: #666666">.</span>predict(X_test)
|
|
<span style="color: #408080; font-style: italic"># root mean square error of the model</span>
|
|
rmse <span style="color: #666666">=</span> (np<span style="color: #666666">.</span>sqrt(mean_squared_error(Y_test, y_test_predict)))
|
|
|
|
<span style="color: #408080; font-style: italic"># r-squared score of the model</span>
|
|
r2 <span style="color: #666666">=</span> r2_score(Y_test, y_test_predict)
|
|
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"The model performance for testing set"</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"--------------------------------------"</span>)
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'RMSE is {}'</span><span style="color: #666666">.</span>format(rmse))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'R2 score is {}'</span><span style="color: #666666">.</span>format(r2))
|
|
</pre></div>
|
|
<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"># plotting the y_test vs y_pred</span>
|
|
<span style="color: #408080; font-style: italic"># ideally should have been a straight line</span>
|
|
plt<span style="color: #666666">.</span>scatter(Y_test, y_test_predict)
|
|
plt<span style="color: #666666">.</span>show()
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec31">Reducing the number of degrees of freedom, overarching view </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
Many Machine Learning problems involve thousands or even millions of
|
|
features for each training instance. Not only does this make training
|
|
extremely slow, it can also make it much harder to find a good
|
|
solution, as we will see. This problem is often referred to as the
|
|
curse of dimensionality. Fortunately, in real-world problems, it is
|
|
often possible to reduce the number of features considerably, turning
|
|
an intractable problem into a tractable one.
|
|
|
|
<p>
|
|
Later we will discuss some of the most popular dimensionality reduction
|
|
techniques: the principal component analysis (PCA), Kernel PCA, and
|
|
Locally Linear Embedding (LLE).
|
|
|
|
<p>
|
|
Principal component analysis and its various variants deal with the
|
|
problem of fitting a low-dimensional <a href="https://en.wikipedia.org/wiki/Affine_space" target="_blank">affine
|
|
subspace</a> to a set of of
|
|
data points in a high-dimensional space. With its family of methods it
|
|
is one of the most used tools in data modeling, compression and
|
|
visualization.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec32">Preprocessing our data </h2>
|
|
<div class="alert alert-block alert-block alert-text-normal">
|
|
<b></b>
|
|
<p>
|
|
|
|
<p>
|
|
Before we proceed however, we will discuss how to preprocess our
|
|
data. Till now and in connection with our previous examples we have
|
|
not met so many cases where we are too sensitive to the scaling of our
|
|
data. Normally the data may need a rescaling and/or may be sensitive
|
|
to extreme values. Scaling the data renders our inputs much more
|
|
suitable for the algorithms we want to employ.
|
|
|
|
<p>
|
|
<b>Scikit-Learn</b> has several functions which allow us to rescale the
|
|
data, normally resulting in much better results in terms of various
|
|
accuracy scores. The <b>StandardScaler</b> function in <b>Scikit-Learn</b>
|
|
ensures that for each feature/predictor we study the mean value is
|
|
zero and the variance is one (every column in the design/feature
|
|
matrix). This scaling has the drawback that it does not ensure that
|
|
we have a particular maximum or minimum in our data set. Another
|
|
function included in <b>Scikit-Learn</b> is the <b>MinMaxScaler</b> which
|
|
ensures that all features are exactly between \( 0 \) and \( 1 \). The
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec33">More preprocessing </h2>
|
|
|
|
<p>
|
|
The <b>Normalizer</b> scales each data
|
|
point such that the feature vector has a euclidean length of one. In other words, it
|
|
projects a data point on the circle (or sphere in the case of higher dimensions) with a
|
|
radius of 1. This means every data point is scaled by a different number (by the
|
|
inverse of it’s length).
|
|
This normalization is often used when only the direction (or angle) of the data matters,
|
|
not the length of the feature vector.
|
|
|
|
<p>
|
|
The <b>RobustScaler</b> works similarly to the StandardScaler in that it
|
|
ensures statistical properties for each feature that guarantee that
|
|
they are on the same scale. However, the RobustScaler uses the median
|
|
and quartiles, instead of mean and variance. This makes the
|
|
RobustScaler ignore data points that are very different from the rest
|
|
(like measurement errors). These odd data points are also called
|
|
outliers, and might often lead to trouble for other scaling
|
|
techniques.
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec34">Simple preprocessing examples, Franke function and regression </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">import</span> <span style="color: #0000FF; font-weight: bold">sklearn.linear_model</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">skl</span>
|
|
<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> train_test_split
|
|
<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> MinMaxScaler, StandardScaler, Normalizer
|
|
|
|
<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">"Results"</span>
|
|
FIGURE_ID <span style="color: #666666">=</span> <span style="color: #BA2121">"Results/FigureFiles"</span>
|
|
DATA_ID <span style="color: #666666">=</span> <span style="color: #BA2121">"DataFiles/"</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">".png"</span>, format<span style="color: #666666">=</span><span style="color: #BA2121">'png'</span>)
|
|
|
|
|
|
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">FrankeFunction</span>(x,y):
|
|
term1 <span style="color: #666666">=</span> <span style="color: #666666">0.75*</span>np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>(<span style="color: #666666">0.25*</span>(<span style="color: #666666">9*</span>x<span style="color: #666666">-2</span>)<span style="color: #666666">**2</span>) <span style="color: #666666">-</span> <span style="color: #666666">0.25*</span>((<span style="color: #666666">9*</span>y<span style="color: #666666">-2</span>)<span style="color: #666666">**2</span>))
|
|
term2 <span style="color: #666666">=</span> <span style="color: #666666">0.75*</span>np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>((<span style="color: #666666">9*</span>x<span style="color: #666666">+1</span>)<span style="color: #666666">**2</span>)<span style="color: #666666">/49.0</span> <span style="color: #666666">-</span> <span style="color: #666666">0.1*</span>(<span style="color: #666666">9*</span>y<span style="color: #666666">+1</span>))
|
|
term3 <span style="color: #666666">=</span> <span style="color: #666666">0.5*</span>np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>(<span style="color: #666666">9*</span>x<span style="color: #666666">-7</span>)<span style="color: #666666">**2/4.0</span> <span style="color: #666666">-</span> <span style="color: #666666">0.25*</span>((<span style="color: #666666">9*</span>y<span style="color: #666666">-3</span>)<span style="color: #666666">**2</span>))
|
|
term4 <span style="color: #666666">=</span> <span style="color: #666666">-0.2*</span>np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>(<span style="color: #666666">9*</span>x<span style="color: #666666">-4</span>)<span style="color: #666666">**2</span> <span style="color: #666666">-</span> (<span style="color: #666666">9*</span>y<span style="color: #666666">-7</span>)<span style="color: #666666">**2</span>)
|
|
<span style="color: #008000; font-weight: bold">return</span> term1 <span style="color: #666666">+</span> term2 <span style="color: #666666">+</span> term3 <span style="color: #666666">+</span> term4
|
|
|
|
|
|
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">create_X</span>(x, y, n ):
|
|
<span style="color: #008000; font-weight: bold">if</span> <span style="color: #008000">len</span>(x<span style="color: #666666">.</span>shape) <span style="color: #666666">></span> <span style="color: #666666">1</span>:
|
|
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>ravel(x)
|
|
y <span style="color: #666666">=</span> np<span style="color: #666666">.</span>ravel(y)
|
|
|
|
N <span style="color: #666666">=</span> <span style="color: #008000">len</span>(x)
|
|
l <span style="color: #666666">=</span> <span style="color: #008000">int</span>((n<span style="color: #666666">+1</span>)<span style="color: #666666">*</span>(n<span style="color: #666666">+2</span>)<span style="color: #666666">/2</span>) <span style="color: #408080; font-style: italic"># Number of elements in beta</span>
|
|
X <span style="color: #666666">=</span> np<span style="color: #666666">.</span>ones((N,l))
|
|
|
|
<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: #666666">1</span>,n<span style="color: #666666">+1</span>):
|
|
q <span style="color: #666666">=</span> <span style="color: #008000">int</span>((i)<span style="color: #666666">*</span>(i<span style="color: #666666">+1</span>)<span style="color: #666666">/2</span>)
|
|
<span style="color: #008000; font-weight: bold">for</span> k <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(i<span style="color: #666666">+1</span>):
|
|
X[:,q<span style="color: #666666">+</span>k] <span style="color: #666666">=</span> (x<span style="color: #666666">**</span>(i<span style="color: #666666">-</span>k))<span style="color: #666666">*</span>(y<span style="color: #666666">**</span>k)
|
|
|
|
<span style="color: #008000; font-weight: bold">return</span> X
|
|
|
|
|
|
<span style="color: #408080; font-style: italic"># Making meshgrid of datapoints and compute Franke's function</span>
|
|
n <span style="color: #666666">=</span> <span style="color: #666666">5</span>
|
|
N <span style="color: #666666">=</span> <span style="color: #666666">1000</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>uniform(<span style="color: #666666">0</span>, <span style="color: #666666">1</span>, N))
|
|
y <span style="color: #666666">=</span> np<span style="color: #666666">.</span>sort(np<span style="color: #666666">.</span>random<span style="color: #666666">.</span>uniform(<span style="color: #666666">0</span>, <span style="color: #666666">1</span>, N))
|
|
z <span style="color: #666666">=</span> FrankeFunction(x, y)
|
|
X <span style="color: #666666">=</span> create_X(x, y, n<span style="color: #666666">=</span>n)
|
|
<span style="color: #408080; font-style: italic"># split in training and test data</span>
|
|
X_train, X_test, y_train, y_test <span style="color: #666666">=</span> train_test_split(X,z,test_size<span style="color: #666666">=0.2</span>)
|
|
|
|
|
|
clf <span style="color: #666666">=</span> skl<span style="color: #666666">.</span>LinearRegression()<span style="color: #666666">.</span>fit(X_train, y_train)
|
|
|
|
<span style="color: #408080; font-style: italic"># The mean squared error and R2 score</span>
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"MSE before scaling: {:.2f}"</span><span style="color: #666666">.</span>format(mean_squared_error(clf<span style="color: #666666">.</span>predict(X_test), y_test)))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"R2 score before scaling {:.2f}"</span><span style="color: #666666">.</span>format(clf<span style="color: #666666">.</span>score(X_test,y_test)))
|
|
|
|
scaler <span style="color: #666666">=</span> StandardScaler()
|
|
scaler<span style="color: #666666">.</span>fit(X_train)
|
|
X_train_scaled <span style="color: #666666">=</span> scaler<span style="color: #666666">.</span>transform(X_train)
|
|
X_test_scaled <span style="color: #666666">=</span> scaler<span style="color: #666666">.</span>transform(X_test)
|
|
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Feature min values before scaling:</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121"> {}"</span><span style="color: #666666">.</span>format(X_train<span style="color: #666666">.</span>min(axis<span style="color: #666666">=0</span>)))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Feature max values before scaling:</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121"> {}"</span><span style="color: #666666">.</span>format(X_train<span style="color: #666666">.</span>max(axis<span style="color: #666666">=0</span>)))
|
|
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Feature min values after scaling:</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121"> {}"</span><span style="color: #666666">.</span>format(X_train_scaled<span style="color: #666666">.</span>min(axis<span style="color: #666666">=0</span>)))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"Feature max values after scaling:</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BA2121"> {}"</span><span style="color: #666666">.</span>format(X_train_scaled<span style="color: #666666">.</span>max(axis<span style="color: #666666">=0</span>)))
|
|
|
|
clf <span style="color: #666666">=</span> skl<span style="color: #666666">.</span>LinearRegression()<span style="color: #666666">.</span>fit(X_train_scaled, y_train)
|
|
|
|
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"MSE after scaling: {:.2f}"</span><span style="color: #666666">.</span>format(mean_squared_error(clf<span style="color: #666666">.</span>predict(X_test_scaled), y_test)))
|
|
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">"R2 score for scaled data: {:.2f}"</span><span style="color: #666666">.</span>format(clf<span style="color: #666666">.</span>score(X_test_scaled,y_test)))
|
|
</pre></div>
|
|
<p>
|
|
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
|
|
|
<h2 id="___sec35">Friday August 28 </h2>
|
|
|
|
<p>
|
|
<a href="https://www.uio.no/studier/emner/matnat/fys/FYS-STK4155/h20/forelesningsvideoer/LectureAug28.mp4?vrtx=view-as-webpage" target="_blank">Video of Lecture</a> and <a href="https://github.com/CompPhysics/MachineLearning/blob/master/doc/HandWrittenNotes/NotesAugust28.pdf" target="_blank">handwritten notes</a>
|
|
|
|
<p>
|
|
More material will be added here, see handwritten notes also.
|
|
|
|
<p>
|
|
|
|
<!-- ------------------- end of main content --------------- -->
|
|
|
|
|
|
<center style="font-size:80%">
|
|
<!-- copyright --> © 1999-2020, Morten Hjorth-Jensen. Released under CC Attribution-NonCommercial 4.0 license
|
|
</center>
|
|
|
|
|
|
</body>
|
|
</html>
|
|
|
|
|