fix w37 math formatting

This commit is contained in:
KarlHenrik
2025-09-10 12:20:55 +02:00
parent fbdf9c32f8
commit 057865dcbf
7 changed files with 163 additions and 144 deletions
Binary file not shown.
@@ -9,7 +9,7 @@
"source": [
"<!-- HTML file automatically generated from DocOnce source (https://github.com/doconce/doconce/)\n",
"doconce format html exercisesweek37.do.txt -->\n",
"<!-- dom:TITLE: Exercises week 37 -->"
"<!-- dom:TITLE: Exercises week 37 -->\n"
]
},
{
@@ -20,9 +20,10 @@
},
"source": [
"# Exercises week 37\n",
"\n",
"**Implementing gradient descent for Ridge and ordinary Least Squares Regression**\n",
"\n",
"Date: **September 8-12, 2025**"
"Date: **September 8-12, 2025**\n"
]
},
{
@@ -35,13 +36,14 @@
"## Learning goals\n",
"\n",
"After having completed these exercises you will have:\n",
"\n",
"1. Your own code for the implementation of the simplest gradient descent approach applied to ordinary least squares (OLS) and Ridge regression\n",
"\n",
"2. Be able to compare the analytical expressions for OLS and Ridge regression with the gradient descent approach\n",
"\n",
"3. Explore the role of the learning rate in the gradient descent approach and the hyperparameter $\\lambda$ in Ridge regression\n",
"\n",
"4. Scale the data properly"
"4. Scale the data properly\n"
]
},
{
@@ -53,7 +55,7 @@
"source": [
"## Simple one-dimensional second-order polynomial\n",
"\n",
"We start with a very simple function"
"We start with a very simple function\n"
]
},
{
@@ -65,7 +67,7 @@
"source": [
"$$\n",
"f(x)= 2-x+5x^2,\n",
"$$"
"$$\n"
]
},
{
@@ -75,10 +77,10 @@
"editable": true
},
"source": [
"defined for $x\\in [-2,2]$. You can add noise if you wish. \n",
"defined for $x\\in [-2,2]$. You can add noise if you wish.\n",
"\n",
"We are going to fit this function with a polynomial ansatz. The easiest thing is to set up a second-order polynomial and see if you can fit the above function.\n",
"Feel free to play around with higher-order polynomials."
"Feel free to play around with higher-order polynomials.\n"
]
},
{
@@ -94,7 +96,7 @@
"standardize the features. This ensures all features are on a\n",
"comparable scale, which is especially important when using\n",
"regularization. Here we will perform standardization, scaling each\n",
"feature to have mean 0 and standard deviation 1."
"feature to have mean 0 and standard deviation 1.\n"
]
},
{
@@ -114,7 +116,7 @@
"term, the data is shifted such that the intercept is effectively 0\n",
". (In practice, one could include an intercept in the model and not\n",
"penalize it, but here we simplify by centering.)\n",
"Choose $n=100$ data points and set up $\\boldsymbol{x}, $\\boldsymbol{y}$ and the design matrix $\\boldsymbol{X}$."
"Choose $n=100$ data points and set up $\\boldsymbol{x}$, $\\boldsymbol{y}$ and the design matrix $\\boldsymbol{X}$.\n"
]
},
{
@@ -145,13 +147,13 @@
"editable": true
},
"source": [
"Fill in the necessary details. Do we need to center the $y$-values? \n",
"Fill in the necessary details. Do we need to center the $y$-values?\n",
"\n",
"After this preprocessing, each column of $\\boldsymbol{X}_{\\mathrm{norm}}$ has mean zero and standard deviation $1$\n",
"and $\\boldsymbol{y}_{\\mathrm{centered}}$ has mean 0. This makes the optimization landscape\n",
"nicer and ensures the regularization penalty $\\lambda \\sum_j\n",
"\\theta_j^2$ in Ridge regression treats each coefficient fairly (since features are on the\n",
"same scale)."
"same scale).\n"
]
},
{
@@ -163,7 +165,7 @@
"source": [
"## Exercise 2, calculate the gradients\n",
"\n",
"Find the gradients for OLS and Ridge regression using the mean-squared error as cost/loss function."
"Find the gradients for OLS and Ridge regression using the mean-squared error as cost/loss function.\n"
]
},
{
@@ -173,7 +175,7 @@
"editable": true
},
"source": [
"## Exercise 3, using the analytical formulae for OLS and Ridge regression to find the optimal paramters $\\boldsymbol{\\theta}$"
"## Exercise 3, using the analytical formulae for OLS and Ridge regression to find the optimal paramters $\\boldsymbol{\\theta}$\n"
]
},
{
@@ -210,8 +212,8 @@
"This computes the Ridge and OLS regression coefficients directly. The identity\n",
"matrix $I$ has the same size as $X^T X$. It adds $\\lambda$ to the diagonal of $X^T X$ for Ridge regression. We\n",
"then invert this matrix and multiply by $X^T y$. The result\n",
"for $\\boldsymbol{\\theta}$ is a NumPy array of shape (n$\\_$features,) containing the\n",
"fitted parameters $\\boldsymbol{\\theta}$."
"for $\\boldsymbol{\\theta}$ is a NumPy array of shape (n$\\_$features,) containing the\n",
"fitted parameters $\\boldsymbol{\\theta}$.\n"
]
},
{
@@ -223,7 +225,7 @@
"source": [
"### 3a)\n",
"\n",
"Finalize, in the above code, the OLS and Ridge regression determination of the optimal parameters $\\boldsymbol{\\theta}$."
"Finalize, in the above code, the OLS and Ridge regression determination of the optimal parameters $\\boldsymbol{\\theta}$.\n"
]
},
{
@@ -235,7 +237,7 @@
"source": [
"### 3b)\n",
"\n",
"Explore the results as function of different values of the hyperparameter $\\lambda$. See for example exercise 4 from week 36."
"Explore the results as function of different values of the hyperparameter $\\lambda$. See for example exercise 4 from week 36.\n"
]
},
{
@@ -252,9 +254,9 @@
"necessary if $n$ and $p$ are so large that the closed-form might be\n",
"too slow or memory-intensive. We derive the gradients from the cost\n",
"functions defined above. Use the gradients of the Ridge and OLS cost functions with respect to\n",
"the parameters $\\boldsymbol{\\theta}$ and set up (using the template below) your own gradient descent code for OLS and Ridge regression.\n",
"the parameters $\\boldsymbol{\\theta}$ and set up (using the template below) your own gradient descent code for OLS and Ridge regression.\n",
"\n",
"Below is a template code for gradient descent implementation of ridge:"
"Below is a template code for gradient descent implementation of ridge:\n"
]
},
{
@@ -301,7 +303,7 @@
"### 4a)\n",
"\n",
"Write first a gradient descent code for OLS only using the above template.\n",
"Discuss the results as function of the learning rate parameters and the number of iterations"
"Discuss the results as function of the learning rate parameters and the number of iterations\n"
]
},
{
@@ -314,7 +316,7 @@
"### 4b)\n",
"\n",
"Write then a similar code for Ridge regression using the above template.\n",
"Try to add a stopping parameter as function of the number iterations and the difference between the new and old $\\theta$ values. How would you define a stopping criterion?"
"Try to add a stopping parameter as function of the number iterations and the difference between the new and old $\\theta$ values. How would you define a stopping criterion?\n"
]
},
{
@@ -339,12 +341,12 @@
"Then we sample feature values for $\\boldsymbol{X}$ randomly (e.g. from a normal distribution). We use a normal distribution so features are roughly centered around 0.\n",
"Then we compute the target values $y$ using the linear combination $\\boldsymbol{X}\\hat{\\boldsymbol{\\theta}}$ and add some noise (to simulate measurement error or unexplained variance).\n",
"\n",
"Below is the code to generate the dataset:"
"Below is the code to generate the dataset:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"id": "8be1cebe",
"metadata": {
"collapsed": false,
@@ -368,7 +370,7 @@
"X = np.random.randn(n_samples, n_features) # standard normal distribution\n",
"\n",
"# Generate target values y with a linear combination of X and theta_true, plus noise\n",
"noise = 0.5 * np.random.randn(n_samples) # Gaussian noise\n",
"noise = 0.5 * np.random.randn(n_samples) # Gaussian noise\n",
"y = X.dot @ theta_true + noise"
]
},
@@ -383,7 +385,7 @@
"significantly influence $\\boldsymbol{y}$. The rest of the features have zero true\n",
"coefficient. For example, feature 0 has\n",
"a true weight of 5.0, feature 1 has -3.0, and feature 6 has 2.0, so\n",
"the expected relationship is:"
"the expected relationship is:\n"
]
},
{
@@ -395,7 +397,7 @@
"source": [
"$$\n",
"y \\approx 5 \\times x_0 \\;-\\; 3 \\times x_1 \\;+\\; 2 \\times x_6 \\;+\\; \\text{noise}.\n",
"$$"
"$$\n"
]
},
{
@@ -405,7 +407,7 @@
"editable": true
},
"source": [
"You can remove the noise if you wish to. \n",
"You can remove the noise if you wish to.\n",
"\n",
"Try to fit the above data set using OLS and Ridge regression with the analytical expressions and your own gradient descent codes.\n",
"\n",
@@ -413,11 +415,15 @@
"close to the true values [5.0, -3.0, 0.0, …, 2.0, …] that we used to\n",
"generate the data. Keep in mind that due to regularization and noise,\n",
"the learned values will not exactly equal the true ones, but they\n",
"should be in the same ballpark. Which method (OLS or Ridge) gives the best results?"
"should be in the same ballpark. Which method (OLS or Ridge) gives the best results?\n"
]
}
],
"metadata": {},
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
@@ -416,7 +416,8 @@ document.write(`
<!-- HTML file automatically generated from DocOnce source (https://github.com/doconce/doconce/)
doconce format html exercisesweek37.do.txt -->
<!-- dom:TITLE: Exercises week 37 --><section class="tex2jax_ignore mathjax_ignore" id="exercises-week-37">
<!-- dom:TITLE: Exercises week 37 -->
<section class="tex2jax_ignore mathjax_ignore" id="exercises-week-37">
<h1>Exercises week 37<a class="headerlink" href="#exercises-week-37" title="Link to this heading">#</a></h1>
<p><strong>Implementing gradient descent for Ridge and ordinary Least Squares Regression</strong></p>
<p>Date: <strong>September 8-12, 2025</strong></p>
@@ -457,18 +458,18 @@ Subtract the mean and divide by the standard deviation for each feature.</p>
term, the data is shifted such that the intercept is effectively 0
. (In practice, one could include an intercept in the model and not
penalize it, but here we simplify by centering.)
Choose <span class="math notranslate nohighlight">\(n=100\)</span> data points and set up <span class="math notranslate nohighlight">\(\boldsymbol{x}, \)</span>\boldsymbol{y}<span class="math notranslate nohighlight">\( and the design matrix \)</span>\boldsymbol{X}$.</p>
Choose <span class="math notranslate nohighlight">\(n=100\)</span> data points and set up <span class="math notranslate nohighlight">\(\boldsymbol{x}\)</span>, <span class="math notranslate nohighlight">\(\boldsymbol{y}\)</span> and the design matrix <span class="math notranslate nohighlight">\(\boldsymbol{X}\)</span>.</p>
<div class="cell docutils container">
<div class="cell_input docutils container">
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># Standardize features (zero mean, unit variance for each feature)
X_mean = X.mean(axis=0)
X_std = X.std(axis=0)
X_std[X_std == 0] = 1 # safeguard to avoid division by zero for constant features
X_norm = (X - X_mean) / X_std
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Standardize features (zero mean, unit variance for each feature)</span>
<span class="n">X_mean</span> <span class="o">=</span> <span class="n">X</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="n">X_std</span> <span class="o">=</span> <span class="n">X</span><span class="o">.</span><span class="n">std</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="n">X_std</span><span class="p">[</span><span class="n">X_std</span> <span class="o">==</span> <span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># safeguard to avoid division by zero for constant features</span>
<span class="n">X_norm</span> <span class="o">=</span> <span class="p">(</span><span class="n">X</span> <span class="o">-</span> <span class="n">X_mean</span><span class="p">)</span> <span class="o">/</span> <span class="n">X_std</span>
# Center the target to zero mean (optional, to simplify intercept handling)
y_mean = ?
y_centered = ?
<span class="c1"># Center the target to zero mean (optional, to simplify intercept handling)</span>
<span class="n">y_mean</span> <span class="o">=</span> <span class="err">?</span>
<span class="n">y_centered</span> <span class="o">=</span> <span class="err">?</span>
</pre></div>
</div>
</div>
@@ -489,18 +490,18 @@ same scale).</p>
<h2>Exercise 3, using the analytical formulae for OLS and Ridge regression to find the optimal paramters <span class="math notranslate nohighlight">\(\boldsymbol{\theta}\)</span><a class="headerlink" href="#exercise-3-using-the-analytical-formulae-for-ols-and-ridge-regression-to-find-the-optimal-paramters-boldsymbol-theta" title="Link to this heading">#</a></h2>
<div class="cell docutils container">
<div class="cell_input docutils container">
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># Set regularization parameter, either a single value or a vector of values
# Note that lambda is a python keyword. The lambda keyword is used to create small, single-expression functions without a formal name. These are often called &quot;anonymous functions&quot; or &quot;lambda functions.&quot;
lam = ?
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Set regularization parameter, either a single value or a vector of values</span>
<span class="c1"># Note that lambda is a python keyword. The lambda keyword is used to create small, single-expression functions without a formal name. These are often called &quot;anonymous functions&quot; or &quot;lambda functions.&quot;</span>
<span class="n">lam</span> <span class="o">=</span> <span class="err">?</span>
# Analytical form for OLS and Ridge solution: theta_Ridge = (X^T X + lambda * I)^{-1} X^T y and theta_OLS = (X^T X)^{-1} X^T y
I = np.eye(n_features)
theta_closed_formRidge = ?
theta_closed_formOLS = ?
<span class="c1"># Analytical form for OLS and Ridge solution: theta_Ridge = (X^T X + lambda * I)^{-1} X^T y and theta_OLS = (X^T X)^{-1} X^T y</span>
<span class="n">I</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">eye</span><span class="p">(</span><span class="n">n_features</span><span class="p">)</span>
<span class="n">theta_closed_formRidge</span> <span class="o">=</span> <span class="err">?</span>
<span class="n">theta_closed_formOLS</span> <span class="o">=</span> <span class="err">?</span>
print(&quot;Closed-form Ridge coefficients:&quot;, theta_closed_form)
print(&quot;Closed-form OLS coefficients:&quot;, theta_closed_form)
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Closed-form Ridge coefficients:&quot;</span><span class="p">,</span> <span class="n">theta_closed_form</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Closed-form OLS coefficients:&quot;</span><span class="p">,</span> <span class="n">theta_closed_form</span><span class="p">)</span>
</pre></div>
</div>
</div>
@@ -508,7 +509,7 @@ print(&quot;Closed-form OLS coefficients:&quot;, theta_closed_form)
<p>This computes the Ridge and OLS regression coefficients directly. The identity
matrix <span class="math notranslate nohighlight">\(I\)</span> has the same size as <span class="math notranslate nohighlight">\(X^T X\)</span>. It adds <span class="math notranslate nohighlight">\(\lambda\)</span> to the diagonal of <span class="math notranslate nohighlight">\(X^T X\)</span> for Ridge regression. We
then invert this matrix and multiply by <span class="math notranslate nohighlight">\(X^T y\)</span>. The result
for <span class="math notranslate nohighlight">\(\boldsymbol{\theta}\)</span> is a NumPy array of shape (n<span class="math notranslate nohighlight">\(\_\)</span>features,) containing the
for <span class="math notranslate nohighlight">\(\boldsymbol{\theta}\)</span> is a NumPy array of shape (n<span class="math notranslate nohighlight">\(\_\)</span>features,) containing the
fitted parameters <span class="math notranslate nohighlight">\(\boldsymbol{\theta}\)</span>.</p>
<section id="id1">
<h3>3a)<a class="headerlink" href="#id1" title="Link to this heading">#</a></h3>
@@ -526,32 +527,32 @@ descent. This is useful to visualize the iterative convergence and is
necessary if <span class="math notranslate nohighlight">\(n\)</span> and <span class="math notranslate nohighlight">\(p\)</span> are so large that the closed-form might be
too slow or memory-intensive. We derive the gradients from the cost
functions defined above. Use the gradients of the Ridge and OLS cost functions with respect to
the parameters <span class="math notranslate nohighlight">\(\boldsymbol{\theta}\)</span> and set up (using the template below) your own gradient descent code for OLS and Ridge regression.</p>
the parameters <span class="math notranslate nohighlight">\(\boldsymbol{\theta}\)</span> and set up (using the template below) your own gradient descent code for OLS and Ridge regression.</p>
<p>Below is a template code for gradient descent implementation of ridge:</p>
<div class="cell docutils container">
<div class="cell_input docutils container">
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># Gradient descent parameters, learning rate eta first
eta = 0.1
# Then number of iterations
num_iters = 1000
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Gradient descent parameters, learning rate eta first</span>
<span class="n">eta</span> <span class="o">=</span> <span class="mf">0.1</span>
<span class="c1"># Then number of iterations</span>
<span class="n">num_iters</span> <span class="o">=</span> <span class="mi">1000</span>
# Initialize weights for gradient descent
theta = np.zeros(n_features)
<span class="c1"># Initialize weights for gradient descent</span>
<span class="n">theta</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="n">n_features</span><span class="p">)</span>
# Gradient descent loop
for t in range(num_iters):
# Compute gradients for OSL and Ridge
grad_OLS = ?
grad_Ridge = ?
# Update parameters theta
theta_gdOLS = ?
theta_gdRidge = ?
<span class="c1"># Gradient descent loop</span>
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_iters</span><span class="p">):</span>
<span class="c1"># Compute gradients for OSL and Ridge</span>
<span class="n">grad_OLS</span> <span class="o">=</span> <span class="err">?</span>
<span class="n">grad_Ridge</span> <span class="o">=</span> <span class="err">?</span>
<span class="c1"># Update parameters theta</span>
<span class="n">theta_gdOLS</span> <span class="o">=</span> <span class="err">?</span>
<span class="n">theta_gdRidge</span> <span class="o">=</span> <span class="err">?</span>
# After the loop, theta contains the fitted coefficients
theta_gdOLS = ?
theta_gdRidge = ?
print(&quot;Gradient Descent OLS coefficients:&quot;, theta_gdOLS)
print(&quot;Gradient Descent Ridge coefficients:&quot;, theta_gdRidge)
<span class="c1"># After the loop, theta contains the fitted coefficients</span>
<span class="n">theta_gdOLS</span> <span class="o">=</span> <span class="err">?</span>
<span class="n">theta_gdRidge</span> <span class="o">=</span> <span class="err">?</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Gradient Descent OLS coefficients:&quot;</span><span class="p">,</span> <span class="n">theta_gdOLS</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Gradient Descent Ridge coefficients:&quot;</span><span class="p">,</span> <span class="n">theta_gdRidge</span><span class="p">)</span>
</pre></div>
</div>
</div>
@@ -582,24 +583,24 @@ Then we compute the target values <span class="math notranslate nohighlight">\(y
<p>Below is the code to generate the dataset:</p>
<div class="cell docutils container">
<div class="cell_input docutils container">
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>import numpy as np
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">numpy</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">np</span>
# Set random seed for reproducibility
np.random.seed(0)
<span class="c1"># Set random seed for reproducibility</span>
<span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
# Define dataset size
n_samples = 100
n_features = 10
<span class="c1"># Define dataset size</span>
<span class="n">n_samples</span> <span class="o">=</span> <span class="mi">100</span>
<span class="n">n_features</span> <span class="o">=</span> <span class="mi">10</span>
# Define true coefficients (sparse linear relationship)
theta_true = np.array([5.0, -3.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0])
<span class="c1"># Define true coefficients (sparse linear relationship)</span>
<span class="n">theta_true</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([</span><span class="mf">5.0</span><span class="p">,</span> <span class="o">-</span><span class="mf">3.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">])</span>
# Generate feature matrix X (n_samples x n_features) with random values
X = np.random.randn(n_samples, n_features) # standard normal distribution
<span class="c1"># Generate feature matrix X (n_samples x n_features) with random values</span>
<span class="n">X</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">randn</span><span class="p">(</span><span class="n">n_samples</span><span class="p">,</span> <span class="n">n_features</span><span class="p">)</span> <span class="c1"># standard normal distribution</span>
# Generate target values y with a linear combination of X and theta_true, plus noise
noise = 0.5 * np.random.randn(n_samples) # Gaussian noise
y = X.dot @ theta_true + noise
<span class="c1"># Generate target values y with a linear combination of X and theta_true, plus noise</span>
<span class="n">noise</span> <span class="o">=</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">randn</span><span class="p">(</span><span class="n">n_samples</span><span class="p">)</span> <span class="c1"># Gaussian noise</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">X</span><span class="o">.</span><span class="n">dot</span> <span class="o">@</span> <span class="n">theta_true</span> <span class="o">+</span> <span class="n">noise</span>
</pre></div>
</div>
</div>
@@ -619,7 +620,7 @@ y \approx 5 \times x_0 \;-\; 3 \times x_1 \;+\; 2 \times x_6 \;+\; \text{noise}.
close to the true values [5.0, -3.0, 0.0, …, 2.0, …] that we used to
generate the data. Keep in mind that due to regularization and noise,
the learned values will not exactly equal the true ones, but they
should be in the same ballpark. Which method (OLS or Ridge) gives the best results?</p>
should be in the same ballpark. Which method (OLS or Ridge) gives the best results?</p>
</section>
</section>
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
"id": "b2bc44f6",
"id": "2c4ae3e0",
"metadata": {},
"source": [
"# Notebooks with MyST Markdown\n",
@@ -19,7 +19,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "4ddd8e91",
"id": "bd842239",
"metadata": {},
"outputs": [],
"source": [
@@ -28,7 +28,7 @@
},
{
"cell_type": "markdown",
"id": "8e6cbd45",
"id": "0b607518",
"metadata": {},
"source": [
"When your book is built, the contents of any `{code-cell}` blocks will be\n",
@@ -9,7 +9,7 @@
"source": [
"<!-- HTML file automatically generated from DocOnce source (https://github.com/doconce/doconce/)\n",
"doconce format html exercisesweek37.do.txt -->\n",
"<!-- dom:TITLE: Exercises week 37 -->"
"<!-- dom:TITLE: Exercises week 37 -->\n"
]
},
{
@@ -20,9 +20,10 @@
},
"source": [
"# Exercises week 37\n",
"\n",
"**Implementing gradient descent for Ridge and ordinary Least Squares Regression**\n",
"\n",
"Date: **September 8-12, 2025**"
"Date: **September 8-12, 2025**\n"
]
},
{
@@ -35,13 +36,14 @@
"## Learning goals\n",
"\n",
"After having completed these exercises you will have:\n",
"\n",
"1. Your own code for the implementation of the simplest gradient descent approach applied to ordinary least squares (OLS) and Ridge regression\n",
"\n",
"2. Be able to compare the analytical expressions for OLS and Ridge regression with the gradient descent approach\n",
"\n",
"3. Explore the role of the learning rate in the gradient descent approach and the hyperparameter $\\lambda$ in Ridge regression\n",
"\n",
"4. Scale the data properly"
"4. Scale the data properly\n"
]
},
{
@@ -53,7 +55,7 @@
"source": [
"## Simple one-dimensional second-order polynomial\n",
"\n",
"We start with a very simple function"
"We start with a very simple function\n"
]
},
{
@@ -65,7 +67,7 @@
"source": [
"$$\n",
"f(x)= 2-x+5x^2,\n",
"$$"
"$$\n"
]
},
{
@@ -75,10 +77,10 @@
"editable": true
},
"source": [
"defined for $x\\in [-2,2]$. You can add noise if you wish. \n",
"defined for $x\\in [-2,2]$. You can add noise if you wish.\n",
"\n",
"We are going to fit this function with a polynomial ansatz. The easiest thing is to set up a second-order polynomial and see if you can fit the above function.\n",
"Feel free to play around with higher-order polynomials."
"Feel free to play around with higher-order polynomials.\n"
]
},
{
@@ -94,7 +96,7 @@
"standardize the features. This ensures all features are on a\n",
"comparable scale, which is especially important when using\n",
"regularization. Here we will perform standardization, scaling each\n",
"feature to have mean 0 and standard deviation 1."
"feature to have mean 0 and standard deviation 1.\n"
]
},
{
@@ -114,7 +116,7 @@
"term, the data is shifted such that the intercept is effectively 0\n",
". (In practice, one could include an intercept in the model and not\n",
"penalize it, but here we simplify by centering.)\n",
"Choose $n=100$ data points and set up $\\boldsymbol{x}, $\\boldsymbol{y}$ and the design matrix $\\boldsymbol{X}$."
"Choose $n=100$ data points and set up $\\boldsymbol{x}$, $\\boldsymbol{y}$ and the design matrix $\\boldsymbol{X}$.\n"
]
},
{
@@ -145,13 +147,13 @@
"editable": true
},
"source": [
"Fill in the necessary details. Do we need to center the $y$-values? \n",
"Fill in the necessary details. Do we need to center the $y$-values?\n",
"\n",
"After this preprocessing, each column of $\\boldsymbol{X}_{\\mathrm{norm}}$ has mean zero and standard deviation $1$\n",
"and $\\boldsymbol{y}_{\\mathrm{centered}}$ has mean 0. This makes the optimization landscape\n",
"nicer and ensures the regularization penalty $\\lambda \\sum_j\n",
"\\theta_j^2$ in Ridge regression treats each coefficient fairly (since features are on the\n",
"same scale)."
"same scale).\n"
]
},
{
@@ -163,7 +165,7 @@
"source": [
"## Exercise 2, calculate the gradients\n",
"\n",
"Find the gradients for OLS and Ridge regression using the mean-squared error as cost/loss function."
"Find the gradients for OLS and Ridge regression using the mean-squared error as cost/loss function.\n"
]
},
{
@@ -173,7 +175,7 @@
"editable": true
},
"source": [
"## Exercise 3, using the analytical formulae for OLS and Ridge regression to find the optimal paramters $\\boldsymbol{\\theta}$"
"## Exercise 3, using the analytical formulae for OLS and Ridge regression to find the optimal paramters $\\boldsymbol{\\theta}$\n"
]
},
{
@@ -210,8 +212,8 @@
"This computes the Ridge and OLS regression coefficients directly. The identity\n",
"matrix $I$ has the same size as $X^T X$. It adds $\\lambda$ to the diagonal of $X^T X$ for Ridge regression. We\n",
"then invert this matrix and multiply by $X^T y$. The result\n",
"for $\\boldsymbol{\\theta}$ is a NumPy array of shape (n$\\_$features,) containing the\n",
"fitted parameters $\\boldsymbol{\\theta}$."
"for $\\boldsymbol{\\theta}$ is a NumPy array of shape (n$\\_$features,) containing the\n",
"fitted parameters $\\boldsymbol{\\theta}$.\n"
]
},
{
@@ -223,7 +225,7 @@
"source": [
"### 3a)\n",
"\n",
"Finalize, in the above code, the OLS and Ridge regression determination of the optimal parameters $\\boldsymbol{\\theta}$."
"Finalize, in the above code, the OLS and Ridge regression determination of the optimal parameters $\\boldsymbol{\\theta}$.\n"
]
},
{
@@ -235,7 +237,7 @@
"source": [
"### 3b)\n",
"\n",
"Explore the results as function of different values of the hyperparameter $\\lambda$. See for example exercise 4 from week 36."
"Explore the results as function of different values of the hyperparameter $\\lambda$. See for example exercise 4 from week 36.\n"
]
},
{
@@ -252,9 +254,9 @@
"necessary if $n$ and $p$ are so large that the closed-form might be\n",
"too slow or memory-intensive. We derive the gradients from the cost\n",
"functions defined above. Use the gradients of the Ridge and OLS cost functions with respect to\n",
"the parameters $\\boldsymbol{\\theta}$ and set up (using the template below) your own gradient descent code for OLS and Ridge regression.\n",
"the parameters $\\boldsymbol{\\theta}$ and set up (using the template below) your own gradient descent code for OLS and Ridge regression.\n",
"\n",
"Below is a template code for gradient descent implementation of ridge:"
"Below is a template code for gradient descent implementation of ridge:\n"
]
},
{
@@ -301,7 +303,7 @@
"### 4a)\n",
"\n",
"Write first a gradient descent code for OLS only using the above template.\n",
"Discuss the results as function of the learning rate parameters and the number of iterations"
"Discuss the results as function of the learning rate parameters and the number of iterations\n"
]
},
{
@@ -314,7 +316,7 @@
"### 4b)\n",
"\n",
"Write then a similar code for Ridge regression using the above template.\n",
"Try to add a stopping parameter as function of the number iterations and the difference between the new and old $\\theta$ values. How would you define a stopping criterion?"
"Try to add a stopping parameter as function of the number iterations and the difference between the new and old $\\theta$ values. How would you define a stopping criterion?\n"
]
},
{
@@ -339,12 +341,12 @@
"Then we sample feature values for $\\boldsymbol{X}$ randomly (e.g. from a normal distribution). We use a normal distribution so features are roughly centered around 0.\n",
"Then we compute the target values $y$ using the linear combination $\\boldsymbol{X}\\hat{\\boldsymbol{\\theta}}$ and add some noise (to simulate measurement error or unexplained variance).\n",
"\n",
"Below is the code to generate the dataset:"
"Below is the code to generate the dataset:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"id": "8be1cebe",
"metadata": {
"collapsed": false,
@@ -368,7 +370,7 @@
"X = np.random.randn(n_samples, n_features) # standard normal distribution\n",
"\n",
"# Generate target values y with a linear combination of X and theta_true, plus noise\n",
"noise = 0.5 * np.random.randn(n_samples) # Gaussian noise\n",
"noise = 0.5 * np.random.randn(n_samples) # Gaussian noise\n",
"y = X.dot @ theta_true + noise"
]
},
@@ -383,7 +385,7 @@
"significantly influence $\\boldsymbol{y}$. The rest of the features have zero true\n",
"coefficient. For example, feature 0 has\n",
"a true weight of 5.0, feature 1 has -3.0, and feature 6 has 2.0, so\n",
"the expected relationship is:"
"the expected relationship is:\n"
]
},
{
@@ -395,7 +397,7 @@
"source": [
"$$\n",
"y \\approx 5 \\times x_0 \\;-\\; 3 \\times x_1 \\;+\\; 2 \\times x_6 \\;+\\; \\text{noise}.\n",
"$$"
"$$\n"
]
},
{
@@ -405,7 +407,7 @@
"editable": true
},
"source": [
"You can remove the noise if you wish to. \n",
"You can remove the noise if you wish to.\n",
"\n",
"Try to fit the above data set using OLS and Ridge regression with the analytical expressions and your own gradient descent codes.\n",
"\n",
@@ -413,11 +415,15 @@
"close to the true values [5.0, -3.0, 0.0, …, 2.0, …] that we used to\n",
"generate the data. Keep in mind that due to regularization and noise,\n",
"the learned values will not exactly equal the true ones, but they\n",
"should be in the same ballpark. Which method (OLS or Ridge) gives the best results?"
"should be in the same ballpark. Which method (OLS or Ridge) gives the best results?\n"
]
}
],
"metadata": {},
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+35 -29
View File
@@ -9,7 +9,7 @@
"source": [
"<!-- HTML file automatically generated from DocOnce source (https://github.com/doconce/doconce/)\n",
"doconce format html exercisesweek37.do.txt -->\n",
"<!-- dom:TITLE: Exercises week 37 -->"
"<!-- dom:TITLE: Exercises week 37 -->\n"
]
},
{
@@ -20,9 +20,10 @@
},
"source": [
"# Exercises week 37\n",
"\n",
"**Implementing gradient descent for Ridge and ordinary Least Squares Regression**\n",
"\n",
"Date: **September 8-12, 2025**"
"Date: **September 8-12, 2025**\n"
]
},
{
@@ -35,13 +36,14 @@
"## Learning goals\n",
"\n",
"After having completed these exercises you will have:\n",
"\n",
"1. Your own code for the implementation of the simplest gradient descent approach applied to ordinary least squares (OLS) and Ridge regression\n",
"\n",
"2. Be able to compare the analytical expressions for OLS and Ridge regression with the gradient descent approach\n",
"\n",
"3. Explore the role of the learning rate in the gradient descent approach and the hyperparameter $\\lambda$ in Ridge regression\n",
"\n",
"4. Scale the data properly"
"4. Scale the data properly\n"
]
},
{
@@ -53,7 +55,7 @@
"source": [
"## Simple one-dimensional second-order polynomial\n",
"\n",
"We start with a very simple function"
"We start with a very simple function\n"
]
},
{
@@ -65,7 +67,7 @@
"source": [
"$$\n",
"f(x)= 2-x+5x^2,\n",
"$$"
"$$\n"
]
},
{
@@ -75,10 +77,10 @@
"editable": true
},
"source": [
"defined for $x\\in [-2,2]$. You can add noise if you wish. \n",
"defined for $x\\in [-2,2]$. You can add noise if you wish.\n",
"\n",
"We are going to fit this function with a polynomial ansatz. The easiest thing is to set up a second-order polynomial and see if you can fit the above function.\n",
"Feel free to play around with higher-order polynomials."
"Feel free to play around with higher-order polynomials.\n"
]
},
{
@@ -94,7 +96,7 @@
"standardize the features. This ensures all features are on a\n",
"comparable scale, which is especially important when using\n",
"regularization. Here we will perform standardization, scaling each\n",
"feature to have mean 0 and standard deviation 1."
"feature to have mean 0 and standard deviation 1.\n"
]
},
{
@@ -114,7 +116,7 @@
"term, the data is shifted such that the intercept is effectively 0\n",
". (In practice, one could include an intercept in the model and not\n",
"penalize it, but here we simplify by centering.)\n",
"Choose $n=100$ data points and set up $\\boldsymbol{x}, $\\boldsymbol{y}$ and the design matrix $\\boldsymbol{X}$."
"Choose $n=100$ data points and set up $\\boldsymbol{x}$, $\\boldsymbol{y}$ and the design matrix $\\boldsymbol{X}$.\n"
]
},
{
@@ -145,13 +147,13 @@
"editable": true
},
"source": [
"Fill in the necessary details. Do we need to center the $y$-values? \n",
"Fill in the necessary details. Do we need to center the $y$-values?\n",
"\n",
"After this preprocessing, each column of $\\boldsymbol{X}_{\\mathrm{norm}}$ has mean zero and standard deviation $1$\n",
"and $\\boldsymbol{y}_{\\mathrm{centered}}$ has mean 0. This makes the optimization landscape\n",
"nicer and ensures the regularization penalty $\\lambda \\sum_j\n",
"\\theta_j^2$ in Ridge regression treats each coefficient fairly (since features are on the\n",
"same scale)."
"same scale).\n"
]
},
{
@@ -163,7 +165,7 @@
"source": [
"## Exercise 2, calculate the gradients\n",
"\n",
"Find the gradients for OLS and Ridge regression using the mean-squared error as cost/loss function."
"Find the gradients for OLS and Ridge regression using the mean-squared error as cost/loss function.\n"
]
},
{
@@ -173,7 +175,7 @@
"editable": true
},
"source": [
"## Exercise 3, using the analytical formulae for OLS and Ridge regression to find the optimal paramters $\\boldsymbol{\\theta}$"
"## Exercise 3, using the analytical formulae for OLS and Ridge regression to find the optimal paramters $\\boldsymbol{\\theta}$\n"
]
},
{
@@ -210,8 +212,8 @@
"This computes the Ridge and OLS regression coefficients directly. The identity\n",
"matrix $I$ has the same size as $X^T X$. It adds $\\lambda$ to the diagonal of $X^T X$ for Ridge regression. We\n",
"then invert this matrix and multiply by $X^T y$. The result\n",
"for $\\boldsymbol{\\theta}$ is a NumPy array of shape (n$\\_$features,) containing the\n",
"fitted parameters $\\boldsymbol{\\theta}$."
"for $\\boldsymbol{\\theta}$ is a NumPy array of shape (n$\\_$features,) containing the\n",
"fitted parameters $\\boldsymbol{\\theta}$.\n"
]
},
{
@@ -223,7 +225,7 @@
"source": [
"### 3a)\n",
"\n",
"Finalize, in the above code, the OLS and Ridge regression determination of the optimal parameters $\\boldsymbol{\\theta}$."
"Finalize, in the above code, the OLS and Ridge regression determination of the optimal parameters $\\boldsymbol{\\theta}$.\n"
]
},
{
@@ -235,7 +237,7 @@
"source": [
"### 3b)\n",
"\n",
"Explore the results as function of different values of the hyperparameter $\\lambda$. See for example exercise 4 from week 36."
"Explore the results as function of different values of the hyperparameter $\\lambda$. See for example exercise 4 from week 36.\n"
]
},
{
@@ -252,9 +254,9 @@
"necessary if $n$ and $p$ are so large that the closed-form might be\n",
"too slow or memory-intensive. We derive the gradients from the cost\n",
"functions defined above. Use the gradients of the Ridge and OLS cost functions with respect to\n",
"the parameters $\\boldsymbol{\\theta}$ and set up (using the template below) your own gradient descent code for OLS and Ridge regression.\n",
"the parameters $\\boldsymbol{\\theta}$ and set up (using the template below) your own gradient descent code for OLS and Ridge regression.\n",
"\n",
"Below is a template code for gradient descent implementation of ridge:"
"Below is a template code for gradient descent implementation of ridge:\n"
]
},
{
@@ -301,7 +303,7 @@
"### 4a)\n",
"\n",
"Write first a gradient descent code for OLS only using the above template.\n",
"Discuss the results as function of the learning rate parameters and the number of iterations"
"Discuss the results as function of the learning rate parameters and the number of iterations\n"
]
},
{
@@ -314,7 +316,7 @@
"### 4b)\n",
"\n",
"Write then a similar code for Ridge regression using the above template.\n",
"Try to add a stopping parameter as function of the number iterations and the difference between the new and old $\\theta$ values. How would you define a stopping criterion?"
"Try to add a stopping parameter as function of the number iterations and the difference between the new and old $\\theta$ values. How would you define a stopping criterion?\n"
]
},
{
@@ -339,12 +341,12 @@
"Then we sample feature values for $\\boldsymbol{X}$ randomly (e.g. from a normal distribution). We use a normal distribution so features are roughly centered around 0.\n",
"Then we compute the target values $y$ using the linear combination $\\boldsymbol{X}\\hat{\\boldsymbol{\\theta}}$ and add some noise (to simulate measurement error or unexplained variance).\n",
"\n",
"Below is the code to generate the dataset:"
"Below is the code to generate the dataset:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"id": "8be1cebe",
"metadata": {
"collapsed": false,
@@ -368,7 +370,7 @@
"X = np.random.randn(n_samples, n_features) # standard normal distribution\n",
"\n",
"# Generate target values y with a linear combination of X and theta_true, plus noise\n",
"noise = 0.5 * np.random.randn(n_samples) # Gaussian noise\n",
"noise = 0.5 * np.random.randn(n_samples) # Gaussian noise\n",
"y = X.dot @ theta_true + noise"
]
},
@@ -383,7 +385,7 @@
"significantly influence $\\boldsymbol{y}$. The rest of the features have zero true\n",
"coefficient. For example, feature 0 has\n",
"a true weight of 5.0, feature 1 has -3.0, and feature 6 has 2.0, so\n",
"the expected relationship is:"
"the expected relationship is:\n"
]
},
{
@@ -395,7 +397,7 @@
"source": [
"$$\n",
"y \\approx 5 \\times x_0 \\;-\\; 3 \\times x_1 \\;+\\; 2 \\times x_6 \\;+\\; \\text{noise}.\n",
"$$"
"$$\n"
]
},
{
@@ -405,7 +407,7 @@
"editable": true
},
"source": [
"You can remove the noise if you wish to. \n",
"You can remove the noise if you wish to.\n",
"\n",
"Try to fit the above data set using OLS and Ridge regression with the analytical expressions and your own gradient descent codes.\n",
"\n",
@@ -413,11 +415,15 @@
"close to the true values [5.0, -3.0, 0.0, …, 2.0, …] that we used to\n",
"generate the data. Keep in mind that due to regularization and noise,\n",
"the learned values will not exactly equal the true ones, but they\n",
"should be in the same ballpark. Which method (OLS or Ridge) gives the best results?"
"should be in the same ballpark. Which method (OLS or Ridge) gives the best results?\n"
]
}
],
"metadata": {},
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}