diff --git a/semester3/numcs/numcs-summary.pdf b/semester3/numcs/numcs-summary.pdf index 5fe27c5..642b060 100644 Binary files a/semester3/numcs/numcs-summary.pdf and b/semester3/numcs/numcs-summary.pdf differ diff --git a/semester3/numcs/parts/05_curve-fitting/02_non-linear/02_gauss-newton.tex b/semester3/numcs/parts/05_curve-fitting/02_non-linear/02_gauss-newton.tex index 2311c6c..a42fc5b 100644 --- a/semester3/numcs/parts/05_curve-fitting/02_non-linear/02_gauss-newton.tex +++ b/semester3/numcs/parts/05_curve-fitting/02_non-linear/02_gauss-newton.tex @@ -18,3 +18,62 @@ Die Iterationsvorschrift ist gegeben durch: \begin{align*} x^{(k + 1)} = x^{(k)} - s \smallhspace \text{ mit } s := \argmin{z \in \R^n} ||F(x^{(k)}) - DF(x^{(k)})z||^2_2 \end{align*} + +\begin{code}{python} +import numpy as np + +def gauss_newton(start_vec, Func, Jacobian, tolerance): + # Start vector has to be chosen intelligently + s = np.linalg.lstsq(Jacobian(start_vec), Func(start_vec))[0] + start_vec = start_vec - s + # now we perform the iteration + while np.linalg.norm(s) > tolerance * np.linalg.norm(start_vec): + # every time we update x by subtracting s, found with the least square method + s = np.linalg.lstsq(Jacobian(start_vec), Func(start_vec))[0] + start_vec = start_vec - s + return start_vec +\end{code} + +Der Vorteil ist, dass die zweite Ableitung nicht benötigt wird, jedoch ist die Konvergenzordnung niedrieger ($p \leq 2$) + +\newpage +\setLabelNumber{all}{3} +\inlineex Wir haben zwei Modellfunktionen, $F_1(t) = a_1 + b_1 e^{-c_1 t}$ and $F_2(t) = a_2 - b_2 e^{-c_2 t}$. ($F_1$ ist ein Heizvorgang, $F_2$ ist ein Abkühlvorgang). +Untenstehender code berechnet die Lösung des nichtlinearen Ausgleichsproblems +\begin{code}{python} +import numpy as np + +t = np.arange(0, 30, 5); n = len(t) +curr_heating = np.array([24.34, 18.93, 17.09, 16.27, 15.97, 15.91]) +curr_cooling = np.array([9.66, 18.8, 22.36, 24.07, 24.59, 24.91]) +# define the functions that have to be minimized +F_1 = lambda a: a[0] + a[1] * np.exp(-a[2] * t) - curr_heating +F_2 = lambda a: a[0] - a[1] * np.exp(-a[2] * t) - curr_cooling + +# define the corresponding Jacobi matrices +def J_1(a): + mat = np.zeros((n, 3)) + for k in range(n): + mat[k, 0] = 1.0 + mat[k, 1] = np.exp(-t[k] * a[2]) + mat[k, 2] = -t[k] * a[1] * np.exp(-t[k] * a[2]) + return mat + +def J_2(a): + mat = np.zeros((n, 3)) + for k in range(n): + mat[k, 0] = 1.0 + mat[k, 1] = -np.exp(-t[k] * a[2]) + mat[k, 2] = t[k] * a[1] * np.exp(-t[k] * a[2]) + return mat + +# guess starting vector +x_1 = np.array([10.0, 5.0, 0.0]) +x_2 = np.array([30.0, 10.0, 0.0]) + +# use the Gauss-Newton algorithm declared above +a_1 = gauss_newton(x_1, F_1, J_1, tolerance=10e-6) +a_2 = gauss_newton(x_2, F_2, J_2, tolerance=10e-6) +print("Heating ", a_1) +print("Cooling ", a_2) +\end{code} diff --git a/semester3/numcs/parts/05_curve-fitting/02_non-linear/03_further-methods.tex b/semester3/numcs/parts/05_curve-fitting/02_non-linear/03_further-methods.tex index e69de29..69e2ba8 100644 --- a/semester3/numcs/parts/05_curve-fitting/02_non-linear/03_further-methods.tex +++ b/semester3/numcs/parts/05_curve-fitting/02_non-linear/03_further-methods.tex @@ -0,0 +1,20 @@ +\newpage +\subsubsection{Weitere Methoden: BFGS, GD, SGC, CG, LM, ADAM} +Für unterschiedliche Probleme können andere Funktionen günstiger oder besser geeignet sein. +Eine Liste einiger bekannter Methoden: +\begin{itemize} + \item \bi{BFGS} (basiert auf Broyden): $D\Phi(x^{(k)}) = DF(x^{(k)})^\top F(x^{(k)})$, oder günstiger mit $D\Phi(x^{(k)})^\top DF(x^{(k)})s = DF(x^{(k)})^\top F(x^{(k)})$ + \item \bi{GD} (Gradient Descent): $s = \lambda_k D\Phi(x^{(k)})$ (in ML wird $\lambda_k$ als ``Learning rate'' bezeichnet) + \item \bi{LM} (Levenberg-Marquant): wir minimieren $||F(x^{(k)}) + DF(x^{(k)})||^2 + \lambda ||s||^2_2$ (also werden kleine Schritte bevorzugt) + \item \bi{CG} (Conjugated Gradient): GD ist sehr langsam, aber auch günstig. Mit höheren Kosten kann durch Wahl von + $s = \lambda z^k$ und $z^k = D\Phi(x^{(k)}) + \beta z^(k - 1)$ eine schnellere Konvergenz erreicht werden (Dämpfung) + \item \bi{ADAM} Hier werden spezielle $\lambda$ und $\beta$ gewählt und liefert die einfache Iterationen + \rmvspace + \begin{align*} + x^{(k + 1)} & = x^k - \lambda z^k \\ + z^{(k + 1)} & = D\Phi(x^{(k)}) + \beta z^{(k)} \\ + \end{align*} +\end{itemize} + +\drmvspace\drmvspace +\innumpy gibt es via \texttt{scipy.optimize.leastsq} eine Implementation mit verschiedenen Iterationsmethoden, oder alternativ \texttt{scipy.optimize.minimize}