הרצאה 1 - מבוא
Setup¶
In [ ]:
## Importing packages
import os # A build in package for interacting with the OS. For example to create a folder.
import numpy as np # Numerical package (mainly multi-dimensional arrays and linear algebra)
import pandas as pd # A package for working with data frames
import matplotlib.pyplot as plt # A plotting package
import imageio # A package to read and write image (is used here to save gif images)
## Setup matplotlib to output figures into the notebook
## - To make the figures interactive (zoomable, tooltip, etc.) use ""%matplotlib notebook" instead
%matplotlib inline
## Setting some nice matplotlib defaults
plt.rcParams['figure.figsize'] = (4.5, 4.5) # Set default plot's sizes
plt.rcParams['figure.dpi'] = 120 # Set default plot's dpi (increase fonts' size)
plt.rcParams['axes.grid'] = True # Show grid by default in figures
## Auxiliary function for prining equations, pandas tables and images in cells output
from IPython.core.display import display, HTML, Latex, Markdown
## Create output folder
if not os.path.isdir('./output'):
os.mkdir('./output')
Missing number¶
In [ ]:
data = np.array([
[0, 2],
[1, 4],
[3, 16],
])
x_grid = np.arange(0, 4, 0.1)
Plot problem¶
In [ ]:
with plt.xkcd():
fig, ax = plt.subplots(figsize=(4.5, 3))
# ax.set_title(r'$p_{t|p}(t|p)$')
ax.plot(data[:, 0], data[:, 1], 'x', ms=15, mew=4)
ax.text(2, 10, '?', size=25, color='red')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(-1, 4)
ax.set_ylim(0, 20)
ax.set_xticks([0, 1, 2, 3])
ax.set_yticks([2, 4, 16])
fig.savefig('./output/missing_number.png', dpi=240)
In [ ]:
f = lambda x: 2 * 2 ** x
y_exp = f(x_grid)
res_exp = f(2)
with plt.xkcd():
fig, ax = plt.subplots(figsize=(4.5, 3))
ax.plot(data[:, 0], data[:, 1], 'x', ms=15, mew=4)
ax.plot(x_grid, y_exp, zorder=-1)
ax.plot(2, res_exp, 'x', color='red', ms=15, mew=4)
ax.text(2, res_exp + 2, f'{res_exp:.2g}', size=25, color='red', ha='right')
ax.set_title(r'$y=2\times2^{x}$')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(-1, 4)
ax.set_ylim(0, 20)
ax.set_xticks([0, 1, 2, 3])
ax.set_yticks([2, 4, 16])
fig.savefig('./output/missing_number_exp.png', dpi=240)
In [ ]:
x_mat = data[:, 0, None] ** np.array([0, 1, 2])
theta = np.linalg.solve(x_mat, data[:, 1])
f = lambda x: theta[0] + theta[1] * x + theta[2] * x ** 2
print(f'Polinomial coeffs: a={theta[0]:.3g}, b={theta[1]:.3g}, c={theta[2]:.3g}')
In [ ]:
y_poly = f(x_grid)
res_poly = f(2)
with plt.xkcd():
fig, ax = plt.subplots(figsize=(4.5, 3))
ax.plot(data[:, 0], data[:, 1], 'x', ms=15, mew=4)
ax.plot(x_grid, y_poly, zorder=-1)
ax.plot(2, res_poly, 'x', color='red', ms=15, mew=4)
ax.text(2, res_poly + 2, f'{res_poly:.2g}', size=25, color='red', ha='right')
ax.set_title(r'$y=2+\frac{2}{3}x+\frac{4}{3}x^2$')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(-1, 4)
ax.set_ylim(0, 20)
ax.set_xticks([0, 1, 2, 3])
ax.set_yticks([2, 4, 16])
fig.savefig('./output/missing_number_poly.png', dpi=240)
In [ ]:
x_mat = np.stack([np.sin(data[:, 0] / 3),
np.cos(data[:, 0] / 3),
np.sin(data[:, 0] * 2 / 3),
], axis=1)
theta = np.linalg.solve(x_mat, data[:, 1])
f = lambda x: theta[0] * np.sin(x / 3) + theta[1] * np.cos(x / 3) + theta[2] * np.sin(x * 2 / 3)
print(f'Harmonic coeffs: a={theta[0]:.3g}, b={theta[1]:.3g}, c={theta[2]:.3g}')
In [ ]:
y_harm = f(x_grid)
res_harm = f(2)
with plt.xkcd():
fig, ax = plt.subplots(figsize=(4.5, 3))
ax.plot(data[:, 0], data[:, 1], 'x', ms=15, mew=4)
ax.plot(x_grid, y_harm, zorder=-1)
ax.plot(2, res_harm, 'x', color='red', ms=15, mew=4)
ax.text(2, res_harm + 2, f'{res_harm:.2g}', size=25, color='red', ha='right')
ax.set_title(f'$y={theta[0]:.3g}\\sin(x/3)+{theta[1]:.3g}\\cos(x/3)$\n${theta[2]:.3g}\\sin(2x/3)$')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(-1, 4)
ax.set_ylim(0, 20)
ax.set_xticks([0, 1, 2, 3])
ax.set_yticks([2, 4, 16])
plt.tight_layout()
fig.savefig('./output/missing_number_harm.png', dpi=240)
In [ ]:
from scipy import interpolate
f = interpolate.interp1d(data[:, 0], data[:, 1], kind='previous', fill_value="extrapolate")
y_prev = f(x_grid)
res_prev = f(2)
with plt.xkcd():
fig, ax = plt.subplots(figsize=(4.5, 3))
ax.plot(data[:, 0], data[:, 1], 'x', ms=15, mew=4)
ax.plot(x_grid, y_prev, zorder=-1)
ax.plot(2, res_prev, 'x', color='red', ms=15, mew=4)
ax.text(2, res_prev + 2, f'{res_prev:.2g}', size=25, color='red', ha='right')
ax.set_title(f'Interpolation: previous')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(-1, 4)
ax.set_ylim(0, 20)
ax.set_xticks([0, 1, 2, 3])
ax.set_yticks([2, 4, 16])
fig.savefig('./output/missing_number_prev.png', dpi=240)
In [ ]:
from scipy import interpolate
spl = interpolate.splrep(data[:, 0], data[:, 1], k=2)
f = lambda x: interpolate.splev(x, spl)
y_spline = f(x_grid)
res_spline = f(2)
with plt.xkcd():
fig, ax = plt.subplots(figsize=(4.5, 3))
ax.plot(data[:, 0], data[:, 1], 'x', ms=15, mew=4)
ax.plot(x_grid, y_spline, zorder=-1)
ax.plot(2, res_spline, 'x', color='red', ms=15, mew=4)
ax.text(2, res_spline + 2, f'{res_spline:.2g}', size=25, color='red', ha='right')
ax.set_title(f'Interpolation: spline')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(-1, 4)
ax.set_ylim(0, 20)
ax.set_xticks([0, 1, 2, 3])
ax.set_yticks([2, 4, 16])
fig.savefig('./output/missing_number_spline.png', dpi=240)
Drive duration prediction¶
In [ ]:
gt_model = lambda x: 60 + 120 * (1 - 0.5 ** (x / 200))
std = 5
rand_gen = np.random.RandomState(42)
x = rand_gen.randint(0, 1000, 20)
y = gt_model(x) + rand_gen.randn(*x.shape) * std
x_grid = np.arange(0, 1000, 1)
x0 = np.array([500])
In [ ]:
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
# ax.set_title(f'')
ax.set_ylabel('Duration [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
fig.savefig('./output/drive_prediction_dataset.png', dpi=240)
In [ ]:
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
ax.text(x0[0], gt_model(x0)[0], '?', size=15, color='red')
# ax.set_title(f'')
ax.set_ylabel('Duration [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
fig.savefig('./output/drive_prediction.png', dpi=240)
In [ ]:
models = ((60, 0.3), (80, 0.1), (140, 0.02), (120, 0.06))
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
for (a, b) in models:
f = lambda x: a + b *x
ax.plot(x_grid, f(x_grid), zorder=-1)
ax.set_title(f'Optional linaer models')
ax.set_ylabel('Duration [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
fig.savefig('./output/drive_prediction_linear_models.png', dpi=240)
In [ ]:
aug_func = lambda x: x[:, None]
x_aug = aug_func(x)
theta = np.linalg.lstsq(x_aug, y, rcond=None)[0]
h = lambda x: aug_func(x) @ theta
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
ax.plot(x_grid, h(x_grid), zorder=-1)
ax.set_title(f'Linear model - no bias')
ax.set_ylabel('Duration [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
fig.savefig('./output/drive_prediction_linear_no_bias.png', dpi=240)
In [ ]:
order = 1
aug_func = lambda x: x[:, None] ** np.arange(order + 1)[None, :]
theta = np.linalg.lstsq(aug_func(x), y, rcond=None)[0]
h = lambda x: aug_func(x) @ theta
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
ax.plot(x_grid, h(x_grid), zorder=-1)
ax.set_title(f'Linear model')
ax.set_ylabel('Duration [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
fig.savefig('./output/drive_prediction_linear.png', dpi=240)
In [ ]:
order = 2
aug_func = lambda x: x[:, None] ** np.arange(order + 1)[None, :]
theta = np.linalg.lstsq(aug_func(x), y, rcond=None)[0]
h = lambda x: aug_func(x) @ theta
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
ax.plot(x_grid, h(x_grid), zorder=-1)
ax.set_title(f'2ed order polinomial')
ax.set_ylabel('Duration [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
fig.savefig(f'./output/drive_prediction_poly_{order}.png', dpi=240)
In [ ]:
order = 4
aug_func = lambda x: x[:, None] ** np.arange(order + 1)[None, :]
theta = np.linalg.lstsq(aug_func(x), y, rcond=None)[0]
h = lambda x: aug_func(x) @ theta
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
ax.plot(x_grid, h(x_grid), zorder=-1)
ax.set_title(f'{order}th order polinomial')
ax.set_ylabel('Duration [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
fig.savefig(f'./output/drive_prediction_poly_{order}.png', dpi=240)
In [ ]:
order = 15
aug_func = lambda x: (x[:, None] / 1000) ** np.arange(order + 1)[None, :]
theta = np.linalg.lstsq(aug_func(x), y, rcond=None)[0]
h = lambda x: aug_func(x) @ theta
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
ax.plot(x_grid, h(x_grid), zorder=-1)
ax.set_title(f'{order}th order polinomial')
ax.set_ylabel('Time [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
fig.savefig(f'./output/drive_prediction_poly_{order}.png', dpi=240)
In [ ]:
y_scaling = 1 # 0.01
x_scaling = 0.1 # 0.001
h = lambda x, theta: (theta[0] - theta[1] * np.exp(- x / theta[2]))
grad_func = lambda theta, x, y: 2 * ((theta[0] - theta[1] * np.exp(- x / theta[2]) - y)[:, None] * np.stack((
np.ones(x.shape[0]),
-np.exp(-x / theta[2]),
-theta[1] / theta[2] ** 2 * x * np.exp(-x / theta[2]),
), axis=1)).mean(axis=0)
## Initializing the parameters
theta = np.array([100, 100, 100])
## The algorithm's parameters controling the steps size
eta = 0.1
## Initializing the output figure
with plt.xkcd():
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(x, y, 'x', ms=5, mew=2)
model_obj = ax.plot([], [], zorder=-1)[0]
title = ax.set_title(f'Exponantial model')
ax.set_ylabel('Time [min]')
ax.set_xlabel('Number of cars')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.set_xlim(0, 1000)
ax.set_ylim(0, 180)
plt.tight_layout()
imgs = []
## Running the algorithm
for t in range(0, 300):
## The update step
theta = theta - eta * grad_func(theta, x * x_scaling, y * y_scaling)
## Plot intermidiate
if t % 3 == 0:
model_obj.set_data(x_grid, h(x_grid * x_scaling, theta) / y_scaling)
title.set_text(f'Exponantial model - Step {t}')
fig.canvas.draw()
imgs.append(np.frombuffer(fig.canvas.tostring_rgb(), dtype='uint8').reshape(*fig.canvas.get_width_height()[::-1], 3))
imageio.mimsave('./output/fitting_exp_model.gif', imgs, fps=10)
plt.close(fig)
display(HTML('<img src="./output/fitting_exp_model.gif"/>'))
display(Markdown(r'$\theta=$' + f'[{theta[0] / y_scaling:.0f}, {theta[1] / y_scaling:.0f}, {theta[2] / x_scaling:.0f}]'))
In [ ]: