\chapter{Gradient Descent}%
\label{cha:Gradient Descent}
Zum Einlernen von Neuronalen Netzwerken wird zumeist das \nameref{cha:Gradient Descent} Verfahren mit Mini-Batches (\cref{sub:Mini-Batches}) verwendet.
Dies ist dadurch begründet,
dass sich diese Verfahren am effizientesten mithilfe von \glspl{GPU} berechnen lassen
und die Größe der Batches an die Anzahl der \gls{GPU} Rechenkerne angepasst ist.
\begin{equation} \label{eq:neural_networks:mini-batches}
    \bm{\theta}_{t+1} = \bm{\theta}_t - \dfrac{\eta}{b}\sum_i \nabla_{\bm{\theta}} l(\bm{x}_i;\bm{\theta}_t)
\end{equation}
Um den Gradienten für die einzelnen Gewichte zu errechnen wird die \dref{sec:Backpropagation} verwendet.

\section{Backpropagation}%
\label{sec:Backpropagation}
Um ein \nameref{sec:Gradient Descent} für ein Neurales Netzwerk durchzuführen,
müssen zunächst die einzelnen Gradienten der einzelnen Gewichte rückwirkend durch die verschiedenen Schichten eines Neural Networks ermittelt werden.
Die Loss Function errechnet sich hier durch
\begin{equation} \label{eq:backpropagration_loss_function}
    \mathcal L(\bm\theta,\mathcal D) = \sum_{i=1}^N l(\bm x_i,\bm\theta) + \nomeq{regularization_factor}\text{ penalty}(\bm\theta)
\end{equation}
\begin{wrapfigure}{r}{.5\textwidth}
    \vspace*{-5mm}
    \centering
    \includegraphics[width=.8\linewidth]{back_propagation.png}
    \caption{Zusammenhang zwischen Errechnung der Loss Function und Errechnung der partiellen Ableitungen}
    \label{fig:backpropagation}
    \vspace*{-15mm}
\end{wrapfigure}
Um die Gewichtsvektoren auf Basis dieser Loss Function anzupassen muss die partielle Ableitung für die jeweilige Gewichtsmatrix und den Biasvektor gezogen werden.
Hierfür ist die Kettenregel nützlich,
die die Regeln für die partielle Ableitung vorgibt
\begin{equation} \label{eq:backpropagation:chain_rule}
    \frac{d}{dt}f(x(t)) = \frac{df}{dx}\frac{dx}{dt}
\end{equation}
In \cref{fig:backpropagation} ist dieser Ablauf am Beispiel eines zweistufigen Neuronalen Netzes gezeigt.
Hier berechnet sich der Loss durch
\begin{align} \label{eq:forward_pass}
    z &= wx + b\\
    y &= \sigma(z)\\
    \mathcal L &= \frac{1}{2}(y-t)^2
\end{align}
Für dieses Neural Network ist die Backpropagation dann
\begin{alignat}{5} \label{eq:backward_pass}
    \frac{\partial \mathcal L}{\partial y} &= y - t && 
                                           &&=\overline{y}\\
    \frac{\partial \mathcal L}{\partial z} &= \frac{\partial\mathcal L}{\partial y}\frac{\partial y}{\partial z} &&= \frac{\partial\mathcal L}{\partial y}\sigma'(z) 
                                           &&=\overline{z} &&= \overline{y}\sigma'(z)\\
    \frac{\partial \mathcal L}{\partial w} &= \frac{\partial\mathcal L}{\partial z}\frac{\partial z}{\partial w} &&= \frac{\partial\mathcal L}{\partial z} x 
                                           &&=\overline{w} &&= \overline{z}x \\
    \frac{\partial \mathcal L}{\partial b} &= \frac{\partial\mathcal L}{\partial z}\frac{\partial z}{\partial b} 
                                           &&= \frac{\partial\mathcal L}{\partial z} \cdot 1 &&=\overline{b} &&=\overline{z}
\end{alignat}
Wenn sich der Graph des Neural Networks sich allerdings verzweigt (mehrere Neuronen auf einer Schicht) muss die multivariable Kettenregel (multivariable chain rule) verwendet werden
\begin{equation} \label{eq:multivariable_chain_rule}
    \frac{d}{dt}f(x(t),y(t)) = \frac{\partial f}{\partial x}\frac{dx}{dt} + \frac{\partial f}{\partial y}\frac{dy}{dt}
\end{equation}
Die Anwendung dieser Regel wird in den folgenden zwei Beispielen deutlich

