From fa6433815206f16cb56e18fe97fa6a38e5ee10fe Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Fri, 3 Feb 2017 09:33:39 +0100 Subject: [PATCH] solution (python) for eod fit problem --- projects/project_eod/solution/fit_eod.py | 80 ++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 projects/project_eod/solution/fit_eod.py diff --git a/projects/project_eod/solution/fit_eod.py b/projects/project_eod/solution/fit_eod.py new file mode 100644 index 0000000..3af725e --- /dev/null +++ b/projects/project_eod/solution/fit_eod.py @@ -0,0 +1,80 @@ +import matplotlib.pyplot as plt +import numpy as np +from IPython import embed +import scipy.io as scio + +def load_data(filename): + data = scio.loadmat(filename) + t = data['t'] + eod = data['eod'] + return t[0], eod[0] + + +def eod_model(p, t): + b_0 = p[0] + omega_0 = p[1] + + params = p[2:] + n = len(params)/2 + eod = np.zeros(t.shape) + for i in range(n): + eod += params[i*2] * np.sin(2 * np.pi * t * (i+1) * omega_0 + params[i*2+1]) + eod += b_0 + return eod + + +def fit_error(p, t, y): + y_dash = eod_model(p,t) + err = np.mean((y - y_dash)**2) + return err + + +def gradient(p, t, y, scale=None): + if scale is None: + scale = np.ones(len(p)) + grad = np.zeros(len(p)) + h = 0.002 + for i in range(len(p)): + p_temp = list(p) + p_temp[i] = p[i] + scale[i] * h + grad[i] = (fit_error(p_temp, t, y) - fit_error(p, t, y)) / h + return grad + + +def gradient_descent(t, y): + count = 80 + b_0 = np.mean(y) + omega_0 = 650 + params = [b_0, omega_0, np.min(y) + np.max(y), np.pi/2, (np.min(y) + np.max(y))/2, np.pi/3, (np.min(y) + np.max(y))/4, np.pi/4, (np.min(y) + np.max(y))/5, np.pi] + scale = np.ones(len(params)) + scale[1] = 1000 + eps = 0.01 + grad = None + errors = [] + plt.axis([0, t[count], -3, 3.5]) + plt.ion() + plt.plot(t[:count], y[:count]) + l = None + while (grad is None) or (np.linalg.norm(grad) > 0.01): + errors.append(fit_error(params, t[:count], y[:count])) + + grad = gradient(params, t[:count], y[:count]) + params -= eps * scale * grad + if l is None: + l = plt.plot(t[:count], eod_model(params, t[:count])) + else: + l[0].set_data(t[:count], eod_model(params, t[:count])) + plt.title("norm: %.2f, freq: %.2f" % (np.linalg.norm(grad), params[1])) + plt.pause(0.005) + embed() + exit() + + + +if __name__ == "__main__": + datafile = '../data/EOD_data.mat' + t, eod = load_data(datafile) + # eod = eod_model([0.0, 600, 1.0, 0.0], t[:100]) + gradient_descent(t, eod) + embed() + exit()