\paragraph{Example: univariate logistic least squares regression}%
\label{par:Example: univariate logistic least squares regression}
\mbox{}\\
\includegraphics[scale=.65]{univariate_logisitc_least_squares_regression.png}

\paragraph{Example: Multi-layer Perceptron (multiple outputs)}%
\label{par:Example: Multi-layer Perceptron}
\mbox{}\\
\includegraphics[scale=.65]{multi-layer_perceptron.png}\\
Mithilfe der Matrix-Rechentricks aus \cref{sec:Matrix-Calculus} ist es möglich die Backpropagation für das Multi-layer Perceptron in Matrix-Form aufzuschreiben:\\
(Herleitung: \cref{sec:Herleitung: Backpropagation in Matrix-Form})\\
\includegraphics[scale=.65]{multi-layer_perceptron_matrix_form.png}

\subsection{Computational costs}%
\label{sub:Computational costs}
Die Computational Costs für eine Backpropagation ergibt sich als Summe aus dem Forward Pass und dem Backward Pass.
Die Kosten für den Forward Pass sind in etwa linear in der Anzahl der Gewichte,
da für jedes Gewicht in etwa eine Addition und Multiplikation nötig ist.
\begin{equation} \label{eq:computational_cost_forward_pass}
    \bm z = \bm W\bm x + \bm b
\end{equation}
Die Kosten für den Backward Pass sind ebenfalls in etwa linear,
mit jeweils zwei Additionen und Multiplikationen pro Gewicht.
\begin{equation} \label{eq:computational_cost_backward_pass}
    \overline{\bm W} = \overline{\bm h}\bm z^T,\quad\overline{\bm h} = \bm W^T\overline{\bm y}
\end{equation}
In Summe ergeben sich also \say{nur} etwa 3 Additionen und Multiplikationen pro Gewicht.
Da der Algorithmus allerdings während des Trainings eines Neural Networks sehr sehr oft durchlaufen wird,
ist der Rechenaufwand dennoch sehr hoch, weshalb sich Neural Networks erst in den letzten 5"~10 Jahren durchsetzen konnten.

\section{Learning Rate}%
\label{sec:Neural Networks:Learning Rate}
Wie schon von anderen Anwendungen des \nameref{sec:Gradient Descent} Verfahrens bekannt,
ist es wichtig die richtige Lernrate zu wählen:\\
\includegraphics[scale=.7]{neural_net_learning_rate.png}\\

\subsection{Variable Learning Rates}%
\label{sub:Variable Learning Rates}
Ein Problem von \glspl{SDG} ist,
dass gerade bei störbehafteten Loss Functions (z.B. wegen der Verwendung von Mini-Batches),
die Möglichkeit besteht,
dass der \nameref{cha:Gradient Descent} sehr langsam voran kommt.
Daher ist es sinnvoll,
eine variable Lernrate zu wählen.
Für die Wahl der aktuellen Lernrate gibt es verschiedene Verfahren.

\paragraph{Momentum Term}%
\label{par:Momentum Term}
Bei diesem Verfahren wird nicht die Lernrate an sich verändert,
sondern der Gradient,
der für die Anpassung der Gewichte verwendet wird.
Hierbei wir auf Basis der Gradienten $\bm g$ ein Moment $\bm m$ berechnet,
wobei es verschiedene Algorithmen zur Berechnung von $\bm m$ gibt
\begin{itemize}
    \item $\bm m_0 = 0,\quad \bm m_{k+1} = \gamma_k\bm m_k + (1-\gamma_k)\bm g_k$
    \item Geometric Average (constant $\gamma$):
        $\bm m_k = (1-\gamma)\sum_{i=1}^k \gamma^{k-i} \bm g_i$
    \item Arithmetic Average ($\gamma = \frac{k-1}{k}$):
        $\bm m_k = \frac{1}{k}\sum_{i=1}^k \bm g_i$
\end{itemize}
Anschließend wird das Moment $m$ anstatt dem Gradient $g$ für die Anpassung der Parameter verwendet.
\begin{equation} \label{eq:gradient_descent:momentum_update}
    \bm\theta_{k+1} = \bm\theta_k - \eta\bm m_{k+1}
\end{equation}

\paragraph{Gradient Normalisiation}%
\label{par:Gradient Normalisiation}
Ein Algorithmus,
der Wahlweise auch als ADADELTA oder \glsxtrshort{RMS}Prop bezeichnet wird,
ist die Gradient Normalisiation.
Hierbei wird die Lernrate normalisiert.
\begin{align} \label{eq:Gradient Normalisation}
    \bm g_k &= \nabla\mathcal L(\bm\theta_k)\\
    \bm v_{k+1,i} &= \gamma\bm v_{k,i} + (1+\gamma)\bm g_{k,i}^2\\
    \bm\theta_{k+1,i} &= \bm\theta_{k,i} - \frac{\eta}{\sqrt{\bm v_{k+1} + \epsilon}}\bm g_{k,i}
\end{align}
\begin{itemize}
    \item $\bm v_{k,i}$ errechnet fortlaufend den Durchschnitt der quadrierten Gradienten (\gls{RMS})
    \item $\epsilon$ ist nur enthalten um einer Division mit 0 vorzubeugen (sehr klein)
\end{itemize}

\paragraph{Adaptive Momentum (Adam)}%
\label{par:Adaptive Momentum}
Eine Kombination aus \nameref{par:Momentum Term} und \nameref{par:Gradient Normalisiation}.
Allerdings kann hierbei nicht mehr sichergestellt werden,
dass die Funktion konvergiert.
\begin{align} \label{eq:adam}
    \bm g_k &= \nabla\mathcal L(\bm\theta_k)\\
    \bm v_{k+1,i} &= \gamma_1\bm v_{k,i} + (1+\gamma_1)\bm g_{k,i}^2\\
    \bm m_{k+1} &=\gamma_2\bm m_k + (1-\gamma_2)\bm g_k\\
    \bm\theta_{k+1,i} &= \bm\theta_{k,i} - \frac{\eta c_2(k)}{\sqrt{c_1(k)\bm v_{k+1} + \epsilon}}\bm m_{k+1,i}
\end{align}
\begin{itemize}
    \item Initialisierung mit $\bm m_0 =0,\quad\bm v_0=0,\quad c_i(k) = \frac{1}{1-\gamma_i^k}$
    \item $\gamma_1=0.9,\quad\gamma_2=0.999,\quad\epsilon=10^{-8}$ sind gute Werte für die Parameter von Adam
\end{itemize}

\paragraph{Learning Rate Decay}%
\label{par:Learning Rate Decay}
Unter Learning Rate Decay fallen alle Algorithmen,
bei denen die Lernrate abhängig von der Anzahl der Durchläufe des \nameref{cha:Gradient Descent} Algorithmus nachlässt.
\begin{table}[H]
    \centering
    \caption{Verschiedene Learning Rate Decay Algorithmen}
    \label{tab:learning_rate_decay_algorithms}
    \begin{tabularx}{\textwidth}{X|Y|Y}
        \bfseries\centering Verfahren & \bfseries Learning Rate & \bfseries Training Loss\\
        \hline
        \textbf{Step:} Lernrate verändert sich nach einer bestimmten Anzahl von Algorithmus-Durchläufen & & \includegraphics[width=\linewidth,align=c]{learning_rate_decay_step.png}\\
        \hline
        \textbf{Cosine:}$\alpha_t = \frac{1}{2}\alpha_0(1+\cos(\frac{t\pi}{T}))$ &
        \includegraphics[width=\linewidth,align=c]{learning_rate_decay_cosine_learning_rate.png} &
        \includegraphics[width=\linewidth,align=c]{learning_rate_decay_cosine_training_loss.png} \\
        \hline
        \textbf{Linear:}$\alpha_t = \alpha_0(1-\frac{t}{T})$ &
        \includegraphics[width=\linewidth,align=c]{learning_rate_decay_linear_learning_rate.png} & \\
        \hline
        \textbf{Inverse sqrt:}$\alpha_t = \frac{\alpha_0}{\sqrt{t}}$ &
        \includegraphics[width=\linewidth,align=c]{learning_rate_decay_inverse_sqrt.png} & \\
    \end{tabularx}
    ($\alpha_0$: inital learning rate, $\alpha_t$: learning rate at epoch $t$, $T$: total number of epochs) 
\end{table}

\section{Second Order Optimization}%
\label{sec:Second Order Optimization}
Statt den Gradienten durch eine lineare Funktion zu approximieren ist es auch möglich,
den Gradienten durch eine Funktion 2-ten Grades zu approximieren.
Dies hat den Vorteil,
dass eine solche Approximation immer einen Tiefpunkt hat (da konvex),
welcher als neuer Punkt für den nächsten Schritt des \nameref{cha:Gradient Descent}s verwendet werden kann.
Zudem benötigt diese Art von Approximation keine Hyper-Parameter oder Lernraten und brauchen zudem weniger Schritte zum Ziel.
Der Nachteil ist jedoch, 
dass Funktionen dieser Art sehr rechenintensiv sind.\\
(mehr Informationen: \cref{sec:Zusaetzliche Informationen: Second Order Optimization}) 

