From 4446c1be47d2c1b77f37041302d11e22a07840e0 Mon Sep 17 00:00:00 2001 From: Morten Hjorth-Jensen Date: Mon, 26 Apr 2021 00:16:57 -0400 Subject: [PATCH] update book --- doc/BookChapters/chapter11.dlog | 29 + doc/BookChapters/chapter11.do.txt | 2319 ++++++++++++ doc/BookChapters/chapter12.dlog | 6 + doc/BookChapters/chapter12.do.txt | 578 +++ doc/BookChapters/chapter12.do.txt~ | 578 +++ .../_build/.doctrees/chapter1.doctree | Bin 432356 -> 432356 bytes .../_build/.doctrees/chapter10.doctree | Bin 419044 -> 419100 bytes .../_build/.doctrees/chapter11.doctree | Bin 0 -> 554808 bytes .../_build/.doctrees/environment.pickle | Bin 174283 -> 0 bytes .../_build/html/reports/chapter10.log | 29 + .../_build/html/reports/chapter5.log | 41 + .../_build/html/reports/chapter6.log | 66 + .../_build/html/reports/chapter7.log | 46 + .../_build/html/reports/linalg.log | 31 + .../_build/html/reports/statistics.log | 58 + .../_build/jupyter_execute/chapter1.ipynb | 4 +- .../_build/jupyter_execute/chapter10.ipynb | 16 +- .../_build/jupyter_execute/chapter11.ipynb | 3310 +++++++++++++++++ .../_build/jupyter_execute/chapter11.py | 2345 ++++++++++++ .../_build/jupyter_execute/chapter11_47_2.png | Bin 0 -> 23383 bytes .../_build/jupyter_execute/chapter11_49_3.png | Bin 0 -> 23773 bytes .../_build/jupyter_execute/chapter11_55_3.png | Bin 0 -> 29269 bytes .../_build/jupyter_execute/chapter11_63_3.png | Bin 0 -> 29269 bytes .../_build/jupyter_execute/chapter11_63_4.png | Bin 0 -> 34714 bytes .../_build/jupyter_execute/chapter11_76_3.png | Bin 0 -> 27786 bytes .../_build/jupyter_execute/chapter11_88_3.png | Bin 0 -> 27786 bytes .../_build/jupyter_execute/chapter11_88_4.png | Bin 0 -> 27580 bytes doc/LectureNotes/_toc.yml | 2 + doc/LectureNotes/chapter11.ipynb | 3023 +++++++++++++++ doc/LectureNotes/chapter12.ipynb | 732 ++++ 30 files changed, 13206 insertions(+), 7 deletions(-) create mode 100644 doc/BookChapters/chapter11.dlog create mode 100644 doc/BookChapters/chapter11.do.txt create mode 100644 doc/BookChapters/chapter12.dlog create mode 100644 doc/BookChapters/chapter12.do.txt create mode 100644 doc/BookChapters/chapter12.do.txt~ create mode 100644 doc/LectureNotes/_build/.doctrees/chapter11.doctree delete mode 100644 doc/LectureNotes/_build/.doctrees/environment.pickle create mode 100644 doc/LectureNotes/_build/html/reports/chapter10.log create mode 100644 doc/LectureNotes/_build/html/reports/chapter5.log create mode 100644 doc/LectureNotes/_build/html/reports/chapter6.log create mode 100644 doc/LectureNotes/_build/html/reports/chapter7.log create mode 100644 doc/LectureNotes/_build/html/reports/linalg.log create mode 100644 doc/LectureNotes/_build/html/reports/statistics.log create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11.ipynb create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11.py create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11_47_2.png create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11_49_3.png create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11_55_3.png create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11_63_3.png create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11_63_4.png create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11_76_3.png create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11_88_3.png create mode 100644 doc/LectureNotes/_build/jupyter_execute/chapter11_88_4.png create mode 100644 doc/LectureNotes/chapter11.ipynb create mode 100644 doc/LectureNotes/chapter12.ipynb diff --git a/doc/BookChapters/chapter11.dlog b/doc/BookChapters/chapter11.dlog new file mode 100644 index 000000000..05b99d6dc --- /dev/null +++ b/doc/BookChapters/chapter11.dlog @@ -0,0 +1,29 @@ +Translating doconce text in chapter11.do.txt to ipynb +*** replacing \bm{...} by \boldsymbol{...} (\bm is not supported by MathJax) + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{pmatrix} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. + +*** warning: latex envir \begin{aligned} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments. +Failed to remove ans_at_end environment +Failed to remove sol_at_end environment +output in chapter11.ipynb diff --git a/doc/BookChapters/chapter11.do.txt b/doc/BookChapters/chapter11.do.txt new file mode 100644 index 000000000..487acc23b --- /dev/null +++ b/doc/BookChapters/chapter11.do.txt @@ -0,0 +1,2319 @@ +======= Solving Differential Equations with Deep Learning ======= + +The Universal Approximation Theorem states that a neural network can +approximate any function at a single hidden layer along with one input +and output layer to any given precision. + + +An ordinary differential equation (ODE) is an equation involving functions having one variable. + +In general, an ordinary differential equation looks like + +!bt +\begin{equation} \label{ode} +f\left(x, \, g(x), \, g'(x), \, g''(x), \, \dots \, , \, g^{(n)}(x)\right) = 0 +\end{equation} +!et + +where $g(x)$ is the function to find, and $g^{(n)}(x)$ is the $n$-th derivative of $g(x)$. + +The $f\left(x, g(x), g'(x), g''(x), \, \dots \, , g^{(n)}(x)\right)$ is just a way to write that there is an expression involving $x$ and $g(x), \ g'(x), \ g''(x), \, \dots \, , \text{ and } g^{(n)}(x)$ on the left side of the equality sign in (ref{ode}). +The highest order of derivative, that is the value of $n$, determines to the order of the equation. +The equation is referred to as a $n$-th order ODE. +Along with (ref{ode}), some additional conditions of the function $g(x)$ are typically given +for the solution to be unique. + + + +Let the trial solution $g_t(x)$ be + +!bt +\begin{equation} + g_t(x) = h_1(x) + h_2(x,N(x,P)) +\end{equation} +!et + + +where $h_1(x)$ is a function that makes $g_t(x)$ satisfy a given set +of conditions, $N(x,P)$ a neural network with weights and biases +described by $P$ and $h_2(x, N(x,P))$ some expression involving the +neural network. The role of the function $h_2(x, N(x,P))$, is to +ensure that the output from $N(x,P)$ is zero when $g_t(x)$ is +evaluated at the values of $x$ where the given conditions must be +satisfied. The function $h_1(x)$ should alone make $g_t(x)$ satisfy +the conditions. + +But what about the network $N(x,P)$? + + +As described previously, an optimization method could be used to minimize the parameters of a neural network, that being its weights and biases, through backward propagation. + + + +For the minimization to be defined, we need to have a cost function at hand to minimize. + +It is given that $f\left(x, \, g(x), \, g'(x), \, g''(x), \, \dots \, , \, g^{(n)}(x)\right)$ should be equal to zero in (ref{ode}). +We can choose to consider the mean squared error as the cost function for an input $x$. +Since we are looking at one input, the cost function is just $f$ squared. +The cost function $c\left(x, P \right)$ can therefore be expressed as + +!bt +C\left(x, P\right) = \big(f\left(x, \, g(x), \, g'(x), \, g''(x), \, \dots \, , \, g^{(n)}(x)\right)\big)^2 +!et + +If $N$ inputs are given as a vector $\bm{x}$ with elements $x_i$ for $i = 1,\dots,N$, +the cost function becomes + +!bt +\begin{equation} \label{cost} + C\left(\bm{x}, P\right) = \frac{1}{N} \sum_{i=1}^N \big(f\left(x_i, \, g(x_i), \, g'(x_i), \, g''(x_i), \, \dots \, , \, g^{(n)}(x_i)\right)\big)^2 +\end{equation} +!et + +The neural net should then find the parameters $P$ that minimizes the cost function in +(ref{cost}) for a set of $N$ training samples $x_i$. + + + +To perform the minimization using gradient descent, the gradient of $C\left(\bm{x}, P\right)$ is needed. +It might happen so that finding an analytical expression of the gradient of $C(\bm{x}, P)$ from (ref{cost}) gets too messy, depending on which cost function one desires to use. + +Luckily, there exists libraries that makes the job for us through automatic differentiation. +Automatic differentiation is a method of finding the derivatives numerically with very high precision. + + +=== Example: Exponential decay === + +An exponential decay of a quantity $g(x)$ is described by the equation + +!bt +\begin{equation} \label{solve_expdec} + g'(x) = -\gamma g(x) +\end{equation} +!et + +with $g(0) = g_0$ for some chosen initial value $g_0$. + +The analytical solution of (ref{solve_expdec}) is + +!bt +\begin{equation} + g(x) = g_0 \exp\left(-\gamma x\right) +\end{equation} +!et + +Having an analytical solution at hand, it is possible to use it to compare how well a neural network finds a solution of (ref{solve_expdec}). + + + +The program will use a neural network to solve + +!bt +\begin{equation} \label{solveode} +g'(x) = -\gamma g(x) +\end{equation} +!et + +where $g(0) = g_0$ with $\gamma$ and $g_0$ being some chosen values. + +In this example, $\gamma = 2$ and $g_0 = 10$. + + +To begin with, a trial solution $g_t(t)$ must be chosen. A general trial solution for ordinary differential equations could be + +!bt +g_t(x, P) = h_1(x) + h_2(x, N(x, P)) +!et + +with $h_1(x)$ ensuring that $g_t(x)$ satisfies some conditions and $h_2(x,N(x, P))$ an expression involving $x$ and the output from the neural network $N(x,P)$ with $P $ being the collection of the weights and biases for each layer. For now, it is assumed that the network consists of one input layer, one hidden layer, and one output layer. + + + +In this network, there are no weights and bias at the input layer, so $P = \{ P_{\text{hidden}}, P_{\text{output}} \}$. +If there are $N_{\text{hidden} }$ neurons in the hidden layer, then $P_{\text{hidden}}$ is a $N_{\text{hidden} } \times (1 + N_{\text{input}})$ matrix, given that there are $N_{\text{input}}$ neurons in the input layer. + +The first column in $P_{\text{hidden} }$ represents the bias for each neuron in the hidden layer and the second column represents the weights for each neuron in the hidden layer from the input layer. +If there are $N_{\text{output} }$ neurons in the output layer, then $P_{\text{output}} $ is a $N_{\text{output} } \times (1 + N_{\text{hidden} })$ matrix. + +Its first column represents the bias of each neuron and the remaining columns represents the weights to each neuron. + +It is given that $g(0) = g_0$. The trial solution must fulfill this condition to be a proper solution of (ref{solveode}). A possible way to ensure that $g_t(0, P) = g_0$, is to let $F(N(x,P)) = x \cdot N(x,P)$ and $A(x) = g_0$. This gives the following trial solution: + +!bt +\begin{equation} \label{trial} +g_t(x, P) = g_0 + x \cdot N(x, P) +\end{equation} +!et + +=== Reformulating the problem === + +We wish that our neural network manages to minimize a given cost function. + +A reformulation of out equation, (ref{solveode}), must therefore be done, +such that it describes the problem a neural network can solve for. + +The neural network must find the set of weights and biases $P$ such that the trial solution in (ref{trial}) satisfies (ref{solveode}). + +The trial solution + +!bt +g_t(x, P) = g_0 + x \cdot N(x, P) +!et + +has been chosen such that it already solves the condition $g(0) = g_0$. What remains, is to find $P$ such that + +!bt +\begin{equation} \label{nnmin} +g_t'(x, P) = - \gamma g_t(x, P) +\end{equation} +!et + +is fulfilled as *best as possible*. + + +The left hand side and right hand side of (ref{nnmin}) must be computed separately, and then the neural network must choose weights and biases, contained in $P$, such that the sides are equal as best as possible. +This means that the absolute or squared difference between the sides must be as close to zero, ideally equal to zero. +In this case, the difference squared shows to be an appropriate measurement of how erroneous the trial solution is with respect to $P$ of the neural network. + +This gives the following cost function our neural network must solve for: + +!bt +\min_{P}\Big\{ \big(g_t'(x, P) - ( -\gamma g_t(x, P) \big)^2 \Big\} +!et + +(the notation $\min_{P}\{ f(x, P) \}$ means that we desire to find $P$ that yields the minimum of $f(x, P)$) + +or, in terms of weights and biases for the hidden and output layer in our network: + +!bt +\min_{P_{\text{hidden} }, \ P_{\text{output} }}\Big\{ \big(g_t'(x, \{ P_{\text{hidden} }, P_{\text{output} }\}) - ( -\gamma g_t(x, \{ P_{\text{hidden} }, P_{\text{output} }\}) \big)^2 \Big\} +!et + +for an input value $x$. + + + +If the neural network evaluates $g_t(x, P)$ at more values for $x$, say $N$ values $x_i$ for $i = 1, \dots, N$, then the *total* error to minimize becomes + +!bt +\begin{equation} \label{min} +\min_{P}\Big\{\frac{1}{N} \sum_{i=1}^N \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P) \big)^2 \Big\} +\end{equation} +!et + +Letting $\bm{x}$ be a vector with elements $x_i$ and $C(\bm{x}, P) = \frac{1}{N} \sum_i \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P) \big)^2$ denote the cost function, the minimization problem that our network must solve, becomes + +!bt +\min_{P} C(\bm{x}, P) +!et + +In terms of $P_{\text{hidden} }$ and $P_{\text{output} }$, this could also be expressed as + +$$ +\min_{P_{\text{hidden} }, \ P_{\text{output} }} C(\bm{x}, \{P_{\text{hidden} }, P_{\text{output} }\}) +$$ + + +For simplicity, it is assumed that the input is an array $\bm{x} = (x_1, \dots, x_N)$ with $N$ elements. It is at these points the neural network should find $P$ such that it fulfills (ref{min}). + +First, the neural network must feed forward the inputs. +This means that $\bm{x}s$ must be passed through an input layer, a hidden layer and a output layer. The input layer in this case, does not need to process the data any further. +The input layer will consist of $N_{\text{input} }$ neurons, passing its element to each neuron in the hidden layer. The number of neurons in the hidden layer will be $N_{\text{hidden} }$. + + +For the $i$-th in the hidden layer with weight $w_i^{\text{hidden} }$ and bias $b_i^{\text{hidden} }$, the weighting from the $j$-th neuron at the input layer is: + +!bt +\begin{aligned} +z_{i,j}^{\text{hidden}} &= b_i^{\text{hidden}} + w_i^{\text{hidden}}x_j \\ +&= +\begin{pmatrix} +b_i^{\text{hidden}} & w_i^{\text{hidden}} +\end{pmatrix} +\begin{pmatrix} +1 \\ +x_j +\end{pmatrix} +\end{aligned} +!et + + + +The result after weighting the inputs at the $i$-th hidden neuron can be written as a vector: + +!bt +\begin{aligned} +\bm{z}_{i}^{\text{hidden}} &= \Big( b_i^{\text{hidden}} + w_i^{\text{hidden}}x_1 , \ b_i^{\text{hidden}} + w_i^{\text{hidden}} x_2, \ \dots \, , \ b_i^{\text{hidden}} + w_i^{\text{hidden}} x_N\Big) \\ +&= +\begin{pmatrix} + b_i^{\text{hidden}} & w_i^{\text{hidden}} +\end{pmatrix} +\begin{pmatrix} +1 & 1 & \dots & 1 \\ +x_1 & x_2 & \dots & x_N +\end{pmatrix} \\ +&= \bm{p}_{i, \text{hidden}}^T X +\end{aligned} +!et + + +The vector $\bm{p}_{i, \text{hidden}}^T$ constitutes each row in $P_{\text{hidden} }$, which contains the weights for the neural network to minimize according to (ref{min}). + +After having found $\bm{z}_{i}^{\text{hidden}} $ for every $i$-th neuron within the hidden layer, the vector will be sent to an activation function $a_i(\bm{z})$. + +In this example, the sigmoid function has been chosen to be the activation function for each hidden neuron: + +!bt +f(z) = \frac{1}{1 + \exp{(-z)}} +!et + +It is possible to use other activations functions for the hidden layer also. + +The output $\bm{x}_i^{\text{hidden}}$ from each $i$-th hidden neuron is: + +$$ +\bm{x}_i^{\text{hidden} } = f\big( \bm{z}_{i}^{\text{hidden}} \big) +$$ + +The outputs $\bm{x}_i^{\text{hidden} } $ are then sent to the output layer. + +The output layer consists of one neuron in this case, and combines the +output from each of the neurons in the hidden layers. The output layer +combines the results from the hidden layer using some weights $w_i^{\text{output}}$ +and biases $b_i^{\text{output}}$. In this case, +it is assumes that the number of neurons in the output layer is one. + + + +The procedure of weighting the output neuron $j$ in the hidden layer to the $i$-th neuron in the output layer is similar as for the hidden layer described previously. + +!bt +\begin{aligned} +z_{1,j}^{\text{output}} & = +\begin{pmatrix} +b_1^{\text{output}} & \bm{w}_1^{\text{output}} +\end{pmatrix} +\begin{pmatrix} +1 \\ +\bm{x}_j^{\text{hidden}} +\end{pmatrix} +\end{aligned} +!et + + +Expressing $z_{1,j}^{\text{output}}$ as a vector gives the following way of weighting the inputs from the hidden layer: + +!bt +\bm{z}_{1}^{\text{output}} = +\begin{pmatrix} +b_1^{\text{output}} & \bm{w}_1^{\text{output}} +\end{pmatrix} +\begin{pmatrix} +1 & 1 & \dots & 1 \\ +\bm{x}_1^{\text{hidden}} & \bm{x}_2^{\text{hidden}} & \dots & \bm{x}_N^{\text{hidden}} +\end{pmatrix} +!et + +In this case we seek a continuous range of values since we are approximating a function. This means that after computing $\bm{z}_{1}^{\text{output}}$ the neural network has finished its feed forward step, and $\bm{z}_{1}^{\text{output}}$ is the final output of the network. + + +The next step is to decide how the parameters should be changed such that they minimize the cost function. + +The chosen cost function for this problem is + +!bt +C(\bm{x}, P) = \frac{1}{N} \sum_i \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P) \big)^2 +!et + +In order to minimize the cost function, an optimization method must be chosen. + +Here, gradient descent with a constant step size has been chosen. + +=== Gradient descent === + +The idea of the gradient descent algorithm is to update parameters in +a direction where the cost function decreases goes to a minimum. + +In general, the update of some parameters $\bm{\omega}$ given a cost +function defined by some weights $\bm{\omega}$, $C(\bm{x}, +\bm{\omega})$, goes as follows: + +!bt +\bm{\omega}_{\text{new} } = \bm{\omega} - \lambda \nabla_{\bm{\omega}} C(\bm{x}, \bm{\omega}) +!et + +for a number of iterations or until $ \big|\big| \bm{\omega}_{\text{new} } - \bm{\omega} \big|\big|$ becomes smaller than some given tolerance. + +The value of $\lambda$ decides how large steps the algorithm must take +in the direction of $ \nabla_{\bm{\omega}} C(\bm{x}, \bm{\omega})$. +The notation $\nabla_{\bm{\omega}}$ express the gradient with respect +to the elements in $\bm{\omega}$. + +In our case, we have to minimize the cost function $C(\bm{x}, P)$ with +respect to the two sets of weights and biases, that is for the hidden +layer $P_{\text{hidden} }$ and for the output layer $P_{\text{output} +}$ . + +This means that $P_{\text{hidden} }$ and $P_{\text{output} }$ is updated by + +!bt +\begin{aligned} +P_{\text{hidden},\text{new}} &= P_{\text{hidden}} - \lambda \nabla_{P_{\text{hidden}}} C(\bm{x}, P) \\ +P_{\text{output},\text{new}} &= P_{\text{output}} - \lambda \nabla_{P_{\text{output}}} C(\bm{x}, P) +\end{aligned} +!et + +=== The code for solving the ODE === + +!bc pycod +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +# Assuming one input, hidden, and output layer +def neural_network(params, x): + + # Find the weights (including and biases) for the hidden and output layer. + # Assume that params is a list of parameters for each layer. + # The biases are the first element for each array in params, + # and the weights are the remaning elements in each array in params. + + w_hidden = params[0] + w_output = params[1] + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + ## Hidden layer: + + # Add a row of ones to include bias + x_input = np.concatenate((np.ones((1,num_values)), x_input ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_input) + x_hidden = sigmoid(z_hidden) + + ## Output layer: + + # Include bias: + x_hidden = np.concatenate((np.ones((1,num_values)), x_hidden ), axis = 0) + + z_output = np.matmul(w_output, x_hidden) + x_output = z_output + + return x_output + +# The trial solution using the deep neural network: +def g_trial(x,params, g0 = 10): + return g0 + x*neural_network(params,x) + +# The right side of the ODE: +def g(x, g_trial, gamma = 2): + return -gamma*g_trial + +# The cost function: +def cost_function(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial(x,P) + + # Find the derivative w.r.t x of the neural network + d_net_out = elementwise_grad(neural_network,1)(P,x) + + # Find the derivative w.r.t x of the trial function + d_g_t = elementwise_grad(g_trial,0)(x,P) + + # The right side of the ODE + func = g(x, g_t) + + err_sqr = (d_g_t - func)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum / np.size(err_sqr) + +# Solve the exponential decay ODE using neural network with one input, hidden, and output layer +def solve_ode_neural_network(x, num_neurons_hidden, num_iter, lmb): + ## Set up initial weights and biases + + # For the hidden layer + p0 = npr.randn(num_neurons_hidden, 2 ) + + # For the output layer + p1 = npr.randn(1, num_neurons_hidden + 1 ) # +1 since bias is included + + P = [p0, p1] + + print('Initial cost: %g'%cost_function(P, x)) + + ## Start finding the optimal weights using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_grad = grad(cost_function,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of two arrays; + # one for the gradient w.r.t P_hidden and + # one for the gradient w.r.t P_output + cost_grad = cost_function_grad(P, x) + + P[0] = P[0] - lmb * cost_grad[0] + P[1] = P[1] - lmb * cost_grad[1] + + print('Final cost: %g'%cost_function(P, x)) + + return P + +def g_analytic(x, gamma = 2, g0 = 10): + return g0*np.exp(-gamma*x) + +# Solve the given problem +if __name__ == '__main__': + # Set seed such that the weight are initialized + # with same weights and biases for every run. + npr.seed(15) + + ## Decide the vales of arguments to the function to solve + N = 10 + x = np.linspace(0, 1, N) + + ## Set up the initial parameters + num_hidden_neurons = 10 + num_iter = 10000 + lmb = 0.001 + + # Use the network + P = solve_ode_neural_network(x, num_hidden_neurons, num_iter, lmb) + + # Print the deviation from the trial solution and true solution + res = g_trial(x,P) + res_analytical = g_analytic(x) + + print('Max absolute difference: %g'%np.max(np.abs(res - res_analytical))) + + # Plot the results + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(x, res_analytical) + plt.plot(x, res[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('x') + plt.ylabel('g(x)') + plt.show() +!ec + + +===== The network with one input layer, specified number of hidden layers, and one output layer ===== + +It is also possible to extend the construction of our network into a more general one, allowing the network to contain more than one hidden layers. + +The number of neurons within each hidden layer are given as a list of integers in the program below. + +!bc pycod +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +# The neural network with one input layer and one output layer, +# but with number of hidden layers specified by the user. +def deep_neural_network(deep_params, x): + # N_hidden is the number of hidden layers + + N_hidden = np.size(deep_params) - 1 # -1 since params consists of + # parameters to all the hidden + # layers AND the output layer. + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + # Due to multiple hidden layers, define a variable referencing to the + # output of the previous layer: + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output + +# The trial solution using the deep neural network: +def g_trial_deep(x,params, g0 = 10): + return g0 + x*deep_neural_network(params, x) + +# The right side of the ODE: +def g(x, g_trial, gamma = 2): + return -gamma*g_trial + +# The same cost function as before, but calls deep_neural_network instead. +def cost_function_deep(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial_deep(x,P) + + # Find the derivative w.r.t x of the neural network + d_net_out = elementwise_grad(deep_neural_network,1)(P,x) + + # Find the derivative w.r.t x of the trial function + d_g_t = elementwise_grad(g_trial_deep,0)(x,P) + + # The right side of the ODE + func = g(x, g_t) + + err_sqr = (d_g_t - func)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum / np.size(err_sqr) + +# Solve the exponential decay ODE using neural network with one input and one output layer, +# but with specified number of hidden layers from the user. +def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb): + # num_hidden_neurons is now a list of number of neurons within each hidden layer + + # The number of elements in the list num_hidden_neurons thus represents + # the number of hidden layers. + + # Find the number of hidden layers: + N_hidden = np.size(num_neurons) + + ## Set up initial weights and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 ) + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: %g'%cost_function_deep(P, x)) + + ## Start finding the optimal weights using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_deep_grad = grad(cost_function_deep,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases + # in the hidden layers and output layers evaluated at x. + cost_deep_grad = cost_function_deep_grad(P, x) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_deep_grad[l] + + print('Final cost: %g'%cost_function_deep(P, x)) + + return P + +def g_analytic(x, gamma = 2, g0 = 10): + return g0*np.exp(-gamma*x) + +# Solve the given problem +if __name__ == '__main__': + npr.seed(15) + + ## Decide the vales of arguments to the function to solve + N = 10 + x = np.linspace(0, 1, N) + + ## Set up the initial parameters + num_hidden_neurons = np.array([10,10]) + num_iter = 10000 + lmb = 0.001 + + P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb) + + res = g_trial_deep(x,P) + res_analytical = g_analytic(x) + + plt.figure(figsize=(10,10)) + + plt.title('Performance of a deep neural network solving an ODE compared to the analytical solution') + plt.plot(x, res_analytical) + plt.plot(x, res[0,:]) + plt.legend(['analytical','dnn']) + plt.ylabel('g(x)') + plt.show() +!ec + + + +=== Example: Population growth === + +A logistic model of population growth assumes that a population converges toward an equilibrium. +The population growth can be modeled by + +!bt +\begin{equation} \label{log} + g'(t) = \alpha g(t)(A - g(t)) +\end{equation} +!et + +where $g(t)$ is the population density at time $t$, $\alpha > 0$ the growth rate and $A > 0$ is the maximum population number in the environment. +Also, at $t = 0$ the population has the size $g(0) = g_0$, where $g_0$ is some chosen constant. + +In this example, similar network as for the exponential decay using Autograd has been used to solve the equation. However, as the implementation might suffer from e.g numerical instability +and high execution time (this might be more apparent in the examples solving PDEs), +using a library like TensorFlow is recommended. +Here, we stay with a more simple approach and implement for comparison, the simple forward Euler method. + + + +Here, we will model a population $g(t)$ in an environment having carrying capacity $A$. +The population follows the model + +!bt +\begin{equation} \label{solveode_population} +g'(t) = \alpha g(t)(A - g(t)) +\end{equation} +!et + +where $g(0) = g_0$. + +In this example, we let $\alpha = 2$, $A = 1$, and $g_0 = 1.2$. + + +We will get a slightly different trial solution, as the boundary conditions are different +compared to the case for exponential decay. + +A possible trial solution satisfying the condition $g(0) = g_0$ could be + +$$ +h_1(t) = g_0 + t \cdot N(t,P) +$$ + +with $N(t,P)$ being the output from the neural network with weights and biases for each layer collected in the set $P$. + +The analytical solution is + +$$ +g(t) = \frac{Ag_0}{g_0 + (A - g_0)\exp(-\alpha A t)} +$$ + + + +The network will be the similar as for the exponential decay example, but with some small modifications for our problem. + +!bc pycod +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +# Function to get the parameters. +# Done such that one can easily change the paramaters after one's liking. +def get_parameters(): + alpha = 2 + A = 1 + g0 = 1.2 + return alpha, A, g0 + +def deep_neural_network(P, x): + # N_hidden is the number of hidden layers + N_hidden = np.size(P) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + # Due to multiple hidden layers, define a variable referencing to the + # output of the previous layer: + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = P[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = P[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output + + +def cost_function_deep(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial_deep(x,P) + + # Find the derivative w.r.t x of the trial function + d_g_t = elementwise_grad(g_trial_deep,0)(x,P) + + # The right side of the ODE + func = f(x, g_t) + + err_sqr = (d_g_t - func)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum / np.size(err_sqr) + +# The right side of the ODE: +def f(x, g_trial): + alpha,A, g0 = get_parameters() + return alpha*g_trial*(A - g_trial) + +# The trial solution using the deep neural network: +def g_trial_deep(x, params): + alpha,A, g0 = get_parameters() + return g0 + x*deep_neural_network(params,x) + +# The analytical solution: +def g_analytic(t): + alpha,A, g0 = get_parameters() + return A*g0/(g0 + (A - g0)*np.exp(-alpha*A*t)) + +def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb): + # num_hidden_neurons is now a list of number of neurons within each hidden layer + + # Find the number of hidden layers: + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 ) + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: %g'%cost_function_deep(P, x)) + + ## Start finding the optimal weigths using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_deep_grad = grad(cost_function_deep,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases + # in the hidden layers and output layers evaluated at x. + cost_deep_grad = cost_function_deep_grad(P, x) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_deep_grad[l] + + print('Final cost: %g'%cost_function_deep(P, x)) + + return P + +if __name__ == '__main__': + npr.seed(4155) + + ## Decide the vales of arguments to the function to solve + Nt = 10 + T = 1 + t = np.linspace(0,T, Nt) + + ## Set up the initial parameters + num_hidden_neurons = [100, 50, 25] + num_iter = 1000 + lmb = 1e-3 + + P = solve_ode_deep_neural_network(t, num_hidden_neurons, num_iter, lmb) + + g_dnn_ag = g_trial_deep(t,P) + g_analytical = g_analytic(t) + + # Find the maximum absolute difference between the solutons: + diff_ag = np.max(np.abs(g_dnn_ag - g_analytical)) + print("The max absolute difference between the solutions is: %g"%diff_ag) + + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(t, g_analytical) + plt.plot(t, g_dnn_ag[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('t') + plt.ylabel('g(t)') + + plt.show() +!ec + +===== Using forward Euler to solve the ODE ===== + +A straightforward way of solving an ODE numerically, is to use Euler's method. + +Euler's method uses Taylor series to approximate the value at a function $f$ at a step $\Delta x$ from $x$: + +$$ +f(x + \Delta x) \approx f(x) + \Delta x f'(x) +$$ + +In our case, using Euler's method to approximate the value of $g$ at a step $\Delta t$ from $t$ yields + +!bt +\begin{aligned} + g(t + \Delta t) &\approx g(t) + \Delta t g'(t) \\ + &= g(t) + \Delta t \big(\alpha g(t)(A - g(t))\big) +\end{aligned} +!et +along with the condition that $g(0) = g_0$. + +Let $t_i = i \cdot \Delta t$ where $\Delta t = \frac{T}{N_t-1}$ where $T$ is the final time our solver must solve for and $N_t$ the number of values for $t \in [0, T]$ for $i = 0, \dots, N_t-1$. + +For $i \geq 1$, we have that +!bt +\begin{aligned} +t_i &= i\Delta t \\ +&= (i - 1)\Delta t + \Delta t \\ +&= t_{i-1} + \Delta t +\end{aligned} +!et + +Now, if $g_i = g(t_i)$ then + +!bt +\begin{equation} + \begin{aligned} + g_i &= g(t_i) \\ + &= g(t_{i-1} + \Delta t) \\ + &\approx g(t_{i-1}) + \Delta t \big(\alpha g(t_{i-1})(A - g(t_{i-1}))\big) \\ + &= g_{i-1} + \Delta t \big(\alpha g_{i-1}(A - g_{i-1})\big) + \end{aligned} +\end{equation} \label{odenum} +!et +for $i \geq 1$ and $g_0 = g(t_0) = g(0) = g_0$. + +Equation (ref{odenum}) could be implemented in the following way, +extending the program that uses the network using Autograd: + +!bc pycod +# Assume that all function definitions from the example program using Autograd +# are located here. + +if __name__ == '__main__': + npr.seed(4155) + + ## Decide the vales of arguments to the function to solve + Nt = 10 + T = 1 + t = np.linspace(0,T, Nt) + + ## Set up the initial parameters + num_hidden_neurons = [100,50,25] + num_iter = 1000 + lmb = 1e-3 + + P = solve_ode_deep_neural_network(t, num_hidden_neurons, num_iter, lmb) + + g_dnn_ag = g_trial_deep(t,P) + g_analytical = g_analytic(t) + + # Find the maximum absolute difference between the solutons: + diff_ag = np.max(np.abs(g_dnn_ag - g_analytical)) + print("The max absolute difference between the solutions is: %g"%diff_ag) + + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(t, g_analytical) + plt.plot(t, g_dnn_ag[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('t') + plt.ylabel('g(t)') + + ## Find an approximation to the funtion using forward Euler + + alpha, A, g0 = get_parameters() + dt = T/(Nt - 1) + + # Perform forward Euler to solve the ODE + g_euler = np.zeros(Nt) + g_euler[0] = g0 + + for i in range(1,Nt): + g_euler[i] = g_euler[i-1] + dt*(alpha*g_euler[i-1]*(A - g_euler[i-1])) + + # Print the errors done by each method + diff1 = np.max(np.abs(g_euler - g_analytical)) + diff2 = np.max(np.abs(g_dnn_ag[0,:] - g_analytical)) + + print('Max absolute difference between Euler method and analytical: %g'%diff1) + print('Max absolute difference between deep neural network and analytical: %g'%diff2) + + # Plot results + plt.figure(figsize=(10,10)) + + plt.plot(t,g_euler) + plt.plot(t,g_analytical) + plt.plot(t,g_dnn_ag[0,:]) + + plt.legend(['euler','analytical','dnn']) + plt.xlabel('Time t') + plt.ylabel('g(t)') + + plt.show() +!ec + + + + +===== Solving the one dimensional Poisson equation ===== + +The Poisson equation for $g(x)$ in one dimension is + +!bt +\begin{equation} \label{poisson} + -g''(x) = f(x) +\end{equation} +!et + +where $f(x)$ is a given function for $x \in (0,1)$. + +The conditions that $g(x)$ is chosen to fulfill, are +!bt +\begin{align*} + g(0) &= 0 \\ + g(1) &= 0 +\end{align*} +!et + +This equation can be solved numerically using programs where e.g Autograd and TensorFlow are used. +The results from the networks can then be compared to the analytical solution. +In addition, it could be interesting to see how a typical method for numerically solving second order ODEs compares to the neural networks. + + +Here, the function $g(x)$ to solve for follows the equation + +!bt +-g''(x) = f(x),\qquad x \in (0,1) +!et + +where $f(x)$ is a given function, along with the chosen conditions + +!bt +\begin{aligned} +g(0) = g(1) = 0 +\end{aligned}\label{cond} +!et + +In this example, we consider the case when $f(x) = (3x + x^2)\exp(x)$. + +For this case, a possible trial solution satisfying the conditions could be + +!bt +g_t(x) = x \cdot (1-x) \cdot N(P,x) +!et + +The analytical solution for this problem is + +!bt +g(x) = x(1 - x)\exp(x) +!et + + +!bc pycod +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + # Due to multiple hidden layers, define a variable referencing to the + # output of the previous layer: + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output + +def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb): + # num_hidden_neurons is now a list of number of neurons within each hidden layer + + # Find the number of hidden layers: + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 ) + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: %g'%cost_function_deep(P, x)) + + ## Start finding the optimal weigths using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_deep_grad = grad(cost_function_deep,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases + # in the hidden layers and output layers evaluated at x. + cost_deep_grad = cost_function_deep_grad(P, x) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_deep_grad[l] + + print('Final cost: %g'%cost_function_deep(P, x)) + + return P + +## Set up the cost function specified for this Poisson equation: + +# The right side of the ODE +def f(x): + return (3*x + x**2)*np.exp(x) + +def cost_function_deep(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial_deep(x,P) + + # Find the derivative w.r.t x of the trial function + d2_g_t = elementwise_grad(elementwise_grad(g_trial_deep,0))(x,P) + + right_side = f(x) + + err_sqr = (-d2_g_t - right_side)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum/np.size(err_sqr) + +# The trial solution: +def g_trial_deep(x,P): + return x*(1-x)*deep_neural_network(P,x) + +# The analytic solution; +def g_analytic(x): + return x*(1-x)*np.exp(x) + +if __name__ == '__main__': + npr.seed(4155) + + ## Decide the vales of arguments to the function to solve + Nx = 10 + x = np.linspace(0,1, Nx) + + ## Set up the initial parameters + num_hidden_neurons = [200,100] + num_iter = 1000 + lmb = 1e-3 + + P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb) + + g_dnn_ag = g_trial_deep(x,P) + g_analytical = g_analytic(x) + + # Find the maximum absolute difference between the solutons: + max_diff = np.max(np.abs(g_dnn_ag - g_analytical)) + print("The max absolute difference between the solutions is: %g"%max_diff) + + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(x, g_analytical) + plt.plot(x, g_dnn_ag[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('x') + plt.ylabel('g(x)') + plt.show() +!ec + +=== Comparing with a numerical scheme === + +The Poisson equation is possible to solve using Taylor series to approximate the second derivative. + +Using Taylor series, the second derivative can be expressed as + +$$ +g''(x) = \frac{g(x + \Delta x) - 2g(x) + g(x-\Delta x)}{\Delta x^2} + E_{\Delta x}(x) +$$ + +where $\Delta x$ is a small step size and $E_{\Delta x}(x)$ being the error term. + +Looking away from the error terms gives an approximation to the second derivative: + +!bt +\begin{equation} \label{approx} +g''(x) \approx \frac{g(x + \Delta x) - 2g(x) + g(x-\Delta x)}{\Delta x^2} +\end{equation} +!et + +If $x_i = i \Delta x = x_{i-1} + \Delta x$ and $g_i = g(x_i)$ for $i = 1,\dots N_x - 2$ with $N_x$ being the number of values for $x$, (ref{approx}) becomes + +!bt +\begin{aligned} +g''(x_i) &\approx \frac{g(x_i + \Delta x) - 2g(x_i) + g(x_i -\Delta x)}{\Delta x^2} \\ +&= \frac{g_{i+1} - 2g_i + g_{i-1}}{\Delta x^2} +\end{aligned} +!et + +Since we know from our problem that + +!bt +\begin{aligned} +-g''(x) &= f(x) \\ +&= (3x + x^2)\exp(x) +\end{aligned} +!et + +along with the conditions $g(0) = g(1) = 0$, +the following scheme can be used to find an approximate solution for $g(x)$ numerically: + +!bt +\begin{equation} + \begin{aligned} + -\Big( \frac{g_{i+1} - 2g_i + g_{i-1}}{\Delta x^2} \Big) &= f(x_i) \\ + -g_{i+1} + 2g_i - g_{i-1} &= \Delta x^2 f(x_i) + \end{aligned} +\end{equation} \label{odesys} +!et + +for $i = 1, \dots, N_x - 2$ where $g_0 = g_{N_x - 1} = 0$ and $f(x_i) = (3x_i + x_i^2)\exp(x_i)$, which is given for our specific problem. + +The equation can be rewritten into a matrix equation: + +!bt +\begin{aligned} +\begin{pmatrix} +2 & -1 & 0 & \dots & 0 \\ +-1 & 2 & -1 & \dots & 0 \\ +\vdots & & \ddots & & \vdots \\ +0 & \dots & -1 & 2 & -1 \\ +0 & \dots & 0 & -1 & 2\\ +\end{pmatrix} +\begin{pmatrix} +g_1 \\ +g_2 \\ +\vdots \\ +g_{N_x - 3} \\ +g_{N_x - 2} +\end{pmatrix} +&= +\Delta x^2 +\begin{pmatrix} +f(x_1) \\ +f(x_2) \\ +\vdots \\ +f(x_{N_x - 3}) \\ +f(x_{N_x - 2}) +\end{pmatrix} \\ +\bm{A}\bm{g} &= \bm{f}, +\end{aligned} +!et + +which makes it possible to solve for the vector $\bm{g}$. + + +We can then compare the result from this numerical scheme with the output from our network using Autograd: + +!bc pycod +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + # Due to multiple hidden layers, define a variable referencing to the + # output of the previous layer: + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output + +def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb): + # num_hidden_neurons is now a list of number of neurons within each hidden layer + + # Find the number of hidden layers: + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 ) + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: %g'%cost_function_deep(P, x)) + + ## Start finding the optimal weigths using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_deep_grad = grad(cost_function_deep,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases + # in the hidden layers and output layers evaluated at x. + cost_deep_grad = cost_function_deep_grad(P, x) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_deep_grad[l] + + print('Final cost: %g'%cost_function_deep(P, x)) + + return P + +## Set up the cost function specified for this Poisson equation: + +# The right side of the ODE +def f(x): + return (3*x + x**2)*np.exp(x) + +def cost_function_deep(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial_deep(x,P) + + # Find the derivative w.r.t x of the trial function + d2_g_t = elementwise_grad(elementwise_grad(g_trial_deep,0))(x,P) + + right_side = f(x) + + err_sqr = (-d2_g_t - right_side)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum/np.size(err_sqr) + +# The trial solution: +def g_trial_deep(x,P): + return x*(1-x)*deep_neural_network(P,x) + +# The analytic solution; +def g_analytic(x): + return x*(1-x)*np.exp(x) + +if __name__ == '__main__': + npr.seed(4155) + + ## Decide the vales of arguments to the function to solve + Nx = 10 + x = np.linspace(0,1, Nx) + + ## Set up the initial parameters + num_hidden_neurons = [200,100] + num_iter = 1000 + lmb = 1e-3 + + P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb) + + g_dnn_ag = g_trial_deep(x,P) + g_analytical = g_analytic(x) + + # Find the maximum absolute difference between the solutons: + + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(x, g_analytical) + plt.plot(x, g_dnn_ag[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('x') + plt.ylabel('g(x)') + + ## Perform the computation using the numerical scheme + + dx = 1/(Nx - 1) + + # Set up the matrix A + A = np.zeros((Nx-2,Nx-2)) + + A[0,0] = 2 + A[0,1] = -1 + + for i in range(1,Nx-3): + A[i,i-1] = -1 + A[i,i] = 2 + A[i,i+1] = -1 + + A[Nx - 3, Nx - 4] = -1 + A[Nx - 3, Nx - 3] = 2 + + # Set up the vector f + f_vec = dx**2 * f(x[1:-1]) + + # Solve the equation + g_res = np.linalg.solve(A,f_vec) + + g_vec = np.zeros(Nx) + g_vec[1:-1] = g_res + + # Print the differences between each method + max_diff1 = np.max(np.abs(g_dnn_ag - g_analytical)) + max_diff2 = np.max(np.abs(g_vec - g_analytical)) + print("The max absolute difference between the analytical solution and DNN Autograd: %g"%max_diff1) + print("The max absolute difference between the analytical solution and numerical scheme: %g"%max_diff2) + + # Plot the results + plt.figure(figsize=(10,10)) + + plt.plot(x,g_vec) + plt.plot(x,g_analytical) + plt.plot(x,g_dnn_ag[0,:]) + + plt.legend(['numerical scheme','analytical','dnn']) + plt.show() + +!ec + + +===== Partial Differential Equations ===== + +A partial differential equation (PDE) has a solution here the function +is defined by multiple variables. The equation may involve all kinds +of combinations of which variables the function is differentiated with +respect to. + +In general, a partial differential equation for a function $g(x_1,\dots,x_N)$ with $N$ variables may be expressed as + +!bt +\begin{equation} \label{PDE} + f\left(x_1, \, \dots \, , x_N, \frac{\partial g(x_1,\dots,x_N) }{\partial x_1}, \dots , \frac{\partial g(x_1,\dots,x_N) }{\partial x_N}, \frac{\partial g(x_1,\dots,x_N) }{\partial x_1\partial x_2}, \, \dots \, , \frac{\partial^n g(x_1,\dots,x_N) }{\partial x_N^n} \right) = 0 +\end{equation} +!et + +where $f$ is an expression involving all kinds of possible mixed derivatives of $g(x_1,\dots,x_N)$ up to an order $n$. In order for the solution to be unique, some additional conditions must also be given. + +=== Type of problem === + +The problem our network must solve for, is similar to the ODE case. +We must have a trial solution $g_t$ at hand. + +For instance, the trial solution could be expressed as +!bt +\begin{align*} + g_t(x_1,\dots,x_N) = h_1(x_1,\dots,x_N) + h_2(x_1,\dots,x_N,N(x_1,\dots,x_N,P)) +\end{align*} +!et +where $h_1(x_1,\dots,x_N)$ is a function that ensures $g_t(x_1,\dots,x_N)$ satisfies some given conditions. +The neural network $N(x_1,\dots,x_N,P)$ has weights and biases described by $P$ and $h_2(x_1,\dots,x_N,N(x_1,\dots,x_N,P))$ is an expression using the output from the neural network in some way. + +The role of the function $h_2(x_1,\dots,x_N,N(x_1,\dots,x_N,P))$, is to ensure that the output of $N(x_1,\dots,x_N,P)$ is zero when $g_t(x_1,\dots,x_N)$ is evaluated at the values of $x_1,\dots,x_N$ where the given conditions must be satisfied. The function $h_1(x_1,\dots,x_N)$ should alone make $g_t(x_1,\dots,x_N)$ satisfy the conditions. + + + +=== Network requirements === + +The network tries then the minimize the cost function following the +same ideas as described for the ODE case, but now with more than one +variables to consider. The concept still remains the same; find a set +of parameters $P$ such that the expression $f$ in (ref{PDE}) is as +close to zero as possible. + +As for the ODE case, the cost function is the mean squared error that +the network must try to minimize. The cost function for the network to +minimize is + +!bt +\begin{equation*} +C\left(x_1, \dots, x_N, P\right) = \left( f\left(x_1, \, \dots \, , x_N, \frac{\partial g(x_1,\dots,x_N) }{\partial x_1}, \dots , \frac{\partial g(x_1,\dots,x_N) }{\partial x_N}, \frac{\partial g(x_1,\dots,x_N) }{\partial x_1\partial x_2}, \, \dots \, , \frac{\partial^n g(x_1,\dots,x_N) }{\partial x_N^n} \right) \right)^2 +\end{equation*} +!et + + +If we let $\bm{x} = \big( x_1, \dots, x_N \big)$ be an array containing the values for $x_1, \dots, x_N$ respectively, the cost function can be reformulated into the following: +!bt +\[ + C\left(\bm{x}, P\right) = f\left( \left( \bm{x}, \frac{\partial g(\bm{x}) }{\partial x_1}, \dots , \frac{\partial g(\bm{x}) }{\partial x_N}, \frac{\partial g(\bm{x}) }{\partial x_1\partial x_2}, \, \dots \, , \frac{\partial^n g(\bm{x}) }{\partial x_N^n} \right) \right)^2 +\] +!et + +If we also have $M$ different sets of values for $x_1, \dots, x_N$, that is $\bm{x}_i = \big(x_1^{(i)}, \dots, x_N^{(i)}\big)$ for $i = 1,\dots,M$ being the rows in matrix $X$, the cost function can be generalized into +!bt +\begin{equation*} +C\left(X, P \right) = \sum_{i=1}^M f\left( \left( \bm{x}_i, \frac{\partial g(\bm{x}_i) }{\partial x_1}, \dots , \frac{\partial g(\bm{x}_i) }{\partial x_N}, \frac{\partial g(\bm{x}_i) }{\partial x_1\partial x_2}, \, \dots \, , \frac{\partial^n g(\bm{x}_i) }{\partial x_N^n} \right) \right)^2. +\end{equation*} +!et + + +===== Example: The diffusion equation ===== + +In one spatial dimension, the equation reads +!bt +\begin{equation*} + \frac{\partial g(x,t)}{\partial t} = \frac{\partial^2 g(x,t)}{\partial x^2} +\end{equation*} +!et + +where a possible choice of conditions are +!bt +\begin{align*} +g(0,t) &= 0 ,\qquad t \geq 0 \\ +g(1,t) &= 0, \qquad t \geq 0 \\ +g(x,0) &= u(x),\qquad x\in [0,1] +\end{align*} +!et +with $u(x)$ being some given function. + + + +For this case, we want to find $g(x,t)$ such that + +!bt +\begin{equation} + \frac{\partial g(x,t)}{\partial t} = \frac{\partial^2 g(x,t)}{\partial x^2} +\end{equation} \label{diffonedim} +!et + +and + +!bt +\begin{align*} +g(0,t) &= 0 ,\qquad t \geq 0 \\ +g(1,t) &= 0, \qquad t \geq 0 \\ +g(x,0) &= u(x),\qquad x\in [0,1] +\end{align*} +!et +with $u(x) = \sin(\pi x)$. + +First, let us set up the deep neural network. +The deep neural network will follow the same structure as discussed in the examples solving the ODEs. +First, we will look into how Autograd could be used in a network tailored to solve for bivariate functions. + + + + +The only change to do here, is to extend our network such that +functions of multiple parameters are correctly handled. In this case +we have two variables in our function to solve for, that is time $t$ +and position $x$. The variables will be represented by a +one-dimensional array in the program. The program will evaluate the +network at each possible pair $(x,t)$, given an array for the desired +$x$-values and $t$-values to approximate the solution at. + +!bc pycod +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # x is now a point and a 1D numpy array; make it a column vector + num_coordinates = np.size(x,0) + x = x.reshape(num_coordinates,-1) + + num_points = np.size(x,1) + + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assume that the input layer does nothing to the input x + x_input = x + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output[0][0] +!ec + + +The cost function must then iterate through the given arrays +containing values for $x$ and $t$, defines a point $(x,t)$ the deep +neural network and the trial solution is evaluated at, and then finds +the Jacobian of the trial solution. + +A possible trial solution for this PDE is + +$$ +g_t(x,t) = h_1(x,t) + x(1-x)tN(x,t,P) +$$ + +with $A(x,t)$ being a function ensuring that $g_t(x,t)$ satisfies our given conditions, and $N(x,t,P)$ being the output from the deep neural network using weights and biases for each layer from $P$. + +To fulfill the conditions, $A(x,t)$ could be: + +$$ +h_1(x,t) = (1-t)\Big(u(x) - \big((1-x)u(0) + x u(1)\big)\Big) = (1-t)u(x) = (1-t)\sin(\pi x) +$$ +since $(0) = u(1) = 0$ and $u(x) = \sin(\pi x)$. + + + +The Jacobian is used because the program must find the derivative of +the trial solution with respect to $x$ and $t$. + +This gives the necessity of computing the Jacobian matrix, as we want +to evaluate the gradient with respect to $x$ and $t$ (note that the +Jacobian of a scalar-valued multivariate function is simply its +gradient). + +In Autograd, the differentiation is by default done with respect to +the first input argument of your Python function. Since the points is +an array representing $x$ and $t$, the Jacobian is calculated using +the values of $x$ and $t$. + +To find the second derivative with respect to $x$ and $t$, the +Jacobian can be found for the second time. The result is a Hessian +matrix, which is the matrix containing all the possible second order +mixed derivatives of $g(x,t)$. + +!bc pycod +# Set up the trial function: +def u(x): + return np.sin(np.pi*x) + +def g_trial(point,P): + x,t = point + return (1-t)*u(x) + x*(1-x)*t*deep_neural_network(P,point) + +# The right side of the ODE: +def f(point): + return 0. + +# The cost function: +def cost_function(P, x, t): + cost_sum = 0 + + g_t_jacobian_func = jacobian(g_trial) + g_t_hessian_func = hessian(g_trial) + + for x_ in x: + for t_ in t: + point = np.array([x_,t_]) + + g_t = g_trial(point,P) + g_t_jacobian = g_t_jacobian_func(point,P) + g_t_hessian = g_t_hessian_func(point,P) + + g_t_dt = g_t_jacobian[1] + g_t_d2x = g_t_hessian[0][0] + + func = f(point) + + err_sqr = ( (g_t_dt - g_t_d2x) - func)**2 + cost_sum += err_sqr + + return cost_sum +!ec + + +=== Setting up the network using Autograd; The full program === + +Having set up the network, along with the trial solution and cost function, we can now see how the deep neural network performs by comparing the results to the analytical solution. + +The analytical solution of our problem is + +$$ +g(x,t) = \exp(-\pi^2 t)\sin(\pi x) +$$ + +A possible way to implement a neural network solving the PDE, is given below. +Be aware, though, that it is fairly slow for the parameters used. +A better result is possible, but requires more iterations, and thus longer time to complete. + + +Indeed, the program below is not optimal in its implementation, but rather serves as an example on how to implement and use a neural network to solve a PDE. +Using TensorFlow results in a much better execution time. Try it! + +!bc pycod +import autograd.numpy as np +from autograd import jacobian,hessian,grad +import autograd.numpy.random as npr +from matplotlib import cm +from matplotlib import pyplot as plt +from mpl_toolkits.mplot3d import axes3d + +## Set up the network + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # x is now a point and a 1D numpy array; make it a column vector + num_coordinates = np.size(x,0) + x = x.reshape(num_coordinates,-1) + + num_points = np.size(x,1) + + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assume that the input layer does nothing to the input x + x_input = x + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output[0][0] + +## Define the trial solution and cost function +def u(x): + return np.sin(np.pi*x) + +def g_trial(point,P): + x,t = point + return (1-t)*u(x) + x*(1-x)*t*deep_neural_network(P,point) + +# The right side of the ODE: +def f(point): + return 0. + +# The cost function: +def cost_function(P, x, t): + cost_sum = 0 + + g_t_jacobian_func = jacobian(g_trial) + g_t_hessian_func = hessian(g_trial) + + for x_ in x: + for t_ in t: + point = np.array([x_,t_]) + + g_t = g_trial(point,P) + g_t_jacobian = g_t_jacobian_func(point,P) + g_t_hessian = g_t_hessian_func(point,P) + + g_t_dt = g_t_jacobian[1] + g_t_d2x = g_t_hessian[0][0] + + func = f(point) + + err_sqr = ( (g_t_dt - g_t_d2x) - func)**2 + cost_sum += err_sqr + + return cost_sum /( np.size(x)*np.size(t) ) + +## For comparison, define the analytical solution +def g_analytic(point): + x,t = point + return np.exp(-np.pi**2*t)*np.sin(np.pi*x) + +## Set up a function for training the network to solve for the equation +def solve_pde_deep_neural_network(x,t, num_neurons, num_iter, lmb): + ## Set up initial weigths and biases + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 + 1 ) # 2 since we have two points, +1 to include bias + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: ',cost_function(P, x, t)) + + cost_function_grad = grad(cost_function,0) + + # Let the update be done num_iter times + for i in range(num_iter): + cost_grad = cost_function_grad(P, x , t) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_grad[l] + + print('Final cost: ',cost_function(P, x, t)) + + return P + +if __name__ == '__main__': + ### Use the neural network: + npr.seed(15) + + ## Decide the vales of arguments to the function to solve + Nx = 10; Nt = 10 + x = np.linspace(0, 1, Nx) + t = np.linspace(0,1,Nt) + + ## Set up the parameters for the network + num_hidden_neurons = [100, 25] + num_iter = 250 + lmb = 0.01 + + P = solve_pde_deep_neural_network(x,t, num_hidden_neurons, num_iter, lmb) + + ## Store the results + g_dnn_ag = np.zeros((Nx, Nt)) + G_analytical = np.zeros((Nx, Nt)) + for i,x_ in enumerate(x): + for j, t_ in enumerate(t): + point = np.array([x_, t_]) + g_dnn_ag[i,j] = g_trial(point,P) + + G_analytical[i,j] = g_analytic(point) + + # Find the map difference between the analytical and the computed solution + diff_ag = np.abs(g_dnn_ag - G_analytical) + print('Max absolute difference between the analytical solution and the network: %g'%np.max(diff_ag)) + + ## Plot the solutions in two dimensions, that being in position and time + + T,X = np.meshgrid(t,x) + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Solution from the deep neural network w/ %d layer'%len(num_hidden_neurons)) + s = ax.plot_surface(T,X,g_dnn_ag,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Analytical solution') + s = ax.plot_surface(T,X,G_analytical,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Difference') + s = ax.plot_surface(T,X,diff_ag,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + ## Take some slices of the 3D plots just to see the solutions at particular times + indx1 = 0 + indx2 = int(Nt/2) + indx3 = Nt-1 + + t1 = t[indx1] + t2 = t[indx2] + t3 = t[indx3] + + # Slice the results from the DNN + res1 = g_dnn_ag[:,indx1] + res2 = g_dnn_ag[:,indx2] + res3 = g_dnn_ag[:,indx3] + + # Slice the analytical results + res_analytical1 = G_analytical[:,indx1] + res_analytical2 = G_analytical[:,indx2] + res_analytical3 = G_analytical[:,indx3] + + # Plot the slices + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t1) + plt.plot(x, res1) + plt.plot(x,res_analytical1) + plt.legend(['dnn','analytical']) + + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t2) + plt.plot(x, res2) + plt.plot(x,res_analytical2) + plt.legend(['dnn','analytical']) + + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t3) + plt.plot(x, res3) + plt.plot(x,res_analytical3) + plt.legend(['dnn','analytical']) + + plt.show() +!ec + + +===== Solving the wave equation with Neural Networks ===== + +The wave equation is +!bt +\begin{equation*} + \frac{\partial^2 g(x,t)}{\partial t^2} = c^2\frac{\partial^2 g(x,t)}{\partial x^2} +\end{equation*} +!et + +with $c$ being the specified wave speed. + +Here, the chosen conditions are +!bt +\begin{align*} + g(0,t) &= 0 \\ + g(1,t) &= 0 \\ + g(x,0) &= u(x) \\ + \frac{\partial g(x,t)}{\partial t} \Big |_{t = 0} &= v(x) +\end{align*} +!et +where $\frac{\partial g(x,t)}{\partial t} \Big |_{t = 0}$ means the derivative of $g(x,t)$ with respect to $t$ is evaluated at $t = 0$, and $u(x)$ and $v(x)$ being given functions. + + +The wave equation to solve for, is + +!bt +\begin{equation} \label{wave} +\frac{\partial^2 g(x,t)}{\partial t^2} = c^2 \frac{\partial^2 g(x,t)}{\partial x^2} +\end{equation} +!et + +where $c$ is the given wave speed. +The chosen conditions for this equation are + +!bt +\begin{aligned} +g(0,t) &= 0, &t \geq 0 \\ +g(1,t) &= 0, &t \geq 0 \\ +g(x,0) &= u(x), &x\in[0,1] \\ +\frac{\partial g(x,t)}{\partial t}\Big |_{t = 0} &= v(x), &x \in [0,1] +\end{aligned} \label{condwave} +!et + +In this example, let $c = 1$ and $u(x) = \sin(\pi x)$ and $v(x) = -\pi\sin(\pi x)$. + + + +Setting up the network is done in similar matter as for the example of solving the diffusion equation. +The only things we have to change, is the trial solution such that it satisfies the conditions from (ref{condwave}) and the cost function. + +The trial solution becomes slightly different since we have other conditions than in the example of solving the diffusion equation. Here, a possible trial solution $g_t(x,t)$ is + +$$ +g_t(x,t) = h_1(x,t) + x(1-x)t^2N(x,t,P) +$$ + +where + +$$ +h_1(x,t) = (1-t^2)u(x) + tv(x) +$$ + +Note that this trial solution satisfies the conditions only if $u(0) = v(0) = u(1) = v(1) = 0$, which is the case in this example. + + +The analytical solution for our specific problem, is + +$$ +g(x,t) = \sin(\pi x)\cos(\pi t) - \sin(\pi x)\sin(\pi t) +$$ + + + +!bc pycod +import autograd.numpy as np +from autograd import hessian,grad +import autograd.numpy.random as npr +from matplotlib import cm +from matplotlib import pyplot as plt +from mpl_toolkits.mplot3d import axes3d + +## Set up the trial function: +def u(x): + return np.sin(np.pi*x) + +def v(x): + return -np.pi*np.sin(np.pi*x) + +def h1(point): + x,t = point + return (1 - t**2)*u(x) + t*v(x) + +def g_trial(point,P): + x,t = point + return h1(point) + x*(1-x)*t**2*deep_neural_network(P,point) + +## Define the cost function +def cost_function(P, x, t): + cost_sum = 0 + + g_t_hessian_func = hessian(g_trial) + + for x_ in x: + for t_ in t: + point = np.array([x_,t_]) + + g_t_hessian = g_t_hessian_func(point,P) + + g_t_d2x = g_t_hessian[0][0] + g_t_d2t = g_t_hessian[1][1] + + err_sqr = ( (g_t_d2t - g_t_d2x) )**2 + cost_sum += err_sqr + + return cost_sum / (np.size(t) * np.size(x)) + +## The neural network +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # x is now a point and a 1D numpy array; make it a column vector + num_coordinates = np.size(x,0) + x = x.reshape(num_coordinates,-1) + + num_points = np.size(x,1) + + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assume that the input layer does nothing to the input x + x_input = x + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output[0][0] + +## The analytical solution +def g_analytic(point): + x,t = point + return np.sin(np.pi*x)*np.cos(np.pi*t) - np.sin(np.pi*x)*np.sin(np.pi*t) + +def solve_pde_deep_neural_network(x,t, num_neurons, num_iter, lmb): + ## Set up initial weigths and biases + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 + 1 ) # 2 since we have two points, +1 to include bias + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: ',cost_function(P, x, t)) + + cost_function_grad = grad(cost_function,0) + + # Let the update be done num_iter times + for i in range(num_iter): + cost_grad = cost_function_grad(P, x , t) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_grad[l] + + + print('Final cost: ',cost_function(P, x, t)) + + return P + +if __name__ == '__main__': + ### Use the neural network: + npr.seed(15) + + ## Decide the vales of arguments to the function to solve + Nx = 10; Nt = 10 + x = np.linspace(0, 1, Nx) + t = np.linspace(0,1,Nt) + + ## Set up the parameters for the network + num_hidden_neurons = [50,20] + num_iter = 1000 + lmb = 0.01 + + P = solve_pde_deep_neural_network(x,t, num_hidden_neurons, num_iter, lmb) + + ## Store the results + res = np.zeros((Nx, Nt)) + res_analytical = np.zeros((Nx, Nt)) + for i,x_ in enumerate(x): + for j, t_ in enumerate(t): + point = np.array([x_, t_]) + res[i,j] = g_trial(point,P) + + res_analytical[i,j] = g_analytic(point) + + diff = np.abs(res - res_analytical) + print("Max difference between analytical and solution from nn: %g"%np.max(diff)) + + ## Plot the solutions in two dimensions, that being in position and time + + T,X = np.meshgrid(t,x) + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Solution from the deep neural network w/ %d layer'%len(num_hidden_neurons)) + s = ax.plot_surface(T,X,res,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Analytical solution') + s = ax.plot_surface(T,X,res_analytical,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Difference') + s = ax.plot_surface(T,X,diff,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + ## Take some slices of the 3D plots just to see the solutions at particular times + indx1 = 0 + indx2 = int(Nt/2) + indx3 = Nt-1 + + t1 = t[indx1] + t2 = t[indx2] + t3 = t[indx3] + + # Slice the results from the DNN + res1 = res[:,indx1] + res2 = res[:,indx2] + res3 = res[:,indx3] + + # Slice the analytical results + res_analytical1 = res_analytical[:,indx1] + res_analytical2 = res_analytical[:,indx2] + res_analytical3 = res_analytical[:,indx3] + + # Plot the slices + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t1) + plt.plot(x, res1) + plt.plot(x,res_analytical1) + plt.legend(['dnn','analytical']) + + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t2) + plt.plot(x, res2) + plt.plot(x,res_analytical2) + plt.legend(['dnn','analytical']) + + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t3) + plt.plot(x, res3) + plt.plot(x,res_analytical3) + plt.legend(['dnn','analytical']) + + plt.show() +!ec + + +===== Resources on differential equations and deep learning ===== + +o "Artificial neural networks for solving ordinary and partial differential equations by I.E. Lagaris et al":"https://pdfs.semanticscholar.org/d061/df393e0e8fbfd0ea24976458b7d42419040d.pdf" +o "Neural networks for solving differential equations by A. Honchar":"https://becominghuman.ai/neural-networks-for-solving-differential-equations-fa230ac5e04c" +o "Solving differential equations using neural networks by M.M Chiaramonte and M. Kiener":"http://cs229.stanford.edu/proj2013/ChiaramonteKiener-SolvingDifferentialEquationsUsingNeuralNetworks.pdf" +o "Introduction to Partial Differential Equations by A. Tveito, R. Winther":"https://www.springer.com/us/book/9783540225515" + + + + diff --git a/doc/BookChapters/chapter12.dlog b/doc/BookChapters/chapter12.dlog new file mode 100644 index 000000000..06b7d3cc2 --- /dev/null +++ b/doc/BookChapters/chapter12.dlog @@ -0,0 +1,6 @@ +Translating doconce text in chapter12.do.txt to ipynb +*** error: figure file "figslides/nn.jpeg" does not exist! +Translating doconce text in chapter12.do.txt to ipynb +Failed to remove ans_at_end environment +Failed to remove sol_at_end environment +output in chapter12.ipynb diff --git a/doc/BookChapters/chapter12.do.txt b/doc/BookChapters/chapter12.do.txt new file mode 100644 index 000000000..b3815444f --- /dev/null +++ b/doc/BookChapters/chapter12.do.txt @@ -0,0 +1,578 @@ +======= Convolutional Neural Networks (recognizing images) ======= + + +Convolutional neural networks (CNNs) were developed during the last +decade of the previous century, with a focus on character recognition +tasks. Nowadays, CNNs are a central element in the spectacular success +of deep learning methods. The success in for example image +classifications have made them a central tool for most machine +learning practitioners. + +CNNs are very similar to ordinary Neural Networks. +They are made up of neurons that have learnable weights and +biases. Each neuron receives some inputs, performs a dot product and +optionally follows it with a non-linearity. The whole network still +expresses a single differentiable score function: from the raw image +pixels on one end to class scores at the other. And they still have a +loss function (for example Softmax) on the last (fully-connected) layer +and all the tips/tricks we developed for learning regular Neural +Networks still apply (back propagation, gradient descent etc etc). + +What is the difference? _CNN architectures make the explicit assumption that +the inputs are images, which allows us to encode certain properties +into the architecture. These then make the forward function more +efficient to implement and vastly reduce the amount of parameters in +the network._ + +Here we provide only a superficial overview, for the more interested, we recommend highly the course +"IN5400 – Machine Learning for Image Analysis":"https://www.uio.no/studier/emner/matnat/ifi/IN5400/index-eng.html" +and the slides of "CS231":"http://cs231n.github.io/convolutional-networks/". + +Another good read is the article here URL:"https://arxiv.org/pdf/1603.07285.pdf". + + +As an example, consider +an image of size $32\times 32\times 3$ (32 wide, 32 high, 3 color channels), so a +single fully-connected neuron in a first hidden layer of a regular +Neural Network would have $32\times 32\times 3 = 3072$ weights. This amount still +seems manageable, but clearly this fully-connected structure does not +scale to larger images. For example, an image of more respectable +size, say $200\times 200\times 3$, would lead to neurons that have +$200\times 200\times 3 = 120,000$ weights. + +We could have +several such neurons, and the parameters would add up quickly! Clearly, +this full connectivity is wasteful and the huge number of parameters +would quickly lead to possible overfitting. + +#FIGURE: [figslides/nn.jpeg, width=500 frac=0.6] A regular 3-layer Neural Network. + + + +Convolutional Neural Networks take advantage of the fact that the +input consists of images and they constrain the architecture in a more +sensible way. + +In particular, unlike a regular Neural Network, the +layers of a CNN have neurons arranged in 3 dimensions: width, +height, depth. (Note that the word depth here refers to the third +dimension of an activation volume, not to the depth of a full Neural +Network, which can refer to the total number of layers in a network.) + +To understand it better, the above example of an image +with an input volume of +activations has dimensions $32\times 32\times 3$ (width, height, +depth respectively). + +The neurons in a layer will +only be connected to a small region of the layer before it, instead of +all of the neurons in a fully-connected manner. Moreover, the final +output layer could for this specific image have dimensions $1\times 1 \times 10$, +because by the +end of the CNN architecture we will reduce the full image into a +single vector of class scores, arranged along the depth +dimension. + +#FIGURE: [figslides/cnn.jpeg, width=500 frac=0.6] A CNN arranges its neurons in three dimensions (width, heigh#t, depth), as visualized in one of the layers. Every layer of a CNN transforms the 3D input volume to a 3D out#put volume of neuron activations. In this example, the red input layer holds the image, so its width and heigh#t would be the dimensions of the image, and the depth would be 3 (Red, Green, Blue channels). + + + + +A simple CNN is a sequence of layers, and every layer of a CNN +transforms one volume of activations to another through a +differentiable function. We use three main types of layers to build +CNN architectures: Convolutional Layer, Pooling Layer, and +Fully-Connected Layer (exactly as seen in regular Neural Networks). We +will stack these layers to form a full CNN architecture. + +A simple CNN for image classification could have the architecture: + +* _INPUT_ ($32\times 32 \times 3$) will hold the raw pixel values of the image, in this case an image of width 32, height 32, and with three color channels R,G,B. +* _CONV_ (convolutional )layer will compute the output of neurons that are connected to local regions in the input, each computing a dot product between their weights and a small region they are connected to in the input volume. This may result in volume such as $[32\times 32\times 12]$ if we decided to use 12 filters. +* _RELU_ layer will apply an elementwise activation function, such as the $max(0,x)$ thresholding at zero. This leaves the size of the volume unchanged ($[32\times 32\times 12]$). +* _POOL_ (pooling) layer will perform a downsampling operation along the spatial dimensions (width, height), resulting in volume such as $[16\times 16\times 12]$. +* _FC_ (i.e. fully-connected) layer will compute the class scores, resulting in volume of size $[1\times 1\times 10]$, where each of the 10 numbers correspond to a class score, such as among the 10 categories of the MNIST images we considered above . As with ordinary Neural Networks and as the name implies, each neuron in this layer will be connected to all the numbers in the previous volume. + + + +CNNs transform the original image layer by layer from the original +pixel values to the final class scores. + +Observe that some layers contain +parameters and other don’t. In particular, the CNN layers perform +transformations that are a function of not only the activations in the +input volume, but also of the parameters (the weights and biases of +the neurons). On the other hand, the RELU/POOL layers will implement a +fixed function. The parameters in the CONV/FC layers will be trained +with gradient descent so that the class scores that the CNN computes +are consistent with the labels in the training set for each image. + + + +=== CNNs in brief === + +In summary: + +* A CNN architecture is in the simplest case a list of Layers that transform the image volume into an output volume (e.g. holding the class scores) +* There are a few distinct types of Layers (e.g. CONV/FC/RELU/POOL are by far the most popular) +* Each Layer accepts an input 3D volume and transforms it to an output 3D volume through a differentiable function +* Each Layer may or may not have parameters (e.g. CONV/FC do, RELU/POOL don’t) +* Each Layer may or may not have additional hyperparameters (e.g. CONV/FC/POOL do, RELU doesn’t) + +For more material on convolutional networks, we strongly recommend +the course +"IN5400 – Machine Learning for Image Analysis":"https://www.uio.no/studier/emner/matnat/ifi/IN5400/index-eng.html" +and the slides of "CS231":"http://cs231n.github.io/convolutional-networks/" which is taught at Stanford University (consistently ranked as one of the top computer science programs in the world). "Michael Nielsen's book is a must read, in particular chapter 6 which deals with CNNs":"http://neuralnetworksanddeeplearning.com/chap6.html". + + + + +===== CNNs in more detail, building convolutional neural networks in Tensorflow and Keras ===== + + +As discussed above, CNNs are neural networks built from the assumption that the inputs +to the network are 2D images. This is important because the number of features or pixels in images +grows very fast with the image size, and an enormous number of weights and biases are needed in order to build an accurate network. + +As before, we still have our input, a hidden layer and an output. What's novel about convolutional networks +are the _convolutional_ and _pooling_ layers stacked in pairs between the input and the hidden layer. +In addition, the data is no longer represented as a 2D feature matrix, instead each input is a number of 2D +matrices, typically 1 for each color dimension (Red, Green, Blue). + + + +It means that to represent the entire +dataset of images, we require a 4D matrix or _tensor_. This tensor has the dimensions: +!bt +\[ +(n_{inputs},\, n_{pixels, width},\, n_{pixels, height},\, depth) . +\] +!et + + + +The MNIST dataset consists of grayscale images with a pixel size of +$28\times 28$, meaning we require $28 \times 28 = 724$ weights to each +neuron in the first hidden layer. + +If we were to analyze images of size $128\times 128$ we would require +$128 \times 128 = 16384$ weights to each neuron. Even worse if we were +dealing with color images, as most images are, we have an image matrix +of size $128\times 128$ for each color dimension (Red, Green, Blue), +meaning 3 times the number of weights $= 49152$ are required for every +single neuron in the first hidden layer. + + + +Images typically have strong local correlations, meaning that a small +part of the image varies little from its neighboring regions. If for +example we have an image of a blue car, we can roughly assume that a +small blue part of the image is surrounded by other blue regions. + +Therefore, instead of connecting every single pixel to a neuron in the +first hidden layer, as we have previously done with deep neural +networks, we can instead connect each neuron to a small part of the +image (in all 3 RGB depth dimensions). The size of each small area is +fixed, and known as a "receptive":"https://en.wikipedia.org/wiki/Receptive_field". + + + +The layers of a convolutional neural network arrange neurons in 3D: width, height and depth. +The input image is typically a square matrix of depth 3. + +A _convolution_ is performed on the image which outputs +a 3D volume of neurons. The weights to the input are arranged in a number of 2D matrices, known as _filters_. + + +Each filter slides along the input image, taking the dot product +between each small part of the image and the filter, in all depth +dimensions. This is then passed through a non-linear function, +typically the _Rectified Linear (ReLu)_ function, which serves as the +activation of the neurons in the first convolutional layer. This is +further passed through a _pooling layer_, which reduces the size of the +convolutional layer, e.g. by taking the maximum or average across some +small regions, and this serves as input to the next convolutional +layer. + + + +By systematically reducing the size of the input volume, through +convolution and pooling, the network should create representations of +small parts of the input, and then from them assemble representations +of larger areas. The final pooling layer is flattened to serve as +input to a hidden layer, such that each neuron in the final pooling +layer is connected to every single neuron in the hidden layer. This +then serves as input to the output layer, e.g. a softmax output for +classification. + + + +=== Prerequisites: Collect and pre-process data === +!bc pycod +# import necessary packages +import numpy as np +import matplotlib.pyplot as plt +from sklearn import datasets + + +# ensure the same random numbers appear every time +np.random.seed(0) + +# display images in notebook +%matplotlib inline +plt.rcParams['figure.figsize'] = (12,12) + + +# download MNIST dataset +digits = datasets.load_digits() + +# define inputs and labels +inputs = digits.images +labels = digits.target + +# RGB images have a depth of 3 +# our images are grayscale so they should have a depth of 1 +inputs = inputs[:,:,:,np.newaxis] + +print("inputs = (n_inputs, pixel_width, pixel_height, depth) = " + str(inputs.shape)) +print("labels = (n_inputs) = " + str(labels.shape)) + + +# choose some random images to display +n_inputs = len(inputs) +indices = np.arange(n_inputs) +random_indices = np.random.choice(indices, size=5) + +for i, image in enumerate(digits.images[random_indices]): + plt.subplot(1, 5, i+1) + plt.axis('off') + plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest') + plt.title("Label: %d" % digits.target[random_indices[i]]) +plt.show() +!ec + + +=== Importing Keras and Tensorflow === +!bc pycod +from tensorflow.keras import datasets, layers, models +from tensorflow.keras.layers import Input +from tensorflow.keras.models import Sequential #This allows appending layers to existing models +from tensorflow.keras.layers import Dense #This allows defining the characteristics of a particular layer +from tensorflow.keras import optimizers #This allows using whichever optimiser we want (sgd,adam,RMSprop) +from tensorflow.keras import regularizers #This allows using whichever regularizer we want (l1,l2,l1_l2) +from tensorflow.keras.utils import to_categorical #This allows using categorical cross entropy as the cost function +#from tensorflow.keras import Conv2D +#from tensorflow.keras import MaxPooling2D +#from tensorflow.keras import Flatten + +from sklearn.model_selection import train_test_split + +# representation of labels +labels = to_categorical(labels) + +# split into train and test data +# one-liner from scikit-learn library +train_size = 0.8 +test_size = 1 - train_size +X_train, X_test, Y_train, Y_test = train_test_split(inputs, labels, train_size=train_size, + test_size=test_size) +!ec + + +!bc pycod +def create_convolutional_neural_network_keras(input_shape, receptive_field, + n_filters, n_neurons_connected, n_categories, + eta, lmbd): + model = Sequential() + model.add(layers.Conv2D(n_filters, (receptive_field, receptive_field), input_shape=input_shape, padding='same', + activation='relu', kernel_regularizer=regularizers.l2(lmbd))) + model.add(layers.MaxPooling2D(pool_size=(2, 2))) + model.add(layers.Flatten()) + model.add(layers.Dense(n_neurons_connected, activation='relu', kernel_regularizer=regularizers.l2(lmbd))) + model.add(layers.Dense(n_categories, activation='softmax', kernel_regularizer=regularizers.l2(lmbd))) + + sgd = optimizers.SGD(lr=eta) + model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy']) + + return model + +epochs = 100 +batch_size = 100 +input_shape = X_train.shape[1:4] +receptive_field = 3 +n_filters = 10 +n_neurons_connected = 50 +n_categories = 10 + +eta_vals = np.logspace(-5, 1, 7) +lmbd_vals = np.logspace(-5, 1, 7) +!ec + + +!bc pycod +CNN_keras = np.zeros((len(eta_vals), len(lmbd_vals)), dtype=object) + +for i, eta in enumerate(eta_vals): + for j, lmbd in enumerate(lmbd_vals): + CNN = create_convolutional_neural_network_keras(input_shape, receptive_field, + n_filters, n_neurons_connected, n_categories, + eta, lmbd) + CNN.fit(X_train, Y_train, epochs=epochs, batch_size=batch_size, verbose=0) + scores = CNN.evaluate(X_test, Y_test) + + CNN_keras[i][j] = CNN + + print("Learning rate = ", eta) + print("Lambda = ", lmbd) + print("Test accuracy: %.3f" % scores[1]) + print() +!ec + + +=== Final visualization === + +!bc pycod +# visual representation of grid search +# uses seaborn heatmap, could probably do this in matplotlib +import seaborn as sns + +sns.set() + +train_accuracy = np.zeros((len(eta_vals), len(lmbd_vals))) +test_accuracy = np.zeros((len(eta_vals), len(lmbd_vals))) + +for i in range(len(eta_vals)): + for j in range(len(lmbd_vals)): + CNN = CNN_keras[i][j] + + train_accuracy[i][j] = CNN.evaluate(X_train, Y_train)[1] + test_accuracy[i][j] = CNN.evaluate(X_test, Y_test)[1] + + +fig, ax = plt.subplots(figsize = (10, 10)) +sns.heatmap(train_accuracy, annot=True, ax=ax, cmap="viridis") +ax.set_title("Training Accuracy") +ax.set_ylabel("$\eta$") +ax.set_xlabel("$\lambda$") +plt.show() + +fig, ax = plt.subplots(figsize = (10, 10)) +sns.heatmap(test_accuracy, annot=True, ax=ax, cmap="viridis") +ax.set_title("Test Accuracy") +ax.set_ylabel("$\eta$") +ax.set_xlabel("$\lambda$") +plt.show() +!ec + + + + +===== The CIFAR01 data set ===== + +The CIFAR10 dataset contains 60,000 color images in 10 classes, with +6,000 images in each class. The dataset is divided into 50,000 +training images and 10,000 testing images. The classes are mutually +exclusive and there is no overlap between them. + +!bc pycod +import tensorflow as tf + +from tensorflow.keras import datasets, layers, models +import matplotlib.pyplot as plt + +# We import the data set +(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data() + +# Normalize pixel values to be between 0 and 1 by dividing by 255. +train_images, test_images = train_images / 255.0, test_images / 255.0 + +!ec + + + + +To verify that the dataset looks correct, let's plot the first 25 images from the training set and display the class name below each image. + +!bc pycod +class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', + 'dog', 'frog', 'horse', 'ship', 'truck'] +​ +plt.figure(figsize=(10,10)) +for i in range(25): + plt.subplot(5,5,i+1) + plt.xticks([]) + plt.yticks([]) + plt.grid(False) + plt.imshow(train_images[i], cmap=plt.cm.binary) + # The CIFAR labels happen to be arrays, + # which is why you need the extra index + plt.xlabel(class_names[train_labels[i][0]]) +plt.show() +!ec + + +The 6 lines of code below define the convolutional base using a common pattern: a stack of Conv2D and MaxPooling2D layers. + +As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to these dimensions, color_channels refers to (R,G,B). In this example, you will configure our CNN to process inputs of shape (32, 32, 3), which is the format of CIFAR images. You can do this by passing the argument input_shape to our first layer. + +!bc pycod +model = models.Sequential() +model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3))) +model.add(layers.MaxPooling2D((2, 2))) +model.add(layers.Conv2D(64, (3, 3), activation='relu')) +model.add(layers.MaxPooling2D((2, 2))) +model.add(layers.Conv2D(64, (3, 3), activation='relu')) + +# Let's display the architecture of our model so far. + +model.summary() +!ec + +You can see that the output of every Conv2D and MaxPooling2D layer is a 3D tensor of shape (height, width, channels). The width and height dimensions tend to shrink as you go deeper in the network. The number of output channels for each Conv2D layer is controlled by the first argument (e.g., 32 or 64). Typically, as the width and height shrink, you can afford (computationally) to add more output channels in each Conv2D layer. + + + +To complete our model, you will feed the last output tensor from the +convolutional base (of shape (4, 4, 64)) into one or more Dense layers +to perform classification. Dense layers take vectors as input (which +are 1D), while the current output is a 3D tensor. First, you will +flatten (or unroll) the 3D output to 1D, then add one or more Dense +layers on top. CIFAR has 10 output classes, so you use a final Dense +layer with 10 outputs and a softmax activation. + +!bc pycod +model.add(layers.Flatten()) +model.add(layers.Dense(64, activation='relu')) +model.add(layers.Dense(10)) +Here's the complete architecture of our model. + +model.summary() +!ec +As you can see, our (4, 4, 64) outputs were flattened into vectors of shape (1024) before going through two Dense layers. + +Compile and train the model. + +!bc pycod +model.compile(optimizer='adam', + loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), + metrics=['accuracy']) +​ +history = model.fit(train_images, train_labels, epochs=10, + validation_data=(test_images, test_labels)) + +!ec + +Finally, we evaluate the model. + +!bc pycod +plt.plot(history.history['accuracy'], label='accuracy') +plt.plot(history.history['val_accuracy'], label = 'val_accuracy') +plt.xlabel('Epoch') +plt.ylabel('Accuracy') +plt.ylim([0.5, 1]) +plt.legend(loc='lower right') + +test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2) + +print(test_acc) + +!ec + + + +===== Recurrent neural networks: Overarching view ===== + +Till now our focus has been, including convolutional neural networks +as well, on feedforward neural networks. The output or the activations +flow only in one direction, from the input layer to the output layer. + +A recurrent neural network (RNN) looks very much like a feedforward +neural network, except that it also has connections pointing +backward. + +RNNs are used to analyze time series data such as stock prices, and +tell you when to buy or sell. In autonomous driving systems, they can +anticipate car trajectories and help avoid accidents. More generally, +they can work on sequences of arbitrary lengths, rather than on +fixed-sized inputs like all the nets we have discussed so far. For +example, they can take sentences, documents, or audio samples as +input, making them extremely useful for natural language processing +systems such as automatic translation and speech-to-text. + + + + +=== A simple example === + +!bc pycod +# Start importing packages +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import tensorflow as tf +from tensorflow.keras import datasets, layers, models +from tensorflow.keras.layers import Input +from tensorflow.keras.models import Model, Sequential +from tensorflow.keras.layers import Dense, SimpleRNN, LSTM, GRU +from tensorflow.keras import optimizers +from tensorflow.keras import regularizers +from tensorflow.keras.utils import to_categorical + + + +# convert into dataset matrix +def convertToMatrix(data, step): + X, Y =[], [] + for i in range(len(data)-step): + d=i+step + X.append(data[i:d,]) + Y.append(data[d,]) + return np.array(X), np.array(Y) + +step = 4 +N = 1000 +Tp = 800 + +t=np.arange(0,N) +x=np.sin(0.02*t)+2*np.random.rand(N) +df = pd.DataFrame(x) +df.head() + +plt.plot(df) +plt.show() + +values=df.values +train,test = values[0:Tp,:], values[Tp:N,:] + +# add step elements into train and test +test = np.append(test,np.repeat(test[-1,],step)) +train = np.append(train,np.repeat(train[-1,],step)) + +trainX,trainY =convertToMatrix(train,step) +testX,testY =convertToMatrix(test,step) +trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1])) +testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1])) + +model = Sequential() +model.add(SimpleRNN(units=32, input_shape=(1,step), activation="relu")) +model.add(Dense(8, activation="relu")) +model.add(Dense(1)) +model.compile(loss='mean_squared_error', optimizer='rmsprop') +model.summary() + +model.fit(trainX,trainY, epochs=100, batch_size=16, verbose=2) +trainPredict = model.predict(trainX) +testPredict= model.predict(testX) +predicted=np.concatenate((trainPredict,testPredict),axis=0) + +trainScore = model.evaluate(trainX, trainY, verbose=0) +print(trainScore) + +index = df.index.values +plt.plot(index,df) +plt.plot(index,predicted) +plt.axvline(df.index[Tp], c="r") +plt.show() +!ec + + diff --git a/doc/BookChapters/chapter12.do.txt~ b/doc/BookChapters/chapter12.do.txt~ new file mode 100644 index 000000000..6a816eda7 --- /dev/null +++ b/doc/BookChapters/chapter12.do.txt~ @@ -0,0 +1,578 @@ +======= Convolutional Neural Networks (recognizing images) ======= + + +Convolutional neural networks (CNNs) were developed during the last +decade of the previous century, with a focus on character recognition +tasks. Nowadays, CNNs are a central element in the spectacular success +of deep learning methods. The success in for example image +classifications have made them a central tool for most machine +learning practitioners. + +CNNs are very similar to ordinary Neural Networks. +They are made up of neurons that have learnable weights and +biases. Each neuron receives some inputs, performs a dot product and +optionally follows it with a non-linearity. The whole network still +expresses a single differentiable score function: from the raw image +pixels on one end to class scores at the other. And they still have a +loss function (for example Softmax) on the last (fully-connected) layer +and all the tips/tricks we developed for learning regular Neural +Networks still apply (back propagation, gradient descent etc etc). + +What is the difference? _CNN architectures make the explicit assumption that +the inputs are images, which allows us to encode certain properties +into the architecture. These then make the forward function more +efficient to implement and vastly reduce the amount of parameters in +the network._ + +Here we provide only a superficial overview, for the more interested, we recommend highly the course +"IN5400 – Machine Learning for Image Analysis":"https://www.uio.no/studier/emner/matnat/ifi/IN5400/index-eng.html" +and the slides of "CS231":"http://cs231n.github.io/convolutional-networks/". + +Another good read is the article here URL:"https://arxiv.org/pdf/1603.07285.pdf". + + +As an example, consider +an image of size $32\times 32\times 3$ (32 wide, 32 high, 3 color channels), so a +single fully-connected neuron in a first hidden layer of a regular +Neural Network would have $32\times 32\times 3 = 3072$ weights. This amount still +seems manageable, but clearly this fully-connected structure does not +scale to larger images. For example, an image of more respectable +size, say $200\times 200\times 3$, would lead to neurons that have +$200\times 200\times 3 = 120,000$ weights. + +We could have +several such neurons, and the parameters would add up quickly! Clearly, +this full connectivity is wasteful and the huge number of parameters +would quickly lead to possible overfitting. + +FIGURE: [figslides/nn.jpeg, width=500 frac=0.6] A regular 3-layer Neural Network. + + + +Convolutional Neural Networks take advantage of the fact that the +input consists of images and they constrain the architecture in a more +sensible way. + +In particular, unlike a regular Neural Network, the +layers of a CNN have neurons arranged in 3 dimensions: width, +height, depth. (Note that the word depth here refers to the third +dimension of an activation volume, not to the depth of a full Neural +Network, which can refer to the total number of layers in a network.) + +To understand it better, the above example of an image +with an input volume of +activations has dimensions $32\times 32\times 3$ (width, height, +depth respectively). + +The neurons in a layer will +only be connected to a small region of the layer before it, instead of +all of the neurons in a fully-connected manner. Moreover, the final +output layer could for this specific image have dimensions $1\times 1 \times 10$, +because by the +end of the CNN architecture we will reduce the full image into a +single vector of class scores, arranged along the depth +dimension. + +FIGURE: [figslides/cnn.jpeg, width=500 frac=0.6] A CNN arranges its neurons in three dimensions (width, height, depth), as visualized in one of the layers. Every layer of a CNN transforms the 3D input volume to a 3D output volume of neuron activations. In this example, the red input layer holds the image, so its width and height would be the dimensions of the image, and the depth would be 3 (Red, Green, Blue channels). + + + + +A simple CNN is a sequence of layers, and every layer of a CNN +transforms one volume of activations to another through a +differentiable function. We use three main types of layers to build +CNN architectures: Convolutional Layer, Pooling Layer, and +Fully-Connected Layer (exactly as seen in regular Neural Networks). We +will stack these layers to form a full CNN architecture. + +A simple CNN for image classification could have the architecture: + +* _INPUT_ ($32\times 32 \times 3$) will hold the raw pixel values of the image, in this case an image of width 32, height 32, and with three color channels R,G,B. +* _CONV_ (convolutional )layer will compute the output of neurons that are connected to local regions in the input, each computing a dot product between their weights and a small region they are connected to in the input volume. This may result in volume such as $[32\times 32\times 12]$ if we decided to use 12 filters. +* _RELU_ layer will apply an elementwise activation function, such as the $max(0,x)$ thresholding at zero. This leaves the size of the volume unchanged ($[32\times 32\times 12]$). +* _POOL_ (pooling) layer will perform a downsampling operation along the spatial dimensions (width, height), resulting in volume such as $[16\times 16\times 12]$. +* _FC_ (i.e. fully-connected) layer will compute the class scores, resulting in volume of size $[1\times 1\times 10]$, where each of the 10 numbers correspond to a class score, such as among the 10 categories of the MNIST images we considered above . As with ordinary Neural Networks and as the name implies, each neuron in this layer will be connected to all the numbers in the previous volume. + + + +CNNs transform the original image layer by layer from the original +pixel values to the final class scores. + +Observe that some layers contain +parameters and other don’t. In particular, the CNN layers perform +transformations that are a function of not only the activations in the +input volume, but also of the parameters (the weights and biases of +the neurons). On the other hand, the RELU/POOL layers will implement a +fixed function. The parameters in the CONV/FC layers will be trained +with gradient descent so that the class scores that the CNN computes +are consistent with the labels in the training set for each image. + + + +=== CNNs in brief === + +In summary: + +* A CNN architecture is in the simplest case a list of Layers that transform the image volume into an output volume (e.g. holding the class scores) +* There are a few distinct types of Layers (e.g. CONV/FC/RELU/POOL are by far the most popular) +* Each Layer accepts an input 3D volume and transforms it to an output 3D volume through a differentiable function +* Each Layer may or may not have parameters (e.g. CONV/FC do, RELU/POOL don’t) +* Each Layer may or may not have additional hyperparameters (e.g. CONV/FC/POOL do, RELU doesn’t) + +For more material on convolutional networks, we strongly recommend +the course +"IN5400 – Machine Learning for Image Analysis":"https://www.uio.no/studier/emner/matnat/ifi/IN5400/index-eng.html" +and the slides of "CS231":"http://cs231n.github.io/convolutional-networks/" which is taught at Stanford University (consistently ranked as one of the top computer science programs in the world). "Michael Nielsen's book is a must read, in particular chapter 6 which deals with CNNs":"http://neuralnetworksanddeeplearning.com/chap6.html". + + + + +===== CNNs in more detail, building convolutional neural networks in Tensorflow and Keras ===== + + +As discussed above, CNNs are neural networks built from the assumption that the inputs +to the network are 2D images. This is important because the number of features or pixels in images +grows very fast with the image size, and an enormous number of weights and biases are needed in order to build an accurate network. + +As before, we still have our input, a hidden layer and an output. What's novel about convolutional networks +are the _convolutional_ and _pooling_ layers stacked in pairs between the input and the hidden layer. +In addition, the data is no longer represented as a 2D feature matrix, instead each input is a number of 2D +matrices, typically 1 for each color dimension (Red, Green, Blue). + + + +It means that to represent the entire +dataset of images, we require a 4D matrix or _tensor_. This tensor has the dimensions: +!bt +\[ +(n_{inputs},\, n_{pixels, width},\, n_{pixels, height},\, depth) . +\] +!et + + + +The MNIST dataset consists of grayscale images with a pixel size of +$28\times 28$, meaning we require $28 \times 28 = 724$ weights to each +neuron in the first hidden layer. + +If we were to analyze images of size $128\times 128$ we would require +$128 \times 128 = 16384$ weights to each neuron. Even worse if we were +dealing with color images, as most images are, we have an image matrix +of size $128\times 128$ for each color dimension (Red, Green, Blue), +meaning 3 times the number of weights $= 49152$ are required for every +single neuron in the first hidden layer. + + + +Images typically have strong local correlations, meaning that a small +part of the image varies little from its neighboring regions. If for +example we have an image of a blue car, we can roughly assume that a +small blue part of the image is surrounded by other blue regions. + +Therefore, instead of connecting every single pixel to a neuron in the +first hidden layer, as we have previously done with deep neural +networks, we can instead connect each neuron to a small part of the +image (in all 3 RGB depth dimensions). The size of each small area is +fixed, and known as a "receptive":"https://en.wikipedia.org/wiki/Receptive_field". + + + +The layers of a convolutional neural network arrange neurons in 3D: width, height and depth. +The input image is typically a square matrix of depth 3. + +A _convolution_ is performed on the image which outputs +a 3D volume of neurons. The weights to the input are arranged in a number of 2D matrices, known as _filters_. + + +Each filter slides along the input image, taking the dot product +between each small part of the image and the filter, in all depth +dimensions. This is then passed through a non-linear function, +typically the _Rectified Linear (ReLu)_ function, which serves as the +activation of the neurons in the first convolutional layer. This is +further passed through a _pooling layer_, which reduces the size of the +convolutional layer, e.g. by taking the maximum or average across some +small regions, and this serves as input to the next convolutional +layer. + + + +By systematically reducing the size of the input volume, through +convolution and pooling, the network should create representations of +small parts of the input, and then from them assemble representations +of larger areas. The final pooling layer is flattened to serve as +input to a hidden layer, such that each neuron in the final pooling +layer is connected to every single neuron in the hidden layer. This +then serves as input to the output layer, e.g. a softmax output for +classification. + + + +=== Prerequisites: Collect and pre-process data === +!bc pycod +# import necessary packages +import numpy as np +import matplotlib.pyplot as plt +from sklearn import datasets + + +# ensure the same random numbers appear every time +np.random.seed(0) + +# display images in notebook +%matplotlib inline +plt.rcParams['figure.figsize'] = (12,12) + + +# download MNIST dataset +digits = datasets.load_digits() + +# define inputs and labels +inputs = digits.images +labels = digits.target + +# RGB images have a depth of 3 +# our images are grayscale so they should have a depth of 1 +inputs = inputs[:,:,:,np.newaxis] + +print("inputs = (n_inputs, pixel_width, pixel_height, depth) = " + str(inputs.shape)) +print("labels = (n_inputs) = " + str(labels.shape)) + + +# choose some random images to display +n_inputs = len(inputs) +indices = np.arange(n_inputs) +random_indices = np.random.choice(indices, size=5) + +for i, image in enumerate(digits.images[random_indices]): + plt.subplot(1, 5, i+1) + plt.axis('off') + plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest') + plt.title("Label: %d" % digits.target[random_indices[i]]) +plt.show() +!ec + + +=== Importing Keras and Tensorflow === +!bc pycod +from tensorflow.keras import datasets, layers, models +from tensorflow.keras.layers import Input +from tensorflow.keras.models import Sequential #This allows appending layers to existing models +from tensorflow.keras.layers import Dense #This allows defining the characteristics of a particular layer +from tensorflow.keras import optimizers #This allows using whichever optimiser we want (sgd,adam,RMSprop) +from tensorflow.keras import regularizers #This allows using whichever regularizer we want (l1,l2,l1_l2) +from tensorflow.keras.utils import to_categorical #This allows using categorical cross entropy as the cost function +#from tensorflow.keras import Conv2D +#from tensorflow.keras import MaxPooling2D +#from tensorflow.keras import Flatten + +from sklearn.model_selection import train_test_split + +# representation of labels +labels = to_categorical(labels) + +# split into train and test data +# one-liner from scikit-learn library +train_size = 0.8 +test_size = 1 - train_size +X_train, X_test, Y_train, Y_test = train_test_split(inputs, labels, train_size=train_size, + test_size=test_size) +!ec + + +!bc pycod +def create_convolutional_neural_network_keras(input_shape, receptive_field, + n_filters, n_neurons_connected, n_categories, + eta, lmbd): + model = Sequential() + model.add(layers.Conv2D(n_filters, (receptive_field, receptive_field), input_shape=input_shape, padding='same', + activation='relu', kernel_regularizer=regularizers.l2(lmbd))) + model.add(layers.MaxPooling2D(pool_size=(2, 2))) + model.add(layers.Flatten()) + model.add(layers.Dense(n_neurons_connected, activation='relu', kernel_regularizer=regularizers.l2(lmbd))) + model.add(layers.Dense(n_categories, activation='softmax', kernel_regularizer=regularizers.l2(lmbd))) + + sgd = optimizers.SGD(lr=eta) + model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy']) + + return model + +epochs = 100 +batch_size = 100 +input_shape = X_train.shape[1:4] +receptive_field = 3 +n_filters = 10 +n_neurons_connected = 50 +n_categories = 10 + +eta_vals = np.logspace(-5, 1, 7) +lmbd_vals = np.logspace(-5, 1, 7) +!ec + + +!bc pycod +CNN_keras = np.zeros((len(eta_vals), len(lmbd_vals)), dtype=object) + +for i, eta in enumerate(eta_vals): + for j, lmbd in enumerate(lmbd_vals): + CNN = create_convolutional_neural_network_keras(input_shape, receptive_field, + n_filters, n_neurons_connected, n_categories, + eta, lmbd) + CNN.fit(X_train, Y_train, epochs=epochs, batch_size=batch_size, verbose=0) + scores = CNN.evaluate(X_test, Y_test) + + CNN_keras[i][j] = CNN + + print("Learning rate = ", eta) + print("Lambda = ", lmbd) + print("Test accuracy: %.3f" % scores[1]) + print() +!ec + + +=== Final visualization === + +!bc pycod +# visual representation of grid search +# uses seaborn heatmap, could probably do this in matplotlib +import seaborn as sns + +sns.set() + +train_accuracy = np.zeros((len(eta_vals), len(lmbd_vals))) +test_accuracy = np.zeros((len(eta_vals), len(lmbd_vals))) + +for i in range(len(eta_vals)): + for j in range(len(lmbd_vals)): + CNN = CNN_keras[i][j] + + train_accuracy[i][j] = CNN.evaluate(X_train, Y_train)[1] + test_accuracy[i][j] = CNN.evaluate(X_test, Y_test)[1] + + +fig, ax = plt.subplots(figsize = (10, 10)) +sns.heatmap(train_accuracy, annot=True, ax=ax, cmap="viridis") +ax.set_title("Training Accuracy") +ax.set_ylabel("$\eta$") +ax.set_xlabel("$\lambda$") +plt.show() + +fig, ax = plt.subplots(figsize = (10, 10)) +sns.heatmap(test_accuracy, annot=True, ax=ax, cmap="viridis") +ax.set_title("Test Accuracy") +ax.set_ylabel("$\eta$") +ax.set_xlabel("$\lambda$") +plt.show() +!ec + + + + +===== The CIFAR01 data set ===== + +The CIFAR10 dataset contains 60,000 color images in 10 classes, with +6,000 images in each class. The dataset is divided into 50,000 +training images and 10,000 testing images. The classes are mutually +exclusive and there is no overlap between them. + +!bc pycod +import tensorflow as tf + +from tensorflow.keras import datasets, layers, models +import matplotlib.pyplot as plt + +# We import the data set +(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data() + +# Normalize pixel values to be between 0 and 1 by dividing by 255. +train_images, test_images = train_images / 255.0, test_images / 255.0 + +!ec + + + + +To verify that the dataset looks correct, let's plot the first 25 images from the training set and display the class name below each image. + +!bc pycod +class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', + 'dog', 'frog', 'horse', 'ship', 'truck'] +​ +plt.figure(figsize=(10,10)) +for i in range(25): + plt.subplot(5,5,i+1) + plt.xticks([]) + plt.yticks([]) + plt.grid(False) + plt.imshow(train_images[i], cmap=plt.cm.binary) + # The CIFAR labels happen to be arrays, + # which is why you need the extra index + plt.xlabel(class_names[train_labels[i][0]]) +plt.show() +!ec + + +The 6 lines of code below define the convolutional base using a common pattern: a stack of Conv2D and MaxPooling2D layers. + +As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to these dimensions, color_channels refers to (R,G,B). In this example, you will configure our CNN to process inputs of shape (32, 32, 3), which is the format of CIFAR images. You can do this by passing the argument input_shape to our first layer. + +!bc pycod +model = models.Sequential() +model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3))) +model.add(layers.MaxPooling2D((2, 2))) +model.add(layers.Conv2D(64, (3, 3), activation='relu')) +model.add(layers.MaxPooling2D((2, 2))) +model.add(layers.Conv2D(64, (3, 3), activation='relu')) + +# Let's display the architecture of our model so far. + +model.summary() +!ec + +You can see that the output of every Conv2D and MaxPooling2D layer is a 3D tensor of shape (height, width, channels). The width and height dimensions tend to shrink as you go deeper in the network. The number of output channels for each Conv2D layer is controlled by the first argument (e.g., 32 or 64). Typically, as the width and height shrink, you can afford (computationally) to add more output channels in each Conv2D layer. + + + +To complete our model, you will feed the last output tensor from the +convolutional base (of shape (4, 4, 64)) into one or more Dense layers +to perform classification. Dense layers take vectors as input (which +are 1D), while the current output is a 3D tensor. First, you will +flatten (or unroll) the 3D output to 1D, then add one or more Dense +layers on top. CIFAR has 10 output classes, so you use a final Dense +layer with 10 outputs and a softmax activation. + +!bc pycod +model.add(layers.Flatten()) +model.add(layers.Dense(64, activation='relu')) +model.add(layers.Dense(10)) +Here's the complete architecture of our model. + +model.summary() +!ec +As you can see, our (4, 4, 64) outputs were flattened into vectors of shape (1024) before going through two Dense layers. + +Compile and train the model. + +!bc pycod +model.compile(optimizer='adam', + loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), + metrics=['accuracy']) +​ +history = model.fit(train_images, train_labels, epochs=10, + validation_data=(test_images, test_labels)) + +!ec + +Finally, we evaluate the model. + +!bc pycod +plt.plot(history.history['accuracy'], label='accuracy') +plt.plot(history.history['val_accuracy'], label = 'val_accuracy') +plt.xlabel('Epoch') +plt.ylabel('Accuracy') +plt.ylim([0.5, 1]) +plt.legend(loc='lower right') + +test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2) + +print(test_acc) + +!ec + + + +===== Recurrent neural networks: Overarching view ===== + +Till now our focus has been, including convolutional neural networks +as well, on feedforward neural networks. The output or the activations +flow only in one direction, from the input layer to the output layer. + +A recurrent neural network (RNN) looks very much like a feedforward +neural network, except that it also has connections pointing +backward. + +RNNs are used to analyze time series data such as stock prices, and +tell you when to buy or sell. In autonomous driving systems, they can +anticipate car trajectories and help avoid accidents. More generally, +they can work on sequences of arbitrary lengths, rather than on +fixed-sized inputs like all the nets we have discussed so far. For +example, they can take sentences, documents, or audio samples as +input, making them extremely useful for natural language processing +systems such as automatic translation and speech-to-text. + + + + +=== A simple example === + +!bc pycod +# Start importing packages +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import tensorflow as tf +from tensorflow.keras import datasets, layers, models +from tensorflow.keras.layers import Input +from tensorflow.keras.models import Model, Sequential +from tensorflow.keras.layers import Dense, SimpleRNN, LSTM, GRU +from tensorflow.keras import optimizers +from tensorflow.keras import regularizers +from tensorflow.keras.utils import to_categorical + + + +# convert into dataset matrix +def convertToMatrix(data, step): + X, Y =[], [] + for i in range(len(data)-step): + d=i+step + X.append(data[i:d,]) + Y.append(data[d,]) + return np.array(X), np.array(Y) + +step = 4 +N = 1000 +Tp = 800 + +t=np.arange(0,N) +x=np.sin(0.02*t)+2*np.random.rand(N) +df = pd.DataFrame(x) +df.head() + +plt.plot(df) +plt.show() + +values=df.values +train,test = values[0:Tp,:], values[Tp:N,:] + +# add step elements into train and test +test = np.append(test,np.repeat(test[-1,],step)) +train = np.append(train,np.repeat(train[-1,],step)) + +trainX,trainY =convertToMatrix(train,step) +testX,testY =convertToMatrix(test,step) +trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1])) +testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1])) + +model = Sequential() +model.add(SimpleRNN(units=32, input_shape=(1,step), activation="relu")) +model.add(Dense(8, activation="relu")) +model.add(Dense(1)) +model.compile(loss='mean_squared_error', optimizer='rmsprop') +model.summary() + +model.fit(trainX,trainY, epochs=100, batch_size=16, verbose=2) +trainPredict = model.predict(trainX) +testPredict= model.predict(testX) +predicted=np.concatenate((trainPredict,testPredict),axis=0) + +trainScore = model.evaluate(trainX, trainY, verbose=0) +print(trainScore) + +index = df.index.values +plt.plot(index,df) +plt.plot(index,predicted) +plt.axvline(df.index[Tp], c="r") +plt.show() +!ec + + diff --git a/doc/LectureNotes/_build/.doctrees/chapter1.doctree b/doc/LectureNotes/_build/.doctrees/chapter1.doctree index 9cc4eb4c874a7f7cc18d1b129e83f0013f1800a3..91b118b9462de0aaee6d590bf95e115dd167d0aa 100644 GIT binary patch delta 165 zcmW-YyA8rH6h#$&5*Z(|CIIL*?w8y>oEtZ$BL0`40-WC|m#l diff --git a/doc/LectureNotes/_build/.doctrees/chapter10.doctree b/doc/LectureNotes/_build/.doctrees/chapter10.doctree index 75555916a1f3dbfddeb53b62a633946cd93c4c38..51ed9de1dfe5d56c5fd15a45cfce577437d1fa81 100644 GIT binary patch delta 6754 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 SuTH_gjuAhwgIGIOO#TmT>$YtG diff --git a/doc/LectureNotes/_build/.doctrees/chapter11.doctree b/doc/LectureNotes/_build/.doctrees/chapter11.doctree new file mode 100644 index 0000000000000000000000000000000000000000..df4f51c9cfb80baa89d5c7fdbf735f0756770b86 GIT binary patch literal 554808 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 z zNggsjE2de@HyI5tZ|iu_8!m6Ql=Lb|(S;O(5AKDHI48Hzn%7JwN*{4>BLCF37Pmfg zy6(PX&Ud+R8aod#*K24F|66;(c(b~VEgT75nhaIl3Q{(64`&-r zK;8S0DaYmNkgw!m6OT~nZ|~rd`2k$(!@R-#+)$zyNrJn0eU-xqcKKYj=r?B&Aq!+fx`V&|Nt&Ph3)EGO;} zy}{1lIehFBO7zD^x?=KTCX)9c2bYu?^aF8tf>{t-{f-$DC;Ht&3;aWV2yZ+w4Bsq^ zj_%<#zs!ycfscygdy|pQ8e#Mzl3yg)hH`Zmu3#A?s%x+J&|$b&%Q*~u@6qU1FpBb6 z6K7>}0J^eG~oHcIOP9V(wR%TE>fXjYsaHk=Ex4pqjl-5re}RIYQh? zUSqi@;bw#LE|FoQhjf6+Nq0mt5C^A7Zk-1VUkQe2$%5t@vm{$ic3bpH^lZP~h&0;g zv$7`po=!<%Qs4Vo+4mkm4*#JR+jPcsNm@%j*=p?dh5WkZ))oGpjT(GM5nOswPUhP2 zgB>P)eOzXSrdh*!Q|#Ub5fx#({AoN@&tn|y@w`rtp+<4jW>!8oh0NS-CROHR*~(Z3 z1Ua1+ziU(Dd_?KAoX=Gw2mXmJw|tv5IdWE`D2PHKwz|=7Z|bdG9Sm(*?u^cUcxq0M zUL53zm6hYh>EPm_ANk^#mm*MatagY)1)H zcIbGhPnhaEMKa_g%YPnZ901;1WOx_XDO8wF-Qk@}$}S8mW8k)%+Fg@wRHX=J}E;&#%g^UI28W%n$tLPL$!Lmm zv-~})fsUOnuiXa?eYH5{+{Q}oTM7{i?wn=WF>TXMICRqe_Iw&Umr3o>q|K|pH`=xt zcDpq#%UjRcxixKsDsTQEtBL zt|;f3sHfzFiMh2J0#7#)f}6{GcYLEndl{53lWCA3pLIta1W8W zyY*3XVn_3*k58>+cV#!fKWt3H}#m;yOV4m>mS~^BHHIhW0C0O63O`B3; z$x^tS?sVZ>wg@a5J#BoyWDWjSPz3V%4E7Wi@84PcItLHKg!zrxMg^@u1x%U8n@|WEeNH!?F783DR%LNnDCH({;&s=xYG<#d$GEfb!)`cD zMs&{=qFiNrX(7v$Ha$!;(sF^aPA+HKl-|-$ltispI3c8oQJkF)plKwQ&oU3DTk-G< z*A^4VEFN)5nU7&}=`ZV;(~Aq*N(si3GpO6(U6R)W#o5Bl9f8#l&Ss4g9vg;Wri|3X z@ITGfS(t}iEGOzNgT1;6A2X$KkDHVOgS!kh;NO6N zEil(B>(ar%J<(Wm>f(fHkmsBG&i5PB4uS}5fD3Sb+=_x)N{(LkdMjXFIqPW!i9wuu zA@<{j)J1BZ=xl6H)W6UfxOtXRWA4WA<{Y!AC9^v%@}!2aWM9=}Us5z0mq6H~60Cg@ zU?Zn=MWLF_%zt!+)nQm;LD5Ls_lQS0?5$q-<*X{maS9rI8aSSXS(LW0D@QAu#Y=>7GCHs#Mjyy5drqs^nYp!g83>Y|dBnQ@9tVe6GMZ_JunYudl{g^xeENaKhKoN!Kcn&F6fc^ zSl8TV6kD2NAt_3*vjULWI~IY~G^+1<1Y0rh=k{FA36*e7Hyf#kuGJrG5w7R|NdrZia`i}m4I!9NmsxB`M7pZ2=Dpt->9~XS=4p9 zA9>wqKFe>f-1=iSuf6^ZJKmrm+of@htyXiuLt3j9`&{z9t4!I5H0VLUbv8GO_zgw%K!Ws zG5);X^xwOLM;eQFVyT5;+dNGjnifs>jpR{hnph?iZ*!!7Peic66DCush>fL`rO1g#dBHrYQ@y9Xr0se<5-;peDHlEl!Hp7D`n zDPBFxRaE8hqo`QMSI+B+=hz3&7Z%YpR-EuJ{lOX9j$ZFfkQb8ucm!LH9J&odpwC2G z%MkT1wqEVhPH)D0>u(FiXmx1Bl;!(C0RJ~VWirmk?E<>SeZotmTR z_9hXa_Y?JxErjvX;o2Te_L@$-4YNi=Os2^I*1z50z_^MFG#E*~ktgjq&gF8p+vd9Y zOoT4WuQ*M;yI}?HU?m3@m<_ntMPuyeaiy(3D1fAPD!5qN_fbi)(=ebT9mUFC#Q8$d z`L=Bzn`C*)f`PD>JCICaT@(eCvy4Fx7C3tB1Md`bVQ_dy_tCnpNe=J73|2B-7MO4< zb+Y_uNE)r{`k8zTYAow|RS^WC+vD1R$-Pq}|Jmx}8fgPfr$y?-*AB)RMw6=P-7~(x z0Bf%H=#=5J1*wN&*wu|?d()ggSH9ZfnM6_aak7EAG0X?1xQ?%Zu?a{S5ENE-+fb57 zN*={No?bd^fmHl>6tyO>Vtec?1HYkl&%0@v4$33uOW*(2F`Q_miNK0v)z#WHies1@ zP0hakk{(|3q05yveArD`=>|0!El~K#{9&Y={eqEX5iASOJ0}fx6)c1)a46~uP;?r6 z->;5hy&DIRtUi{iVn^gQP`U&>6^Zf?ySl+5&CXY{HNFh-^dj6cNY62L|7;XpJ!isH zUzvJ@QMu*$ywMPJ|Nx`7W!e(SrEV4HJA zu_de&dQx0=B=gN|Sj>4vB|m+2;o+V4y2|2z`v{^{y^cmTU@&3$iZBpP*=!+rlyEO~ zy#b3dwTk`|?{D1v?PJWq1;iK6c)HeUm}amBLH<8FT6p6sVHk(XcbgNfief{t)c9EVDJ zwggx9G$iUhZvYp-ccA^7;t&HUwzKL^J9o!(>If$xAno|gJcW_a<~EKaaQ0yCYJf9~ zjl48nmHMBn7QJy|&+l{LUbH?qg$I5N#_3+Li=Fp5F+htGrn*a>nlcvH)g+~lsm2DeWm5!_(G^#U6%(-ULk3@p~2ReZ)!XyAYWBk zNcI_P8@m#%x2){Xv@2J6NH9(?&*=qYNz>-0iH3W=(_20=zZ>%$Uw8`%N%IGlILm|B zcgsp}?GA}4H#?IAq)rtNyift`EkKEI;a z>iy!1@Hs+x((;?U*Og2HC6bvct~ZhPYAVR@Yj56BRD?QDMg+IBr?X-Zzg^d2FM|(X zScEs{`Xrm}4O4!v&v5b;PZQ3Wc8_M6c_g?)S?*|Pe9vk8n}cawP<@=+$A@G&#{X(# z7{P5qO|=Dn<@NgwFRiz|AfaecS3>-T^g6kSA5Qu70Lg;Oo(szjSc2ya!%tt~{W2RQ zZI^)svzu1{h7KxRf3JzCAjb}2FF!X|}VpgP{uQMyAJRMS)vd}3&6!6yX&g7iDs zxh{BDED<`Lsm}2>hDXC!t?#<-^}341*zSQOYTc^DH9|w5XQftfKq_&ivyPqLKhg$=Ky7N*Z znfUh{fFrHEHR_X??iqK6-2)#x_eLA>Tc%U9#0smu9>&T(^+sStFt|E{k$HF-xZ#ZqTPKrdtY->D8><-I+%ej3_O$;>m)y`BK8 zQEAnm$zKdP=;!>uW5^m;8z^e2BXc(7Tsxh;Y~;6jLxjIRFI&~VGj)om6(`j&%H%Or z!+M~&`M5HdC}1NunImQ-k)O8UrxUPu-~+Ohr&ax-&WJRPf$Xc6h z9vocRSiN4z9CcXj_s(vw796+&NHjQ8@2TyJ#_VGNfAO3+G4dvApehmc9+|$ZxA{PX zFShNg_Ztmw86oiQq9r@T!ak$tIOwK0oX>yuqC*}m%?(>H)I-0AdOR5nBRLWVFxa^z zhS}UZ`JZG1|o`{BZT9`;@m5 zA>+{@D{3g{Kfm9>?`!*wK)U`px<5Kq?UF&No}K3^-J^|GrZb9UURMeLj)Nk=?^}#w~_v=y>gN(_H-QTnc`d zSNnV`a-wpKxnfxq_J{Ike{{$1+T*L|dlt-hD`Fbrv zVQ52M|7=B2mIHF72+NNSitoJn3 z4K=|G{gPxj5JDXL5%P$13g7=(mp44$do_%MmAbs;d<@1yB z%(V}rp;xX#=zsgD0h_q!34i;%`t-41%R6}jbf-Q4@9%qR{ac$As03Lx27_Z6jRqOg zaf7?pjy}=h)h!;3k3wJV(^MY|avfY4H2wGaE*=NA5mFXo1JeO-VoAA)-rOf(Mnw&c zyjPoyUm}QG^rd;3k4`g!f8R|x&`d=lV>Q=uin!N9U(I7vH}H#&56`t;12HdlEW`7X z$rx|;EN$OYCjRU1uPuEmKp&PSqc$_1<058Y17bXy=YP)zW4Fzx(%tBRkM2tPjEQ!b z^}+qmZv9sS@#HZ=IMg(*k1zh6tZhB6)#0D-74G1BPgffP=9Xtv*pqbl-+okDcsIS= zKWYdEui$BBj|IJw?pgd>`Fe5cmAIZerMq<_(Gh%!PKbJ9h20 zv9OY%on3yxX7E6PZ3+evZOqCm68iW@rr z>a_64#!Z({?@K-@^+6)*oIFux>>qW*e?e7W=A zqepq;`1k&AUiSTA=Hx9^yHlp(#EH0Y&je=`V{LsveqckL6E6w|2QB1PQnPUb5hBt^ zehdH%Wxng}Z$7|w0>19>1Tv7PM`Ou@X5~X{rI4Rklu9&Hgx()X6EJxFLXa!}F~`wW z+2HoiR(!#rE0K`O>keeffub?)UGe8n_`}&hK!`yz9qIXWKQ=$KN<3c%Eg>vU(dW zQT!xPYNRq~>26U%7&c6eFTQ>QLLzZD+n2y#ubT%nG;7(*Yxt9&6_^+_=_=tlPh}pv zGMUw`4+Dwr^**xp|M#A*_etnj`b*KbZC0;fhf9kKi1$@vnnH0eTo0h^h|>K;z0srG zH<~j(K-XPEeHs`t@6tS_P^KYI588>g80#Ay`V6(-+x=tw+iMpn6DpnwkA82n5=UN_ z33x|(1TyBo=k-OvBM)qiERKHGQR;>y&U=6NqoH(HJ-^-!wCG<5Y&IyItv^oW2>!!| z*X?EP8F9inqg)Y%Pu_?W=g`Kk&xpInDB0;ZS03>TA|Kl}p+zxg-5D&XwINV4v#$3pTI z+%K!}g@Wr={)=(L7k=UnG6MVS#gO|YeTK;BMk2}&=RdEsU?~fB{aiC3c99KxV}TlM zse_j7e{uE({;s(vpQ<89JMH5*brI$MwN7k3c31|DejPy}O^SLiw!NZ4)5w?2t~%30 zm%s1Wg`L|oN^INfi*`HEr0{n#w108tvQqGhKr7b}6W8H$@EzwqNppvD|6bqmYKUbM zEnT0jYm{)xNeuBMirFCk@v*uNI6@3Xx16EA@0b44-AT@Hbo0Mh895!i!;5l7^i)Bn z4|#FQH_hY!`9oR+<*XQbTfSCb0R%pQdb(5)#{c5MTnezh*N<{zUe7y@Jk)$ms?Z2s z&g@FCLf>h?XJ2A7%cA1Yb4$!(gp(h`_|Mio3}l|S#~6Jui{i%GQ%=KauTkyTe`C^M zgo^z&dM6v=`83YUG;6N&B$*#pZ?EB9-wi@{^85Eb5jq=2?361FPyBlZsR1(xkIqxn z+gwaUMH_QRkh=%@_pO^C9x0*26MQ{L!N;{e5B|aIpMO|@3kP9px_9&>^!mH2okO@W zqSXIAU-0!Ub$QC4?YqA?Kr~`9SjZ!Wbl^XH$#pWwSf8J0N~oU=UBBt6F|UB!s=rvQ zfDh!wbJA84qn|e{2{4yO1m1=H__cmGRC_yO^f04$4B}hbN4nH`_tsjuP~`c8x18Hm zS-!@K`&~Rs{;5t7(}mVS?tkrAyJnE*DP*-cpZ0n#emX1?A-}|bc2L;2LfYV3j`e)j zcmlZpEZ7(;&{+jz_V zd%j+2KC|pNe3{+*F;x zNhp>FyEScrXz^eF_GxOkjXv;GoLfbLT(|euB2yGNYDNFGq0zA69t!I12Ni0^X+r`o zSyHVwe)-2m6++S}e8`yI`}@^w{)z+4Sr9(|`+mQ_`o@j&6z>HxO_!M$^`6#s@XG10 zJz35A8X&f~nBFX{?Z18Yd{Vwoe_l^if4@fl8O!5%!I>}e7q^JN`%k{rNCy3jI->M) zfWjc({@%apT{~0^VjaJI@Gq)N>#a9~WwhvwY5!tk(WAi!`NrwChe7eZj;9YgsAEb4 zz2$#ALkYOn0jWm&L5z{tcqYG0k7#G)_3vKs2Oo4--K@eZ?HY~=jVM);mW3)tQgapL z&%avKID;;qzBX(ALShfWGdN#&*vn@4>+}8YtLS_8wLa0;P|byOsM5tct}g&Afkx0K z{U1*4BEK28&d)h#@g5cX_z)|uclBVMshU%9YW(t5(1iu zWv0X~8PFXa|JLC0Ht2)Eu9%DM?0pr1t{4iULy2IB_jZW&d4*V|)I;oQLe8nfdv=2! z51+9KJJWwV2S%oW&;@nH>X6fQ;dRR_%?3PLne_R>Csv1l-+d^Ve(MA@#Vv<|G6xb zhX_ls=bmfyqW%B#zgIoY7LZF6E!n@E>2f#^Vl@?apVB+Tt`7XNpIz@A+^93%pw~d~ zEzy3feG8$^i-g_cZS-|}i!>N)Wg^;}pzC{CW33~y2qnCTwNik;>tgOf|8j~n#AddU zx7`_py;=hoQyHa+jt&(xQQ{~OO*=a8Tz z7gC_Oi})ODo2IkFwQ@Px#kzGIU``TKcZIA<3D0OEM4}Pvv?{}kFFftI3DHpv*&yWd zAVD?qJs@`aFYFW}amUAnn7jjHQrkg|EBE0zr+`#Guwo4)edHs1wInEVaT}Praq=CC7mf_{B!|CGH&~ zK`+5gWu-ORbr}TDvQp^{e>#7!xsTvuc28N;>p^NS=<#4{LZ=tbCmYaU{}&5?c;p3m zgz{~@BBoGnjXnZ>O@V^S$3fg4{cCqu9|s?*tIhKY)#~buA1w~#xpKa&vBjTpod6pM zK8w*I=3VaTl0gx3j1qjhkF*g%znbNYk$>5a^$Qp^Rd?WX`deIYJ&zX>wXvnh)2bS+T)YCKcFEhq~aHTAL{$wCBY#~RWaPsq`M&$- z<-OjJ6(Zc0vo*vMz@ER)`F}t6ep+qiJ_{Z6j_Pc0c!XSV&jy)Z3HSo^1rI#}{MYT; zjhi6K+aJ=BV-D9R=rXxO`N{qR#EF=fB+L#(|R&L$Vm zg)$5i>#(&i8^lE;5RNbfMni&zj_-Z2M$)bj6{?gCsX$Th&vTeRUGha?3gR=jy6hQL zNsc4mM!X32sRX$Nabo_(i4Is|eWG>?D%#^du-IwSS3q}$!a4vQqVx?Ee$qquy3Jst zM^Iq~Fe6MzV8}2LrV^3sgN=j49@)QpBOqW*iNR211NVbt&96#d{3Iiiovvr;Ry>|DzHd(@w4B%AiE9a^}wS!zk ziV?ecM=iwkKkt%;cloSPtA(<#-7B%*j&8nks^V=jBhQZ#z|?=w^NX{(bi+OeuWg4i zaxQ2ozx*4eQjnZ3bMWtZ!asWe0?slXFNsTcoCuz)mc_z7Am0XV0XFl2v(Z(+UYFr& zh**9GWT~Ed%f}h=i3R&*?AJHJh^^*>eL#Kn*6F|f7tZwb3R_d{?=-7dIO~vv%Qw6D z%}^#T(;sdC5)m{ny5U`eBeRemY8%0KuqU-MdA5~%seB^P^Yq8()KD|fpXv}rSLiup z9%5(pQ?JtmRtOD(t|D|8njH@OzZd_m-$5hadxwV3ET~^&i1#Cec!oB`$>(A>1 zd8IA|%8NQ5=i*KrQhm+%sNZcFW;eDbq4Q_imJ%kDT%Rfzk`jcP^0Vr1VtP5*!5$R| zhd{$F6=^+?Aym75UW5B#Ca{+8K0LAe;YKXhK9=NuU@CPBwAsbG^H|RxSE)em3sqWm z2@IM(BOE}v+rB1wLhR?GG@+6e(bL~`6>rpUU8|a-=db26$m8 zAOOWI!N?!_*H{uzIOi)L4+|CLh#Z|t5PT#Mjewrp1iP{!0Cl(D%euF39Ev!lXB*I? zKuTB(d+Jx_O}89(>t6vV{QPX-1*}7FP>>Y__a~nE@bDK#%o|kXrpunP?Z10Xe)p=< zgySQ!HI8?>EDj%EGFCJ`c;lg{K&~Y4(b>=EGlY?^b@#pb>8ODpU>i{yX9iBOi7u7_M=DKyD4XnC8+#x#}T>C&egdKS9q#>I@ss zUC0!d6{O7}X;Pmr|f6Us^991d=hOzvAw2l81Gf8vSw zu7p0R2(?2NZ;fxWOj1yo*&}F9R7JEMh4NXlTKT6og@o*HNwROG|Bp{1xPH&V*M7d& zz1~p{^n-t&(YgKkaCH*Sgqf_fX&gx*CZS|cd+-^pN&v}4DD0y@>$idG2G(y#+Y_w5 zXTwFO`A?}}u0j|J>aP31qth=JhnnfAZ@*X+s*jtKP*dVjyQ2_bi;ml!!>?+a;Wx^;gL4UQ@ItH zMA-!{H1_uHjo4FFi%eulf=jAMH;Bj57@yHM_TR$@%-(@qgSn+v$wD#Bzw0eB{OYg2 z+Nt`BwZ6m*_LIP$o?ZTsa4tN)qOIUJgkH);;j4@e>fHF z)rr8UUf1`LRu)yT0fV|QYX{my2u?1|CcQi+@lQ<1YsgK(X2oythWyqdH}{k?&`2Hy z@mMn=yq!Mu7dWg1Z7Fo0aG)zl0ot;5K7%khSJMe{qKMLzXm&m^2e!1*Z)|!Q;QaV< zx1qTZc%Mk#0JF9K*+YA^ZXn;EipR~ZLB%GGFvQrjGCZI*4X7>@}FJ?hkkY7qCk`G?2bS-<|s&nz;nv6PGs%KaqfWN z%2~qK)fXUN@=VDXGlx#o6*}Uky(7705L#RA;^jzR;7A?)D-?EdP1AvcF;W!aTE())h~}9{Nf7=g@=&Y%B9uZ~9}$ z&^x+TVh@#iPD0Pupv_2xuXpo;x*{;8$t&zu`uUbbb|n(;9-;Y{ec$e(LG?g8xF+;* zqT8gh=r1+~UtMp@=C&((bN!WhbkG|mgfBq(!+TG}(fftG?1Cc};ak>0WFs(jhdHEX z5eXc&a`uAs`#?0+&ld+yD89MCoW}#cFcCOy$|ayn^p$QRW6qB>`5*iDR$t$H<6-w_ zxKd*GZ*0iu|;#~}_XO!YQ6JrWo|%)ikM-33AqSSIW{!T{MDVm3Fzt$FD*Sdb|Q|TG3%RjAb`K$ zH&M1|gq)TpscsG7`Z4*9fW&Hw+pO5oK92f8rVnKr6U@@NV|o)n#XoXI|a zrOaI}FR$>LM-FhdCtMlaAO*L?a&GyV%g!bs=dh%=YHs_@p96WeAde+d^a*wB&ev_Y zRtGi1lHuW8fhek=A@~y^lJn60M7vp9Fm=XTCIz)&`SB^ zJ4HD~oz!t1#Xug>69jyLF{2`mRI^-PyZdFdATl;L+hnA_I=%NTl<&*Yp)G=Z_7gv;D3%Uu;!0VJrdR!{LS@kfu_aVsi)IApi;x%zH)5J z`-=4QX}yXIWb;{mL&$q#9X+z~+rRg51I;_#yvJkC4{e;9Ijx-U zN?xG0uLmR=;U46DhWCc|5qznumvQBRmQNdrC&{z9WO4Y%{%!0VdwL)iSwAj{O(7V^ zv$-iY4ayiuO_Y|%??^-sM{*?L(8$djaD-erxJ2m97ZrwV=Kr%P9MGKSn%7fnKbx8q z_fvIxs-t_Z}<2#ZM2S9OR~(t&&PKjQ#yYx!Cie zuZ?@WZz`r1`=oCpUn>M9<@hgGL!j;-RJS)CcJCv%VxZCptf4A3kDKJ;$}=N_?o4Ej z%faj{CwZaYVZcLQ&JL>G{&;Hll0nUpwnJ-R^B%r4tc>`O5gr-mO+#K8ND`Vb_#HGe zLkhOIp8_{{u03}=0O(wj4>|c>8_lgB!h}<`i_9wV0(A;R*5=V6^)K$dPUEZhWq4R{ zc7#!b3wqiVQW?>o{FeFcZ<}XHW_#b8B6cCRUG}7W3_yU`+Z!-=*f)j!mQv`lI9Cn@ zBQS!-tOTln23%-vJulSylyv3xis^8^Q*VL?c|UGJe16P3O`NY4F~<|t`Xdt*zMQD} z{_{`qaf~P5#k=@vI*{8o(02KT|F-a7XA>|CDmr50^Zt0b;UAreJoZDRkK+la-7sbG z5|8auCiW_GaJUE|OQ3PQ>!2Tegl$N9pR!m*n*rN4F2K-t7Uck{?;lA>pWtAt{x&>Q;d7es6xIUHcbRUbBw@gn0S|shT2xvfumln| zUYu9@YjQ?1B7xmCW$6+`=h>&kD}C{zwwsEC2u>GEpnAVRvZjD|Cv?Vqa_K>QEyNhV zt#oiP?hYj2b+5&7LOBzx4+IxRcVq5klVgINfErzLg{csEkgX4~Qx35mG&u7DrNW<@ z5me!bbX_a7+_6&1M>Ww-;scy*X1LcZ>maF=ww{2F4=9>nTH%t^j-2MP{<8T#Sg3ijNoc-5vDDb)n)gadk*WpmIYZiV%{4!wQ6cw{9L{r25xk)3Jh{Jd7xPv;yT>m#huVa z>;?BcF7wIn5F3Ac*>!ICs)Uztvf%s|>*G{4k$UrbZM(Pfh;`_z&!O?1!Hd&*S z2$~T0mS6!@&3RJeGfKTf;EiuDzHa!Y+lgX_UUf%nWJCzyTq)=xY%)9270JARANlYK z7m&&Z0ccT63y$fa*~7D9IQ{|`p4vMtp-@F2`1)h2E|Uy!6R>~6i9(`nja4)>&pe=i znLpXdY+fK^SoI^EU;_*`BS4?-24^kQ(3ecSjOiUmJ)<9RsLsx%S@&5`=p^GmVo2jSA9%on!g}5Zr*;=y9nP0csd; z(j-tDYQ$K+9hlyCX%taR&41d^oXuLBb6p*V1>OcI_ZodQg2xEHg7@e%eF6)y0I7xU z$;IyA2(evsuAiMK`J^mWlK8EQ24okUAosB=Gn>2(vlenB_U5IY_<_%ccyW~-QC=dp zqndubGaL)}8~WMu=ZbDl236I5ji{6ZhM`BH^H6#eFZYcGpSi!CHM1vBYx(c*Bzwt|(Pd&k^9-8Ua@T%09tW!h5$~5zIFK83p6pF@6a2}*zJy-#NARnIkD2FKk%!q8H`977j^`v(q^OM&POTO#(kUa@-p9T(bMMO@iKslbb4_oc<+fKIu2p&R5n*~^-GBBKPbG2! z5e^s@>XMg5{y*@O+%vlLXeUzEKr0*D$fapO9o_?BPvBc(9;{NH++ z;0PU4)W6YE%+L|Ws~hxZcLdZi^YNWvW&X~3nsc_6GoJ&xkG}<%I`7ud|EI3<^&v(x zmqRD7LGM=7s*qy(h3fkv{y@6LY63wx|(ikZIy(Qu%nN4`a;y{N6QudsBfo=6ya7 zR~F73S`6@+0l0}pMyo)5a5JTc4{hXRGRP#xqr9vVBhetVvuCnzRotikc zhX7D!e7R%-zFW29K+lwrQ0^&IE+I@L@d=9?`G*hrqye*O=^}?#&zcNoWrP5yyTk{a z{^0KTcl_b}TW1)C1FEkB=#s}xshVc&Uc!wNv6~DJU)z&>-DOa9ruvjlq4?7YIM7t* zfgb-V+Vpuo$YhBH*8;oLni5V4yIOu5jW>EXvaY-MT#pABjAjpx)MYD*=bHE>K{(bwX=?#w&V( z6Pmnf)vOXuaWF8T_9+n>#AoJD9tfOWLc}2GfYShp&cs8bztR_#?pl?@^5Xu5a0RWU zNgx~Fa;D)t)UklZ`Pqlot?6xAt-TLA?5X5e=Yj(uw3JU?bII61Z0hMkLs(QGDo2?E zZIdq&65*41%AE3hhOHSs&abDv6;|hSQ7s(4z=wxVysFKIDp^Kjv#H=N-k>To9)-!qkmuceXaoG*Ci|1-4^ZeIQNGY82%%F@$jRC!%Wfd!TFe=WsCqR< zib3Yzo>#)5-PnvCmo&NkaQejZeL;_3?5oZ+oEGw_r4lWL($Nql8-6^`pZF3Q9ULkN zEj1rXPk@eF4Wx@Lnl`56BR(lkfTMhlkF`GTeZA`W0P(Eoe+|1gqxV_-!an(k#MSe4 znjW-jYvnt+-}V)GKpWFF+HwlYALz>mk=Iod!RgbA#9Xt0A(hWgz5i$?Fi3dZ{B}4{ zYr4k7(r)tosyF05a!)S=-uO@c>q$TD0vsa($9Q~b>UE;u+t)9duyQ)xlJXX_n8$H_ ze<|^i14@B?xGF!ssOzLL_+RY3TdeGAo*&em%uLUmj37$TB$6r%c(C28cRpn)W{_fxZ^85e($`ta)xsd%3 zvFC~(4`guCxSZ9<#$u0A+q7%J^1;<{@3uZ__!*n{%WD7`q^&xK6S!;-aQz2$tGd-gcuPDv`(zwnc|S92E%tj5a#4+W_`M9RQ=&RFRPtj(b2Hk zA9(mUVMB5O9)(Oo#QjarzkueV1!@^(cU4J_-9!Ncx~}9n~d&D&b_EVb}GQ z-jd{C)C-0e0Jf-pIvCgcehrMmtk#)^%U13tt2$V=>)j zywfH)yVK%;3jhf)AGXog!)AQdsDT$PF6I@==kAa~ekb8tBo$1?66l3#Vl$RJX)A8Y zc9!8>wnnJ%bO8h55Ccyv1dvl*jRWEz2Gh}d1n%YW^(>yoH3U%%&a2t{LFrbkjc>WHjtSn(^0vhhUEEh z25zUrw;8s#K91I{;+PzJXA(B2?XHfxS|F{Njbf*>c3^ZjGssP1vsO*l!x?O>FNM<8 zVcFu+gWe6AXd`uAPn5A9sCxoN5i+AoR;c$%c5xVRTByOX>EG!Pcnvx-EtX!nvt9^> znqA%2SApN=w(FCf6z*&j9vH7h(TTDP*4}6pHS1@ysw`8P_6#3}`2#1n&7NEm7GaX* zHrWK)fKhwEoDb-PuM5DL5iPYjL2a0Xll>C3pMb&i&i=dyz0{n~L1S`s!eg78BHE)k z$}X6ri@KKsipAX8Dm3;@(_Ia0Z+~v#jL1i!u*%tPuEg=|5RM0Nzh@lEwr!VYht}#| zkpnG*`8$l+M!xK?6e8S3h)_YNO7Ig=CeagHn`{R4(bmWIKxGUe3p9J|ttp_7gAD>x z!1~OuPwP5?@8rBDw}@W%MKGn+3_w3#;^?6b@3)U6dbS}(#~L=GsGwTLxiq?IVL`zWhwxn@E|BW8(T1f%sa*q^ zwKX~lNr(!35FXcACRA=BTsj@YgEcPgcu}`viU&sWK9~IT3{Z^BGWuk<7Tav#bc=Oc zqraI?!~BY?o`c70acUGua9{K*j{%65sZ&loTW59n=B$0Fij z4~;36oo4G1wLNme4vOM5mRXxq_NOdI(^FR0z{ypV*3^NLxjjh?$(G=g86Fq6wIlW@ zW7}U@WKQi(?F`Fc)jO)H)!s-(hwheEsFe1^VJ2xZQRmt1*|~eutyHO-STHnoNt1Nf zP(wk4136f!#2-fb`5cuQ;MX`lrtl!-{SN$bkl z!qfn2T{0>vzaAD&iTDO!c>ubc`$82qvD89^&f56PY}Q+cE|KeLF&e8-ujIp!%E`S& zxRdd&GX!2`K+j39b4?qic<3X1V7)=iegwO{21!Cd>|RcWQ38ve0Vxy6N01>2)LZ*#C*ZTBc%uK7|6Tc zeySWyukXjdxa#x zXNkRZI8?dsGF^&_+F&9C(zLMwInA6?0=HfI~^a2o8$ zm8o>Q8;R&z?HpmIB(rVo={Naqd1A$7%z(hU0*0{z9wM>7&)YOi@ao+c*$H=pjRF6_ z5Rr!z4wwmoxF^6P%wpJ^b&v1m>)niDwq@r~dT@GQd#MjUrU+Iw%SiZb&jA<`s)33# zu>qc-hYlj*-*EcX&QZOc6Zu@5-kxI?jV*2GQ64L8N`t|<)0`6mf7^oe)piEtMpP=s zMpb>0TJ;utuI{gwrm=5@ru|FOX(^sh`-gTc%Iuo}TnaWb{#jApv#7RL#iv&pL z@e#WJ9&Wk4sVC}K>JX!JLnicP-}sJ16FdBHHt6oHL=h$o=<@e{qvRQu+cPW`HUIb+ zWM(c1oQp*#=Lz^AwgK#58Mgbu0e(4de&Kt*o(xT^6}HIW3SN$ZZ)!(InXOt%sg9JC zB*qgro@p4@3W*x{p=7u$-Z9vf91Kh(*d*yQ@b`o#RsNoJvbpW0fzw(04);= zdz_r$X+hXsi3qasHsH#%J!98a4SPv)kP%-IG|>fe7QvQsRspc%5Zh<$8XdNz2M2n3 zk;7yFy#Ers&dh$|rDLXDj9W89Orl)}Hpl}0n|^Q62fLzP8r&Ip9Ea(TN2$#24{F|ynccNcf;HMdYvPxl@*`=M$*p(l^@MW))-7ba9IG*N~K+3Zz_1f~TNg>>HiFI`8TIaE>FRKQPM_{_D|MKDh}0*o;Pqmk_RdWGj%hDH&u2 zxTRBFu4?131{MtJhIZk3ZhWahBCrHoC^2QH6k*u@?gHu}$H@6nO#nC1*<_QsFHUj@ znTLK(WNs@@%dR+`&^F?7v1gIYjGbfyXLIL%YUx%Jn;;{`)`b#0W_pBn!x&x!(Qz}g z&|5oycG)Q79qb_WpkrM8eYMD$tW_Nq4tuXqjm{g2t`lu~fw@d-F-yS0^jl0qANE{l zeX;WEbgd)ah~`RXanYA8kbdkgMcV6Tmu@RrXBOB)p+6o(zrpWMKl`d2igq;QmZ|IW4j_dJD2M`EOUhOdHbdwcbQ=Y|9hn{21AY-d%kGq>mEI5 zS65uK$0N6zw?LrZamqAaz@nS^V8d%zK?-(lBCXHlvhB7i*o!VFpE9Ez+ljmu4e&R! zJ0ZxX<69biu#MfI@ND>3}|%5bCNkCba@}@P6}A?o5Eilwsg-}p7pcK zxzR$&0L_^ncA%v$WYe-POqX*JCOMe`&PBmKPe^9up<@XPMs? zl#JH3Wv)5=!3cnUL z1fb=C6U`>Gu@BY*a5K|{BqAP9P^CtnewmX>Z&L#(?Yg~7MsGYMta!G(Lt~J1XZ*VzfH^|F_4{qnO z-9}j3?Roz8yt+U}iOiNdSWI%J$C}^u#5z|nTbhHh9Lo~3Pm1Dzcr$WwF$UEDI9(C= z;&o#)=`R5kTVAe_rDe8q-Y`9ICzdcgkZpm>RjZ}Q18`X+6kqY{E>a835$l+3Fn1b4 zA7GjRVoGO_D%KrmECf4tO2<8^4!|3KPFf2lFL-xK^oB|k88?t7Y#&@BHj8tn(J-di zCxg1!tcgYU?E7lEi7$qic25ZL4^OMe5@>3?TojO}MV6RN$gWH#RtGF)X`}O=C*#Td za@a?8Bflp((8MJdCb`s?E4w6mhR1%J3biu{Mw)1WXFuLCbL7dQ{Z&Z=kCvx1a5i&~kJ?o`f^ zv#uyBQ!Axz2K;6W!mQhRpYr}?%Ow8!nnJzrBDNF$&-M(NfB4Q0aY2JFbbS_PjxP4w z-oA;WY@WT@*rr48w$?%0hS*T7^%E?;(Z-fQ9ONt0uq1F6!%9h?+tv0&R(Y#L?8E%F z&X&8?xi_Mm({-#_D)_WOwOsGdTvqR)|8I(+nC=v07h>I-zC8y6L$f{wT{!GLVCRhC zdRp6Q1+hTN2c0pkR~$KUCeko-#wVFn^dTrFwsX~D0lbTSZ9X+;oOB&S6 z(~;ffuHn)!m1wwiMhZ7~#sKLp==%1~UBiilcbfiuBp+ER1#!UHa(1o}7XEHqcM{uQ z7u5dXld(`MURG+KpXaZo0@6x-|TKxw8UuyC_^>Mxr) zEDo1(!)tY%tgFjrmhQ(}7%78bp)g#2K%_gAifdvc*vD5W+o}LVDn{Lv00;J+hnF}; zWoh_%rg%LZ9)_Hg&f0O@+{q(GTuebvgz;ajg*$#%1mqX{CBJGVG09ssBHKozZOg4W z-ES+?^%YBqUNcVK-772WG#%#+UKZjm4w?p)qHgEu=FsS%6s=xr=#i&7C_1E;8iNyn z=m^vdW=@(R!N^G)9vXTqco(OGsB#N9Ytt)i6&5@V`^_R{IB&Vj#ta0+MSeGiRKwSDj=W5dBmkl1g>jn%O^f!B@U!CWJN_AhF7IDuN#GHf|H- znj#LfIY^)fL03;or(HL^RK3%-P37)LskzCR)cf7tz5o015&aJin@JOky&_pK@HFSx zeAF|Dt$!OgZ!%i=+sKQ31iXT$hDuD+R^wtl2XVGM z-9bU%hh>9b%X&2WWOw2l8!RZBkLyVgh3C_jg5Is4*6B)1TBB}ntX)keMAni%(JOXb z;vm-JHr|a%9j1vEg6Q@A!9f(6qGjqV=uHu+*u5;<*98yRZ((&=gE%+X^JsDc_X_rk zVPwqxv208W$v|i|!|3opk3)J-Uj>=;{i#)UV{Uf#5Gy(BPX+L5ohP0&YPceDheT$v zD_a5d9%ydJlZI37JMx7KxJxb1G1W|@M;Q*y;3gMNB8@i>+L0K0{DSLrSs_BSS4WsT zsZo*^jU83U4IyzM>K-@XmTC4vu;hXZss_m3{4>OW+S$o@#5z2CH zFy;M*%cVJUmemv@dOpj#lTL?2?k4-YU;>zbwI|k zCvQUo4nj{@ra`w)T?x}YLnNV$*ngO zvSG6G;zDvtir5e%HJC~-Hk~oh|9!WSG~ffioLFsgA;}ZxkC2v1=?(Z1;A*ggd5We; z?Wu6cTGN)cQn1r45L1#9hqk)E0b9T&f2e?Sq2~4ZES?i-)H)peeZnd38Oe-vd}g_6 zqSSrhUlceAgUJceh~qwE@Hy;V)6s+~*c}(v$O=L%(g5072R_K|@H)jB=)*S{14LkY z?!X%KWMUc$CNmf=?Y;~bL^ssHp&PaB9kbyEQtgKwcWk))nB8^3gTV`~khTi2dUai- z?12r-v63A`OGW*} zsfOpwQxzj2l<~D7D=CrNh^eBMCytZ1$oooy^U2ID-}EQCU)<)6Tv zQg-+e%to5;aVIULrCfl^Sn%BO6@UOYp_M!p^AS{P9d5#PoNMF&6kGj)J8m%!?~|5r z;OlN3R)Prel}TFD8FOs-OcpHyW)GT@qodTL1JfOP-MN9ZM3y8Xly)bEFyA)v1iaNa zs0M*-2)U4`fGuq^GA#y5r;Dt&J44^Ptbc-^@*-NHGbOgwN#$Hdqm^~xLuO(pNb__z zm9R$a_5vvewajQtucs_*DT#I2olGbXs#R7-AEbC4aL(uf_y-U(0KI_}=7)jqm;=fo z_z5pB_CheqkG+U8u0^-CoKOBR6$y=1S_ zi$JWeAlx=v8-vaZSb2bOB;aGnM;*Uoud`7bNe^~2#F$%QpFd905p7;6s4J}$iQTBY zr6}9hDHc}ahmHI_-gkKL3W*>}gfSIlSzO=X67d);(Wf^VE>br=Q3Jzt z!?$22nzwFnqX2355o?76U%-=sAOE1wJ-W4!n3>y6Ht`m6tj}oDb^>5BfEtawnkkhD z=4hmSL=2OPaGJ#KgqxVh?wamN7=~-N#hsHjOl)q4k%ykYiPbJZ(2h@Q-Z&l$4V^}F zhE6pnZ5~4+B8PT?~T+ zoS~i3kb+tgKkrbvu3G*EK@#jR7KA2T`PN>EMtfx!u?TT@D9&ej#tf!ZIoPa45=Izv zPgZJel&s~Q)od+Tareq}tkTe!xTxF9GIih~*bd2!N>Xwx*y^>290P>hpEm@Ag>$ z7CXM#69`{|B41mDACOAmOO5>wNZmr*jx048oPg^qMxH(u{iqp+MlLRxs&yXdL_KIb zY`@~E*y2@_Cg``YvK1t z+!N?>`gy~B5EMJdR+L(ZkebvfG6Pzfq8I^=&HF)X?9laayVXQ zQ33}|!x?;A2cAiurwwuG};J*ELp<~ zYbx)Y_Ca|SLN%>*ErUl+8&Ndx?TgbI{?lgviV+E?PE0^V`ul13I=En9N+54N!<#Mk zFdi%xO1#aOeGjm%;MnmDFctJ!FyqgYbtgtDnW{7NfRnz}?mQ8Bx|^j6Lo&+L0Lyy; zNBY=G99|w>bAvstvuT?Kb3rJNYs#B9HXkur&F}mRNOmDf$Ii+C$J>1l$Gc>ox-9J1 z6U|v7ovJBc{Fda=KEh7MhH&Jr%*dz6#c>f#W8j(1vtG}T06Ye7#iesfAXhYe5Vx^d zS=dXEy$FXu*u+>AAXvF1n@)EK4C1EtiZwEAr_kq+t`zH~{-vn%%1Zm?2Z4^$kUe_pl)y`up8u|W8zGFjDr z1PQHxQyHnSKx$N*<_`MYwYS!p&IP`86;P-i;*7Q9Z4iJN@fHBQ;-DWez3q5ktVXa) z!@nO*s-qTk2;er5bhxGm$bdpo3cxKxwgedC5?IS^8>))fRP1*4m#xqeR4|u$Zw!h-CIkj7QTmFgIr9O5ui85-~Lw`EGd%(POZ^A{KL>r56AX z;j`z0tEf@EgaLj8XLBL7xO`=S!-2eldHsyFuc=`iiYhQC3&iSf5$T^?)YH0pT2re@ zchotBW!c4Xb3AN}rDlc9MDIEh#|5oeUjhak$FviW0@9zw@{HP@PomWcr{`AHl%*~j zyx?8FKvsw&jJ?Y%;WWGvjt#dS-A>15=z&3S4cN?u4HA2Y^kwm(pihgSm1+@fOmw!p zoy8!)%n{QnotyG7Lx9WjGmQY{0+@IPGW7^sz}BwFtYcUM-w;D?4^) zQ#l@)oiid4)(2vDgiC01K%Abo^6ffkLdkDsl9!gHHg@G2)XGy8Za+Yr=PdwG71k&l zQdD}@_;874F6aAG7q-JP_jCmisAM%^v#lsvcGPfk-PY>qOzuF(u|Nn^cc4ct589I_ zM&a06oDkz~UJqtX)zj)4L|9~{C;9peR9YHqVBg$%fLWJ0ILd(cxXTgK0mq_dBsXJu z`fwV8G*f8ej`M8-!~A&;YtM<@ru(_Nn2w19NO4GFFiM62TsD_>($WvX#CK-nqH1f9 z@9*0kU|R#FK#0K#(nHssXA6&Xv}I@6nMfKvKlQ3LjK~UCJ0-iXC{hyBIoB2XhBkv^ zb2~XBqiPE{$mG%ko%Q1xG&z>Wstz>=S<8Y!v|IKYAGgfaAqA`YEcs?Vb?Q@n3`!(sof0c`FN3#w6>s-6Kz1379(HFy zgEyr);BW@FplX-;8WyH^ob$HvWVp~M^d0+ zKrXalp=Mzl5Fg;Gk!QCfFD@fsc7w|5XT4|!CbxU1<}=!NWUtE7vPUcX;+kIM$k-tq zh&du{d0V@7&m83cp1R##PpnzdPQ4A4BwMvEu|8#+bAElK52{4Xa-#<|@(9J^>1fzq z4DbMYX6fubdPu?`oUwL3IKY)RnGzr;l8&1U=Ofra*3xKmo@?FN!3Ro-BVtfb^|rDW znK1D%Cx6WLf{qFXv&VgXxk(Nw`2R?HQ6QylQ*So}iCbD~q|@hjwH}xgI_(1Exzba* zg^ddt(OoEs`T;3PmaX+n(1TqYd7$1MWkGNO*%)#w_Z)D4wtJ~WbydZxSaTm|9KB4( zoa}VMebtEmt9j2>o3k-R`VGWJGMA#66UZQB<`@0iaQ8P80u))2x0kN~JUB)_w%YUC)}W|vR>9tzfHc5j zxAbJbpb$#MkE2s+(mZklX*-Z1Xhv|5Mm@0L%tx3DF%%zu=Q;<9x%p`46}G~&MCt8z zKWd@`ZrjyxM%Y}T4c0URpISNXGKW|=lig)^GUc#AjMI^kXh}!U4|^;wP*vNIs1QJi ztmf+q?G8+DYMJR8vQ{P>z~FZ)*WC!mQy1vjvf*hQX!C(hjA4>xCy5nZXpGasw)X%a zATK!!5p$jP?0O%x3~2pQ%g94ZzhoZb!C36^$4!&b5I&WYDGe7}#5&YDU?kiyUbMw3 zZF6PEm!)X1C;8syVxJDai2hm)Ys#O3B+F3e*S36N)$_WOU3ws53HI?d&$c@UIJ28v ze;D_{cQ?wqQxR5?J?kVyM>r1dBwj7A^#R|=6 z<-OHB+O?!!Nw&Zrc<^e;ASzMBHK1j1&VTMQBqRl#jXfI>H0Myhp!f$sqPo3mf^iBcrGTqy;m zv{$MiM(kA(OhGr(H3iuhkDJ;eS_{5^K^ArG^<-Rl#b9DqwNva(-~jhmE11_Oaf_GHgQ2+3j|@Gw z>Ewtxx4>=^m%Z!x-5CsrQ8x>NE~D$c0S7@1dyi%#mk5$+^%HeN>tT%Zyp_^Ot~W=L ztsE9eU5GPlX0|T;QA0MdcpMye>csD7rZ`BLp!^B%aZ`fArcC=Y(a_r^f*wwnh@5aFx7;3yUbp9qM0GZXl3a^zb3HYBL>ZPBA@Bh%(>kG^ z50f}ufX+d(1~GDi_YtehuGS_tLDf|Dt`zw03HEi!V;VlN?rUgmAqO485jI9z1ccyNnB zZ{neOWKIu(R2UnDd{jlGX&<+yT|_mSgG%bnr-tW5;~vLuFAG9M#GJZRTUXu6Z0uo` zk!sYnH_5s~SZhRYBM3D1gulS0lOws#`I#*$i3vaEtCw>V*{UZ>`0C6qc7H{%^FsNP9$izwbfU-1xAv( zw&tdJmIg(Kun9%rKqs|yf)0Hi?>sO`^m?-`oc62h9-c|ZZ01UDxL9Hib-U$BgEQ6& zn1rx$4j2y{Y7JN63<(DeM}as3GI5v-O6Ra;29v?$dfp`3u&foxYSM-PV2r#ZR$V7z z>GmAf;K=iKb4tbDwPuDAg_L>d0>oy4EqM&;qE6keK=LXiW?l&f6#vnT!+Ia{Enw8g z>w=yP6Aj5&+0eB?sMl=*`f>^cDc3{Es;!{;Hjm!nu9Qm%E_X3Wg1@WW=4fsZw~=i>wByTK?v<}1#g{Qb>Dd&KrYXY(3v1zbWLT^Thpdvj+WQDe=0c!_tfZ&RJd=7s;~ zvpaMPYw!#%>1Gbxs&jiu6E6d3C~OtCmptXU=1(`1RD+?|BiCjD`hx{TRw3An#15zK zG#`)xTlJ)sxr~UNy7R%3ck1nqx_43gJGBKG8$>n^Hk%{zlnm!=0pM2QTUTfa{kGPc z$-ywbw6q~Khf@$C#}3;Ofi6L7KI}(gXP0!jo%qQQzpJtw;6m zL)|{_zzabGO*zdE1y(GGf#!+06)4?sEpI&sR|5k=g|*IKP2}v6Q>NACL2ek%(s2RI zw`K@i@kp^+e_y+6@aEVH0jUGReqzj`qpeisraqQ(&Z~P335-Of-rY4hZUwR&FXktt zfmNAIAHa{FRD?*eyx`~ID4lA2#c2u3J_Q4J(HZM&ZoTMtOQbgCkl3B#ft^|*J4h-o z*{oNxNY08xx9gdFVhU!W@LdW7C+r2`Bz<{hwpIaxw~gpp8)vwQ)TNv5g+!Vp73^_> z4TF2g<{S4|<;Qt~K#$YNp10VnqrBMWwq6H^LvWIp14g;H z+rGW>^5t>?9wxdDDeZ)8J9{l;lWaNez#cOOuO%?~z<^rL6Y_~o8WM3r`IEQY9Z$z=AYc^ zljVX8`7X!yw28SMTITd@?1rH$N!>NFe75_h7lu@WYbTP5y39`` z2P%w_BXpSc4%yB+L}0WwTYendk~rfzDF$rIQe=Z4Edc@yLV3P&tHF$+8w00r)T8bo zr}|z&?v`}JO%aTLpbhW)b5eJCTL5Zslm)KTS zFQmqckGB7han1jqn;-wA`SG9N$ESbp?JNI(#fQJ>|5N<@3oq{Xe%AXr?_1x0>;3T` zynW^U34D0KzhA+>kMZwMfB)^9UySlB&a>BMl!w{d+0W$OEC27K6z|jNpa080{|)cg zJi`07|7U&)SH9`}{@l>tE6V?8xK)2yVDtRH*F67i|4%(WbSvZ2**9{8QoO8(|9^k@ z@S9&S?I3uaRk8i{&Ci&TWxs98`|W#qf9Vh3EAeIJz4>DZYCXq+{dpY4d7x*{A}Pt98Ip>=!eJ_z@# zFY3F;D;^$S@zA{D0k3$tz2f2aiq9V2z2o8jj)%y3xWD6mNBY?VUUGZx{*wD;yyS!C z{-OG*x!y0{huZrCm|4xdd7MPAyg&GK;myaJ^ccDiP6UW?Vm%D=z)l{r=pl`Q!hUF~ zy%-GN-lpC!{SI&b*WW(A&Ht;-#QC=W+xYe2g!^EsdH*~H>fiW#@8;=WzCGf7{;r-f z|Bz;hegui~Q(cjVsOhAprcD#{u&HX(dv|Tk_PtH|&%2;S7XfWPRtU zMaoa2*nje`{mtispIiTL-CO^+nqOFQ-ml5tr}EeJ!)NG+x9|7E;~+lw#pyOm?;6vz zFMU|+RS+c)DH@M&Xtf^4NpwA)_3S>5g&ySggPuL;4^AGM&BA*4*!lQ=CC%*k;o~m` zc97{0*N-2ZBsxEQeEs;lw~l({{nDG+?WHf8`g?fo+jpJxX7Uqj%UjH}zw<#~dw=I? z0{Q>d@5eASJLoUH`KI$+0c@+^_W%749(#Xp{BWxNZ4A-B`8-5V@5~Jp{Rduj=krV6 zzxxTOBd)9iRde&oEmJ`fL2o&V{>7x(q^fa{;W z_``$q2`+r}G&n!@bMKGg|BkwR)sFDy=fbE=^!V*x#HZWQ^H%nL;QcGj(e~SD*57!Z zhA*1+yi+)n@FB{R2UAb&&#+*dee#0^_ak=-Y^@)=U$#ADPul}NR7X3o(s!H0pZ!tq zd%16X)f-<7^>6&BvYt1-uPh1kHR_Zg%6(k`rY7fJrBdv zD}S8b;OUvC6XHcRpB8`iRNLnZ?^pVd|HLZ&wD#YX|K{n+SN5p?jep^JH^@HdQt~HO zyKg;Bx##M=yYwaX`}&>X#n`=ALeD$HU-;+?!*-A1Z|T9&4Q=ZOA3Z#{ud?SYA^Y^< zPd{xI_`{3MB71N@X)b*61)llS-)kOw@2_7NNB7kidJud1?QgI6htF>xK5hQ;=|^AK zq4oUQry217p9;Mjg4>Qi!WjQv_OgHbzkg5q`yr`^&|y(?@6vN4mzq&%9dA-h=0U3Y z*nQRd^Z}jxy7lp0ylbSEKk?NMJx|lGy%Upb_rWZFu}(jFe*4ony}a~(PyI_Dl=Jl) z%-{RQFFdI*PnEcBFyH*na|^ux^GmAu_4EHl(J$uz^AYk7BpaQZy*{FEj}KqK>6Ja5 zlGy)C&ra-jf@6kzzHk!V{H^s5eoKCxeNO%0-7V{nZ_+ph&N+s9@Q@wP_U&xCX&TAH zIZv}ktpfu7P1pGtMSOhIL7r8jn-rTi`U)!b@WnBF_|4X559{yaOlmGQwZ!)?P)jIG zw<^4t4L{Sg<+;b++`psSt{;rZi;?}MFK_zODF3KGzdz!C?t}8be#HNS=MjIZ+-=0a z_1NVvTJi4ES2yIBA7z^_8KkGieAO-QH|XvEiw*MsT2uJTL4oPwW_EZnEZ|g%TYwkt+zUr>8 zZpbgbT)0mydjI14P5Uo@Vom$m+cxo{6^|FbqQZauS7PWn_|N;H`Fg&`|?12{MkckKY04hD5T%#VROL# zOmo+Z{=9!jcm7`=wDrYA{&}1uw?dz~?)k#|{q>DM`o8@B_1os(f8I8qDsbC2|G5vU z|L#3+KK#pDw^2KXk^yRY<>Hm-r*_%_zymLC+xiF%x8(@+j3OGwAZMoH>m_- z_3PuOH$fr1&8TKx{`}KTFXra+H4O5nAIz;6^Ya&9mishE-@o{Ni`yTR_4V`gzmeay z@u?!WdHS=>)*HU4^W%jtsqoj&$`>zr(UHMBqX+TpfAaIsABLCwW@U#x*?>>+K~Eo| z#Da{LR1d*1Jf#nxfBqZq3?4t$Gw=7(>}%%*L^zl$-+KS@la1qacM(kgNsjLNw*RHA z_@lpW9gByf^}Sz#n*oC2ul&ZZBb`?9T;(5q!~69+{O;@bzx+`B-mQJ@mvMSLEr0v5 zuNx)uOVrByo^YSfFSW)WTJujjsOSqd_5SC3 z8IL90l~pw8J$3c=?Ol5xzPQb<-?|Uc4<5eAboaNY_79%s)lYi~=6H0=kLsoOXX^25 zXX;m*4gYB~UGEOT7fb4Shb13%smG)Lu8cvkZq#dRws$@I%hc_kX&!vBd)>cd9idPxn2^Q7i~_+bOS{+M{tOJ6!0{?&IU#H-(=+TVZmtM^6x>8CKk z*%rK-H}$~*>u`iHQdn&C>a&mRYliKi`P$fS;F)q0{fy7B+}zw( z&DAFd>D^Av=UH=;_3VQB=(!><#_r`+4B+4Wplkg9|+=Lzip6@U$%#vM(D>+hBS_J^+d zfAhs9ZT+opeB)Oi_%wwR`93+}M}BsfS~hG~H=83YP>qMQnYE8lgm-iL{n`7`uRiFo zkOh$mKdkl8n9IKN(MJ$oU%w9Zv;F$@!}q@T@X71fXZ;wye*MXJAs9S7gmLnn)V8fx z48^jaessI`tH1g%01Cl+=gftd7cLrPwL@LQ?B?=qs`Jjb3+Kqqw03)1Zmd33>-Krw ze7t>XE{5@UAmyd8ZrZO}pRHju%bwq;!d{lgw`SfN4!d2fW8vDFous!SAaK3D!xUbJ zcAi9GiZXwbYPCLNTc5Sr@4vh0h(~U9Xx(cOoQ>wI{W*PapMr0<`o6~Y^4hZP_*S4E z;MWbB@hbbQaqfTcw)?fF@XsDl(N@+?&5z42x8o95L<~XRb z1}Jd5>FFy>^pE}h0BQj1*7UOuH+p`4&<#{DhdbRmf(kpaL(|6QmzB1C-|}vMMGxEu zvAOA91#~frc!ggm;nlmk!Pftx7N6cL7AMCrd-W@8j3l1i`xSnr$J+khE2{Mw)xzs;9nsv79kalG^@#$4(?$SqnuVFw3@1A0 zX;W^-<^{~cjLw(|n9-PK&9r;!KRj{k2Gr@3#}?rYaS&zA_`TQQckh4x>wVN<(f#iC zpC1lv;Ige(zxm1YJ3jgBlQ8_`#XZ-X;PmQ~?8Qr~$7_w-1($EH!z#KBE5IVp_=pAx z@z@Nko|{YIzKGEs�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
h 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 z RC!rLaD#y)qSC+@M%xX;_UKaaPE#jRbBNvb9Xzba$qgp4J4Z;(th3TNQEf>x6 zIz|4Tu4oYX+ogemlB%U0zY$ah+ZWCT(*Z9|#*-c!beHFT+sF_fjI!lo3U$+%6;D!s z!0k@vrb6(PD0^$vI|puqvpwU~)CA>%{~)5uA{cAA=}cLJQ?_!g$5yRlZ}d~sZlBG{ zG8&F*uw`z~%sSLSYejh!7*epPrDl@vrS18!4)?dRXHH2ib44gee9VB1o14qEx^~uz z6A8pnqsty9x91!q%{H=U4S2(Z+!YBn2zF#)-ak_%P6P|~v2u)-8v2kQ*fe5Gj6i5M zjin`>eVz9hWa-#i;s(fhc!b$8WdBsi{o#NlX3bhp*+*IzEb7)qoHu-h-ve9)+Ha_0 zy(K6oZhhD?mkb~1PG?d>#47N4A?PQ&r$y%gU3WYwPKU)aEZYh^Sl2ycFa%U-k`{-C z;nqxSGXc@<8>9V3L>7;6QkjNX(aH4&OxqOuBjABR%K$<@r@K9jXDUxXpPs0(Q&i|c zrlw#V^LY{*0KKs@O^qhUO2Tp@&MJ-qf7+5Cmj;*P^A-N;ITPUMMDb763sH3wxW?zBLJ zCiVNdjU3W*=$5R77{)$=Vs`7G(#Is1kmL#>(Mn6G@0G)T4m-tVY#`8gCsCazrT%%h zu+5FN!CrwZT9ef1?n?q_H%*9M-5PqV``V{fZ+J(HGG9=E7qQ^*Mae_U}2g^-RIZU9Gknsd^ zb+olkEW3=3O!IhvZoKJ9!n{UJ)3Ul2Rq?=|)O{)UsY0$WesfB) zXwusOl~y)M*y-4y4!D-xu^sj3@imn?Z4zL;>vA2w&eoul49`Vp-JEIk7WlQW0qMPpelYHq@(&|TUKZaM8(>(u1M0|(a%#H5e@Z%8x5QeuageRM)o$FRIpi1s@^ze_y&X$Nh~#l#stp8)tn&VAqyKbFTVf@k7K?HX zNyWGk4e$>vPsQ2#urumd_ltG+9Ev3upn+Hz`QWhKc^jh>sA5{F?Z8}^>-AHiHU;Aa z&LdhEt_}eUDeS_xuj*^jtb*m)lHf1j5-Gx-CDOY_i8G2c#qOc=- zCF#wKJ2bHZW2IO&(v^=q8K?7p6pqZHeARP1lW=3WQ61mr2nHq}R)!$)Bp5f$7VtDD3f(KMN>2L#t}$+t4XcYI*V{x|>M&K$ zUzh{+M1e*>k42ht;1`<~xnqB@pu{fhQN^mE%d6e7%1oVe*>=t+6u`RecDU)01Mhr~ z9q6DySb2`SFV5IGJaxqru)~75a3oLiW+RCY>IW`AkHMzp%ori;=_mH=w2?x?MFJ=) zIVxkTuda}HLftb-%dc?ftzBt>QYVS#3_tH2G9*F);AFlOhI=~V>{@wH%Q*RB$4dCv zJnzJCx$(^{_W7>LZK~RF-fowVrq?K!y=1jJ;kf0T8RYCs!T+=4%57T}n|-h*N%lc< z#^VF@5V#~|Zwi#zNS4n5*e1sa2&uS6Yov5wS5DOg9g{3qx?@#Jj02}rQ$L&IW*~6j zQ)cS?a(<&`f7EMTc@ zAHfE#WPp4Y7~GnZP?gVf^suqitRa+8Ie3>;bZuX+uXvtW?dD z`nx^OWE8jlQf#@SvG6Z9MzSi2u=tYPhS+wh$2h2olg4Cvni+0%K+Fd0q`+@6RlVd7 zPWukwAYN}p@WV~1C_{vNNmsd=+bGwSifD9Ap}2+b7=F(~7@O75_q5SUJaH<0?I&dc z>cKT9X+;J3sG^Z&j&+*}&XZ;L*w4blj@d|DIuro6I!iNkSAl5`&X9(Yen;P@ukDKjKpJGIqQF;buy5PN(#_JIf6xnKFLsruJaW!=s_x>Eg@2CB{S$oP#A`bfjbDm zR=nRHXPX)F)5);CwWp}ENUyR>kXK9J z?+n|Vm~0aXwoatJ1V(^%5QF42n!6$I;BkV}%6-KC5ebCBkd3_!$4OATPm>KuoMwxW zDlW9EPa3wXJ-84%{62w6eg>*_IZR~iTc_H&S#z8!BjAj`**lm1uU53B}<;ibq>-RP1puw&(jwLrpF=x-r#j!A6&~8RU*Y#x2uMO52q2+{1B* zqw3%~XK;VI2hw)uh-P2o=zL!s*mGoDqDnr`pp`)M5ZpTP1o+rDn~ETIyQ6YL#d(+5aS$53-`3n3avu!k z%3g1QdII>i7LdpC9IhWR8TT8iF>a3Oo(+9zhM zOgLg!T7$y0$#BTsU;|sH*07wc3D_b5;$xc#72P#X0ib1IQy@O7X%`8E)^sPXOYI5= zrr(rnsl74mW=30#!c7X^y4;6pReW%+kAmf5CUg_xXPB0b7?;j`9)dcEO1j;64z0E` znceE#S}Z+ongSl_G%Z9u;k**F?Q%6K_rc~A2K#Y}STyWC6K^0wu^K357q(X5ozq=* zoTC5ORSMgwB!B_OjcPij4oSiXVrRo6hEndA26G46Ok&t&-+}$6wQi4>_3BVdXr^hM zsIFJ!y5R!$9-FOF(1mn+!vW*opq64k?!^AFC@VDZKx-F#EJVilz(~;bqz=xK2umaD zK$Hi2u%+)e4SLxbW;)>NBe`fzdPRa8hH^WC!mmQuF_Ue3HV160n)6b!I3TnrAVuM? zGQ%AxZV}_qnJxf~+Vxhm^?uk8i0=_{t+nsl%dsa8r7a)&%`q>V!8XT;0zWp=e9T#- zjvJ?#NDJhl81d~AlAY9d%MP_HiHD$n9V0GmS33MrJZepHr1Zf-K8ufCdFeOVLo=H# zvW)H=j@=H4VJ5a4S@b$kR>NJ*6*>m?Z8H8Vi`J*0>26+Bi?FT z1c1hN`*~~$a5t@PxGVW(U!KP0-l}$T5^Q&iN#_X0&Y`s4otx$Db^Wk%!{-Pz(XZ1E zmd|iX15XJmEuaC-bc0$Ie>I=QzgHZ?4MXaKW(DvU*fJBnO?vlh(9Z>>KdR zo;ylJO|Ro`f#7GLc9YSjDwJV+$AJv|nwG$pQ)b;0!h;Z}wE#>l)pqTozQ8$8&6%DD zv!_k?Ww5U;5HlyRt=QberZCV(9@7NA2xq3Y3?>>=8X)JV7mb)=dwrf;{y7r(l5mvH zOU3{yv+Ff&!odTKFb7TxrN0}p>~MTkHu;%<1eHuGP1^Ix#Au$bc5Oh9+|s!fwQ;aR ziXcn~P+no))>o;GbJH@_FlPPHLTKFNW~+sKohx=JR@-T&bFh7ZqY$wbeZ&*@1GT(b zh$-FZu82KzvERnEqbo!I+zF>7>uYnu7pljrwQ3_sMLtr!pzmb0^8|vHZ|wo-6Wjb) zGLl8BX;wfAbDY-Iv{k3gw$nTLzLk5F8sJLeI%)KNMxsuh)}H(tTm zB9*~+Kx|(_o35{x{5l-+i~tbQYOn0998m+tAD4f9Eu1U7sq4A#Avz0iR$Ju0T+2w$f(9J1uy= z+Fq2vMM(T*-inpv-QEdANiGN(1E`IdOYUHgU^UOL!UeXdC%_jV zG?&!dE7gQ@tt-|Y<^#Eq=CK_XTgHVl3X+EiG3fKOMcDZo=R%^)#$ zc{^opw*fM%rk&hP3Y@p!TTM}yep*K^t-N(_MpyJIdD2eaUinm zU|*4GtA4CD=~joAXc38SFBmbWn;6Bxqy$KwszE553*v)mtO2B1PR=W8x)MC#%T~<( zg6l=cN66Va><19}QzyZ@6b+*U(S8WWhBE9R;g+8EX?6EPfq&x$eSnqWkb6Eo(@`MN=iv-qT#I zcJY<_L~4{+17wu^@0uI zry}!q-Ik>uE3>fawhkIF4a+vwZc&xOIjY7X6Z^W({F_#pgi&;E@=ZhSMG#$Kc%CWq=F&)_Qmf2CF9G{%J>(2ICaD zn{!+M^c%sfial=*k~+YZMaa#LxAUU`lWeHNA>%DAMc&5k#eVFlda8il9e7JH#>8#V zdO=TO>G{06R>o9}XzLZ22#b@_RsXPuG!k7i@MWW|CX$Tti{m&__6R{5gq9-BZuSOS zSd+_YT{h))pc^R_4f}z2P9|wy^Qg*6K*NGat51dEA>~KW-9CAJO4B{VNp1+HAY8?Gd8v5gJCniEQj`#aTSKrr?SF?JhB?)dne9>fCNV5yc8qP z&k%mIssi82uF9@9ezBE;2Uij*yN0`ynwVgik0eZ53`&ieriu0O4EE1WwG%FmgL-QZ z>y$T}MYHYzh#}~FZ7^OU%>eLdahce>I^AS5rF2@U4~jdN>hNLN%lFKIRoczLIcdwX z-81^gK`+jaeuRDeysYtMYNP`Asg-L z)iMGS^K+GMIdfpt2NA4zNl!l1AnSIRKW#rjY{7Q2x98wmiNlhCjKRd7inHxtsSNrE zdR+)w(%GLn$$rlzGhsRfHj`kPjGJ!AVte&OiQRUnYRrOGy@5H%*OP72&V-t@F#LoM zOEu#XkBgjV6*q+-5=)*96y%Afdqt4i#kQh>c&uU8QonfugfTyJAU>c$NG&TbOADIBU4cqPeU z*(n|Ob#Abk?3YCy?l<_DLSO-!ywvN;XB++~ANyPP>Ql)HY}Dq|7@8m&Oiu8nwn$w< zQ&u)G230bfK{COMZ=b~PCDSr%ftmX_c6FgTWP1JhlmzUF=P^Fzv(UnZw!Zk@5LYl8 zEwN2t0mpLb*h_DUzJRIbM~$XrRuV*;?`7_&C(HjQF|8wb&%owzalj=D{LkijH1NTy5tupoP$4nVpL2 zxlqNC7MC5n+iLv~w$n3CF7)8UY^$wSCGi?senw07Ic zWE(b;uG-+qG~@c?Hi>J`Ka%*``~&Mo@O8qM;=!*{QR4r zT2&jOHxR1I3Y_wxd*;Z$4H}FveqG`#s}*k*Q-F_7@OZe*A=0Rh7v`$hlf-77Ms7qv z=#h@X6?=%#P7g*;8u7>_yjoWirtJY4t|CX>NkKmt;3Jy1>Vb}D)8>f*L_$L@31%)V zGU09c9t_wSEs)HiOUt{4~Et55?X}PM{;VKYXz42%eutGd+ zHMxqmsX9jm@lsSp+^{9YChhcgQeTzM<&JWOQ8}u#0qRF7lNA1Hue9>R3TRF1TvZWS zDgxi!u}`fB#%O}f#iJhEjtTcoW3DZZOry=8r;r-~%Te`BQ0a;zPF0(`Og&pQoNh8Y zsFGZ}4Ap4~H8?nnT4#}$2nGUonk_5I#fW=EZ;wsE&)yFoMK8-Kf!k~aypT&^XY6+Lt z8hB6D5GG@t1*;X55&&QiNx6K`7P;9(Lr^--^bsJ95L>@u>prfdiwO%wBjhpVo)?e#I<(eennXKzF^7HPJA)Php^ z9E_Lnx0a4x8L`2($;d)*q*ry{a(PdrT0>Psf;DZA9yG(_=`;ax#CkN=R|q&2*~N6P zgNA2puF4*=&BTdGzP=hwUAbd5MMZWb0)sdW$rmmC4yzK8t5a z8(^FSWwSdH(veVZ)B`r7F%HzCd^}Z_=)Ya1+iSFDXLkvjJ8yIVHCYlzCcTezrbKVo zPG8f@C3;_HxUwFP+j`y5*QR8)RrMS?hfQ>n%L&$mjN&nEQB1uHlMc(9v!$Ow2Mb_As^{2gJ|wxRAjPsv9)Ra^jc`&BJM$7Bz&VSvHb?0Fa-lbYPKlgB zYpjb5a%padu8Lga4agZ9|5WG&;K8YsMqO}7%W-cZ6|Meezh$B3f$&}dNw+g|)ST0G z-Pvx7;{(E2_{oDBPm)*aEpMUAe{r1n>zhM93 z4`18A_UY>f`!C=_0sp>>fA8Vn_kQ^LvtNb=5vIv2#0dq->*3F(_JjKeD8>GO|F8bt zKlv^DL%V2y$9?z?uKbMsv*}uUR+RhqaI5yTK=S;*N}m6Y`=_oC^<5xI3iCxeNLAo^~N7wv9tlQ?+e4Y2qw||^FfA{tEJ+4C<^&Qv3uQxm6jc%}i z6@B=({_edGjrcfhYLj#D#Dd$IjX}3(2k!@BD*VNMq6t zMLYSss1TzSW=y^WdsYMr@2!^LUKAFa`YtdE25x{e+BujX-P-ua@~+2TI$nAyCBHCj z><`EG2jj2muNUaAzx}+wE_3clpZ)gi^F8t6?QJjUT2NS<1v3jHGmcH8pvAZD_`??S z*wWvme%?3!ijMKhX-f{<6T} z(g(PPUoY?1KmF0|dOfy3wf_mMd;70oLj2Ef?WV^?G&$O4WES4LHTpfWfV4uq)qJe;#0(3u zb2bYamc@H-bj5p^9b{RNm19N`R#pPixXY4xu)qD;FIHpZ)nSZuOJuf7xAM-lSiB zqw8)h``q>C4g9yiwg!It3&!gHzR$ksj<+=I`8M=sKNB(Zq@Rh{{+t+^3cH<0=8gtN z-~x!#wr|X$xL`s2VkQPpgftQFklJsR)Zf2#=^sVWkG=FqQ963~zx#;>n)LAh`Z$xH z^ss+lM8)6w^_MRT+-+C%wYBM^JLAGGGMoU8*@Eu`UR-$j^0)6I?I(KX-Y5A|{5xpC zmy0RTEMcF0ZU5sp>EvDX5dQD|$}ba*;H|Cr2Y<_O4h6^f_`8>_`n$jVTgZWWc&zdl z-|)PC|NBp0zyIxX^?Tf8{^C2ItWC=aesohmJ}rEbclD1h^~IlwX8nk+etO%DKDm7H zhuD+e`NRy2#~0p5@Bb5ZdEVE|SPj__L_zlYJ!r z6I1@rqI;gIcTe`f-}tdwb(48N=H1T+=hxnN`&aLtf1-LHj$769-Sg-3&VACr>xD0G z;x9iPj9W{dUwmF+>T9ep8Tw}x&M$m^)ZoVtoUt5cQ z7K{9`@Xzu;-%>C4A46^Kd+?v2tGDhZAMd^WS^mX$-1CoJJy$}xpZ(%h!sLhgf0VTQ z1OAKFfBz+N*o*d@#0gFQ3xC zhdJ}*iq@BJsek5^y9|FagpXV5yRw5M^o65Y@KDf2HQ%LC0frJ-REU~Rl(@@!`?2o5 zSKs}Y$aMdX`!{~u%anO26AM80JIn{4 zz^FkE^SLVZxry<$m3MD@K6L;3A9CoJ-+x;-JPzIOYX0tKts`e7V#{)fO)M_FXFZgN zCB%B5$*O2vJUv?KJ%YX33WO^{+giWB1p5_Qn@)sqj~CYflFFiA?-|?JWJRfB36JJeJ*02O z{&BYd0(k-&NWK>k1p~VQ$|0HpQ5}jG)!}8~sydJxZ^y>pVaWc0XGm4ZvHM<;=ZEmy zssGY(w^M)Z)BEB4|DTO}J}>^lSI&zsS50PQa(u~Y|DVoxoXa7skRRAzJUOvn%-Ghe z64~Zn{pfO($MBNf?sE9Qj3h2V56E>z{JiS|7-JmdkG7-R#1>4fk3oLGC(2J8n!2-b z^qUs+Xyg95{M>l&htDp5V+nqQ&iI0}{hxbl6K-F&-{K~C! zZ&k}Tv0p@+i38xt-f_S570q~SU*DVY_HUmzga6u^@g*jRTXXMQ@}sBWy12i1O59rW z)i*wG*bl$9hJE-GOv-y5KKn_Yddnz(^_KZ$Iz8DkA9YdSmf#e+S)Z?-#K=5GPLg0@ zIRWv$7O;s$PIkZVZo~g6pMGrrPgwxE;_wrV966mBk1Oj*SKRlty>-jI zcp{>4LO}`S6O(^>d;d`=l_WP^phulS)b+i-q(Nq zjq<))Mfs<;_ujo#=5o&d=&^0~|M`}xe)V?sr0BN}oV$Rz1cnX_O#r(I0X|(2K|sEM zE%4@{hGO_82rCqsGxf<0Qy0y8=8BJYYlV$)=2MVfKniKEqx0o@-PcZL6z6Zf z-}^CnB|-T-EtMGL>B752F92c;7U9dwh*2?i;)HlX^D9Vd7+tV*zzdOAK6_Dt9e47p z*Ts>){+;~w?-tlN2BHvxG5~NxvYizut|WB)8n&i7IJHUa!l$^J*0gWF0L8yTr~xO&6TW zwQiReyt@2_*W8Nhq&diN3mM^r031GR{0jgHVL=6W3J&AQ(Fh_jGC}%pBJ7Ibrt()@ zD|YQ5bSvpZAnp#%E{zL$%`T&xy&_jhBQN#1*5Tbk|1#v4q5b~lGTCQ*^lSlh)G{A# zV||?{m%ixUU^o8f2UPmai}9CKM&E%WUr*o@aIC~8m>i?9b}*qYn;E9sWmrk6 z5`K&hz|_6WoFDi7&>$$%>#Jk1j9eyJU}njsfAS3mmi2sqpKcbIaBp_uz0KM6UH8Ej zbGY$sUR)PKOdc!^mTaNEexKF!W&cXCme#$kHGoy?N59E zQl;m;pFQ4sd+O2)S8;j!{wh-m&i57UZ?E1aF0+d;AVL)K>+**K$@QY(Z`XI}NoLVy zv~zJw948nV;s(=zmbwT%+yjgynY7o!as>bj&D1dDPuKr-$O>KJMEMe7eCgub3dL+i z$K=wOROkAVoBVpWAY-W05Gxy=9f-y^*Q6QWUOTwlLBN~j<+u7j3hm2#CA{zlW2~be zet4G>*o1HhdzbtoLh80ENio;Cb6N2D?2~>_`e9z_DBll*hbPs>S1$@o;j)_E5J~il zTa%v%B?(gE3k&m6*wey&%-MTYpVgE|r&~XCuNwEWnv<0+{eV1Ay8Bl1>y~lt^ZaYl z1$kH8w!vKRVOCr_#kjmC1WrDAc>mhxkeG4u{lafp@Baq*^lFm^I&qohQ}aP08}^d{ zO*CjI#M74V38as~0R;H%eQYn_b)ttjP)Z6F+2NZwv{5kHYhz}vX} zq7U2)x$ZNhdiN);!sPf-^wC9}lwJb&f7$c2$iiNYw*yp|Z=UD^G9TWQIQe#-e{)?5 zL==6l>p$NsxtfK+AQgQ0{MRpT68znQaFuoGMc@LUZeaH26N9Yi0{RY%fDAC1a1QE! z-2=(gA$L5PZtoU2qD|c3|M%XxDhGOsjSp>pdn2Wf^0$yTy<1Sw7kRZw8FwX#hz|7h zZKCH3DpzLW-^}~y{=&yT|NOh2yajC`o&HqHT!j789*zs&drh6Gi$-Uy}Q-%Qye^l8DyAhnH8}UwYR9t}6z@5i^}s z?8jO!SJ5xM^Uk|>QAm1(6mXx%H*-CF*mn)(%`g$DNtZ#3$c~Av9a_hAO^6*X*V18a zx;F3n)`#+kIey^7519`>gpj^s2=bfru6@>#mp;6zV{c3}SUu6|+wG4>$lHW_6w(DL zAAajqLKerX{K1PD$zDh|A@aDzJVve*E>kMIwd(mR^Fj^g)ur4wk2?>ayYTeQSc@M# zJia~ez*l((UceTYX@h`(SMfeVtsh=qU-Yu@c<%@3#Jm!D$Kf213*wLP;o~%IT?>9PMVw9H)hke3o3CCKKK{7y{;OA8%?Vz;djC=*vIWJaX*^Wu zYV|g%?-n}nI$>Ut362#F(TW**6U4c`Ouo6#BJ9+8uv6ZxV{#gzOZjK=5p@CHI}SD7 zd?>xZMmHu6By0BhLb~Y{k25g8iO9}3G$W`DObJDmNk`$6#jlY6op)&B5)_T;6f z>otM`!R6a*x;8WKEz*iKxdi52)ELqh%%*37gqKH+e9BS}n7S}M+{(KtyyUs7yNJ!- z#9~M>tIuY%!x3I4^)9 zCki4SAq$24mtQ5m3Qs`i7t4P~;*(3Z-RLfGeDl`myoy6$OHulC_h{>|nU z{=`d-3{n$YDt4wH(BDVp9y=+IawL6p^SR{@TCbq|UHS>DU-PYx$SgA-*cW+`*T=1E z@%P>&vVk-$|Kjo{6p|NqTQ?F>c=I8CTqp5;q2yadPVM|FLlA62|1gTA0=MUww>(F>h*l`Gm>7azQ`7^uDn2^K)lBF5Hc_(B;4T z8@JkEZj#Djir{j^RBkT+)ns;v)4D4S~6LP)tTt(&vd!`Sn-Xe_8UtrnHk?$YA<1A z-&ktDvD7{@{p6OWn-Sp~OYJw7+HWkirv8nk7F*^`C_Hh2d}FD-n{oe0EVXywa1NjU zPrm{_PnezDe;F8D_iy3{VV?Zw@f$GU|Ktt>1{-G1WceHo?*1#d?{hSm{~USv1OA_V zeTRkrN7r)FwfnE(%jbw-_usf*a{n!SBpBg4z30D&3!nW$oJ6L!eeM4H*S`#CVegQeHapB@Y#48A9_5wzaG|K`O0#L~WzhZcZ06>Lb=;0pic!9UQ+(j>w zl)zZwXC`>D_One60lR;#W6*-p~gP zU|aI!3ph^0)5l%SkMS8?XJ+(q{u9KFPk3Fwaws1s#((}4qEh;(R4UUYnl8Vipfd0X zeNFx)QgEqKtCSjzKXl1&I%U3JAf+?4TBF+dvR?RQ!-+#6`(6Rbs=apq3oMI!KYjM6 z1K<gKL_zyD$b6}HV25<(69x~Y@0+soEq zu^i!3tl)>h9XWOz9#Mf-)GYbjWIn9~V%adt*_t-{#fFYt>*u4KRkr7P-}dU~l09La z7U!*1v(jh_)5$LBpX#l;OeN8jJ)QRMtgE$R&$Ey?GFr8Zr;r)d&p{{72KBNSHK?%L za)Z&75n9DDc;jo;={#EW_nui^(ls%v^tWP?GyHRk<~IzQC2akx?lJr+vKp{p*RLZt zz`1hFij`8y7>+9hGKl)SwJhr&ZR<==9i>{_)VIBK zl&;kkeLnPhf@B7?=f$0QdASHW#YW6zUUrDkdRLZKXWMp5V9^f2pzXA!QAu12)tO@! z>#N#w(CzWsX|-u5lD%m7Ob^W8p#1lmNX}4?MTQ-hlJVLs@6-%wU#pWocmV552AN6i zWvA0yA>%;Q;kKn$Wauhi2O7jCaQ{2CMw0w-8OSB5XE|o!Y3F%(*q)^=y5u zF^rff>(;_Q1f#^9wv%O_UfILNDAm_{dd!Ygwo++r5>sBfE4_bWI}4_(>O;lg%C*Va zVv(7^-!BIDP)eY1!ZsDauEC#-zT zGAoM=e#{?SbH-9su}10r(xg_}?6xIOm@lYmlyw?bFLd<^HQ!i*K}lYvRXuj9R!eEq z$IWuf1`X~I%k{~!BJSDV-kJ{^z2Z(iv<~IXxJVt2qwJ6rH|=!NqK=!m#aFr;%f$3Z z6H4zak8H=PHd^VRrC0W|UTLABx{hsE zwIumL4DfC!34}MoNWcs$;SnCbzEkH`^`Hkm(5ky$9T_&cb4Nx-5=D6ZJbrJ?gf*vH zvO=!wl9wcTiQ8MtqGy57j4sXSnfjQwq7zHqg140M)$2kSF?pqRd6}`CYzJ43&Qo#*eS8#*Jw`XsI9RPUGM1tI2nvlBm?<<1lXTuSTd3ux{ z>P5&6M36<*!joXSfPzIIT%?2?2f7Cy>t|>mgWFVb9(Y#lJ$gM0R&KLcq>w>IZ$rX& z>!n~5_&wEId?CjkUY+w9vkZzy*(3|nyuBXq{C-R$-^XEhX!&wZc?*skvE@&ay5llO z5@bT%kt<&3@&(r^3U%r;|V=kofI`RveLoieIHZ&+g*$qUFnC0 z#)OuwTe4c~5wYko7AeXH%Y|1o`^wUrGTO#WZpA(}Xke~#=phND-S8>EZ=T4*&Ubr5 z!NUo>0Cx68&a4D3flPWmPzi#@x`<&G+AF%*ZrW^D{oP)pX{Nt;_Ym{TLJygaobM}I z6&@K-B*r(n$`{TassmU%^!erNs^EO+1@Zz%X^1HHd~&ss@|R~d<@~|E8s@VaLdO{K{36i|6U=eR!;o*^K3R-@+cQNDj?3xj!AjpFoWWfLR``=aA`8{v!jlJyJkFe3?>dR# zsLWR}Wk>d&OjmOPn--zohFPA$e47Q=Jgy-NA}E*#drI}?bEio1Q~mabbmF9+fT^jA zTw>`Kvy{J2hN#nHBiME-%L_NG?;X7?39GO6n=C4R?~0@-ZU_~yc1Cs;P4-`sB)tHk zli^)xbkI-%a>=QS_7<#aSdd*48uTWw={(SP3asMZuy7=zMrXTlba8d4K9g4mE@6G; z7lOo4n~KOcN(k4X;KA^IJkP>@=REi$j()nD8T!_9KJA75qI!jub`%eO2k;&_IhBkZ z^fwwHuNk$yO$8&!TVihdDz_@F+YcV)8j9pTD|g2UW2Q>Wag`07z;qUD%FJLaVmpy? zm+hFX)z^t9N4&V=7|C5@H+W>p*%uKD`CvZ4X?*dyvnvo&Kkjk3uZzdPz7S}AEG{i} zmC>;POKgi9Dc;IW6dQ>O3(Rv|7;sS4*z>Z_sXZU0(4QBCiP-3C%iOj-Dzf0Mx4kkX zu_ZigUr(?z6g(O3C`+S#eo{Qo!~bWZYk|G042!G4==CMwBzNMY z?BwD~JNlWl<;>v}M;{hm+&XW!Q#RpZrkKJaNycYwQ5MNr521S}cIb5vaF}O(+#aP% zR(#n0LL*mRcY_jr38>TCNgFH*T_|7<->vlKyz2$+F5sS-#yVt2b{ijXTN8r_st{XU zjKVF0VdP;0-%F&nDH?9zgp%6`4wQK|qUMZVSjr>?PC6=vWo7h?wiLbd;8qRVP3xJQ z=H~XcM{d?pc)YzAGdKr}-JEe(`Fv1C(yuSdTQf~vBOhZ9$)qoA*=#u;a27_QJWlbX zN*8KwCYC}7YfDKqjtVAY)=Y8DUG$A$j>%zT_}Oqv*ucG6;O(od#6f{}o6gx>vyr^7 zp-3g@Mb&H{xMmHKJ@~IvaiDxsOxZEDt!cZMqlYQ+)`4&^xNC;T+wOsEc(#)vF zKW5qE+XvtPbZL<-creb*MxB;}^K-_EHn=>dq$|>AD!l~0pf9&*vJ#2jRu{P*8<-;A zXb7NTp{{aqV%)7DhVA8XmY=He!b6w`vsc)uM{wZPyj>E3eJ<1u;7v%r>VPo8=6<2p zjG<;M!S0W}xMSW0E^x`WgqAB64vIqP9A4E*J9;{wxq$} zZk5p<&N=K54!!`}YSw%i1wp~HM$*2T@%oNrXDt&cIC2(5!PqOUwpXj?3NO0XG%k$( zZWH!p4GBviNzqsvgWZaU-V@e}2AjB;&59F%J6uc*8&(#^hrbj#U7+SIo}!e&@G^?x z(*pM$1jC!;O#)tvs58otOF{NHac(i%kV{A)#GQv4@+}bvw^99MMlW;yX2AnT#zT{P)aSyQgL5YOHR~>Ax&IR1w@(}VC7n2=>yrPQSuKN~k z)?_9ywnV;3bxTy__Svh-YE_=MQvKACl#55 zulpFU7&r3d`{vK?UCeVlG{|LoMB$MzQ_tOk3Ka{7osfLJ&vfxro_yf2LT<8&%#*yw zkcoXA(!v9JW5l+YS;nOKoYc(5Dv3rBo_r%_rSbtAOe?`rE1-OkzDNx)Ml!4O4oRC#)(u^l#I90VI#@i@=hHMPo*h33 zibixr8gGUd0OwQSL{-5$&hT${HT>^4YS1Ehn{aOA4Aej+yau$h5_Zq=#mv?c&+NYN zIy-px2G1*ZaKI%s8ZZ`^XddsqnMagA-_{y#GcDOX_e3B12!?tIg4SXb68csR1taln zhGX4D*0*F&?dVPBK{9i#-mVsPQg0clW`wcC3$O1*tuX%BP%Ami?ag*x-J-Fma;*BA z2uS6C_a4Wg8x(E&R)BM^$b%p80N=CD!@1hePTNkYeVKC>Ed$jwiAH80xu`hT;)3(_ zq)cK9l!Ek8?ds1<%)io=9K{tq6G@hdZ8H-XAxmNw2kvf@gUbfKh-i?|c;W4yjuKvd`K0`QX&b^?Yv^S0KnlhQuodT)M`hdj$x~;7fMGC&03Ox=VzR zR7aohmjkANir0|jh3R0*|j z2pQ28>Vl=2R@L|FyfADvK1&NV(o_lesPyuY?21?xqTXSvK8rsDC0)T<2~3%aH*v9d zVJHf4A%lAbKHa7GD7Jgf#TZ&;g?`}{@|!=;MIz7Mp#zuCg}3Ir+2ZCGj3W2$w56;0 zsgxQg7h@Y75|TaIU2`b+hPMx{bHQqXm-mWyM2L&jPImr7@WEZNz1&iq-ZMTyRmi1K zRFfku&wNb+R&jThyo`H8z3IwRA8;M8pYdy9TdGW>1e37bPOpf;1HKf0j#lvE06I3C z)k%`&R$%SAo`6~R;EiVAx5wB80`BUc zb?``}r7NEnG(Ih21W(tCjRbJ1o>YA;Sa&csn=lrKFo2t)Jli*vWMOL>gDvJ^D=Oq9 z@m^5pEL#RHxuG)`>DxV!T0@pvq2vM*OFeB35H8|!0<6;4lwRkO9M|-M_D}LOpL`Xd z^1RdSk4o6=2~I~oNfVCcWCrKi3;68V>m1ncs!;B$f!;L}9l3(L-k1X?Vw?hNZI1lB zJ=UFq0TDB0^K$Be|6CX~k{k~1bzkURhPpQn```MAEVvyScfJMNPq?1M3l@4G~q*qE{cUN{99lVjPj*cTyT_<{>Vkw6S937i(iz&Ef& z_Y%7(z@My~#M+f3muz_AbI-wP%yH$peHT7~@3)W-m_lz<16ZM2CN8YElbeSwGSVoG z`(5P{TxM-63qq7MgYVbKLlNBYeDbRXpCFGQ1*8uGNd)voy~aMj-j3&Vv+LL1S+I`J z*G0~~okE9KV6zUoq2EAt#~o#o%Fl2*q0Pn4Fq;&iHp0SnFTTS(4k%@mGAW#x^)BSxDH+uQ|uPVp+gwUE;zX6%g2n`6?k+7wkdqBx^v>?FB(A zIleMqbB4n|=gxaZLG2)LA^nNpzoK$YS6DwH1V3FH7fF`$z93;5NX3Q-i+ZR`;$N?tBCl2Pka{eU+i%8~YgX97#y|6pf*A4l- z;b%xpxtwk27>qkB*^H1e0`ty_PM}1#$k!=>-!p7kGX_}3l1b_0Hs7|>lblmzU4zQD z1Upwz8U36LAH3eTYZ!+#Sapt+!lLE7fFmkK(HBo{82xD8P%`0s8h_GtJ@hnTKNx0H z9fp{Tn05Ti=P7WReZbkUeaAs-|WROJbs|o9AJ5|RSP-3 z30?!sDBQ)oeD&4B~8@KJ#bzwd$2(i%D4Du$E(9XzCT}HaLhHY<`Mn5Ay&<9 zdJmk=gT{Y0F$3P2F67?I^=Dl<`tNsc(SHAP$#p-gesJ~2@NSRO0L)cc6ZJ^(*d^{C zC1~jU;@1CqlOXQ+aX;Mi)6k;N!hLhbe%ZRV;x>v25~qp*ZdRbE*XgVZmR* z0%dTP3yl`I0_^ec^B4WmzViIY%01j`CcBlkU4+2v*Xj+JyoTj#+9(}Q?XmJnumCi+ z9E~QmX3_)pW>42hQS>CeBU^#;$OISo)!N|_-|9her}4Ju#o9FYlF!fED+mm&_haxX z*FJA%b_WvbB*cO$`BdBU`jM*7soq@ZIT*t2^H?HVu8$teZTeeQRjc#J`kc}EgO`^c zxP5Ws(G^lk>jk{l&SzUcu?)%4@v-6TdboL^3N_t^U+p%e2qg2d*6XxLRnl#7z82MWy$j#NW9VTB5jJ_Arfpgl<&s%s^a!40Mhg->jwJC~{;tQeZPP$kaxH+Vq9{1sSGGH8)Sl8b zM>u>|-L$*l*EBG;=Mz7#dyj!7dc;j+KI<{qZNl#P=v~X|^6_CCc&q;T?C60%vjRLb zgPnH=pJ^cm9$#(wCXbW;`DH#{_@r+NkMK8hSrCkfCWxi%pi{JiyvveZHgU*OR!7QO z(ZZ%n<~?!mK0)K>6%{K!lBmh0X>lUUx?(huRgpJf^vtFPrzzkN`ZM%&bFHM-fz<0W z4etARU&v~O%iB=``L@INapBOy^R6tJ(@|EOlOF`!4%bQIXV9u;*i9shq86WLrc}Ef zNfOd?A(MAN(aWlQ)&j@xrakAM-Hft-ZrQ?T=cc;z@fnUg;rd3q=pCKH1f*QWeYP|j&z+Izbv3^JQvsza}DlFN| z9HE~6IirfY1oaR{3Bzq78sqkE>kB#k>c{lz0ca6}$IF517U9d?M}}V$j=Eq8 zjS9~o(u}X#hib32o6-1==R&sYKA*3x5<`i6F2VCL@sXH)6?D4X?|W;#DNlaLwh6Ak zMk0xO?RmH}*`}CLeK*wNbqa18*im=l?)vVXhBkrxFiIbTcu4=de3IK5rUfqZ z))5hXWcT8y|8vNFHFB0Ug-?}eE~X*C)zKndMa%-m0^BUD~f8Z%C(rsrtRsY6SMmL2AgN&2Kje4G7-D^ zZ9P`Kt0@&hqBl;jj}Ez3?eZ?&^qrR1;4p5eKI6y*s?MO?=W--0Iy_ddr$#$~bCkCqNLkESADJyjiRz_*(lEi9f?05*Dn}yM~i&!Lm;7kk$W5v4)*5yM&E(@#*!CaWG#~1ZO(vVG^I2c3H`=zGZE`Ml zMKkm@Zpq^PhPG-jx$Y&Bo{jMueeEK^8I1!<42g>bDWizU^F84j90y7Vt&O!2b{Pey zW@s-Fa;Ft&JJqcaKsY`RV?l1%D05x=xsx`R-BF{eK3FxU4y{Y=D9cB~m*L8i>hW_~ zmJ3g#0Rn`RFVW%c%Te{C0d_~{}C&=-i2 zOP$W>-7aj|DjCWv9}n@*!8t(sktm8UTRhTK;#Y(At%lrf(~<^uwrIGKrKYa}&VBUr z>-mMbMnwyaa9kFF5`Ia*A`zvN=C(wn|HYi@k?O(oE&vywHc7NfQ*Z=ZK#w#X%x7d{y%~WB|@mos&d;#6m0{V1Yfv z-{bf&)aP(#?kwvVx|2Bzi9NVTOBLFo&6GF?DwpxwRSOjGI2(wmoBAQ-X}2B$3iySm zXo07p;06xIp)wIDq9IL2HAi==stlp{>f~Cxe!hy0jpUQbr+!v(^(uCMc+wnh$Acy8 zZY#O)H6rrb1*DFj3DUd>ZDR1pRU>WJ6C!g_&E53pkT-=VZiaawh8KWCZ;4j?<365& z_5~dAP8Fc^+gy`}kA&M4C+8>;{b=bbWOhHMt821f2b58s0kObW4g`5_`;C9z%pppo zZTf_-dp@(tTYtT_NxcDPPx$Gs?;ALHd-W|V>QR%?!?T9(w`&>pL?}Aa&oVq8G{3e| zmkdD5o&JS7v-R+J9JMITgGT#>@nqunQ6YKGV)85y9!pnMdK ze@^Id#wg?-a_qyX=egEeEvsqdH-X%drPt<}CY82p82p2gchhKtIA*YSnfMVZyLE|8 z;rGcBcOdj9u7&z*>YS6*dBQXO?LMj^Ph96K!g=kzHmL~7-v%&pAUuIo7{uidlVQHq z-Xf}DXitCP@oPsGH&`sU)?y0QkqE1@t^*s3_tpgR059kE)KdpncZ&yScSn4+Lb0RV zn~I3!b$_F+p#mh5Ti-QPXX_*RX~=%iSq1U|QP9)wu;NO#dQkfw=l)#fwFf3VO&I|<)l7yUmOWS zE~a77v4fWAS2mIqx$FW~eOd1l9M^%xZ+zT<649VOdBg!ZJ`iREdMo$l7>*T{U%v~% z?K8>JCE3P}4pLq>1=`NdjK;s~^(`pYlJ~CJg>>mmKqpv;83C~^w$1tXJ8Epu86DQt z9;SB61u|zU$SKQn^+f#z)F@EG%cX&B#~4yTduUg36rZWPI{3%%QA*7uEPcKU)K-No z3vDKw9np#zW@LD^ifqfGI_oniJcmjw-zb#@6RDdLXl@+yYq$f{pBEFqI%~uu7YrU! zMRE%=t)wpSUg}AE@UfZ*q6fDWR6Cy7duvh`$!>DOb?{qD&sCd0$9pdBG{_;Wl3CyH zK{hlZAkfb3NAtngZ?V#(8ahC?LRES`^YC5q{Wki=xP$G<9k6*X=|UiV3tI_FqJAUo zx?xY6XPa;Mxm6c_r_USzwb4UynaDk9nt%Gw`S%-~!@0w6xOo%%L=p8PL+s6Y@ycI7 zsya7}$?59r%A(hn9{&a^HnDWM3^JPMrNU?SPbp3g#Q38gEt2PER9pkGi3yA$IG(FA z%aU@AsXx1fZb17R$zq%(aP#*T&C@GR-o;mqK^_HR(7=)?mUIF^H<#4vm)tRjp2}(A z>zYcs^ZH6?iC#IUT44xJXB?DXA4{E;;a4k&GO{u4wV_Q8@~BVyaPo%%st);{vK7V^XnB9m!D~^dI&Eek z2|x#T>E23v5siyW9iR^zsP3z7H}Z1n_y+RM_DoW;IZ4tx%mKyX{3zbl6FuJ%{gpJ) zX*z&SbL(WMaU4$)j>=@l1VL1Dn@zeyIUT>tPi_u!k*Vv_L+{;f zej8>*G9eAMT(S zI-)K4fQddv1m?kik|0^AfL8&p)4YRzVN)S(tkb;i$E3jl-e8WQg=4OFmtnKvaGyVuucErNTqj(CJwhHw=Yd7#5I=hc|EMbLDv;{U!bk zGWVfgQ~=Pvcg6K3itqWx4brH^ZJ&K`mAe>HeJ z^eNq$B_+_d1*x^o9xu&4dydbm2D(%E{Fa5vdgUucZRFGzsL?ZA`AARWDylY&4z%hf zd&iUKxtyzIXdCk=b5Y5%Z%DbWFM;HffR2$vXTku(i+u0q(9 zMNBbY=wx55VMRd0i6U=M+t!4?r_ni}#U8dwKVCch6t*T912Kn>_~keC+OxwZk?Ug9 z)IvXJD6@ntkiFSEA7-66VJ7x3G0Hhd$j^!{11Jmywq=9bb&NQl8l{##g*|`yisPV( z|NJByNq=OJbbMmZHvpF>kL*yJ;Uu+Gx1h_w7sr=|jYd_j^TQ#Q^ZvC?JqAb5Z-mT! zyjJ7#N`blq#;SH7Vs>pvbDUa~iUr?xALt+(n8Q__Gpx5H z?&Tlx-`VtNg!P87l9F&; zCu`6|t>(lyOOX>{#7A_He3EnA93|t&RNMPS6=~@*5ul*P%7TZ4kk_$S7-k|EgZ4Wc z9}SM#Cb1TjrG0O%^&&Tq<@kgVzRu_JFQ%ZZ3ks11?f~8L%yW3Xq3=u0`^_%bmGEJ* zQrH1FsXXmHkcfSNQM z;)fM>y~anBaVl#t$7{96yzXJmDT{@8d>SUOr`Vz|4Ya$K)wXSJI=@n@KZaku4b9aJ zAy#G#2qpLKo@Fyrj05vtw8SBOm}2FdvRdjCO<-HvPyVEj&i~xXUynxkR17gj2%_VS zIfZ${V#-x!q(-^fBd=ar$`NvIVua&HA)Exj1dz<|0$&9T9 zBBe*SJd6xmb#7AZ=S)Z?a}ak6D_!yf z^0n@t?>qw7OV?-_SMis((-QFdtRtfofO0W=L?@1|%M~!ZQ3W8KkE0k=d-=igZ?;Xt zvZ=_^|J{E$r$0)gEclA!y#drBs%@a2#Kxj{nAz^!zxBaBipi53RZG?m3&4~FcLIE{ zf4mgY1pC-fTc2cr0I{Q!?}RZ93YV4%UWfD6CGHZH58Q> zw#eyDm0G2{zq9|j)C_xhX!a9ViM9L!Q`3(B@ZKD)0qdRGlwB!(>e$QM5UU_fo!G(nm{7A5h=78@xD$W@W>Pnoh6c*v#?ybTa9N_|&;>xXJUE~~=Qp~TILs7ZyBuR$hC zX|XSZ0-<7<&_mZdI2WJ=`uLp-$Xu{Pi?zr8bc?(~_9>ATiYl>h{ITq;bJK?|lswZc z`l)5k_U{%$hK-@m{buj?KTQk zt3KBwyyIAkn^1+o$=>QIQT)3{&B^RBvQu6*o)?sM4#_K+{O`BTMe_yDFun~TA9lp2 z?%;PoK2(>le&ZT+z>~u(G7wAM?U=3LGW2A!Iv=S9_nVp{QO62V6Tf^AKW)8(=FR%T zkep&6&|B60d(Q*(&Ms@T=`nWU@I7B$ord0mKUYFxzE6y7!?C52I0RHDP$JE@S7{ zgEdF7Uf}2hjFHG;&S5E|c28XP3$aXxD}8E)=kB>}^7#Ey|HWE5J&5r+Dhmh?U*@=9 z#W+oMd9-f26^Z2OwE)@M))=l0)NNi}njUb@0*Um5-v$*EtjznjzFz&rnW=s4ml~!H z4!eF2W_Y;3iNQXtvwAB`G?awwIz}dXC9-9Wj^FQE;`e^1?_YitYK+Z(d;2o{demP6 zcA=^5El!teu){3Hm)7QN-$nIyZRDIucbN7pvMXH5u>Y->+v3pM^H(&w#3B~NQHWfO zUyTO5skq~IwgOl1EC?xE$-54Dbh{hBz4Q9Dvrtyz%Tq_ifKqTd4L5FelfX!!w6C&H&36@(jT1_JTDtG|0W^R8t1Ivq$pPh>q|6;88dJy>0 z3j`6Wh{ImfoQQ$RQ6xnR=aPTjWZe94>$c9X>+l-b%bWX*TBQ2ZuMjOS{`<$p#&lsu zD4~|LlTQ-r2utfjmWOb@RhR{8sCbpOgk@SI(pUctfs@+W$?+AVYb@9ZbQJsus2=n`il0Kwo?T=HEO?M$5zVWi(Nm|;T z6eOSEZ+#z)2xa8lvVZZS6~8_9j(=xz?SeiT?@m@DY9D^&>w#8f2)P@UE0%rQP)KK| zN6EEm`4?O5>d{w*KT(?j&5OBf9sx5Q22<6a2XnGFlOml@lj2o$=N`Wvn@(35E;=oU zq<6@7-TR>F+b>tXMG&H5&SHL>QH6vX?qZ1mE|%$gJIxx+A{q=x_X~qvDd?I6Y390* zx)4BQ7#H@^|L&dgyLSkk&NfK|@!Dh&w8K-Zjtjt;mTPN2xK!cySS^gZ;Fo)rV~l`6rQ*p>`s$w07r%YD8y9mHA%&8o8QzK0cvw+9+?4$(9) z;Yv}%=eOUtk#$r0!lS25+e(M61ls0 z&h3e(zg!YOyTX&K`oiXt1>9}z!4Md74?4X9wZX1*b;2~t{P(xH8#3LpFF+8stY8v% zsgHZ|_WOKyuR&k4RB*WAe*V&x#oj(Y&TXsXpl8_4Yi+D9V(H^qKX|s8YaZFB?vAZp z7(wdRyr)CLaX^V(?K0q&8^l~$8Nb+utGyr4)UgZBF}pl=>~VkobV57OHdmU6(!EX$ z+{IheF~#KbI zY9ugW@_2a#_MGtT4ALLx^Gyx%bfg@Z$IBWOJ8wTxOp&NL1SCnZ(c$^emQe$ z9vspfcf#P7m)=1hb@m5<098SrPZOBI6lPL}0if_nS#pcrocqT7_RYF>e{m|bZ(YBt z64`Zo7$?5|@;XB09t2~dzq2OH(TgcY0?+Pp3qwD*YWiEIa0-~pKQpe$4vLB&@RT+C zmzTu|RWPUU4rKp;MD>6FzSlMA*J?q5K`3KVP=a{RqrB0*=_N=CpeF09=Q3W#9A;P{ zGz4QukSA|^QJ8>m%|$8cxdq*nGHcKSrmL7OhU(Vw)t$KKP#-{3v)WU)(G&p|_)nsJdr(HL`H4%?0`ly-OUw}NC&ogmw8fA%0|HdMW=@g&v-Q)CK z94<9qWJajQFi9NvK5$fU{mLh?qY;IuJRdNSNN)2jfIa$$#8_jR=m zBBEo|tzkqVc%*zqLj1e+-BslP+ijmKU61%-FctaX8t57mtotbmO)Y!?Hf=@$8}_>% z=wl5C$VrV5k5Otwrk-m5-J@P(!3wdYK{Kt;#&zHcV3uXzw0$Q&9Q#~}*2q5TYY8bh zs{yBflpBorp%0E4icn7RYh70!3%O!*EMHgagR8KoxA8DKiVF*{6s~&JoB8Sn7@7~= zQ-p&_PMn|oy%gWTB?N~f;??~EhivWMUNQj$zX@pD^$Fk006H4bJAw_-h(xc;8^suH zcnq&}l=Ntnw7UzJUW-2lumDM#>Lcfx&3+Bx1^ojHaPx<^EFSPhbMpQUj{tc7y~F5d zT?+#G$LIN;%g~y%Lf|6jjLeT)Vga4zkH$k}tVSbwt=I3%mIKWgwhKf4KX*j@RT z!!))$)*b~di6eJkCSYOmw~zhO73HXsVx!D6rtQBV-+&>N@b5b84m6`Fy_W}!)%7bE zcxnn1hGTD2I6HSUSg?_=Xu8nN8!o&NCIwl?0Qm=nfW2Fb%jG$moqepILS=$} zO5rg8e`|X^hfa_{QTM(MR$%oF;4;MrEyT^aNb#%|`MmOi+L$(f3JC0VqpSwsvPC%B z75}l);RZb!71(PW=7h|BC<`-?X#r*xc>QMZKkNIfuyR9QdKA~xkW=>5RUpT8 z*5OxsT4u6-Zp$z`j7GOp+~dM~-qjXnJTCHEg|>`!De1m{rF;@oFl>XR*KD&%q+D!Q zzYQas`fD+DAlx^?kz)J_%Xj+Q%$M3B_oDWNa!Vp@I0~X_;@7AWOyFCwyJ}r(WNgb|P zg6nNzhUbYI<99~cUYxL}utaxC+)(-hwch}O>D1x5SN^qisqWCb z{=-@7<%(N*e~9(gd`}uiIep)H=m>nY{c}-XW+&C;IsmuD?DE-(laG=oL0bz(07HAaC?)-%PTh;nDy+# z6l&7wo2+q_Mj;+1Asq@c47VURxc|bXALDO>FdC~BcML}L{f_+t2GFiYl>h{@FfjJxYnN~TYPv_l1fF-JFQDDWPol#f~~b(Fam9@?Nfpd!G^ z(5)BCq$CuOCf5u@_~djXoKWG6tIW!Qh8!J0PP)3y%=vx_YDBUnOwtycWvffqq2Xph z4!GX#ws$=ep9#-+h2ehlM=Kt;^4A{_jS)!8kxVhf8gS(P8}f-KXX>}97cn?rX8V``01JbD4o#8khGrv#FLJWI^ z&~bGbqBA~r$8`{xP*0Vm^21D)e(mvKu(Xc3pBZQ(D*7CMI2Eu&UL!m_Zm1&S;rCml z-`ZO+H#c>*1#&|Pgi^%3#&A7V!l(+}-H6}k_P@`ab(41K?DS{QhiQ5C@DKa_tCs;2 zYR*gv@YIC+NarK)MeqLp!;0+pi;#^DNjs5b|?3Q;_QdDj8cgshyiBu=u@N=l{7=#5r1_lQFn6?;5p1?)^6{)d=#xD zoYmN`qH%f_YL?>{^Po$;fy6=G;n4#X?E!yT@APdf{SQLtff0^F#ZXx!#=<~xx+U*Aku{VY0AS+a}PkZkP zRLsN=@LZYrXwHK+X4Oz%6U-#B+onaoIOu4QZ4WnqL!1xey$>@tU;pyiQCIY6={2Wu zU=9qw^DfkIB_4-{ma6)LW~Zu(4(okMhvh4#zDGsZV^PV)P&c0ZKc!^+f#Y&!#Z@%)E_ zemy>j>c+NPnR=g1@nDz@ly|`A6gN&(=*@a^zS_eyys!Qq-p46BiNhwan8^DuUBn#a)1!YzPtzc1knL5 zYPew2OFtBfTZ;&TNxjq|PUz=3m{(iSIuO>ml}dB`?MLOeAJ68-7q8c`7HdBbBCz8y zhwwY&)Wf$Y=)W761rI#<@jyfYW<@>vPIKFwhiCeR^0adRUBDS6KCJJ`sU+l)+ma2^ z*Sz%b9IW*1z(~ngMOW8u)VGKXD1H0S-@|iUuCVq`92Vk$DH&MDinCgIqMLN4%WQ)O zK`3A5{P71$pOQ?eucjCmG1U0@j|aVfL0lPwyxB%QRUSO}pM*@|T3z7y!aUts_II6+ zzr52n9+GpA_1Vu?-Dd*EHGVaza~~See_I0dCsI~HBjm^s{znDe+8XMI+u}c;v9~V! z$|__3$j}u9X_kDIoO|8I#kGTHbd68wPOPo?<21CHv)f7CEAcsffr^Fc9XK;9K+7fJ zT6QmG!v_YWr$qVnsA?zt>R&ZG7>Si%>01DgZ%RP+a)UfU zE9!4Qo=Jw_?bgCbbL4H!hpE=@Umr)Q;SqNraLB*ujx@R_=`GB}C9bEo!vU6B|A)Lj87vRseI56WE25HbdUcf59r0CW;TZ*vg}O^7rt!Cq2LQemvb+3@|QU zf^Y`zv2TXcONn-5M?dImplKoOX%y;1r7Q*!cV^%=;)|LH>Q@VD8V(%!=KSJKk*8PnxnsxB8cRDGYhSAXN?={eJJQG`XrI3@ zt}CXh^wV|LFl@rY=mhx=BFK#wjzz#;ky3yk!4LeD)TO+_<6($>fl{IT<8wfwK6*U= z@h9vCd!C1ZO)>iQhvB(*PTF2lmXJTYn2&`5H5A^xP zbn=E?mGUGZKm3(r_K(lzwTZcPdvLI`+pp zfXrh{#}sQezy>`4sw!8QEa*t3uuc#urHll|a6sR3cgrPv`&1wRHV)O!=%XSzu`lOiJS1g7ufP>d6&ATk&h74H05Qoc@PTX%*(4n5{NwjbpUU}K zXbMfOb&oN@;TVbsmVw#UzCf1E>uVYQr?=;n0{taG zli=wu(}h=8^&uXzoLyk{FpQnx(z%w|s9zm(410K8k>{7SAY21TnyFR;ftaNHs- zT*jSB)hl2WStJ5G3kTQjMAxbV9XL$)M`U+x@TaeS&A|zP_-~J1{G6%UTCS{E>PIXb|&ZoxF5z>_INkpZc%N6V1z4d9E=6olG<1>C&-t zjQf<=q5sxjzx?#Q(h$~IZ>_pq&i8B1Zf~nY{&=t4`paflaL{R7RC#jdj6-hbxu-v8 zuN>RI`$`#yJp1}f`qfWUjhLXEn*{^x`!hH%ANeqr_2F4akEf&n>sfzz39=dHI&8dfkwY^?4ehApO7)uNYg=IYzSFnz#4m3n3a7`R9|~7fc*`iSMPU@b{10e zp1d0h^0k(Yo|g%6AauTjTp|bWkrg8j_@Ya@jmG=_Ify$Ky>U~kKHOleW#Fwt9F7LC z*H=$sudEh@3*KP%Tk@l5)rlx=kW+s#LaslCA$~>U);PMnHbE_9l;e1jQdebIf*PMWelh40fLS4ZPX8i83tG@^o>+@GdF|0Y0A43uKLEzt0+$_b zeMeB&+PiPJ&~LdxKUF&tdzpSKAoL27CUE%;xQva)dg{`jMilmwQr6J}JS&$&H79%A zUogo-6mQXhlQkO(dW~iT=}FlW@~BbGzxRjtyKs17*n$h%0W-VI=g~OE#HBX8t)S?V zvZCcL-KeS52CN6oDXkRsaLZjq_9?EOXTy1SBxE<_Jk)DY_@Qm+m(CUoy4h#hUwd5H zzKxWdJ@hrffAk{7yoON@UB|#XvEr-QN^7x)ZWxq^FPd-g@0>;E<`aVT6waX0puhBs z*C#Y#@wgvR)O^&4>Giz6`UEEe^)BM5GCoVk*A*vTeU2M610Lu*Ku*ec3dJ?}uQN$& zZIw>9B}dw0a9if7HFLq8Ut+CWUsPvbL0h5bY@%s{BvTzXdLH!cnZ$I)zdec)%YK{F z+2%YNys`#x48=!!^4Y5{Tsd78f+x8%9E{1DAm84fg0{LIBWPkc84pYh2qS$Z7_Y66 zc5x=XM(sD-Mx9$KhGjgiG`zA|tUuHJT%6uNbs{;4N(O)mL9wAUk8QU8$g3pJ(d-!N zo|)9#wF5_*n+uC{X2BqX%$#qXp`p8049HIuAg?ROdNH0&y-G0(Jec#LaBvO4B5>u+|ua?r#&gnbhK&bpIXygOiX9oyXo-O`*gTVr&F&oIj2 zRvN_dxkF|T-J8<~YBwM+J}{HOfv{x=2oj~Ib=#1_d3$v7GO5U=r-)Rl%}R)xRXfZr za724&*C1orx{5S<%}d|8e%?S08LN1>*Bpu65ri!)=F}4mX6LpNcPS46z$8J&?o-(iU4DRpY*>@rGqNAMEQw#8=tUwO6k?&%H_*G=``%pix z?~6M?+ry*6T^2($G022>Zf;$Bb-9c^ED5&ZD%E7mVsHzooBTZA2&Or1bm8#{kDHn} z)3W2V_45JoUg$D|t>Mruw6vt|0r7?bU^Z-iok|oLDIj zG8;F4^0k+dq2<};{@dQ~);4k@50O@!wf+3I3-^+Ia#FbTzD7I`@k{(ub5y4#&AceJ zP>IQ%7T5_?arB?Wg40N&N4Wi9b&y8ZTPdzP7xaj+fi(Xe>1 zS#^e-fs*6iMv1+<6|VMJF`yfoCu_mF;F-Kr@o@}0`YUZH6@(Au0?(xnAo~5#2N+2J z0T(s_)&TaF_Dngw;WKRp*vgW8|~r|)%rZk)J(tgP|I&JB>rQC@ey9_s0nJk47x zJ-_+$!D{+FlFg+~$&b)Se)g+_QEMyNiomhl)@?6NSJAF7@eL9vJ5(Jzt2=at>|y4n zJT@DnD%<+_d*0StTOHZ#tcK%CzgJjK>i2Y0(7ag_v;ZDbXB?uB3cRB!Nz*NNKvA(t z2<9!dQohV2Ok1whSNbxAQB`HIODUwuSCdV1V&du z${Wo>?geW03C&*wTwxsdHEcI%s}Ph+1x*ss)V@tMfgZ@dz7R;9_h2UcspBj04(Nxc z&o9!~F2b01yA(K^EefX~+o(IhX-h`;*hMp`#lULb9c&qJ;Au4?8h(~~=E}ZX@PdwC z&3ee-SIWf&#T#lp^w6f`lixH~qq1xD&+|mRCpyP{%9AEdJS?sE-kBWN6)GKVSNB>q zYxH~gPR;M$oZ~vQHuNYM-W%#N=!qXx`}K%_bLrEUvh(?%pZDMscc1+d8@6bxg${Qq zIO79cmqMb4jw`wU>AM3<($&|`aP(R#FKP)m+{P4CVv}9?x2E@Zb_KTMO<%Z<%srh> ztQ=s7OX|UbCoC^tp4;n(`)gHt(0q8s)b%%K0>&QDywhuJWwR^%74_adQM>7TccSim z)%LPhA`SktFHVQ^a^OJ5zSx}29-(n7;myG7zQmLya z_FH;Zk47wRr+dj%*vL0n{eKxOXzFR_?j2dt@fd zzuuyJGlXxXoo?|a?uK7nsWET)T2W#!oeahMn08EdTnw>S6p^J9pfqU&{9P& z2D2i3PA~3jR#kb=dT?5r&mceW%>S>e%~u9wYM3fJTUi1Tkzz3Ew3Fsd;6kn0or zinR-2rLWw1M2bEI+PzhCfWDRn{o6gs4h8XT$wpziOezb+g$i@t{0LZfG+mifMX!w| zSPX@Ceji`ah?t)Dki7wJ(&_esr%-W%{b)8N)CLMVolG>nz>`0Pi_3wF*h#7Jqrf9-0H5Z|1>$ z+o3lBj@QnDJWzac$Do}LD#xiesCHGTahFVR!Ts*EcVG^YWfhzE3Ujzr8Sa`YLwX$g zks#D8_)@flm%bKs`ps?mIc^BSCpK=Toc7p9v+v5T;y#0SAI>iVQwE*c<-fSzDOdU< zj`vIYVf*uf2RB2^3@eRp-!9d^9;OwZR9L>ef$8W@n2(_85oZ*~-Iq9rHy`}FwkjZE z7L?QB5goIGRMUUfSWb8;%!0L%PgEPOEZe8u8+c0e4Wph+O5^n3lp z_#E^meGa?FJ*x@~Pf*Wv8Dx;j%Lvs5t=7k-f+bhD0^PSjQ zc@eZp44rn#)6d{>3ua@{iS(=PM7$LS2Dg)< zUoY2#Snl2VxQj;cgYn)b(IMT8Y+^EwC;2nQ$$G(4;=SJyC-riI+Ma%~UW@mI{y|ML zIuvW=n{5TqlwJRI9dD1r*;sUOx|`#*Tc0%+z0CJa2bB+5D>5gckb+HZ2<`7I-QCX| z#^2VLo?3RybRj%B;Fd(CDhQGLH0B~yavClj@28#sIgg33ctPyHslRzRAc>>E z9;|Qe@1dgpO!PZnSjrdRD#(5#6+5_)ocQ}a+{P}gl;KOdvS6$NpI1SCaz8mzk6ib1 zC2nV8MrYf?1naLe<8%g8>Dm$JD9YFv$4t58_Pq8@bhvn2+V!m(iPtZ0z_RUdJ^~&H zvN8$fvhn^CGNOX_7Z6jupzn4M5%~-MUDSMMHHH-Cn;e%+p-u6g#Al zI-eH{7`4(ZJnI9U&zoG#Z2I}d5c78r(Vu?CtA5%YPXT7_`O*CPX8HKdxt5aLd|!vt zCcou58ta%-exS>;pKPTq8IRdg{VM0Kwza(XUAR?ey|}aNyWjDP2=A zsWM#RiOObZxY@#qF&b$LAvEK7{PoBYJ;2E6gcq4w;xwojoT?sZ84N||weQZ*(gBwJE`xp&vK171 zE-%JJEWbi47y5T-&H$$Ynf8OUe=Qog%btMR4L!Y2hG|=ktFKwJZXw^&S_gq8%E3Cn zteGA`&UppZ9^BT^<6r85ni#anW_`~WsyIKO9mqmE%^V-_@36=X#Fl>Azaq+pgS}@- zNFlyHcwThwVlSsCWVvj!Z-kW$j{zWGFTdLR^)x||98R&vgCO$w-M<~~Ux;P9bO}hu zVOW@o$=V9wA9S7wJLo?Vhkfq^`?=Do44{EV)e30Xe)1%eN>A_B><7w)zr6mYvNtGR zpdRt}733cmtLD>^K&?KkEv7cm0^`C3b(HSEZvxU)kK}54uj?yS{R2 zM`?-OHIKZ7SHE0~$ASZLfd*Uy@vtn_KQ+`w@FNzLFmk74joY_=7mOQL3v`-WYjvO=)N9v6YfMhY^TrwELsI+Qi{9jg6Q8_^ zgpB@=i*%ErFLop3;dpXLeUE+=v57+S@fkMs?KLy$Yo6d&2RX;i5InCDuAWVInjS$a zDpc>A2G4Qd3ZmN{T{J>p&^%LiX^tt0Tv~Vg@mjP|9k2j`T_(x5L5A-9K|F`U0<9g{j@0(Mx{otKdtxvd#W$@TKD9z##-Wz%YP2q$rV?O>si!2pVE2kY`YdJp(c zcwf5R7HfHar|T^wb=vw)D|e|MVT1y}$=y}Y-&HNAEOTN<+5FSTYLzCQKYHaRMf}D& zzxU*1;}7@Ujv3;dXPCTwd?u7zubGBtUkCl4kId{+PZy3*O)}EncwH_%@(_$9&HM(G znP!@E3AM=!2qEh%+G>`BzH;ZaxG}B!2w%@NMZYj~62dvY2&F1RPnqTv_x@*n`j2By zqHm4*Cp>V~5k!^}Q)V4{Gq7!0F=cH^oP>Jv)E%>J&ipB`fTc!M^$Uj_!6dc zIbYrVa2%`tLnnsZomIfCX2bSAYqaJt4B_<;O&$B3gcC~-X_!%3H2Tg;3rYs@iUQMd zUuGObJ_p#AQjw{ruT>~(Z6$QyA7h58)y}+dlf=Iorg=FDMBQZclA1M;l}C{DPUFjA zu4LY$DVc)O4IJMUC*=s!wQ1)~L~S84So-n%N}gP0Sl%axMtXoay6B;rqrBH0%*ZpS zbCk|{HJM0<{#vi#pqHJ2&r-o!tF@6EAz?T>r|eWht@!&M?8JsYor&Jt?nVjQCx7sE zuPo6bg)TVsM^o?%*Uyv8p_B3qtuJIq|B79z`EZLuI`3q?eYXaBov^+HMqu><2kFHN zpR@A9k1sf_-;B5z;4=(`Y@BTAYZHh#*^cJvj{nz88ojG8v=Alb+oC0JLu%cu zS`+8i#LfcydTnSGHGcAa{kebg>ujaM5n(rr`4w~_kA5Lno`#q}oE@Xl-nm8`WHj4< z=L+w&e|mHm@~}mZuHDh_j)3D=>b5;ae|XFdUU|8y*2*Wp8zXT3Uc+!o82mszOZ*&F5Uv}*WQ1@Mq^;2k{yn_FZ7)Olsu;@!pd=bJT!0S4qwq5{lRnG zieKOYq${LI8jKt#-zRE3^Cv?R@x$&YB%HEwrZo6+z5-@)&P-C}Z{OJfxCz&k?I zEz;ld{9;*Iz1MGio&X#!Rm*JTXjYRzn+IrY@A5kF3r-#%wpDrvD(@+fR!Thwx%HZ> zn6W3xTGjV^jp04iyGtJj)Zp)%%~*IJoXzz&+(LQ+__i&O$L1ZQAHBUCc`v#Mm(?Lf zzUumSN=rB?!h^ZBOmaS9#@Qxrlt|Iglh>$$)kp5j#dhq2r8I1ir? z1=^7DG?ll4VUd>pbsd~lt*i+H|5x;0K_$YzEa(2~MhEvy`xvL9)(ZjH>JgS>zt5Dq6=)gW4Joj79*gbtyh1G!AU;t5 zRrJG8C7@+cQ&?tHw>=Dmf|b;8#%?V`>9>=&-r<72S+vvZD(RqG_nTop*9A1!wbFHL zb>A*?h8s2Dxk&eW1?eEN-S3+_vRdhC|NWY`j+@K34)DmA@C54#^-3e|m`%$Zq2^ST z-%AHB8qS_;e$tUxove6|UMuj<-DezbxPRiKL+{j3p@5UsY)E?N#qeS2v*AY~i#bxK z`wQ7j8>LL~LjPtP>@F_1Is5I37M>Hi&k1>7Iq3JK;)X;n6sCy`j5|-d`mvFkVjxUw z1w2rYL62pL@dqdp>~ljxEeTrMvJZ6g^o3gbH{n;VbRI*%)islNUJt~A8%A=gA>sEB z?C9%zXWs$a+Wd4WMHC2I5=c?ZtK#YdiCb_Sq?-d^)aUT9gYTJFm)RrY+V*=)-Ak^Y zjki)2!bLIT^8Lez0zant1=cLA<1QT*k^>(KP1#W}JK;XAM7osTm&d=JkzDQ8k}~Ln zFDxZx0S$7y8TO`I2x2dcwlj_^sUP;z!eL%|H>RFTNLH&4o2gQSb9;IIkLM~RH_DBN zEcf?3diZ!~3!$mNNNtxA(PgUZNiU@6#X9vDtb6q?d*I?kw?BOW^jF#=9l?AO>Y~R# zwdB3pE9NBD2J}@(6MU;T0RT;!9e>;s;BL12>O&PwVcr_%@L;D`i{s9@N&^%-&qnZ> z1?K(N{t->SkQZoT!L44{KIhvCcuGiV0S!2xpMK^9&9u%gufYGUaXiyPcrg0ep+(Z& z3|0Jeoo%L)sl_Mp!be~4EmZ+Rb)CkIH*;xHXU0+ zsb#Zc|D-P%&XafgkfZIHF8VS!*Bo%>RB_wHNfWClU(0C$_#)IyI}=JYv2lXuXI^VG zu?yz=vzTjDq13^cT{;3PbDs<8qQL`-af~;`uUI$*<7Ghv@2?T{ng@dSB2e z1h?V{KJl^in1`cxD}Mi2`kBu6-LOMuBLDoTQ#&60`=S>bHjltdK~gaX@=zXMBRgLa zXqD|3fIfYvT#Tr7wnDsyD9mu7NFw7?py(HNwOp~ z)d;ITTpnn)7!33dmfqJnU2zXr397R~s{kQAu8s{7kSCM6{_*dL#-5K|ay^^n4|}j+ z?TV2H^$YsA==)H=eZ0Yur5UZ8eL@~mUBB3dyA1tz*|!4jX7y+EaH|M2!M1uppgP`m z0-sNgqHJ~!1uep5UY0+^YdHf)dl~QUQWKT~W(cc>iyA|g0om{q>?YvSP=inU6AvFb zo3RS^+26kxIPb6T|N1;H<-3sY2RV@s6J*VaK zcZ7}Clhg73Xu;f=@kta9;2Brh;bHBZ20nM^LD(NA2qk3@WGs<3Vl8E-FUV?nvB3z; z;acDeK+RpQJEvHcVfQ-sil*&-)ErYwI0q0#D9yeUevE$%n+-5}V!?n&MAsJZ?78pO-k6Z1%O-~%4E@} zTGnl_GmV32isg_Ll4&o1fqyeU3`aEPY` z!v!F}QR9t%$nOxT16)~0+?4W9QJ?5GA^Uz*o_+`4#`mB8@yiQ43-a#3TS76W*+JF| zd6Kxg-#3AEAseu*A5bDBuGC-oM|xht=$ghX8=p0X$(Z5{m)iP*f^@2$mSO+B-;k;f z)qjo8QYWdA@I`L3Wo>hnKbpi^MR$@_7yY+ezTP0CTKFD#rrzyf7qoRGOyRqkupXaS zkN$M|^zJKO#<#-25e6TpXlTLx#-~w`ix^uyAoj(;hW2a0#ltrZnoouFqJ1xKSEqin z`tUFw^6B%*tjULbH`50Eau|RLryc}*gkA(%(x8!g#Jh@n3lBFA1PI^Ay zF3>^0a0cX>nyQsf7XxyNzvnL}N9Zp)ve%tQB3yc9Z_{j_w{!b_4C@zctg~3KOo%u^ z*%o+Myg9Hnkz_Ta*rjG4rF3DMReGZ{izdUHY0;GeSEJwAiJB0Qz|+R6U|5d}OW==J+h z)HugymsJ?j^^q~q<)8TZl+U^`=9e~=cjfP#;M3JtVkx_ccL{eE>kqeKKuG-6RpIk> z2S)u=ql?!b%$`N8`(XX-iWc00_w}3Jp|#RfR0PN1rJsu0_T*ZpBS^1~>bKH&lG^WA zZf*5;12%KPGDUyS4MiNUxo(JWiQF_IWYu}BL4|AILOQCf;Y3BNR1_Qi;p56Tah-Jt zL^_qHKtWEc)q#MhU6Wcqgva=p?FwN6gz;B%fd91#;i?R=Y6tMtKDV)V+_OoBipKkxUR+`z(MyC<35zr44q7}tkHN&5GN zLxRi`kQCnEFVQNl8`;oyJZjUEkN(Qte>yWv02(?1zbbxPft!4&L!+Il8q9MWyT=M$ZJ~8x1F^>b_SHD(Q%8AlSxpfbY?XoY7 zDE?!3-8K>lY!eLL5gCc~m*+8K9a)S2C>3}c#1~qxI3w>;X5LoP=UY69&Ep=Fa3Bf1 zQiMcYd&i&16<@sg$o$Q`?ROMMU=q94wY31p&4zFv@{kR;Mgr*RZe zJulx<$ol(CEZ6lC7ry%P;-oKp@!yLx_?yd%4lke)u>39ld^GUl$u2PS<;8m8L@)mn zFBUz#2Zu z&hPTgOYK#plasOC5FF{e7pB}Wm#tO@v>WZ?Z1}`zxMY+%xcU! zF-yrYS6O=v56cFqwIX32#~!-%WWIwh==-@z5qe8?V?CfLUuCnr{7LYELE{e%W&L<4 zPoe|(Xu`xJ6V9+vy*TmXa4>X%TfrL<5PH~AWcmRN?XHgwhNi$v_z`ScdY1zk?!lvO zvTz?F=n>twTp8kLJ7J;$k?`RqLElwpRR2SM4-xu|Pl(^s&@E2FZ9->JK^)3=SmX!j zYdG0+8;kL#V>VV=JxXCMsI$ysBXqpxmmn+nes6hm3p7YQnJcRcpmnvwZW!#`$p}3al%KU z0L~8F{(Zf0v%08Rdl}Sp-Q9epl4yq5CwWZtz2fxkgOYA1e*=@iod#IEp@3Hr*N-EP zx$a-{3*Klbfa~L&MW1cuj^*)tHj#S0gd$X}kdy!b+qVqU`}8W{qOy@Br@SPJc-V>X z_E5nu_Utzu@F3woIZ)KDyIO0O+UHZRCo<|khlcL%?70zMNX}v zopI1L*atgZv>o^Ti!wPOtZnEpsR^eYB(UCUsIr@IZSBMgGa3QwL&2!-@ID;zylZzr z+)EQZZuFJN4Sq>6b9r$wZ>5Hu0XH~}X;UqS)q^XZnUd?|_U!pESo6QQgK;%X(-p!I zfp!TWAe`!=bNhyn;km>QCWqTh(^}xvd>L_DPrxuvB|c_RRIgV>07o;O#oKB*^@X|X3l?6u7Xjwj+a&9d7v|Cb-i#rVqm?B^IHi+HwyJdU0FoDq5?mzJtfaJ+BT36QyXA zPv-9MyBLW2XCEooHHJ?^mkhS~R3exe#5bIG5o?YVXrvHB22w&B3m!1hJlnseyLcoo zH~%{`o20e0jeFvL{I4cjZ;1jjek4P_VOD-U_S+3iBI-SSlbx4{Seg-H^k%|yBj%{% zHs6+pH2p7vtE~!;vn*Y5E_fd<-c*QU;~yV@e;d~pO^T(@?BWG9XHjd*i@e`2=v|Rh z!ZRqqz8Ddg?rD{I@EYe4XIA**AuoUq&YIHp(2zEpgJTfSWAc5ANb?|gZ$YH{Wxu?i zrfVR*-^8T{jYT;gKs>=f8yJaQsJ+gF&lE&yUzi`;X&vbJbFxP!-gW>cL zWdR2Pp!w^3QBMSRM#N`x7s`(~W9@Y@h=xbeK)k$Q%>iSJYs)^=X8qS^2`MH24}HGn zc3i{d8kf(E7tp!I3q+}f=)Sz%E*c-d7xS7V`}NigUUz$|h|6Dcv4^m4hmQE}-~Fxo zAO4p8@Bh_5{KNm$1pn$~_P^pw|IPpSxBoi(-|*s}|BL9=RE0nNQ{=b)-?IM$U;CHu z_~-w!jN_>JC%CQW&-&Aq(ck|0KPw=*)c!5|KkF`B<25sgL%jqKR+W5}v7LLnr($U(pdww(dO&;M)LaBf1qJA&D6c zx56;5MVtGS!n#$5qYb6d;P%Yq^EhF&B5T!p=78W49OyqM=lzMW-e6VEheOl;(z8;b zjPqLht;6&AF;+|Bm!1?Sg;)|c{odUDC%=}YVGjhoH8&4?@wi+(HQ^`+h7o?_uGZkKgen^n#w2Fe`1_piGaxBsc;1;%5c>1A=J@c~ z4o+l>Z?z#gbuD+{4PZ)|KN~gZ{QCHqG zx`s^DX^4$S758opFK?}ck~+`Z2GqdLDG<2FjE&|Ezd`fmyiZ7sg}^d&)wlVv^&^G% z1RR4#+WWoxjdE)HemuAb$pcjivTh_xUhVTX6Hn} z|9WnxkTGByTBJfZKY)*!)B4fUjH;?Z(r}f-&h)NF6nzrSYQ{1{pl^wgo7ftKycBj zsIaT7$|D!EXV@pPR13V@c(d<&0Uqsry@ex=IUeRm)13F$$q4Edk7p6x-L{^1#t3>w z5IP$2Y!G#7&n&@vuLuQ>1b2J)08dg1zXQ(TFa&2Gm$y*&JxRg{&3EX}q)95=N(L79 zWB<|_H8=Nd?7rEyO#-)vy?he0n+?O!1Vaq$NO&G2q!f{YNQ^#&t*?2s?Nwt<^b{<) z_~;#h(2Ci@v6pAHcrg`IQ=F)xFXX7$a}ElL0ry$leSP?F!5qx4qt3P0@DaO;9q!!l zIqi4T6JDj3-yYuD5@Sd{wu^_`CQKQ2N90ivn_-Zcm0Z5_KLlY4GCkz zvaW*=Jcw;7POVd)w_EJ#W8n1nZ|c;*^SS0_IDKc+&3FJ|5tJe8wcH zsVf6e6Mz@T6-TaP4cgh;9ak^6p(gcLi#obmIEh!O3{^X4)VbNbIecaT?~u;01=Mw@ zXf5yerGm@bT&*Cx;~ul|eP|!yVYh`=&#I%Z#~CUOTQQE~>kS(xV8+uqHGgZuC^N>c zSJ>ss)h=F}X!;DG`*0iGMQo7abNf`Xam^Mml%{b*2m+e6SZI%TSVD)Kys$WY&Sq2V z#4USYzD%$P69AwABS4mf7LziHr{;*bkX5U1o31Vg>m` zIK;5H%nvX)q?}QryUc)3RfzbzG7R+ut-B8u>z}gZp4B6Y*WY)!;M7|hak@28Wo$MZ zl=M6=N)jpU_bc*R*^P?;`5j|*{~Ghrds1?E1cV6F2}OJ~JApw3H{#tlVO_ z7OpTP7OViio_11IQhGiI(rlg9T^9ZTxT?c&V>p5DW=Mz$!az|JLm_5fxQgL8jvNy4 zPGS0cBUplSCL)QWEzS^Fa1+v7A`ug7ffBRa_05A#gqb;Sf<7 z_lZb1=Lse04wdUroF3=%wG_1D2PNIZcU&#PW^z}czaJ1B zVQ+i%)~<;_cO6mk%;rczM(IVscE@Jx)uCTMj*z90@3UwUBAZ{cbE#!0a1JAIla zHbs2(fBy|nV?m%&-Rht?4tnt7ecl^=*9jvIU&O>sVtr&;fY z{1qHMRs>`{_|lk(1e=x(W4zz2l)$a&I>GaKrCVGUgX_Hj% zC+nLEgTAXwMlp@s*5H?T$w)E@ABOv(YHpr(_!)o@kvqsd zX-E=mimfNy?irpfiWPS*c7R!4-qRA9x$F6PU59#Nxc57W)Afb3y}2eNnL@dIp66RF z^j@C-^_)IHni+(_O4=pC3zNlBVVK6-w> z59g`(^v@1Ps(?3scd59BGIUx1&*Rt}#^G;f7QX~7dt}0o_x;mRw!1HVUOn5}nP15@ zWm~-hbr88vNYw=H^%5PA`HR|<$NOZ{Yd_uw3~W#@j=-<80I;~RFt+Ym(2yj(>7yF0 zTrA9%dOi#yYG106WWelTffbDyTwcTTX4m%$@M=vu<)*e}FHXJRAa8i(;*yskT+H)Z zoj1*&z0|y26?GC}PAsfK`@VmGOGzd3EWun+!*d+xiRB3(@r*3X+KwcmGkoeL4<2a7 zeO#|S2imjp&Ksuf^(?)5((@`wE>7i1W{RFx>O}8OI{k=kp6d25*bT&2{Y{98CB1if zBi$9d*GZ=gK#6Yp=?u*~?>g+y=3tOL;U>&kMR!X3Ko+{Msf;~gmU`%W(Wom;st2v? z6Ug_GZShfnVvSvfg+AnF)EzB>@1dlT)nJCg1x|2aNvg4~FiC0H#QS_%hk#$xx~1fs zobqp~RZ)DYn9ly{X$Kfq```=oBQYa`h}iyWO4sYI>tfHZYlN-bzd*_a@lxNc!FPkX z;U)p}2P5d@ohkCwIrnvUGddurZ2-qd$f_z5m)L->q_~FXLD_fvNnnPn4WHem&QOuJCtb2?zy9m9-(GF9qk(zq zY54wqY6nT<3=KdcQcbGlsCEgeD6oi&yWfA1TRe_Za|xz$Q;=(6U#PPVr-6~n>dtkb zhPcsI{k`0u3-*CjCn#?dmO@;X-ju=gh91Q`04*(`t%nC6@EbOf>Lf7oRuq(OO{^o( z%h-*{hoLYft`1VfR?cp{^!cm_Gv8b!f(#&M7egKkTapi>2u|0Glzmq$X{^!h|6RW= z_rJW4IsRhWoFO|zRYahK@8a|MOnRhfP)7-31_+$TBb{h(=^ziZ>|^`M753lsp%`!@ zkS{{o+eNu41`f($4GC6~Z1V7ad~4*>6zpn%oy% zz%!BXg}-o4{76af)NHwKXuvB7q5x{fR>qQhJ`U1ZT-zbP;?SE&S5?W^&23nlMX$wN zE2fWz(R6YqN~I>ht59J+qf`j*(pc@B)f$2%X?)U18UEQ)Y}+cLy8IewZ~2m;B8~2x8S1~XF;dN4n&$LuA;#q{S-Q^ zlmVGxFj7^7Dze}=96ODmsXa4p)CPcr=j{lqMSSf;48Hg=h?GcyrAnqBdyi|T&(W5+iiA6NZ&}2>4mLZoKd!%^MIvB_Id2zB z`wd=0Y?+|LHaF+2@h2Bh`&OMJ~y<6*i9eidxl2}^LRG2H0VY!Jltp09E; zO;(})*}D?`U0Ww~xD<&rEIqx{_BD|=3GqVB3{QGMrauJHr~ZnDWu;x=`Ym)I#*4Pe z2C^*IVq^0w8mcp!IvVdz5AB-zQLN&Q8%XHb=CF>_9MF7}#L&{q+Ah5Nqt{&~lHwH+ z8PJD(GSK(#C|ZSDPZAC;!!U8kUKvQ!qOUuuuJWBp$b!9HDEY)wueS;BK#?{AAE#3f zmx+)~A!L-8J-eLyy2*V7xB6rDCY7mUw!_P1?2ol33?Cj#W6%^q-9oYaW5GH&1Ht00 zx`fZzG@D!Z{4p~Y3A}1|2pv*^)=!`zUGGzme(orPQ{+>s3{2lr@4(`^JR(s`&^6!_8it`G6tR-4+Zd3r zpOq&hAD-j$Pya8=!0EJ3Jh$XUauvmI14+}S5+trD;CSSd5WsgX2X({7{hCuVNalgM z!L2dkt9knsQD$ec)TSAQM$KV-!M(}Hy1x&c9a`s0H&gE2UqRg$cM^Sv)0s!ZW3$$v znlI5DtgM(ZgtJz@^2Y!V1)gh5ZB4T1@bP51T=&C8LelB?|A(+ISz1-wx_lrSNDWO3 z6se_9q^AffbuIApIr#R8{4*OF+1PO-ZX7=m7HiEp<|rsh$}iYU+Rr)NfCae0h`ee5 z3C6@&8|AfS)Qx)H_CJaEXhTVzba*^5BAQ(o|8e3&id8?RAHN&J+HfqbX-wG?2G?>! zpls?Dyv0evqQ*N7-iwNuV0;eV>~PDQ9Kj)n+Z$F$rR~ASg@my^{9SR2(K)M^+tx=J zAOvJm9FFPMN`V}`T8bB5pf7$dYh^K1#+iH(!wLKFq)C;Xc0dZF8PY-vomU2ZoEv zC~kf|P%cKKI(<&l$shSg_JL1kquMnaGB7mK?odk&XO|eehuFvaPq0vQL=PKY-7g#~ zS@FaNVYJa?Lr3$azP2Dqkh>(e| zTd*H0`LcZ9DfAO#Ch1k5bA&(Q=)5CkcQmh&s7oFVua#o+atBUHAVVKw7@FeHzH$|n z93Y|5qbqgqmx|`Aoy0L=3bPf^yb*MC$fQ8O=AbJMmM^UP^c9Ez&KZb*RWLF1k3}2x z!SSXS(*5+)XLA(bs)Rta8~>b`%_wA7RuGeY;%KekoCK3FVA`2{-flpj>f>^H)P%xI zqL6M5I{^0ec?~qhIb+-cn)v3CWSvHLJKsbg{vB6VurUy93fiSB4Uz3EGtH&ogZKS9 zvqJm1kv!HyE^ze}r~Za4A5XH>PyFjUv#YNI?KfiNf2m#psiO6eg}&Gyaq{{|O!BL_ zXGcydEs8vxm)=C<)n7}{%dHFX+Hj^^vb+*S+5IP0f3#O@ zPt5-QdT};~iKgKJJME~((u_WQ!1^tAbH&L%+}PHb@2UHTIL5pB3F2G8ToC25BSEa= zSaP{}$7TjI8&Nw~<|6gqYM8n7riN}%oZ+i@|2@wb4W~EQxf0rO)X`&LFr?OtP+RmY zUiSKKVmBfBHT>?)+jKXzc7~~;46JMtUSEZ1N~mlKWJxu)mn@1j!vwbE^WTFdgg0a_ zt$sZ{Mp}f~0JGLAN(kypc2@4FG?c=Y-~zFyKfXAS9oPpGXNN5D=6K~9JdjaP!wN=L zPpcL^C%X(3dD7*;H9rm7@IyiV!^JM<@GE|aB{V2@Be)yP$;`-CX}eoJEvK!4$k_hT zCt=Kp9Qf5=2iW(z`21$wH$g||qgo1KYWBWb{x$?QqP)FIq5G}sKkO(h(KjXWpTsVIsCgH`8m;sSb0SZ>^K;(tlZ1|L@s8k zP`Sb0^2?Pc`W>nCx3RKvxoK8)Hl{MKH(5L%A9EnLuuwGl!G0{woW44UAByaIykdrY z!l8OPSvUOe%2_1D+cpR92IfFNYWghjHu9Y;ssJw_qBxP@Twlg=!Ja7|8MF^^5gMOT zmA5o1!f}hR9}2arCci4jiVEiNn9smzOae0UBQgC>3Cl`jy5A)r%xntaaEfw;zucbu z8Oqk(>|}OAE?qt5kq|Pr_$3K(MBBjEq|B* zUSMGB0(Z1<|g_hn()w+?qRcKfVgjypGLOg4*jluS`Nx-!89rf`g{~n zlb(;qf{qrl-7MOLxQQokK`8Rr5)k%NuU}k=M%ljKId_puqL&+ARgRVv7T=DScJT)a29^Am!&se?XaJoH+dJ1gmx(_=f4xY zdNX+Sf-Pq}tj417!gOFJjhT&uf-)DN@-{iVCMoblso<*?EjeWzc{ZZtXDJx)I>9Rn z00sU!Gma{7&Fgrkh9n21jo`}zb6d~6l=vcW40^;fyeF3S!`u*AQqj>*-{i?m!q?o=zpt!o=$|Ty01JZkKA!Si ziB!GvDi&p;IoS~PBtHkw1$idrTQi00=3@O}h#3-pq6XgKnm3+{SiR~ z6r5CMkwChiWMRC-pf@}3P-#Z-=FSl9OXEoM$P#7a#Q;c}z#zx(ZxO51N9t(}3R)3i zcG95Pa4v*~=(7bOvL>Rdw;waU`3lYpkon`00B7L>$nNW?Tb%zdCBa}kA9Cu3k1Ptz~fCQVuec}9boy9A5nsaJj+_F?)F&Nk%gE9&v zkcOYPAq1r(C#~+xn=#Bp?HiZFXTY$xT!ta6w?P(tEq*?b0MX z?mEnmV^7#U$&JbK8Ly&4x3+^lNItKH=_8vMn!eAKk062$noHIb+~;pn9}@_}w_O9{ zBQIc5tJr%Y%F~^Er}g_sVu6gc-nESL{xh0kHNd=wB~BfJEgp_qN{2Z3nl6HIyD}P& z<;aIO%}BvgA>VBlD58D(wyz)EeGTSd5$|xh1=VsMOmwsdIPr&@?zEAT=bK2R@VSV5 zk-!h`cs=TU`w<<( z;aD3t#I^_~JCGj%d06pAmmCbOiWP5ivs=3%#Dxd8ekZJV)Fs5oC^P2yTYw%PBuAWY zTx#(S>(%xhzMh}9w*^q)1*ck`QJ(kq(}$P@L&Jp^WMCb$V_|fvy09SdS0F*2pUr(|9(pcqs3x;Han+;xRS7alpLW2 z+^RGllT*5IHF&`rdT4>h}yhr5o)gJ;Uvuu?vKg53QgL81T;)WLtpXIdHt0^sY^;8!ldBTk zQmh@?Ukq@{J8VWQtO4)zw+2+Kf!1zs{<*$0j3OFA@fjBm?K|)IO*9NTdxg(``@4FW z6WQ=!z9anOSsa+jPd7?_y{w>|)1Y}9v7w$NiCl)=d;1ngi={AL@bY@knE@VQ3E$$# zK$yAneQem7n|c0SJW9+?pJr$yAVUD|ijdN^x67TowtME%29e~SnL2*1@g=LhZTWan zcxd^yI@mm+>>{SU)Hgt94I!Ocv3$FIFm`ZDp(Nah`vh}-4V=jyqyTbOrss0}j5>^N zO~SVPkUF;cai}UbZ+1RmiXSd7UQ<0-~Pm87!h0L zMg3(xf3vT$K?5FS;XyrV%IM8>-X6_3_dJBRt7gn8~my}pyigaP4D-iG+Hp(Rn^RM8Ic{u&`fD)PIhL?JHFOJHv|KLPL*@(XViy zi(@PyT@Jw~OY7E}us(~*Y(iz%vQl~d`s^t%UoZ_=YPtHWZ9X?QAh*(MmiVj;cZ5kc zduIvSuaZWo`3hItsD3;(u-;laC)Hzdh+qDK{83 z2;HUvi&B>sRGygAOw7%45HO@cSBk{quLA0-aEG@pu|Js3YkI2vW*K;Bv(ay07pFFC z){%0ko}(VteLVGle%>CFQiKO5ox>eGbPKVPhO)Qsy~_p-RbTr(%z%sRdWN)cQouXX zoPdO_-3Jv8CPrQxnsESTC(RPp9bD5L1Ti@5?(6y`H4S5l3g)F8^|pp+cC~dMoMq@< z2WKLy$TMvmVq@QIZ5dLh`z=jGPlq-0J8YaU?zO^Y{w_Q}U*^aT8$(`_XrD{B<~cPC ziv*EarC{bdF}s;!<&7osHSGlHFtb2?hWG81O)ys$XfT(^?*dOLV?5-b z4aDJiWk{UAXX?0J&tEAYP=jq^hBRIio3!HV@%X)dKMdSM{&|f;wgeaPZaxT8w=T#u zf6ffQ4FU_vvMV=zcivqp)dQTxdX4iS=wMq9F4Gtcx9tJP%5GxuU>wA1$+&6c=zWPp zA^PGl$6)F3W2;vnBKO46$XS*?Aye-JSgmST2KOmMocq%c!wYs{Ygvpkrq^e5!I>q0 zlv_&{`w#Q9s;kK6&*XNn67X-RntJYOe*QTj(FX2!-_BtU4^LF1v6*w`cHN7zqPr4gDZreFi^!^n@h$u6;Fj>e=QeM7-Iu?CH73m2jFxFf zyj|<=_q9**pMiYI+rt;lgH0c8c+(n-)Ryr0F7SXNcUqjG5F?`Zi7a%7XHS6v#JrH} zeJT)OSL^EjoDuD^K@b9>3(edda`u$u`TBgLs5!m+AID#@dyTiJ&L5v)xfztlSCG&@ znR*yRl0M(aJ*A7D^}3qtz6Zb(*L$@`Z>*$%88v=KcFW`W)h!kZz>a{!wk99)%R)RU zZObFn@QvhHxb+ha61K3U_UeQn9VQ}6q0aKn;Typ5v-O4`JfEbB*}O2|PNf{0O8*I` zi`Mj%$z+m?o8lbCm<`X_#ZLPn%T}dc2#;4f`q02vtVBz^uvEjh;K1E@Z!?S5iwSil znTh6T<=iRBxYYf6;Q8oBg-re9!FX@ZH1%=O&`jk^w8p^>j|rtuyM0zriwL=LOg8Z@ z#|9xFbtB_H_9N?I!HV^n-QP@IL`?BX0&b+;6hW47Fe;HG z1OA<+9;I*=*f_|5L>*5HqE2#iBc$`rL|s6gotklKH!q11&x=E>DsQXl-}AcZTFxZ1 zUirq}di*RbE<}2_4bB>8-&D`4N%9ZIP3t>}z^a^+lMT-1b9s74R;0mvNwWI7N$4N#^vrw zQU2G5b-DBgD7>TL0q_lrWUZ+T$2pmrYCKJHtYbu-anhEc!@e9a2u{-zn-R8y3~J|0 zJU4M#WF*9*@B0I8)|`CcPm-TGALP_`uYQ(O1_}K~+v-+1r7z<;4X!DF)NMb-|B6N>Xpr&HH{R>p9^?Y;Y;p_UaU3LahLdf8g zyt?qzK;P9Io&%`QIBL>4>^{u_7<5aG|D+Ku>kuj*?0fLsHrP)Zr7RXl7U~P3rE=df`we(f0M2m6i%k)`Dek zueA=Uup8h+06v!IzQ>I%&t09Ia`|n<3FM0udOm793bZ?K>UJh*r4QU#oixu^4@7Tt z00?e#I4If|Sk&aL*DF6dBDo)xZyvhj>v91-@+5xYgm%d-9Et+!mYg|p*eg4PV7tq@ zCL!FhV(l^^koBDI0mygrjabTdx^j6gb!rd_cT@9O?1~ z>WXo>Tn1i6JQj5~*E4uJgGCm17fGG0dG{tL+~>&eu~)g;m;^+PkOYjciO7RT-CcX4 zuKtxSk_u4&m!>LhbRi9$XB8vCs`g||6K=GQBu#?6caX4Fhh7qGRuv|+>(@rd`(xFQ z2i_lb4=6{@lQ+>K_L(gLY_G2Ger{8E4v3h@63uqlTRSl}T=Q#@?7^&o?b)iGpy;wT^w%DXz7+ z(rviNkhBz=eGObdq*D-O?m~aL;mrPeZ)!Xm-n;T)nHt9HnsrnYIzZxyd~wa*L2n@p z5G}*4{d9PK*8Sg7W4F?5vtw+A!S(GcT%S4qU0?SO6bh#?$^P_v&->m`+kq%L0lo`6 zNA#o~2WNwAmtM-GKek~3t!!Ipjhj@ z0jpl|avmT5*W1hQTLBUkSf=vvaV$a1c@fTS6VjN=Wbi_q`r@^0-Zd=7H_z}KTREHk zaf{^#gthYmUK;4agDi6eife(0nd-*R&sy;23v>g7`yGS9z6wPJ)g%Ufsp&iG8gxIG zvnay6lty4_R{~apPP^>r3u>;R*?5^OKWRmt;0Hyh*7Vw1)@8kCAngNCRXYau_egZ= zPds2>Q*RfR|EcI!LpG{XX}-%PXK=0U%`qV!4p}X0#m8s~n1BG; zA%WX}j84PY3)VuY{i=NXouA3?X~*}x33@|Eie-O#K|-kRRpow!IeK-`2;p$#=)iie z-%E6V-wXU5LlH#!TtccnlN=A~$-=)VwV`2V$9i8k#B4=;btORwI3uBv#SkZ0F<4c# zy)4no<2FCOH|kS*|b5O}pc4JAW=|4}RP@A2-Dmv>bl$kttsfb=Uf6 zfMRt%Ds#MDkQ>Jf>v^8yYy%m6#g&k>w7(zcS3Dsi$rexjc`D<|rC~_TO4$Q7PafS4 ziH3y7wI^VLRTo;|p5wuwNwtZTA(rnHV#@aJZI&fdf;WsP#5?ox{b4x4bzcpMpA;02 zwQo|d4!*YHk1wA2NZr+Dy<>cAKrE&(H}8$#b$wqWSMxo}KI^tWEuAo~{Y!e(?weLt zZ#@_sv<~E}ngp{yVTb8&FTcmUqXA;RM=S}na2dIqZ$wIWx6yr|$E|m3kNZZjKmuPo zL>8X~Lo6SfD+3w)d!B%+0EwR;OuAcZw6eq^lCJ1|T3HSUvhW6y^jdCR@@e) zNvpDG&1g-PCUG=23C?0aOx@1iZ4CZu>&|kh=>0do1Z6iR9vIte|8UR0z?neU{PpMk zwJX}*n~e4den%_6lc;2(Jrto5hkfM7&-v?dR0H_vsgqt$!-G+^BHh-?Hdde593tM) zuobFT{jkjkl#Hi+?Oke*4;{fVKm~~l9^MnpMV1P1fKR)IUf2A32D`gpt&!?Gi0QAC zNeG5Q{LJ|Qvf!$6b%6JL#b|r~k&2MkFD@j^j9PN{v+@g0^+inT+CDz`Hxvc0TN;Sl z%js`+p5^ibGPE);GH!X5pfYaLH{-3f)$w(@14@8OgPeBElOIn@6us|E8h_!IMeCEA z-43_*<4HB%v7Zu=E5H~x-?fI^GSF@OQW&!JXEZn4fO;x&KfF+7sJkPG{VpbD?lmrR zh7+R8p+!V6RDejy$kSc^NsoDfe|4&t>#he4HQ3$oO&Z}N(WIy1F5Sv+c9|YbKJcFn zura!$gY%90Nv$B%XJ_{d>4%R@O#gL@D+Zf+;d~|p+^lK zGsWDG!aI;|ugB+Xn!_Y2*Vx=%q5k&rX)8#)`R&$oSPo9v+Alcki`Ilbr#@=C+i4Gi zY99246Swt`uH*o`>OvuRjUMf8!2^Wf?Ep(byAtr)F%6~kgB2}-un(gqn8C;AC6vlPwRaRjcG$k1rmsF<69l}w>L67Pl^?Sb8H#6 zrzH)LqZ7!k1mnp+AIL@NE^pMROKEdUxTo8yN1zLO`fUeDR-_62jbJ(L+=i3STvnK`$Z)5V0R#oymr zOKOOn0Wwc{&BLcGa-Vg9z*$wy9oY80zm$8pUCC$}9a$&YSAy!!KfM~2dREK~FrtVs zB8V@!vJ~rHtd!d8ymwIZ{b_5OF5Fh%z(+L8~-7Ln#5D}MZ#RspN z@+-3q1~`6mxR``I&M1$bB~Z=;_Hmg*X&wnNu7UiGKa39N@&hdmK6tbd-L#!MFWEVx z#VPHF31rNe5*Wd7qkfWNX%9zW-~RTItAE!X+f-bI^l*Qi-M+T`-Ojy@(~9o^Xxbe&IoegOpnM0=fu}th4-Lj7V|TX!1gU zS1NRW&)8k@rmMTlVA&Qw9YnYnd4EfcRUu>???)WUixC{lh{Lci?YhEnwuS6F$nH!C5I4S zTQFDp>qlMp?0&$WJ6JWX4%sd~p~yy!%xymv>J-?pS{^B0;+9LO8-&yZ=x;$BpWWR> z7=6?zmtig}+3Zes3fp$h&t%k{8iFV7aJT#tcpvG%>Td9em^fri^SAEZ^j4pcxqWM1 z&NWr$&E>lGg%$1h-i8;x4Ekjq_RR{1i10CRaE;s5&ED4+|0{a0=VVYT*CEZdVv32m z8H((@hzB`jgw3GuS|nhw`T4L*;|5c#kC%1g)ZcU@GrjJd|6bcyQ$E8^KBL;rwl#an z?j!3FcPs+3zs`e_k=|pf1cYT}bh9n=EOWiqB$=iy0PD+G440hf1Uyrpll7dQ zl$(VxGc2jMb4%g*#LVs;rjB`J=IA%e0J6fhCitR$OZj6<2S|I<*xT?98GNaz5VUYkiX0{rGMG;DcK3J7Zvg9Z^-Rd%+O7L29_;VWhs6Lb zy5z402M2)4?3|vOBsBfRLQOe5m*TIMRo7b9&-NfF8^`ODI+Nl4t(B1l41Yj;ICv4t zYcB~V3jCkHQQydC+mC8b?#Jx~RPxP%Fqw<@^$?56!`s+9m9Kl6ZSKcgv~2R$Ou>+V zOz5nyYhU~BqW)|sCc|kzR1oY!c!sxG{`R2VROKp~;9>K3ACY-)k+4%=KStQ!rJ&LR zdCT|YeP#~ExZ{`8kZmrRS1%7}i2Jn{aMoTREsUSao1`*6O|`iZd=bQHd$5*&dq8w^ z?$iAAK>-w(bCo{@)SGvE)naq05`l3KXRwcWq&LEM8sOrjfm7{6+Vs7Yu~8bs_KQ%I zDH6{M_72=utozH#N4!tKLfNzfU*-6w@Rw#x8P+wWDa(+)GU<7ogXuED6BJ=-!PmR2 z@0lW6O?HyfLKIYqr$2)N!FIoCR9O9i?+fp4v$3BZYj=XgQR_W{`zv0NGuBOyB5LcPi6&_%UZ zRouehKv)d@uMb76+}gi)S>3~<^)LM$>sDAPJ*sp%msMc7ekK>K0=Edup=F20V^Pz8OdsbS1arLM!TKQ z8S*iu;I@23))4LOjaM;zH;$b2a+oCdSVxfC1|n4qC~^L3@l;>V#)*8`Nc8EEh{AV> zFAxSV8+N$&m#*K*_cbr?t3H4on%xg2SNw+V^Xg;p zoDEXGy*#MH@azsJ(I$|Tvg8xWSB=fpka<6ejy7&f)VcHNBU*3!QR}@We`HQ82RkQ~ zpHSXkI$>#8TaXMzB@{osjkgUU1~W@;BWlT3Eqw3W@S@l=%?y+3_L$B&O08k7mx5FI zuzOeOq{KB4MGPOxa?>)c0_%LNku-1i%f@QCRE%`e@_BA%*Lisq$H%qa>7_*PvAGTb zcaNorLvGL&vsYV}DqkhdU5C92_a$`)Rb!e5XCLGF(?5=lGkXTB(J6f5Rkk=^kAL5p z<@PHbq~x&f0X_jf*4G{E1H&PH-nhRkD+0f3qd$fS*Va@Q%nq=m{$bNk_@aK(_4%G5 zeig_!mz?{4pPxCxLx$ZR^X4-TI5wNBrKiGY_Zw?be(^XvuK*0z&oN5fLy^5pVaZ-y zuRjvrGw`~~hk280m9RFp*atcS^8&~GTf2HO-HA8s1Bk?lGRa#8jyY^8Po_5I_x|yR zhb%3UG8u2K^5nAXxQ9}c;<05x36Cvqm2s_SGw=w&L7Vw;MTh53HvCV?lIVDq{`;J9 zLoY2N0^(Z~aW2xp8tAGZrhm2K7kWE8uVKRz-@*TVl8?iBFFt>3J^U5tm>5FQ-*bbm zE<54^e)#!wa*(0YU_OxLOwGQ;2t6@he1I{*?*@?z-A65lgK3uG+Z_~6)go3|>vq*` zFYDO%E3u#HMw|}ZriHjdgc!;#)SCy|ym2~ulsxYAanCMUYl=Pg-p{#DU|0Wyd8V7k z52h4u6Q1$3K4YiwLXtM=r=TMM^JSTg%G}G}11>PKpV`&Y7Mtg>vd;Sdy#FSwxG#;^=P_n@w?~_X4-EM6vGTa9?KjcKoK$cQ>-ylDZGa)IXC?@s z5pDkHem{51lzf8l;y;09$^_)4Ro<+m8QMZwudt+4{*dj!; z5DzaWs4+SI$nw9nCJ=V7I}G?R^o~}>b9?FLeEeA7TR~iZ3jFh~?3%Z%bBo?ET1FQS zJA4d9vewbX*)nhZ9nNj}d;?%`vLWEU*T5Up(?c{Zm@=X35loIg^^yG~MBdrJo8&<% znS3u!41FR^stpjbqC-Cn%MzjgGT-8^dN@g2~xe}hUeJK=x?Pgd=+nqtz2+X(4|q&EsfT1@+&%FT*y^IC#IFw%P^#kO2B4 zXRMmwMt__sGI>YIzOM8sQ0fSjZ0w!D>yc8Y{0@cA;P?AE5bQ7h^Xn{zgLsm-126mx z{qtdU<>r!W%?!UmzkbmwZFOPHpH2_XgS!Z3ikI?1mQ1S?&b`1^?O!8ne|WyaHG~%V z7|-f@xqqk?raF?9cq5 zRh@S8dW6FlPJfSzgt3Ab%1>T47;6c3Sfet$V_W_v*eZ{3Os*XUzt9ZaykiNaDrrQ< zv$hp09T$2!{%Kk5o9tzg+LVXi;ayBl!Ilv-WUv478rL6TnRFKlj?p5cX@#1S^{SxRP|B=3SwS)_*B{u(HhQReC`7I zw0gZF9(3O$I`ZLP%G5mdtD&MZ>o0~4QRYYHiGT3O*sf8GyT{8pk0Cx~UF(rEMa7Vx zJ<)~@IQ{CX1q%-mcK}TmttTDq)aQD`wRVBxjOxU)Izx(Lq^`ja9SfaMuGwB?oR?!) zJS7fJJ-FZJ)eL^DPg{)78L3F``FdQG5aXr#zjMCIb>>(xXU&f1uAFhSyZ5zzkz+D< zF{b#f_yvMSNQGnno%5>GP~hQ`&U;IR{Fc4!YxI)$3caiBZpb6u#$Jn1anu2?^TKVW zRm%=Mc-2%?6oN6g-zYio?JWV%T|HqwA@`@4j9~_>bfRFsr@TjOPK@3geHsrFIP?A8 zqMqH<4Fbz>uVL%=JdVh32+sVmcfOH9dXM9Mq%mbj4wBDH)U-G9&&(vxqk!$s$?)20 zQ(1GOK?J8x37Fyf;~L~EE4!0ZnA@qE_%QUi+pfg|sK3Re&Dl4Hfbl*qQ`CN6; zF}3fD|9d_lkAllkpQ9&e3Qy#lKG;K5s(r!Ch zg~aWdPE_9Q0-vTm`9(xE;u9wIM_AG8qE1f1K7`}?p0D%uxA8@aW5C(^tKSujP9`3v zvro$ZsDJzYq|TTbkC%2oJJ*DN{e7meYGJi3h8MN^1Zg+b&gwzzh-{vYgPJK6Q$pqT< zXx}&0clsorK;O*cq%zWQ(qz) z^g+$8Rj^=eDdVDWc70%5Ge3w<{>>M9s1)-QfWC^oaayL&Vd!#r#)+ClBi_xiucr2t zhv=q*=+0~Ib$QL*fGzU+ccz$Ab!(%N`n+$tX&pBE{s5dcis=?(ri=FZ!2rQ;$SX`1 z*IJj&K-`8ajInx(8&SUTDV&rO)ads)+o<4==k3(o4g{@X42Yiab7qM4IXaq!IFE9t zfqIX0beyCBC(}IL;B6rboXLUhqub(&BouTF}>E83xWin*Vo&Fy*}UZ zSD5Ka%|?&4S7$6GCq2ve$Fd>(bX({c&Yq{AGD}eJt!@9{7ZX>FTv0a%+GQU2ec!|W zq>qEGChqDTC2Vi7zv-VL%b-bp8*{US&RsGzpZ>wnf799=WYWuZDUs2Gl-7A;zYoTS zwJ(UlI3jA~6j=w`I|-2_gh`Ytzx(a>Rqbca@l4uB=j&_Vbd!@EJW(GhShB);FXGMm zqXM0$G6`p#CN<+lC=N=I?6(17MB`|S^IiN!@V$o@`@md@TaZJsz}GS3Ti)a!FTWx+ zmkyxHdR?u@_q4R{7+n(|D%0lL2M{;fH81@QP)?3*B7G0XLbJE!U3IB`nBJxMc@Ri& zHT&12kcQtqvQj?u*CE?gF=*X|cOX3Ir#s|$_5QX>6vmc~4`8J_YLcRk5KXtg}pg8la-Nne^=O%?FMiWYn z>}bH9@c95v{f!Qj*?6Dil3tH$iu7;U=TUCwS2*4!gYki>(;si) z{Jm%rD#NTY`Cmod6*z30Xn9)WDi{d}K7n7n%EJsi%vkZT?^!q+!p4u&`+>T}elt}e z+A{6C`jk>!m*u*&tz<2PhYpJC<3azc(RcIv?w_9$`jMyk+c3dZgMsEf`?S;YgsF-s zdX-fU(zx&+ng81xfO*X)q_iQI1*4m6_C^Dg;gW>GyT>z%P}sy#AdFvrJ~M zv{FaG?`V5A*XLC&G6Zx2H@}JS@;UWzp`GY>AGalX8|(5$^-HO(ZT!S$Ue=>=t*wqO z40n>)-Bhf1Nb6_>dqu(g9{co;Q!+_9|ETlsI+ptW7wCa?Jsz>gp==1vj(k_03NweP zn(xVW`-fAM=W`m`51;U+PI>m2L*RSb^?O0X(+qal)+i4 zQ6i{#!y<$S?W06pfS-T=floGgh$>0zAa4Ke7y6(2Soz07_~ag~^RSDXPT64sAqNTJ z)avO8c@FOaSM8)KIOn?hFbrT*^`9-s<=k!x8lMlgLKtJQ`i`s1_%-%YC z&cPx@4e~hUrpraGzArxmwD0^;=|aYSiP;E4F3fb#xw;dO;jz6Pin$YUI9zNj%sLt* z;^iXRVH?^E5L7`*_W!N1UGmu|z6Zv`c(Ru-yX$rY6ZWpcnEvuI6vc3SdUz-J4*;LScDfsdRhud1`Ay@9qUnbf-*T`i{)W@9l zG$;=ma8Sobx}GHx-b{(_>L6JK^YYO(0yM!sbXwIpRm)oB zq<7=KL zt)J|R07h{-J&{q29`L{G`oaM`JH@4qpEwJ+}{LLhSi8mMpZ#=8s;iOm8Rlnk-Z7g)W~&Qpaf+9f!~1j%A@zf=*k8TXa0xVh zow2_pU5oiyi`o|1kZ$8DE$BJTtrqqV8|&m;qhs}wEY~7X=*>f zCQry2^e%uxCe{zzw;805CV!b>=OHyUZ~5cp<)7!^EU>_kpB7=)SF}N zBCqRb8IIQ=Fg>_EYkKq_er=0?*pYUDFCFP0*nRk&BVMoaXuV&~{)x61ER1wl$1j?D zoObQMwWz~#FA|S;0@MMKotdjPt)0NTSnA)CfliVYBu_SX&(-gnIN| z&##V-x4e48{7wcqa4lIGjRAM_AgCOV@1^0F)tem5qte>v(Q^x%sSS+F4)>SO;Rbx& zec8`UXXBbf6+sT*cl{A`*EMNA!sTA1^Y{^&WI>+|P5Szx?DIz8ixYfz4ulTfY>5Lv|$}1fWb-(wE(|}`dlSI&G~ud=H3)2{(S`ggdz;a zJcBHxEBMW*Lk}xf>0LB{3)hyNekh}Pl~60sfKShh;NDf1^Tg-jtK;(Fmh5l8+f8)| zFyT@WN*@o!knyUut3AY-jGkUxVF%U?m#HhzgE*+^l~eIFF5fNhcjRl=xo^zMxLtHT zo`e)Sp5trZ8zH8$>~c8$%`}{&Lcod1EA)F;9$=J+_puV}*L^3qd0aBG20_)fKZ&>V zlKnd)zp~jE%jMlji+<{)8#QN+BfN~+Uvme8-w%Am*Iu9jf3W-DEe-hpC`JYYB@2xP5$@1Ti#Ya)zchUGbsnRP<@>@b-R!V7pxJ@v1E) zp&CBMO8atzOWR+TDw=L+nMw427`9&yeen}_cjJLzFTBS)^t4G4deDI?k|gLsz`$=P zO1`iFLr?3TFZYd-osoe1ISx|9AF#O$Z|FMCDU~b_WUg` zohi{%eDJbTV1H)*%FY^$^6Z5U_mpic! z4K}v=6<5HbIxB<%iUo*Vi>(kS3Egvbkgptt0_yYB4lWFsm(v@rTz~to{0^FWOjQkH zH8c3DQRMWIvDe(43kt%K<|<@&())}*4L$0=HRx#OsOFut>(I<$rV;~GfagZcFxoSA z1Z*w2x|}eg|L;4p>!Y@O@X2ilY@mFdeNK;ZzU)i;$<;*a>LoTbCb#-{O-a~1RRB&9@?(Dk4; z(^UV?hV^!Cn=Gk9o2Ha~P?tsU9`K%r)5~74Ph1P^vM{?YMed?*D&;T56)-+4rx^I;VgGv*fAtS~cqp+t^*)ocX~0rr^|Cl3XN0iA&!#evBJtqL zva0vM4S{24-|{-r_r}<2zu_B`WzlQ*@7L0=CH9+Rza@mpnBL^-HGus_b@WatE5G>Z zO(#vS&yU7>G}hk`dlL^mi|M%VkF%3a;|$rqnoQmL8!!}Xu;&m%TNdlRb&7N4Jp?}a zO>lb-yl}&Ab=YiLf3>m!^NkFWO7cKKd5edQ{>|}WyW2L0kJiC+ND3sYx!;(7>+fsx zFQ+(C6l|wq!3SQ#g0piw>wPX};qs!BWVcUP_ zrMkUS?u}E%J~w*3mMXHkzD8b(? zq9D0!A%rV%75tV`ffYH1A{Sn{L90~Z=bxHLsf_6Um}xsnpeMTVd_ln-FYz6XFFhGo|{c> zgnp{zA_DPh z=CA)qWhhy{G)KxX?3%=J5>^jqz}^XO*3=$e&(Ab4dG4bW|GHtr|zbq!u3iB(@? zCzs?hEkS?>t`R*rF!}gw7g^nWBtKRYz}I6s4p+?BE8`1J-i|CyZulp<_!gb(9#`*DM=c9nyra?!ANZsbR6{balrv3_$Z8&UC45U;E5++U3$P?AgseuW!c& zzDLlx<36R-q9is>^GlV-qrGAuMdjl?MGK!U+2_do?I<7@$oM}3pxM^I~^*EC4*mb9FE5F~e zgBbMP#iKaoN$v5TJutaSl^3>3X{ot$&hEUY+Y!Ek1)2=NbR2ko*KbDH@kcN$`)BTw0rQ3hfgQ&pS!Kn zal2Csh2p16+Z!?j-7dKi+1n9dsa`(a4~cRp&~I1wQ!pG78lm;|XzVz=-iBCpZ6o4= zJyL5hNR|67_ePkl*TD|F4=-AA5wb#G1inm&lyokODG!3^9>YcSxR=P`t`*LdVWNT% zsIcYdO9Db}LpJI|T;26{0L7yOrar7~gK6hXYbKo`vZ9Lh#k& zBE#~l_Zwmix`-HH?g4t==w76c1i*)smVhcyN!0y*AT^W@v8`9PYDbVsbe*<*CxQ=pl0bhtxbPu(g-GIy?ijnBlwLd zF0FMTzk{qWy$5fq9L|Q>!zDiq9BaTVfP$+PclX=ijj{5Ue+6W?gNIk3Mwl+kW z>Nwu79>Eq-39pBuDIa1z9SG~GSZAZ?+K53iwQ5lK-4vS4$STS&`yZY;l2zrIp`a4jE0SNL&$cI zq>J^+W<+##L~VV=cZ#ACi|uXJ8z)eH5?{IER&HsRp>DkA7n_hH^KYO zeco2EA@6p1cM2PF@n{okcr%sRl0rgj8~bZ}y-2 z%Jl(&>08IRftMh!IX{L>Fun_|M;D>XusQcjDqI*Cl4uh3gt63|Tv)M`$GQRWn z1;*i^6$xYph(HecfOn^mPIO=gPUr4);PgC)u+pB&peFeQ9JP)}pL()OA?5l5e^=Q# z=)ugZ$?Opz2Q9!pt(ZP;MfMWeF8qJh^hY6n;7du_L1rzrd$8+=>8~nttetcZTg8jr zknDj4bVW(`sm*f4T}dxN&DyDDkAOxXowofVlTjjlW-oZOv~h%>1+Wk=v^~Jc;%mF> z`X9M)>5scdzHp zjBwR()g@a=s3_~F&p*e>;!!Dp-26X^G;S3c&-|8O& z46Wg7rP9JyFSI5VDhWYsd7=Y6-e^XA)e@7_?^ZL?F`QcJJH5S4ZxIpy>d+E5 z;;oA0_AXU@gYGV0I*IQCKc@-F70#vpHf&*A{ex^V?@vpSiVUcww6c>sFGqpPT*)SZ z!|H`T?lcf^ciFjd=dc>vJoEv~2x33jXace2c$e&vfT95T$A;LFmom97t`x_KqRJn) zGP?r+W3V>+jtfU3YjfF~%ck67`5@O#AME3vPqAYUcl%-oCV{vIYkSx+V&(GZ-a-u5 z`OTu@Kj^f1)P9;$?`fNd)zkQauN`d!a>u^F2KIw^?N~f-w*c&r?Y4I_5ooXi5QZMs zeCaspaL!}(WX|vHMj*H89Qgx0&UBs=5zx2CaL*~F<+adK%#~GCUV2dTH!{aTh%-Hi zNOgR?6wJW5d8eK_4yK|h(tY6MRIC&Lm+Ngo*0xg$Di<)6*=+2&)(#4V=AqkH^7Hi= zkTis7Ki6#^on}Ifqf}IzbFp-y=uP>vTk=l!R6@M^BY%(wa79RpO8xZ>xxEpt20fLH zJ!lm+lC2Juq%aHKI6P{=Fzw`I$=j)+4N|*)UO9&}Br14Qy8#@#lt2KTYK$3VC-tTn z>4)O=z54!sy2T%DWXrvNEhQIg(PqXMbxV~F;a!nFu?n1BZ>yFT{l#v*d4Xwh0{^=H zad`=QW=+f->{j|c?*{CPFld#%en&bIHswt@aJnAc6Kg@7!H@I%Yrr}ctMOnlFJxul z?z!N%fxTlh1Kcsivk%2&ViSJwfZf|qw}YqAgJZ$B7fc1~Kt#GIxae+6<>TCU459E| zp_PFr$|-^h)z4vsdY(Ra^FRyEL<(!cV|f0YM_@ETvM`!Qo(BAy`!m46ptRB5Ex<<02Z`Mr9KisL-63$j{&B6aSB+--X{Eg@ptlRD z4os2AE*>%@-0#+Ez0F()A#VBu_=iKH08@>%An!gBdIPu~c=pP*C6`3>*8~8!mBe$* zH`r?d$Ovw*!F+eAepKEG!8oE7YzJbQkN{T!;I84`0lPIQ<4Y$8+cf~R=dm>%y8GgJ z`5eJDjyLkDcJd6pCShyl#r&fV&PE6wRIUB!5vlS%*>3z8pUW@GA8u z=1#BOP6GEIkjHTUJchihBdT}Z&GfmD@$N`lp?Gk;CwK-x*5BC&l05dYEj)>ZJ4xJ6 z>6~0WsGY(hA2L_PyH;Fl;q0`Daou;fgPUuv+IlC(3lQHWqLD~~$>9*xl~3;XlD%*y zAi3(Dcm{xMl%C+v<1t{aB|PP{aWp%sz_T^%--Z`@z73lQ$e5Go*m5^x`9W6k1GDKU zcTuS?oonj~#>^StDYFR<)>4u<3|cE|mW;*S*MS}%Ai6`^0p-MJFa$dG95ZYE%V z(>k1ko9#d^0be}adG^zpVxoJrr*s0j{&Ct{+g5lHvC0JPzFIw! zPusYsM+c#!y{J%JZ^6E{xfX5#hrC8|!=uc8QagwF>!;pk&VM8T>hGkKjs*j-CWvf% zw&KV2rK8^YiM#6C5)lwj>}J$8D;9!E;CwT*3H{c^IW+rO{-{?(G%5H62Lu|RY)cbr9>rg&)`0fs`ZbWw(2e{CObf{Df;;NQ~CvD7Y>3Y#Kw`UsNz7V zCrU@a8T71`ONZq~s3yALCvb>3#D}|^CmZ?pK|tJwaAT9~+9DXNU@rzsb%b$lu@PoOXNK%+*iEYhqURq28n*<@ZflFkl*vee*ZYg_xCoJcC|G- z*jjR@g^jQ~TwQ8(1w;`{m%u+Zn_aP-Svp)xA?(b4c|+XTOc!aG0KnS4K>SL0egPC^ zKi%|q*Ps*GufV2jZP4ZGiLF4-cK|GN%y-zYd(LwyxU5t>6&%lFzCpsb1^Xg|9Sv{D z>+*hIIVg!6OLEMAbc{0v>9FA!li56tr1Pm_K}z*gh`HD7D*Odx(0k36XAf;+yr7H_ zcV#%$Y(|@Ttc`$guPY&S1;!sZ^U6Q12Ci z%h`ujwa`q-p*ZdZet!u}=mh6WoF@`|=;FK(mZK37PC@k)&_!~ddgc}N0_go zxK;{g4uVTNwPZzrjt;3$5k(uau~cuf0VwrCI2eukPRsGI+&Mjtq%#}mCp(2)qO0EJ z;ghhm>Cc}RB9OsIduXG}<0^>I7^J#>>BKeIIXI~`bD4gBV_nXYo`W7#?b4p_1k+OXoer9j)y*_FWzD(WraFRX#b1?dH}z zMa1li7mnH8q8i5WF?M)@5f7Z~ZFe9iIND9D?RWs?nF9O5-F`3AJJ3 zozAXnj}C^e${ z3C5!jH(PD@#;GXrOGkxGu?8{P5+-#f>KcS|umy2nv|$9*-X_A&Yhj@8<>mFPY3N-Y$3!*~a7&{f$B|T3p*ZJ_Q1l zJ6%N_3{{5S4z&_%5r4e7b^@d}*z5+9{9eFN*zqJu32BNjl?~2018x{N)^w zJpG&dy-0JXv5T+}MRB_asKNYUx13#%l+G^@UwZ2TL7wX;vDU$9J=x25FI=iG8tjo; zM;94P|D{4}FI-OU?^l)Hz;jT{@w^AoU))NVzBU%d!4@+XOOU#Vu>74Ve4Zmj6ZOP)URA8z@=P1uF=xp3Os=y`V$cguCx-ritcggaU#4h$LGA7Q7o28{QM zz3fS#vL=@fPXebWErfB;<=n9C$GxTyDP6cv6L93(g%P#rk1VD72M59P2ESE}QT}44 zD|@pSCj>7SXh>yP)9$5qyb4Ul5}kuiE*JC`HzU36?#^c7pfh*#nU8pKn%FBF2bE5UcG$)oh^du;$D#kz7#8iufezd&&V@~ z(@sRVfX76ox7P+J-d?-68#s4W+Jitey>S>06k~zyn8)3%xwA*<25|C(M!g~-=BXSl z_`#e!Jz#wxfKEQRhOw;ywqhxBSUilM7WaTRQg=6Na0l7ouR)-ax!$F;D}12^qTuVQ4^lKJ34H*vlL-v=F2K!K*qQ*G9tc?jxk< z!0+~NOYM>*Mt1hZ%+?*vCrFA?&^73J6) zPWr=ZJiy<(^-OPH-opGxM5i_a()zRg_FxZ~83-Fx3Pt_lij+?S`xWLHJ16VsO8{}+ z?u0zR>Pq={F3Kq?`&1CZN4bK(>u!cld_I@3KJWuS$DVF+X5CJpWA5+5{K}X%bpKBSx-d*P~rxB_;;bO+!40-4^smfUlbj72ilg@Upd*m$@2QVsH+vyDU(!ipM7dATp zkAkO1H~>?)L@Va+w;T1OlE`j060K0Oa?x9oPdD-x-4?8RJP41Oa>v6v!A>lD$Op3_ zk2_J?t}2JwJuGtsoD*WFXp;}L$RcRDaM#vaF*o>vf;|MmALCKTNdw0%^yQ%M3z6T3 zSO~#g^~h5j@XK^joqb< zqDM~TI!g*9NQuO;S5|=H3>&$N@{XV=r47W{MNB8~o#4qpiR9(|TA-EPgzaMfz|_x0 znyu5Ee*ge&1im>R9Co_!oe|`1#BV$BZvg>jM^R1=yq-P}gRHdBKG-RiWnjkb6+@{; zyc}&E3sSY)3wRGI2_>1^0W*i6@9w9zn)N_!H@hcx1DXBMMbInc;+%}*kYyQ2H3*TWjTIscc53(NO%lq9m zml7zavM1hpbidU|7Q*~`=KN^uxVz)9NVgj&fFLb(+d$ z{7$E`ApU)nQdx}s(B-pFR9>qrRql%a>=StMWaYgbL^iY*CH@hT^40<=|JNx0UGbN- zOstH>_!FJHV9)%2jbbVk`YAwO1|e)t^ixUA+4~Fbz6pfLSEX+>E+^ zZ)ViJJY}ejUKvhH>Cl?#^V`yCw0CLqyKao%(&s+4vSRF|T%FGgb!=7GI;0}D5oy5H ztIe9st*m^0P9NGE;0SE!?}3wL0%|Vn{Vrz z_e1Uh>*u#YEWRsz`EAeI!#R#CJ*W#Mg)t58!7|4f2Yp%Qz&-H0B=Lo}ALu-2bmegm z&3E8C5A_0Wm@!EiZ&Z^(QUAampP?n8-oh*k*4$Qq zqsNZG^QCz@gYr#%`=i6LdaT8z#5~y2LAKpO7)Tt2xkj~*U9w052^@2w&7-#tdu^wU z11yydRwhW?d~<%4!+xs%qOF?lF2<1@NwEuen$`1;u#CqIoU4n)Djm*o*(kJ{>USAu zb6EjpGD}}Z{Y~?b{FK@(b2Az0Pr$kUvBrOmL#nZhiofw*b1N#Dxf#p+?U8KLH_C53 z{hZ$UdYx>e+?i2dn*LZg3kLBB1dV9>@vHY?h5oCdgXr5KcMV zR54JGn%!ui_y$pRSIph08|eoB>t;7vT4tQUhb{g14fvFD^EEnWVFj z5*~W(50{f8zf+5g>KRopUY{fHdc8(pviVp>M^0iw)i}XrS8=h? z4sqi>r=IFeNr+Mb6M|g10}%&~YGd6$&&fE-$tAdIsz)z&uCkoER_BOkHH8l3Fb1QX zA0LZ(CTZ;<(o#jCb0sEh6^xREt8ziA=2h|PdIzOt42(Bcx z8tnH7iPfgso*q9i`LBK^GzQFiO6-j+fQre1UL5aeeX=>dGKy#O;V+GpJDop$^Te0| zI#G;2eViR5uNYhlyPcd4Yh5pO{6IW>aeR&#O?7x>Z|YZO*3?f;otKvOUL&znqa8%m zV;%F-@WT%C-%_{ZYp2>QvuS+w7+vh}%HG94IkPVQ^tD#3rK#76Ay@1nRW2rw*$x|Z|^YN7O7labi85l}`LYRJ*;R=rf3qiNmA%8ma2fa^RG6o=I_-7XQx3Ds_^NI;4rrVhAnGnN4{&ZjaT(X*To8(x&Yh zmH0TVdd@z*E!2&^ajM0**H66K{`klgntnw4eUr!NbBmo!zw7F?XQ6yjs>!XGq!Ilu zXV!{45P5S87J{`04z!711V`1)I)?A@tm&sK`f9Ln^~GKBA6%P6F@! zpV)Y=>i73+e9Tg%@yLPd$vnccroL+eUo=}cDV0O*<}Q4d`JJViw1thSC4M9%lM;;W z2j*5ocV+vgg#$J{YzWwKWEciZxc>^0#B%b=9KF*SI@6aaFl@pepl^ff?bcqTUag)_ zY0c@$v6ZmVClkG`nNVmM&KVVm;rQc`N$4~g9MWvhrnf9jnpKH6Zj)t#f6zL3=8U#I zb|`=P6#he#Lt3V=p?}J5V?obtS}nVnJ*aBZl`>78)D*WyVAL^IBQULp-tro@U$;Fv zYN2;CvpP$U8Vi95u0Haq$rq1lI>SHu9z$bfSqg^EaQJh(@JA51x}b3L5AwhYlLrm_ zdAt7*rhX6d)$#%c-=moiGNVWK6n4`PMS`>Qk_2OE+!z#G5_AomCf_7>JwK9r9`_06 z$p9;@`asoc+nIa;rJ`&}Kz2A?Fu7^9iJgIXpm7s=-Qf0fW(zF*&H5BPWFFl}JDDyB zvq&G8Z_;f2gmJS>_90yvp=J7s?>&Fl7(~4x?8JBPnuB2JmuqL4+-c8`46EKRW6$kP z|KiM=9-Y}dGAJC*u1tr{o4#vVM%l7d&0Q<>q`7O^=j<|P*|ao^Wf(M*;WAdMby1IU zDVYA+6D-6HA-2VcmA7X|~R`sz>TfW9_iLDu>lQNk}$r zuX^z}3^r$30OnrxO_kF#LtkcHH=md{o#jX##q5qJ?LM^OKnaJt$;fVZR@L`AaJIMJ zUZ^hW#`QUKnkwg@=#71HY+`uvW_s_hdq6&-i8^GHE2&^u6enKQRVLuafOWFHar` zvtBsW7!Hn3V|F>YF=IQ7rYjhGZg1%K&8(qw<{Yv#%KCJ21J>;;?fMf>AH+v5z}_W4 zGP5qZ!f9 z5yyM?dEF1lTo~qh8h%6*ZLZjKl_ubX{vNj9oqTd|S?-}*3C@;7%q}*rVyUQ&Yzq8O^)Jy0;z$NDm_p;|rXJ?CVH5o=vvq=+p%t<5ttW&3(chk=>{GWO1 zApJ7P99C5`PTi8jG-$ZP(wis4q4ogGX=`LgSZ;Ffqw@7xr~a@vGdYrXGJ_xphwuF@ zqhWf*>^^r_J0Lr@!l-mOF_}YS%uVPj{iB5-;<;nX)3eP~h`7R&zuhuPuX}uxka1MQ z6mmPpbhcQcunr@|;3ubKwG7A9q-a}tq_Zsp^^{74K2-Woqu(uhK3IR%94x(Z zHdu3}>fh1^>r)4Erw@gtI?GUe%aAI*jQ*O;_(^5ph*a@IcU~YfF2`1U+(4?J^9Qzc z?BrvB6_XR$$Mr`ZozAa}(P{Ga@7MXdezYLJxmoVsc3cM?5yR{h9T;QX+~~ipXtIyO zk4+tg$=-H9OhcjKC0M47$?@L{cQt)|v+qXr;(tyH`>y!2^yfyWwI5w}s?(eT-|9V8 zleK-T$uN4FvC&_C%z^%T+Nsmcf&MOYYbO~o{0tW!w5uF8`fF|H|NY1;u}^ua_g;DjS1no3T$RW9i>&4a8fp$tUH7RhEf6Y zs2LPP=UsIidOhBwTJQT)@93F2gHcd5b~_lU((srGJ86=RtX-_>dz`e*vO|0R>9IIa8auRW={=Czu2Scw4h zqRb4vi!Fw?X}D7L6+lYa5H}1n@;PG>kyn6$!fCNO$3+~ARFVLXiAo4pqb|TXj(~-f zigrzy!y;!YL*RK>(BH6{3Fbqu!nTf0HID)SR&HLIpCbo#2n84d5iDB(Uc|&!rlm6D zBg}Y(kOSdo0Nw!XP<{@lN-K`5W;Ua-D0o4D(=@cwv|s9S(_NH^Yt89whaC5LSlJu$ zi8fz_rHy*+S?1I$r(v5zEJQFirJCQJ2I%#&o=*^$%ypPR?jx0n6vs@6Z{!7=2_dyHi;R1 zF}X!|!R+)F_02+9i=s1Y(c-naj!DAs2AQ1N=m3b|*pHD}@Hq?FvnlU!TJ-W{rfZ>f zT1qD>jMXr_!??G8`qzFLCjmBv>NA@{K(Cy1cuLDqDcfi3M1veKj z#~=Mo%cJb8cb<3xuquz;=;w^>kwmcP?O;b*W^5|1rN8xHQTFj9b8zs0F=`l zC8yiqnTq6tKMa*^fjwgfK^aC`S~;(BeKPMNw@1?8z^IBLe(;gUPMY_LAQ@I#Sf%bomZXn|{Z*XuDtud57|F1_ z;sM>%EPBDHuot4gew9m}RjS1zd_X}o9n+8j(4BPF)t=Y+0emZ2VMbb$9!noAax0vN zdzD-9pmX8Dsd{EYOitdNa3{4pv(d!DrI)I-Rm6po5%yGrQDW7rZF!Xo$*|6#lc5G= zQEejR0}zTqAy;gnqna%ox#^Ovnro}?`)Y@sslU)|+HahZyVQ&73$2b3t})^ptn%(6a@x&#oA11`)69aF{Q}U z7DsKw1`rk&@S8F&KpSVyn#D!3KV&)ZjqhWYK#iwOE-LQAqz(n(;EuEGf=;rYSDmtI z?b>MHH&>umf~C+`xubTG?f_cV#%&CukG?+OWT+3Bh;_1Pm|Gyy-i1b+`&wPbU?aw> zF@?0Tew9NM9aicnXqeLo_0F`3Y9E~ys3lpKzlwXHISMMTG03^$5R8w&g;~3`_f?YY zz27&J>bX=3HO{BMf5ZJI{?kqZx9pPf+*@|3uf$t+dCM*}27JpdY3tC~rEv~sSEZlA zL41;?m~hd>{{+WU@vHcNwU_uK_=|(_-$O=KWv9zk?4k$pCy;I|PSsZ^^J45b|F)rD z`3bF@Q6j_}hN{xf+7@YrshIlTNDgOrD^NYD2~wmAL=IJoC$&0dg5(hNOCOzofx2P( z?Abgf=2aX{1#Sy!_#>Q6*-7 zLuRhvF}~0OE-2)&Dt?>22vhd>xyNa<<;wSX2#f;spb?XU77!QX0*LHK3^@p>hyME zk6uS2b7x-X7U~>$^p1VnSW_07Ef1YYb&#=`gP^l72sgK8vPvy<&8Wb~Y16C3W~T8B zV^0`fE4c$b)8!(Tm7?=%tQ3<+FNRDtjh&~Nml@!U=oFIj-i;5eW-@VO<$L|{(@(vzo-D5a9LSSEgF`;*G_NH&Nl4NgYeP4 z(#n{oxeorGV>8TQ_!ZTLBc$rcG}A^)TrdXvsagj>w4uUbt44$d2sSASM?pE&t&EUC zSug08pENnOTd9FUP5b4Doda&qRORR`7qSBqcQ6&7Dq3NM09?!51}B)0CP(Ig$%uzf zsqNRL%=%CJP@Ih9pU%|&mD%}v8+POzQ+tdpifi1apnVi^Te4o z@6!epD|CogP7X^OubE*=L-omKG}L%tZ|K9BHS~eSS8nFh+R{JoY&{dZbs|L956-M7 z$1JTzXY}+9$FkTg4BO;%D;d~9cj_gwXd*s@^QIOiX_=eX`JZmnWTI%?osi8kL=%&t zhktCOt8U7C{@zIb>CER3Oy;9k&X~^}TCPUNc-=z3^{E57)4ShNou&KD{qn6jhFPla zm)Ikf#Rp-4s4zpn6%|m0?VOzjcvN5;1dN>nKZ*dwE)xN(AZ|*>1yn( z(fubQlgTm} zpR-q`^U~4B_HOv*NO{vI=bxAj*NK^SkJ8gQ>~T&up_;vc(|FBEuP;h8+c#iu82jt7xJ$!ZS14#umvaMbj6FrP+>)_nVr-D$u2K?7%=q&sCT%!T=Ew?VZ;Ow*W=2sRy1j%16xr1}^Z3 zjHX&J6jhVWQHyBOb|ZpX8wQ(IMV`~^Tr?Nq)=XMwnbtEZ5EDN-GE1D6p+lO*YxlH; z>KkNoqU?H0@^qv@)0gD`Z7xZ@rPG$Ap6-TAvOY7~o*$XDmR=rv<?;61Wx!Pyozo8C2~1|4F=g4@KPCuD`0A1Py@QGrv^#|Md?<+t6Z9y%+Mi1GuNrg zu=myswIxBb=O%_~IWwsA8RHGY!1@XrXd#pCFiJH23hK7xHCf%}3|efNG&3m(3*BjU0npxkC zYU9LjP|?tX}1B3=ea1Iv-#$newyx8s&L1_DaR8*O(;!HRUyCL_gwOkXmNBQOm2$$y1{E z#gJLRoEztOV)Sq#R|zetmD`DRuj)B%7Fuc!dUU3@b|D2rVXzP_KYIr=dlG@G2Eu6K znW))Ev0Qki|6b7AuUdFh%8I%<=?S%;W;)g%w9WO;$e_Njb{N@)v%QZ!RLqC;g7pL{ zMb9(miG?@%XUodjn-+_4N`~5zNF&G?5X10YOJX!dO>6vQ1Yey?YloJ}+DJ3cSXD)h zAfu8uU=~hv=>Mq0ieB>NuymbjQmFR5o{$C$sq~??zeHG*Gx=P?`vs0V`V951uo6)= zxn)r9#n)c*+Uhn2dg(p|MxhdH2I2a9O*xUhT{O3grm4+Tefi%mnyVI#eH*P~8=a)V zywV`JYV5!I3CDh@ooEpJM}J^k$V*x|qeRTWAozoJ54?rS3;KiM8n#%b1kk`%bZ1u8 z@JN@keO3!342uCxt)}ZkA349#`{KV#4ZkaX|C9mH5jWrS9UszBm%hZZSZwKjI?6Ky z7Yllf)*vV}5aAf6RHU+?y?I32MFz*jP7QeuZHu(w40({``mohq;X|)9jTVsPs z9Z9dkOS)b~y%aKEFUrg}`T9VqLIy~1Fi^j=n(74(qO(7n#GB*z@2lhZH|fufFsX0 zpH+ZE0U#BIA9Pq%k)jN{jq4>gsAgAyp8?6EY~v=jksokufN6d4FD)jjJp}WCnu;`Y zEKVwf9V6DmRv0B1t}+N0)hseEAV}%zTo~)12TT^a6qDxx{iTo#Ommb>7L3kL7}<&in-B#3uN6MF2Cu(WChh26L%`i_hCK6ppxgt6Y< z;d&f;VEU!|nJLTnw|1M@w2DjyrSIQZK(xXjk%XR}YqhZquqWZR2W7jtxMAAdYHBNr z$NnW@CzQyV0M-H68a3oJcr&ZJqm3)-lzZl`6Xe0$T0Dfln0!A=~~ zgdTq=&2=_|!W>#MeKCE=X)!rSuokA`SbXoto_GS=WJ`i_S%V5(h1)*iOJLQt=a|jD z{)W~ZrPQx&%bNURnG9d%9E({6(m}D+P)n24;viUU*IP=xn%4^~G_HEn9#B%s-mWWJ zqIUgEX|?J#aDi3qhb_eiKtrt!eL?mWA+oZG<+S6q3c+!U*g?XeTf~lA7xY^f^jjBn zU=`UBI~ebb2vA9@kSNnc5VtyxTOEh4UBF+9{y~%R{zcMpaIOUtVr%g=rs)In3#2Nf zfCIJ@^i`VZO{P1GicG*Hb`C-}wzSG;`Wu^i4x$?L@0ex~H8SCis$6`{`A3xjJa$VuYZrwxC+#EolQQfulD;s>20=oRqyre* zjl8BRH0eR?Wfp{J6w^w$5;%;?(+bzrc-Jb8X|M=WiPZ;0G&Tm~h+C=xF@>&vBMAe| zH(xU_yWsWYS;R34f2@0b_)%R1y#(m?0_ql0?^l$6x2b1m7+Rer;PTE*Qs?LP3E!Y5-Ui( zLHVuCMdWR3`C9QD>pvaljhaJOeGP34hj=Qh4I#C%a8Da3CjEY$ySL1gies8*Z3ft0 zp3&U|#L%Aw+Z%$w)0(oUA$4_BxG+E;Gjm*`nId-1x zf9P~FQka??Xq1XpIb|6cKz;a@JeFc9oi>Q<&k8Ld?lrSI1IbP6vh6Cw_}A+&&8#3b zH&-ojXJ<{mA)K9Y_wRG}&dwTO31?^b)P?XW7T1x6m1Y;Hs_$unLk&?}@C5X}eU*y{ z1u{3FsREls$YmfA*A1BsorB&-w3Zl8VIz|ymA1$ISuRQ3&f{he=^6N2z1l>~vVwr9 zP>5j5C1FWHeMAZEZ?PWq&Ng`iQDc$V>byuLi6V+was6s&d82pZ5!b1H*DMUeJTc`=tPo3^Js>>oV4IChBhA?Wg^&HkVm^nsvNPSgf1*m3~4Zdvz{sW*SBy~Lj z*g`Z1^sML-Rp?Hx#^iGZ$a4%EljJda$$H=DUOq3wKtk*A70ybP+B$6wCip&wv{VjQ ziWa2sY6|oU4N|n}_&WFL^1V-ESQ~tQK_i3^MX6UXrBfs!p~mR>S>R@Zh&O`yVe??> z3pKto*q4F-&RPxgP_?woa#o!h4IqM+B>%+ASz9ICgMWu4zy^MfcFuKCV zBNXp%BOtf1T)xwo%-#^AJcc+{vi`lr&(6J*ofjI{ z)M`Xs)eY9E`tEndJ2#CY#^RdN0owBU*0ddqHN)3vp#pwZt|J;F+YM>$`XX3bE$B7G z4ix;f3qqZ5U(`@PV#|VJ9-cYYGYQyS--BtdZb0XCmO~Nc`iAIOCCY>fvW~0nVo5nin zy~-6|*&N-2pvuCmAjWeao53reR)8f+tBLZ^yn*hXbW-C_@z6rI<$YZ!BU;JA8~3n{ z-CMqAcIQ3aAabVkYV&Y}-tnh)dM)qYWqN&%{X72DPOs(t_2`vhv9qAZ!pz=kV{Y-& zH81#E{PbJ=bh=)uvY%W0bexRns=}m1>TMmeA`_nd&nbTTtu{s%4BdL17~UT^0+O0V zx5BtJp1;C){#F~qaIK9%Gq>6pRTgurjk(pvw3@ftm|Ja(Lo_afN!q2$x7wH{1IT7V zClWl-Kbr*1(BJ5iB+Xty<+-qZfC!LD4R5tEx7rw8zWeTr;n@U!XH;3Y+8AA_cdL!L z)yA-eW|xlNYGX$F!_+ZcPg^ia@qQ!ikwvd!(H@OIwbN^P|1Q&O(W_YK9e--4*Yf^) z^lI7|!@-9+uD&l-=! zpU2lXFBimLP#-Ob|24i0pOO_x;2W3XH?&`XmzFNYU&62K4}pg*xVH&S z7yRs8IKvSV8Sit!OUKn_D3iX`br*1Xg%wy`)%da?yC9!#4_pXDD!9&gnPIA|wg<1T z`(Edct8x|o&JjYKL~Kx4fSmAB6HaumbDN-sdGnLsdXeQ)jXxy5T!z^Vf`>Be8`zl& zi2o{c3kEP5&yk7dN=sT%I&g#~OEP*O8&Bw)UMR4E$&a2C{(?lHnXnsSky4R_g}ap( z$=#!u?jB>|5?} zJ&ILU&>Kc-d#z>Qf|^Q8g`DAG^h-IHVP@1GXhtU-gHXHAJ`sba^YBvqRgBJ;vpNy#Dom;&_L6GMYXbw}rr8Y6EFRHBx+|uqFlQZ*;}yYRrzw`j0?6@^ z%oxokN`v!Dla7K)2Ty-)1Sm0Yr%3B!6ObV@_n;*4g|{Ctn;*UoFa{N&;i2(}Q{M7E zgf^h?mUnvEKGGTh4)09iMz64avo&RCrUk?D4sAoGb&v`8u)x^+e8C#7N@dSg>>_Lq z;wRX;;d?zH+|<7{GJcjI8&4K=#14G3H}Oj&x$K}iR`y8q@T*wS;h!=ZrB}(2BK5#g zw0xW!VbnaFo)!y3FI~r%G`WV(6RgaJVyIb2qa`xd-=B z7W7`4n$Bp6_#aU{cg4Sbqi!TxBW5>RXf+ql_s>1Z3*~C_ZCH1fo3A~bd%6rearohU z1{X8#!2|m38Ts9ZLjb*JxO$YtzNQ>j-$Ra~-EiN1_BL6ayB|{SE^MXe9>B87s9Nur zZ!4ONFQ69t z|ErO?YhfIo8#h;=c++Jh+s65lWgWIyZ#er9F_eh1uD z2zzFXI~f%YuT0|5i0Q`w%V0Y4@>j-B%ev1NxdsuEmfkbhNoq7h3{jum6~Az!uA{?% zV6rX?#dTdyGF}B~rOy?sU9MWZ{|X&#U-|s!T=;Dg zeAR0^Z4VxuHhGLThvSxh>BGs0b@SUqD}E?^`EAd}!y8>`IQ#bLbpK&@8g|$+DmF&Y zIBprQzJ)Z|N1--#6oBU_@$Jhm%fiIK#RQUl+_zn%lYrqw=O%?OFmDG+~xEf)5 zpeu#SJuG*kIacDQA;=JOtbTDl+A&<>Ac+1 zRgOI6MqExC!5if<8p}B2e>`>GU&$GNsCzYM{4Rqt(uLHKJ5EYsr}3vBoyM<>(P(nW z-?Uvwh2lfNZ5kKSW$rTy_n<7Ct9Mh&)pYEQ^^%I0{Rh?N8}Pn-lkT*3e(7{yb-u1r zIUEY&SV@-4E6CJ&rrxs}FZa4lS<;`!rrGDjFHW5kllk=z)5Ms-uhYBaj7%r_K2HFj z0LK6z!8{?gd#(;2t6pa5@QHLQKxnlfwOS&seAKaU3roBr0T|9d9O2C-OCR20#OVh; z?U%jR{^>~W>74yX{{y3+^s1+YQPI;G+}I3E;S@|(<6%y(?8N`UJ4U?tuc>Hj=NbT^ zChadd53AnaSG~5k;mO6DUgWMCfU%$(quoAzE3y=A*^10F%O9tmF}|@X7#0WE6C!O^ z$@3LwX9DE_T!?yHfv!PaH>3}Q54@p=7*}(wvU5+X3GiMlxMrEf53P{80(Y1~g$LR$ zU0~RmX$1L7CXi1Z16amYLM~OIoTSs0MGnebVHe);y5C%QRp*(Di)^W?DJ|&Tri7{V z?lj)A=-;gxG0{IZG7aezIA@Z=P6iHX1Ugi`<0EC#F?^RQbm$TBi%`QG*VXrU-TFGG zug01lvKM#7rIG%;ny-o}lskOdn249SYl>gMGu$EmuE}fl&S$*#JFlFqCLvd+acJCh z)?gvUku`jcX2Qs7L=bKG&?EXTRrHVR z^9=+`BjpEAz!}W4VU(bGxa4ROX-xn^H>SVyXMuFf6#KJ5FJ{^H$Re;DO+KKHguaT* z2gVd;OlNzlaBS8UC7ND{f0nCo)vW3q83U^p;MR9bJG(V)UpoytB=`XUvnhf z?6B`mT7s3+8HI3?49p+y$|DKeLjmjsy%!Xmq@iSgIt#$BqhIWg8_F@m%nB?M5rBd7 z#n_~IFEI}+UwBMfEQ{r_i^44V8zZyC!VNw#vDNzYo07^t(Es5`ZPWS2&zM82lgjwU z^*Y_CeR#d}4jnR`^H@l9T&{lF$#mBa>%5~gI0ZP-tQHD-q!X(m;L$Q0?G}F?J^sVL z7<+>KL-T&_Mk7F6;pfZ|ur$x)3a?wjpO^tp9stab#Xf=MzzS!%UmIV6ET_+*$0@>S zD&r)-g62IA>-~AB#yY^mPeq51e&-{g!~Yopg;&|9uI|4{tVY@;RJ=pYv~vZ}Y>4HE zPntUF4?;}?yen7nTnD#x!GrmwAhh119@bHLjcrC61}r1ih!Ch&j*TAtdkg~Bs1OLA zW^716!8!r7TEasTP-96)eI^h~Bgzz`!3Ldqtyqs%;9oker~w@*upn(*I;b4D$2$?h zQI8*qicz8dYs6LF=FCRPu8N_ky1S{LYC7tAOTh@pNHH001&)VP^xEPnK5`^Q&c)Fr zBkVnb7JiKYAK8ySfdUf77+AF(o|6sXZR7(Q!Q03Ow~-HSBOlyGK5&kFaK$NC+lKY? z?{&8Hk<$R34(K$AKR7C|^Q1!x^ZY=N#dLlkdA4v1u#T%}q2AG8q;CP%Zvoa-RCfq= zEzy+U1xOEe!n;LS2kWxnug?}?J>Xu3`iyln0pKwJegc1Ye`^8O;aZ9_KN{|Yt#0=_ zy*eEUOWsX%bo*r^ZcWD%56^K+j*Xf}Ydmh8^H<5zp0VDpL^8F(QA#;Wg}Y^3PRg zL~eq2{_eM2Tc>}Kz|Jw*#?ZwHQrvuQB8d}xxcS^f4L70HEzA)K5k6WCKZEZUE=zbC z_9tT$SW;`mSe|I9O}Z@aG!iXOwA3cGw;1OmnCupO3=2xd_*46sS>9g{rDA3%AQpTK z3%%n{?etpSUyoip#`&#I!AVVUt5dkuDctH5mN{Ls_A1vWJ4~3EFq8cnVXK$ezdTptT9)yqrKuWzcRgo3}(A%&t9^;f~* zDtudDVfic>mRArj!zf8bVn=!=w}bAbzpTH$)hXQS6mE42w>pJeokGP7({LNKwW-_& zZH07?Wc0T|TPXmqbI?|H!noBb-0BqU@mlS-ZuQ*hqZzA*XMI zd~Jz1!2}K*3Nk!{SdiUSl4F z@5P_d@vvfBQrn(K+rIJp#xOp?vQ(ZPJ}*GlEJ!@?$j=C9{PHW8x|=o}b%1EJfJ9Hz z8!}UBjJ>vi4FCKaA%yNORSVSok&b3K2HL0+7PtyZMh938`}eBO%MZBS)vZ--k1z8Q z`RPFpUVn3;q9|?ob(gDMEXk{~(4a8)1sP~hKu=h0No7~j9rU=0CEtcma0~0De5vRb zc&~qBE$9!d=hupUuivxb_PdL#C_)9gv-_x5-mS*yv*F#V(3n8Ocdt&kw0)9h>$L!+ zRj>Z!YzNs24e(3mO1P_0HEjWri=8FgcU~`>_!6bF<@~UbQ~VBmwXZhIa{60uBvnLl z?QWxDf#_>Uw>BH$HCQg8RW90U0_j6CmkGlX02oN6gO#$%S6w3J70W^gz**<%{Z2A{y#kXsv6|pE zD^*_N8?B~7Zn;G~pGh<3g+g(d+j3T$bEwt`&_I z{SHVgXG=rOl#k$+P*x|f4&Z;)#&GnGv`L@*?@;OHig<@Az%mhTxJ)XvOx}%Av@V-p zGnWm2z4_0UjV0S#*UP3a8%xgXE}Ov{yG=!E6*~orDnqzUDIO;)oT{vI*MNJKIhE^Y zx>0EIC(fL^b+Dw6=dEJ$$DX}CJFE8l9>TpMfazJTBD^#%f-fD>Ea znGr4e1fN-X=9HdUk(k6^y5S^V)p`B(de}M@|66k^{*~*^DK-@?+5YnNvguRNlGB`u z=C#WqYJ&J7s=;=Ap__vmIKj+04B)P--h);UoW;uQEe8nj@D;iTtr+(pGkA+x006PB zx(m=IV82L>UEjenUqu|dUQVVi@!~!87F~I-+Jjeb*9d9F z`t!1~L_7DB!{-Vei9$S`Y0s0xXY?m5kPI(v;A^+1wTmrF|Hrn{{LA4rO37a+ioYQ`Gq&j{*tF#Jd zd4$MfpwgGaJD^J%Tn=9>wOUFO5H6ON@h6AR%CJ`=KbJms>Bc3VJcoE))i&ZNH5$k& zqsY7J6QM4!Cuh`~XN5X1%ODvwY8i|N&qzYMB`Ifhp)1r8ifK4k;p@iFJHrnN{VMuO z;gyc8C%QAdQxx)@GRk|dr{2Vof&~sk>lH+z5vWm@Um8AFZMHkg8Dev_a8oT`4xjEQ zrIqy+xR+lJKW=|{1}FHIbOy++VqK8X&qQiLxg0*PMT;^^xx-4i9DZWt%}5dA|BNLz zd`>NQJom@#FGeyCU!XR~=%@<1sE#&W4xg<9^{<0?X6W%Ee!oX(UJgHusAV`bogp|F z<_D?))E|20Dd31fvWIU^SBqx|ZC0xGFDp+CpQE5oXXc~fd#adJ&lX{*c4kaGbS!&- z-A9m`e4Pq>o;^YDHf0)q^HEzCI>pvmzd=*#1)&evG2zUblg*NXa@IwlHFb(Ue^#u@ zJc6#FAsUtM*B3-(Y4{8pBO|aC13^cj&uYoeO4T|VhX`KJwT1Q>+C&463M19f z6SJC+>(wZ&7FKChP)e+tiqfc~il-Gmk0nr4DwpvO3_pPh)i^WOmO=iRj4*Wq5VT)n z)Kn4L4yOc!{T78cR74ty+t$p8M%Qo#@TrX z%U4Fu53}Fu&$D`~z-vAD3A$MF1&pt{tT1B4f6kD*)*(3W=fHcEs)FuOm;0A7Nm_*} zPUzM~_ij z$@uXU&Hf^L{(gF>eqRuO7VA^|Y5HhAjgLBgeEkJ{{3Lx0ATt#Khx>&1z7ON$N&5KG zOZfOc`uI!q@sK_uAHzq8KGt5who3%N^s!7IfAT4O{2_hF96s9g@h|D;@6ksBaN}Z( zKDOv1OdtObB(vhbp^u*=(*84ibcRn8-4uB^gCYMop4Yl4MjQ83jpJdy>_h>{MQ+x~PLHlAxI}}n* z?Hvk;r}hp>o>}jROb9xB*1EFTU_V=^V&kBdgbAQNA?~NAQ)iX+iJA^`4eP6sZ`F;( z%94I$$S2>FWSn-MkXQR;FH6Tj+Ujpd15#R-pm3M(kAplSPIv%4$uZ1 z2j0I)0Soc`E0_e|cX>#Bke9&nFzICqb4knOMT14#9)Hky%vKm2_OWYd43-Wt!xu`8 NGwWKS{_5mc|9|4v90dRX literal 0 HcmV?d00001 diff --git a/doc/LectureNotes/_build/.doctrees/environment.pickle b/doc/LectureNotes/_build/.doctrees/environment.pickle deleted file mode 100644 index 8974a9d842eb1fbc595f5751cfe4af388f9196f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174283 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", line 1 + pip3 install tensorflow + ^ +SyntaxError: invalid syntax + +SyntaxError: invalid syntax (, line 1) + diff --git a/doc/LectureNotes/_build/html/reports/chapter5.log b/doc/LectureNotes/_build/html/reports/chapter5.log new file mode 100644 index 000000000..828ec304d --- /dev/null +++ b/doc/LectureNotes/_build/html/reports/chapter5.log @@ -0,0 +1,41 @@ +Traceback (most recent call last): + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/jupyter_cache/executors/utils.py", line 51, in single_nb_execution + executenb( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 1087, in execute + return NotebookClient(nb=nb, resources=resources, km=km, **kwargs).execute() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 74, in wrapped + return just_run(coro(*args, **kwargs)) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 53, in just_run + return loop.run_until_complete(coro) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete + return future.result() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 540, in async_execute + await self.async_execute_cell( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 832, in async_execute_cell + self._check_raise_for_error(cell, exec_reply) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 740, in _check_raise_for_error + raise CellExecutionError.from_cell_and_msg(cell, exec_reply['content']) +nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell: +------------------ +# Import the necessary packages +import numpy +from cvxopt import matrix +from cvxopt import solvers +P = matrix(numpy.diag([1,0]), tc=’d’) +q = matrix(numpy.array([3,4]), tc=’d’) +G = matrix(numpy.array([[-1,0],[0,-1],[-1,-3],[2,5],[3,4]]), tc=’d’) +h = matrix(numpy.array([0,0,-15,100,80]), tc=’d’) +# Construct the QP, invoke solver +sol = solvers.qp(P,q,G,h) +# Extract optimal value and solution +sol[’x’] +sol[’primal objective’] +------------------ + + File "", line 5 + P = matrix(numpy.diag([1,0]), tc=’d’) + ^ +SyntaxError: invalid character in identifier + +SyntaxError: invalid character in identifier (, line 5) + diff --git a/doc/LectureNotes/_build/html/reports/chapter6.log b/doc/LectureNotes/_build/html/reports/chapter6.log new file mode 100644 index 000000000..b9dbedf5f --- /dev/null +++ b/doc/LectureNotes/_build/html/reports/chapter6.log @@ -0,0 +1,66 @@ +Traceback (most recent call last): + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/jupyter_cache/executors/utils.py", line 51, in single_nb_execution + executenb( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 1087, in execute + return NotebookClient(nb=nb, resources=resources, km=km, **kwargs).execute() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 74, in wrapped + return just_run(coro(*args, **kwargs)) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 53, in just_run + return loop.run_until_complete(coro) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete + return future.result() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 540, in async_execute + await self.async_execute_cell( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 832, in async_execute_cell + self._check_raise_for_error(cell, exec_reply) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 740, in _check_raise_for_error + raise CellExecutionError.from_cell_and_msg(cell, exec_reply['content']) +nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell: +------------------ +import os +from sklearn.datasets import load_breast_cancer +from sklearn.tree import DecisionTreeClassifier +from sklearn.model_selection import train_test_split +from sklearn.metrics import confusion_matrix +from sklearn.tree import export_graphviz + +from IPython.display import Image +from pydot import graph_from_dot_data +import pandas as pd +import numpy as np + + +cancer = load_breast_cancer() +X = pd.DataFrame(cancer.data, columns=cancer.feature_names) +print(X) +y = pd.Categorical.from_codes(cancer.target, cancer.target_names) +y = pd.get_dummies(y) +print(y) +X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1) +tree_clf = DecisionTreeClassifier(max_depth=5) +tree_clf.fit(X_train, y_train) + +export_graphviz( + tree_clf, + out_file="DataFiles/cancer.dot", + feature_names=cancer.feature_names, + class_names=cancer.target_names, + rounded=True, + filled=True +) +cmd = 'dot -Tpng DataFiles/cancer.dot -o DataFiles/cancer.png' +os.system(cmd) +------------------ + +--------------------------------------------------------------------------- +ModuleNotFoundError Traceback (most recent call last) + in  + 7  + 8 from IPython.display import Image +----> 9 from pydot import graph_from_dot_data + 10 import pandas as pd + 11 import numpy as np + +ModuleNotFoundError: No module named 'pydot' +ModuleNotFoundError: No module named 'pydot' + diff --git a/doc/LectureNotes/_build/html/reports/chapter7.log b/doc/LectureNotes/_build/html/reports/chapter7.log new file mode 100644 index 000000000..727b82aa1 --- /dev/null +++ b/doc/LectureNotes/_build/html/reports/chapter7.log @@ -0,0 +1,46 @@ +Traceback (most recent call last): + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/jupyter_cache/executors/utils.py", line 51, in single_nb_execution + executenb( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 1087, in execute + return NotebookClient(nb=nb, resources=resources, km=km, **kwargs).execute() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 74, in wrapped + return just_run(coro(*args, **kwargs)) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 53, in just_run + return loop.run_until_complete(coro) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete + return future.result() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 540, in async_execute + await self.async_execute_cell( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 832, in async_execute_cell + self._check_raise_for_error(cell, exec_reply) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 740, in _check_raise_for_error + raise CellExecutionError.from_cell_and_msg(cell, exec_reply['content']) +nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell: +------------------ +heads_proba = 0.51 +coin_tosses = (np.random.rand(10000, 10) < heads_proba).astype(np.int32) +cumulative_heads_ratio = np.cumsum(coin_tosses, axis=0) / np.arange(1, 10001).reshape(-1, 1) +plt.figure(figsize=(8,3.5)) +plt.plot(cumulative_heads_ratio) +plt.plot([0, 10000], [0.51, 0.51], "k--", linewidth=2, label="51%") +plt.plot([0, 10000], [0.5, 0.5], "k-", label="50%") +plt.xlabel("Number of coin tosses") +plt.ylabel("Heads ratio") +plt.legend(loc="lower right") +plt.axis([0, 10000, 0.42, 0.58]) +save_fig("votingsimple") +plt.show() +------------------ + +--------------------------------------------------------------------------- +NameError Traceback (most recent call last) + in  + 1 heads_proba = 0.51 +----> 2 coin_tosses = (np.random.rand(10000, 10) < heads_proba).astype(np.int32) + 3 cumulative_heads_ratio = np.cumsum(coin_tosses, axis=0) / np.arange(1, 10001).reshape(-1, 1) + 4 plt.figure(figsize=(8,3.5)) + 5 plt.plot(cumulative_heads_ratio) + +NameError: name 'np' is not defined +NameError: name 'np' is not defined + diff --git a/doc/LectureNotes/_build/html/reports/linalg.log b/doc/LectureNotes/_build/html/reports/linalg.log new file mode 100644 index 000000000..4cb123d39 --- /dev/null +++ b/doc/LectureNotes/_build/html/reports/linalg.log @@ -0,0 +1,31 @@ +Traceback (most recent call last): + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/jupyter_cache/executors/utils.py", line 51, in single_nb_execution + executenb( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 1087, in execute + return NotebookClient(nb=nb, resources=resources, km=km, **kwargs).execute() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 74, in wrapped + return just_run(coro(*args, **kwargs)) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 53, in just_run + return loop.run_until_complete(coro) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete + return future.result() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 540, in async_execute + await self.async_execute_cell( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 832, in async_execute_cell + self._check_raise_for_error(cell, exec_reply) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 740, in _check_raise_for_error + raise CellExecutionError.from_cell_and_msg(cell, exec_reply['content']) +nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell: +------------------ +import numpy as np +x = np.log(np.array([4.0, 7.0, 8.0]) +print(x) +------------------ + + File "", line 3 + print(x) + ^ +SyntaxError: invalid syntax + +SyntaxError: invalid syntax (, line 3) + diff --git a/doc/LectureNotes/_build/html/reports/statistics.log b/doc/LectureNotes/_build/html/reports/statistics.log new file mode 100644 index 000000000..279cbb99d --- /dev/null +++ b/doc/LectureNotes/_build/html/reports/statistics.log @@ -0,0 +1,58 @@ +Traceback (most recent call last): + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/jupyter_cache/executors/utils.py", line 51, in single_nb_execution + executenb( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 1087, in execute + return NotebookClient(nb=nb, resources=resources, km=km, **kwargs).execute() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 74, in wrapped + return just_run(coro(*args, **kwargs)) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/util.py", line 53, in just_run + return loop.run_until_complete(coro) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete + return future.result() + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 540, in async_execute + await self.async_execute_cell( + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 832, in async_execute_cell + self._check_raise_for_error(cell, exec_reply) + File "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/nbclient/client.py", line 740, in _check_raise_for_error + raise CellExecutionError.from_cell_and_msg(cell, exec_reply['content']) +nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell: +------------------ +# Blocking + @timeFunction + def blocking(self, blockSizeMax = 500): + blockSizeMin = 1 + + self.blockSizes = [] + self.meanVec = [] + self.varVec = [] + + for i in range(blockSizeMin, blockSizeMax): + if(len(self.data) % i != 0): + pass#continue + blockSize = i + meanTempVec = [] + varTempVec = [] + startPoint = 0 + endPoint = blockSize + + while endPoint <= len(self.data): + meanTempVec.append(np.average(self.data[startPoint:endPoint])) + startPoint = endPoint + endPoint += blockSize + mean, var = np.average(meanTempVec), np.var(meanTempVec)/len(meanTempVec) + self.meanVec.append(mean) + self.varVec.append(var) + self.blockSizes.append(blockSize) + + self.blockingAvg = np.average(self.meanVec[-200:]) + self.blockingVar = (np.average(self.varVec[-200:])) + self.blockingStd = np.sqrt(self.blockingVar) +------------------ + + File "", line 2 + @timeFunction + ^ +IndentationError: unexpected indent + +IndentationError: unexpected indent (, line 2) + diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter1.ipynb b/doc/LectureNotes/_build/jupyter_execute/chapter1.ipynb index cb673cd61..ebd1120c1 100644 --- a/doc/LectureNotes/_build/jupyter_execute/chapter1.ipynb +++ b/doc/LectureNotes/_build/jupyter_execute/chapter1.ipynb @@ -441,8 +441,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "[ 0.82672272 0.45257846 -3.50535083 -0.60868993 -0.32256204 0.35390727\n", - " -0.8063309 -0.22751293 -0.26205577 -0.65826338]\n" + "[ 1.3280646 -0.56501263 0.21077998 -0.55360402 0.06730225 1.01324127\n", + " -0.21780848 -0.34317041 0.45298301 0.08215028]\n" ] } ], diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter10.ipynb b/doc/LectureNotes/_build/jupyter_execute/chapter10.ipynb index e0377854a..85d81c6c5 100644 --- a/doc/LectureNotes/_build/jupyter_execute/chapter10.ipynb +++ b/doc/LectureNotes/_build/jupyter_execute/chapter10.ipynb @@ -2378,10 +2378,6 @@ "Learning rate = 1.0\n", "Lambda = 10.0\n", "Accuracy score on test set: 0.05\n", - "\n", - "Learning rate = 10.0\n", - "Lambda = 1e-05\n", - "Accuracy score on test set: 0.08888888888888889\n", "\n" ] }, @@ -2389,6 +2385,10 @@ "name": "stdout", "output_type": "stream", "text": [ + "Learning rate = 10.0\n", + "Lambda = 1e-05\n", + "Accuracy score on test set: 0.08888888888888889\n", + "\n", "Learning rate = 10.0\n", "Lambda = 0.0001\n", "Accuracy score on test set: 0.08611111111111111\n", @@ -2396,7 +2396,13 @@ "Learning rate = 10.0\n", "Lambda = 0.001\n", "Accuracy score on test set: 0.08888888888888889\n", - "\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "Learning rate = 10.0\n", "Lambda = 0.01\n", "Accuracy score on test set: 0.08888888888888889\n", diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter11.ipynb b/doc/LectureNotes/_build/jupyter_execute/chapter11.ipynb new file mode 100644 index 000000000..344f752d3 --- /dev/null +++ b/doc/LectureNotes/_build/jupyter_execute/chapter11.ipynb @@ -0,0 +1,3310 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Solving Differential Equations with Deep Learning\n", + "\n", + "The Universal Approximation Theorem states that a neural network can\n", + "approximate any function at a single hidden layer along with one input\n", + "and output layer to any given precision. \n", + "\n", + "\n", + "An ordinary differential equation (ODE) is an equation involving functions having one variable.\n", + "\n", + "In general, an ordinary differential equation looks like" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{ode} \\tag{1}\n", + "f\\left(x, \\, g(x), \\, g'(x), \\, g''(x), \\, \\dots \\, , \\, g^{(n)}(x)\\right) = 0\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $g(x)$ is the function to find, and $g^{(n)}(x)$ is the $n$-th derivative of $g(x)$.\n", + "\n", + "The $f\\left(x, g(x), g'(x), g''(x), \\, \\dots \\, , g^{(n)}(x)\\right)$ is just a way to write that there is an expression involving $x$ and $g(x), \\ g'(x), \\ g''(x), \\, \\dots \\, , \\text{ and } g^{(n)}(x)$ on the left side of the equality sign in ([1](#ode)).\n", + "The highest order of derivative, that is the value of $n$, determines to the order of the equation.\n", + "The equation is referred to as a $n$-th order ODE.\n", + "Along with ([1](#ode)), some additional conditions of the function $g(x)$ are typically given\n", + "for the solution to be unique.\n", + "\n", + "\n", + "\n", + "Let the trial solution $g_t(x)$ be" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + "\tg_t(x) = h_1(x) + h_2(x,N(x,P))\n", + "\\label{_auto1} \\tag{2}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $h_1(x)$ is a function that makes $g_t(x)$ satisfy a given set\n", + "of conditions, $N(x,P)$ a neural network with weights and biases\n", + "described by $P$ and $h_2(x, N(x,P))$ some expression involving the\n", + "neural network. The role of the function $h_2(x, N(x,P))$, is to\n", + "ensure that the output from $N(x,P)$ is zero when $g_t(x)$ is\n", + "evaluated at the values of $x$ where the given conditions must be\n", + "satisfied. The function $h_1(x)$ should alone make $g_t(x)$ satisfy\n", + "the conditions.\n", + "\n", + "But what about the network $N(x,P)$?\n", + "\n", + "\n", + "As described previously, an optimization method could be used to minimize the parameters of a neural network, that being its weights and biases, through backward propagation.\n", + "\n", + "\n", + "\n", + "For the minimization to be defined, we need to have a cost function at hand to minimize.\n", + "\n", + "It is given that $f\\left(x, \\, g(x), \\, g'(x), \\, g''(x), \\, \\dots \\, , \\, g^{(n)}(x)\\right)$ should be equal to zero in ([1](#ode)).\n", + "We can choose to consider the mean squared error as the cost function for an input $x$.\n", + "Since we are looking at one input, the cost function is just $f$ squared.\n", + "The cost function $c\\left(x, P \\right)$ can therefore be expressed as" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C\\left(x, P\\right) = \\big(f\\left(x, \\, g(x), \\, g'(x), \\, g''(x), \\, \\dots \\, , \\, g^{(n)}(x)\\right)\\big)^2\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If $N$ inputs are given as a vector $\\boldsymbol{x}$ with elements $x_i$ for $i = 1,\\dots,N$,\n", + "the cost function becomes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{cost} \\tag{3}\n", + "\tC\\left(\\boldsymbol{x}, P\\right) = \\frac{1}{N} \\sum_{i=1}^N \\big(f\\left(x_i, \\, g(x_i), \\, g'(x_i), \\, g''(x_i), \\, \\dots \\, , \\, g^{(n)}(x_i)\\right)\\big)^2\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The neural net should then find the parameters $P$ that minimizes the cost function in\n", + "([3](#cost)) for a set of $N$ training samples $x_i$.\n", + "\n", + "\n", + "\n", + "To perform the minimization using gradient descent, the gradient of $C\\left(\\boldsymbol{x}, P\\right)$ is needed.\n", + "It might happen so that finding an analytical expression of the gradient of $C(\\boldsymbol{x}, P)$ from ([3](#cost)) gets too messy, depending on which cost function one desires to use.\n", + "\n", + "Luckily, there exists libraries that makes the job for us through automatic differentiation.\n", + "Automatic differentiation is a method of finding the derivatives numerically with very high precision.\n", + "\n", + "\n", + "### Example: Exponential decay\n", + "\n", + "An exponential decay of a quantity $g(x)$ is described by the equation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{solve_expdec} \\tag{4}\n", + " g'(x) = -\\gamma g(x)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $g(0) = g_0$ for some chosen initial value $g_0$.\n", + "\n", + "The analytical solution of ([4](#solve_expdec)) is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + " g(x) = g_0 \\exp\\left(-\\gamma x\\right)\n", + "\\label{_auto2} \\tag{5}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Having an analytical solution at hand, it is possible to use it to compare how well a neural network finds a solution of ([4](#solve_expdec)).\n", + "\n", + "\n", + "\n", + "The program will use a neural network to solve" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{solveode} \\tag{6}\n", + "g'(x) = -\\gamma g(x)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $g(0) = g_0$ with $\\gamma$ and $g_0$ being some chosen values.\n", + "\n", + "In this example, $\\gamma = 2$ and $g_0 = 10$.\n", + "\n", + "\n", + "To begin with, a trial solution $g_t(t)$ must be chosen. A general trial solution for ordinary differential equations could be" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "g_t(x, P) = h_1(x) + h_2(x, N(x, P))\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $h_1(x)$ ensuring that $g_t(x)$ satisfies some conditions and $h_2(x,N(x, P))$ an expression involving $x$ and the output from the neural network $N(x,P)$ with $P $ being the collection of the weights and biases for each layer. For now, it is assumed that the network consists of one input layer, one hidden layer, and one output layer.\n", + "\n", + "\n", + "\n", + "In this network, there are no weights and bias at the input layer, so $P = \\{ P_{\\text{hidden}}, P_{\\text{output}} \\}$.\n", + "If there are $N_{\\text{hidden} }$ neurons in the hidden layer, then $P_{\\text{hidden}}$ is a $N_{\\text{hidden} } \\times (1 + N_{\\text{input}})$ matrix, given that there are $N_{\\text{input}}$ neurons in the input layer.\n", + "\n", + "The first column in $P_{\\text{hidden} }$ represents the bias for each neuron in the hidden layer and the second column represents the weights for each neuron in the hidden layer from the input layer.\n", + "If there are $N_{\\text{output} }$ neurons in the output layer, then $P_{\\text{output}} $ is a $N_{\\text{output} } \\times (1 + N_{\\text{hidden} })$ matrix.\n", + "\n", + "Its first column represents the bias of each neuron and the remaining columns represents the weights to each neuron.\n", + "\n", + "It is given that $g(0) = g_0$. The trial solution must fulfill this condition to be a proper solution of ([6](#solveode)). A possible way to ensure that $g_t(0, P) = g_0$, is to let $F(N(x,P)) = x \\cdot N(x,P)$ and $A(x) = g_0$. This gives the following trial solution:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{trial} \\tag{7}\n", + "g_t(x, P) = g_0 + x \\cdot N(x, P)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reformulating the problem\n", + "\n", + "We wish that our neural network manages to minimize a given cost function.\n", + "\n", + "A reformulation of out equation, ([6](#solveode)), must therefore be done,\n", + "such that it describes the problem a neural network can solve for.\n", + "\n", + "The neural network must find the set of weights and biases $P$ such that the trial solution in ([7](#trial)) satisfies ([6](#solveode)).\n", + "\n", + "The trial solution" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "g_t(x, P) = g_0 + x \\cdot N(x, P)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "has been chosen such that it already solves the condition $g(0) = g_0$. What remains, is to find $P$ such that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{nnmin} \\tag{8}\n", + "g_t'(x, P) = - \\gamma g_t(x, P)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "is fulfilled as *best as possible*.\n", + "\n", + "\n", + "The left hand side and right hand side of ([8](#nnmin)) must be computed separately, and then the neural network must choose weights and biases, contained in $P$, such that the sides are equal as best as possible.\n", + "This means that the absolute or squared difference between the sides must be as close to zero, ideally equal to zero.\n", + "In this case, the difference squared shows to be an appropriate measurement of how erroneous the trial solution is with respect to $P$ of the neural network.\n", + "\n", + "This gives the following cost function our neural network must solve for:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\min_{P}\\Big\\{ \\big(g_t'(x, P) - ( -\\gamma g_t(x, P) \\big)^2 \\Big\\}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(the notation $\\min_{P}\\{ f(x, P) \\}$ means that we desire to find $P$ that yields the minimum of $f(x, P)$)\n", + "\n", + "or, in terms of weights and biases for the hidden and output layer in our network:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\min_{P_{\\text{hidden} }, \\ P_{\\text{output} }}\\Big\\{ \\big(g_t'(x, \\{ P_{\\text{hidden} }, P_{\\text{output} }\\}) - ( -\\gamma g_t(x, \\{ P_{\\text{hidden} }, P_{\\text{output} }\\}) \\big)^2 \\Big\\}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "for an input value $x$.\n", + "\n", + "\n", + "\n", + "If the neural network evaluates $g_t(x, P)$ at more values for $x$, say $N$ values $x_i$ for $i = 1, \\dots, N$, then the *total* error to minimize becomes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{min} \\tag{9}\n", + "\\min_{P}\\Big\\{\\frac{1}{N} \\sum_{i=1}^N \\big(g_t'(x_i, P) - ( -\\gamma g_t(x_i, P) \\big)^2 \\Big\\}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Letting $\\boldsymbol{x}$ be a vector with elements $x_i$ and $C(\\boldsymbol{x}, P) = \\frac{1}{N} \\sum_i \\big(g_t'(x_i, P) - ( -\\gamma g_t(x_i, P) \\big)^2$ denote the cost function, the minimization problem that our network must solve, becomes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\min_{P} C(\\boldsymbol{x}, P)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In terms of $P_{\\text{hidden} }$ and $P_{\\text{output} }$, this could also be expressed as\n", + "\n", + "$$\n", + "\\min_{P_{\\text{hidden} }, \\ P_{\\text{output} }} C(\\boldsymbol{x}, \\{P_{\\text{hidden} }, P_{\\text{output} }\\})\n", + "$$\n", + "\n", + "\n", + "For simplicity, it is assumed that the input is an array $\\boldsymbol{x} = (x_1, \\dots, x_N)$ with $N$ elements. It is at these points the neural network should find $P$ such that it fulfills ([9](#min)).\n", + "\n", + "First, the neural network must feed forward the inputs.\n", + "This means that $\\boldsymbol{x}s$ must be passed through an input layer, a hidden layer and a output layer. The input layer in this case, does not need to process the data any further.\n", + "The input layer will consist of $N_{\\text{input} }$ neurons, passing its element to each neuron in the hidden layer. The number of neurons in the hidden layer will be $N_{\\text{hidden} }$.\n", + "\n", + "\n", + "For the $i$-th in the hidden layer with weight $w_i^{\\text{hidden} }$ and bias $b_i^{\\text{hidden} }$, the weighting from the $j$-th neuron at the input layer is:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "z_{i,j}^{\\text{hidden}} &= b_i^{\\text{hidden}} + w_i^{\\text{hidden}}x_j \\\\\n", + "&=\n", + "\\begin{pmatrix}\n", + "b_i^{\\text{hidden}} & w_i^{\\text{hidden}}\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "1 \\\\\n", + "x_j\n", + "\\end{pmatrix}\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The result after weighting the inputs at the $i$-th hidden neuron can be written as a vector:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "\\boldsymbol{z}_{i}^{\\text{hidden}} &= \\Big( b_i^{\\text{hidden}} + w_i^{\\text{hidden}}x_1 , \\ b_i^{\\text{hidden}} + w_i^{\\text{hidden}} x_2, \\ \\dots \\, , \\ b_i^{\\text{hidden}} + w_i^{\\text{hidden}} x_N\\Big) \\\\\n", + "&=\n", + "\\begin{pmatrix}\n", + " b_i^{\\text{hidden}} & w_i^{\\text{hidden}}\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "1 & 1 & \\dots & 1 \\\\\n", + "x_1 & x_2 & \\dots & x_N\n", + "\\end{pmatrix} \\\\\n", + "&= \\boldsymbol{p}_{i, \\text{hidden}}^T X\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The vector $\\boldsymbol{p}_{i, \\text{hidden}}^T$ constitutes each row in $P_{\\text{hidden} }$, which contains the weights for the neural network to minimize according to ([9](#min)).\n", + "\n", + "After having found $\\boldsymbol{z}_{i}^{\\text{hidden}} $ for every $i$-th neuron within the hidden layer, the vector will be sent to an activation function $a_i(\\boldsymbol{z})$.\n", + "\n", + "In this example, the sigmoid function has been chosen to be the activation function for each hidden neuron:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "f(z) = \\frac{1}{1 + \\exp{(-z)}}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is possible to use other activations functions for the hidden layer also.\n", + "\n", + "The output $\\boldsymbol{x}_i^{\\text{hidden}}$ from each $i$-th hidden neuron is:\n", + "\n", + "$$\n", + "\\boldsymbol{x}_i^{\\text{hidden} } = f\\big( \\boldsymbol{z}_{i}^{\\text{hidden}} \\big)\n", + "$$\n", + "\n", + "The outputs $\\boldsymbol{x}_i^{\\text{hidden} } $ are then sent to the output layer.\n", + "\n", + "The output layer consists of one neuron in this case, and combines the\n", + "output from each of the neurons in the hidden layers. The output layer\n", + "combines the results from the hidden layer using some weights $w_i^{\\text{output}}$\n", + "and biases $b_i^{\\text{output}}$. In this case,\n", + "it is assumes that the number of neurons in the output layer is one.\n", + "\n", + "\n", + "\n", + "The procedure of weighting the output neuron $j$ in the hidden layer to the $i$-th neuron in the output layer is similar as for the hidden layer described previously." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "z_{1,j}^{\\text{output}} & =\n", + "\\begin{pmatrix}\n", + "b_1^{\\text{output}} & \\boldsymbol{w}_1^{\\text{output}}\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "1 \\\\\n", + "\\boldsymbol{x}_j^{\\text{hidden}}\n", + "\\end{pmatrix}\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Expressing $z_{1,j}^{\\text{output}}$ as a vector gives the following way of weighting the inputs from the hidden layer:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\boldsymbol{z}_{1}^{\\text{output}} =\n", + "\\begin{pmatrix}\n", + "b_1^{\\text{output}} & \\boldsymbol{w}_1^{\\text{output}}\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "1 & 1 & \\dots & 1 \\\\\n", + "\\boldsymbol{x}_1^{\\text{hidden}} & \\boldsymbol{x}_2^{\\text{hidden}} & \\dots & \\boldsymbol{x}_N^{\\text{hidden}}\n", + "\\end{pmatrix}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case we seek a continuous range of values since we are approximating a function. This means that after computing $\\boldsymbol{z}_{1}^{\\text{output}}$ the neural network has finished its feed forward step, and $\\boldsymbol{z}_{1}^{\\text{output}}$ is the final output of the network.\n", + "\n", + "\n", + "The next step is to decide how the parameters should be changed such that they minimize the cost function.\n", + "\n", + "The chosen cost function for this problem is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C(\\boldsymbol{x}, P) = \\frac{1}{N} \\sum_i \\big(g_t'(x_i, P) - ( -\\gamma g_t(x_i, P) \\big)^2\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to minimize the cost function, an optimization method must be chosen.\n", + "\n", + "Here, gradient descent with a constant step size has been chosen.\n", + "\n", + "### Gradient descent\n", + "\n", + "The idea of the gradient descent algorithm is to update parameters in\n", + "a direction where the cost function decreases goes to a minimum.\n", + "\n", + "In general, the update of some parameters $\\boldsymbol{\\omega}$ given a cost\n", + "function defined by some weights $\\boldsymbol{\\omega}$, $C(\\boldsymbol{x},\n", + "\\boldsymbol{\\omega})$, goes as follows:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\boldsymbol{\\omega}_{\\text{new} } = \\boldsymbol{\\omega} - \\lambda \\nabla_{\\boldsymbol{\\omega}} C(\\boldsymbol{x}, \\boldsymbol{\\omega})\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "for a number of iterations or until $ \\big|\\big| \\boldsymbol{\\omega}_{\\text{new} } - \\boldsymbol{\\omega} \\big|\\big|$ becomes smaller than some given tolerance.\n", + "\n", + "The value of $\\lambda$ decides how large steps the algorithm must take\n", + "in the direction of $ \\nabla_{\\boldsymbol{\\omega}} C(\\boldsymbol{x}, \\boldsymbol{\\omega})$.\n", + "The notation $\\nabla_{\\boldsymbol{\\omega}}$ express the gradient with respect\n", + "to the elements in $\\boldsymbol{\\omega}$.\n", + "\n", + "In our case, we have to minimize the cost function $C(\\boldsymbol{x}, P)$ with\n", + "respect to the two sets of weights and biases, that is for the hidden\n", + "layer $P_{\\text{hidden} }$ and for the output layer $P_{\\text{output}\n", + "}$ .\n", + "\n", + "This means that $P_{\\text{hidden} }$ and $P_{\\text{output} }$ is updated by" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "P_{\\text{hidden},\\text{new}} &= P_{\\text{hidden}} - \\lambda \\nabla_{P_{\\text{hidden}}} C(\\boldsymbol{x}, P) \\\\\n", + "P_{\\text{output},\\text{new}} &= P_{\\text{output}} - \\lambda \\nabla_{P_{\\text{output}}} C(\\boldsymbol{x}, P)\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The code for solving the ODE" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial cost: 367.01\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final cost: 0.0666807\n", + "Max absolute difference: 0.0437499\n" + ] + }, + { + "data": { + "image/png": "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4hgvSZK0/pYtW8aECRNYvHhx0lEqhcLCQlq2bEl+fn6Zr2PxkiSpipgwYQK1a9emdevWhBCSjlOhxRiZMWMGEyZMoE2bNmW+nrsaJUmqIhYvXkzDhg0tXRtACIGGDRuu9eihxUuSpCrE0rXhrMtjafGSJEnKEIuXJEmqcB599FHOPvvsNV5m0qRJv/5+yimnMHLkyLW+rz59+nDIIYes9fVWxuIlSZIqpdLF68EHH6Rjx44JJrJ4SZKkDOvevTtdunShU6dO3H///QDUqlWLK664gm222YZu3boxdepUAN544w123HFHtt12W/bZZ59f/77CvHnzaNOmDcuWLQNg7ty5tGnThhdeeIHBgwfTq1cvOnfuzKJFi9hjjz1+/QrCd955h+22245tttmGvffeG4CBAwey0047se2227LzzjszatSoDT7vnk5CkqQq6Oo3RjBy0twNepsdN6rDlb/vtMbLPfzwwzRo0IBFixax/fbbc+SRR7JgwQK6devGv//9by655BIeeOAB/va3v7HrrrvSv39/Qgg8+OCD3Hjjjdxyyy2/3lbt2rXZY489eOutt+jevTvPPvssRxxxBD169OCuu+7i5ptvpmvXrr+5/+nTp3PqqafSt29f2rRpw8yZMwHYfPPN+fTTT8nLy+ODDz7g8ssv56WXXtqgj5HFS5IkZdTtt9/OK6+8AsD48eP54YcfKCgo+PU4qi5duvD+++8DqXOP/eEPf2Dy5MksXbp0pefMOuWUU7jxxhvp3r07jzzyCA888MBq779///787ne/+/W2GjRoAMCcOXM44YQT+OGHHwgh/DqKtiFZvCRJqoLKMjJVHvr06cMHH3zAF198QY0aNdhjjz1YvHgx+fn5v56eITc3l+XLlwNwzjnn8Je//IVDDz2UPn36cNVVV/3Pbe6yyy6MGTOGPn36UFRUxJZbbrlO2f7+97+z55578sorrzBmzBj22GOPdZ3NVfIYL0mSlDFz5syhfv361KhRg++++47+/fuv8fItWrQA4LHHHlvl5Y4//nh69uzJSSed9Ovfateuzbx58/7nst26daNv3778/PPPAL/uaix5X48++uhazVdZWbwkSVLGHHDAASxfvpwtttiCv/71r3Tr1m21l7/qqqvo0aMHXbp0oVGjRqu8XK9evZg1axbHHHPMr3878cQTOeOMM349uH6Fxo0b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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "filenames": { + "image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter11_47_2.png" + }, + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "\n", + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "# Assuming one input, hidden, and output layer\n", + "def neural_network(params, x):\n", + "\n", + " # Find the weights (including and biases) for the hidden and output layer.\n", + " # Assume that params is a list of parameters for each layer.\n", + " # The biases are the first element for each array in params,\n", + " # and the weights are the remaning elements in each array in params.\n", + "\n", + " w_hidden = params[0]\n", + " w_output = params[1]\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " ## Hidden layer:\n", + "\n", + " # Add a row of ones to include bias\n", + " x_input = np.concatenate((np.ones((1,num_values)), x_input ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_input)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " ## Output layer:\n", + "\n", + " # Include bias:\n", + " x_hidden = np.concatenate((np.ones((1,num_values)), x_hidden ), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_hidden)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "# The trial solution using the deep neural network:\n", + "def g_trial(x,params, g0 = 10):\n", + " return g0 + x*neural_network(params,x)\n", + "\n", + "# The right side of the ODE:\n", + "def g(x, g_trial, gamma = 2):\n", + " return -gamma*g_trial\n", + "\n", + "# The cost function:\n", + "def cost_function(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the neural network\n", + " d_net_out = elementwise_grad(neural_network,1)(P,x)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d_g_t = elementwise_grad(g_trial,0)(x,P)\n", + "\n", + " # The right side of the ODE\n", + " func = g(x, g_t)\n", + "\n", + " err_sqr = (d_g_t - func)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum / np.size(err_sqr)\n", + "\n", + "# Solve the exponential decay ODE using neural network with one input, hidden, and output layer\n", + "def solve_ode_neural_network(x, num_neurons_hidden, num_iter, lmb):\n", + " ## Set up initial weights and biases\n", + "\n", + " # For the hidden layer\n", + " p0 = npr.randn(num_neurons_hidden, 2 )\n", + "\n", + " # For the output layer\n", + " p1 = npr.randn(1, num_neurons_hidden + 1 ) # +1 since bias is included\n", + "\n", + " P = [p0, p1]\n", + "\n", + " print('Initial cost: %g'%cost_function(P, x))\n", + "\n", + " ## Start finding the optimal weights using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_grad = grad(cost_function,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of two arrays;\n", + " # one for the gradient w.r.t P_hidden and\n", + " # one for the gradient w.r.t P_output\n", + " cost_grad = cost_function_grad(P, x)\n", + "\n", + " P[0] = P[0] - lmb * cost_grad[0]\n", + " P[1] = P[1] - lmb * cost_grad[1]\n", + "\n", + " print('Final cost: %g'%cost_function(P, x))\n", + "\n", + " return P\n", + "\n", + "def g_analytic(x, gamma = 2, g0 = 10):\n", + " return g0*np.exp(-gamma*x)\n", + "\n", + "# Solve the given problem\n", + "if __name__ == '__main__':\n", + " # Set seed such that the weight are initialized\n", + " # with same weights and biases for every run.\n", + " npr.seed(15)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " N = 10\n", + " x = np.linspace(0, 1, N)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = 10\n", + " num_iter = 10000\n", + " lmb = 0.001\n", + "\n", + " # Use the network\n", + " P = solve_ode_neural_network(x, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " # Print the deviation from the trial solution and true solution\n", + " res = g_trial(x,P)\n", + " res_analytical = g_analytic(x)\n", + "\n", + " print('Max absolute difference: %g'%np.max(np.abs(res - res_analytical)))\n", + "\n", + " # Plot the results\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(x, res_analytical)\n", + " plt.plot(x, res[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('x')\n", + " plt.ylabel('g(x)')\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The network with one input layer, specified number of hidden layers, and one output layer\n", + "\n", + "It is also possible to extend the construction of our network into a more general one, allowing the network to contain more than one hidden layers.\n", + "\n", + "The number of neurons within each hidden layer are given as a list of integers in the program below." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial cost: 324.246\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/numpy/core/_asarray.py:83: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n", + " return array(a, dtype, copy=False, order=order)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final cost: 0.119936\n" + ] + }, + { + "data": { + "image/png": "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F2dXZSTOd1N19n4iWiRoGWPicd5kdHY3SejSrkYRERERH9GuRhEREREfCYhdjRUqVLC1atVyO4aIiIhIvhYuXLjXWpvrl28HRPGqVasWcXFxbscQERERyZcxJs9fUdCuRhEREREfUfESERER8REVLxEREREfCYhjvEREROTUpaens23bNlJTU92OEhSio6OpVq0aERERBb6NipeIiEiI2LZtGyVLlqRWrVo4v0stJ8taS2JiItu2baN27doFvp12NYqIiISI1NRUypcvr9JVCIwxlC9f/oRHD1W8REREQohKV+E5mXmp4iUiIiLiIypeIiIiEnAGDBhA3759873Ojh07/jndq1cvVq5cecKPNXXqVK655poTvl1uVLxEREQkKOUsXv3796dRo0YuJlLxEhERER/r3LkzLVu2pHHjxnz99dcAlChRgueee46mTZtyzjnnsHv3bgDGjBlDmzZtaN68OR06dPjn/GOSk5OpXbs26enpABw8eJDatWszfPhw4uLi6NmzJ82aNePIkSO0a9fun58g/P3332nRogVNmzalffv2AMyfP59zzz2X5s2bc95557FmzZpCn3Z9nYSIiEgIemXMClbuOFio99moSileurZxvtf77rvvKFeuHEeOHKF169Zcf/31HD58mHPOOYc33niDJ598km+++Ybnn3+e888/n7lz52KMoX///rzzzju8//77/9xXyZIladeuHePGjaNz584MGzaMLl260LVrVz777DPee+89WrVq9a/HT0hI4O6772b69OnUrl2bffv2AXDGGWcwY8YMwsPDmTRpEs8++yy//PJLoc4jFS8RERHxqY8//piRI0cCsHXrVtatW0dkZOQ/x1G1bNmSiRMnAs53j3Xr1o2dO3dy9OjRXL8zq1evXrzzzjt07tyZ77//nm+++ea4jz937lwuvPDCf+6rXLlyACQlJXHbbbexbt06jDH/jKIVJhUvERGREFSQkamiMHXqVCZNmsScOXOIiYmhXbt2pKamEhER8c/XM4SFhZGRkQHAAw88wKOPPkrHjh2ZOnUqL7/88n/us23btsTHxzN16lQyMzNp0qTJSWV74YUXuPjiixk5ciTx8fG0a9fuZCczTzrGS0RERHwmKSmJsmXLEhMTw+rVq5k7d26+169atSoAAwcOzPN6t956Kz169OCOO+7457ySJUuSnJz8n+uec845TJ8+nU2bNgH8s6sx+2MNGDDghKaroFS8RERExGeuuOIKMjIyaNiwIU8//TTnnHPOca//8ssv07VrV1q2bEmFChXyvF7Pnj3Zv38/3bt3/+e822+/nd69e/9zcP0xsbGxfP3113Tp0oWmTZvSrVs3AJ588kmeeeYZmjdv/s+IW2Ez1toiuePC1KpVK3vsUwgiIiJyclatWkXDhg3djlEkRowYwejRoxk8eLBPHze3eWqMWWitbZXb9XWMl4iIiAS0Bx54gAkTJjB+/Hi3o+RLxUtEREQC2ieffOJ2hALTMV4iIiIiPlJkxcsY850xZo8xZnm288oZYyYaY9Z5/y1bVI8vIiIi4m+KcsRrAHBFjvOeBv6y1tYD/vKe9gsZ6UfdjiAiIiJBrsiKl7V2OrAvx9mdgGNfwjEQ6FxUj38i5gx8lo3/a0tWZqbbUURERCSI+foYr0rW2p3e/+8CKuV1RWPMPcaYOGNMXEJCQpGGCi9bg/oZa1k6aWiRPo6IiIj828svv8x7773ndgyfce3geut8gVieXyJmrf3aWtvKWtsqNja2SLM0v/IutpgqlJ7/PjZLo14iIiJSNHxdvHYbYyoDeP/d4+PHz1V4RAS7mj3I6ZnxLJ30g9txREREgtobb7xB/fr1Of/881mzZg0A7dq146mnnuLss8+mfv36zJgxA3B+uqdLly5cccUV1KtXjyeffNLN6KfM19/j9RtwG/C299/RPn78PLW46i62LPmYUvPex3bogfGEuR1JRESk6Ex4Gnb9Xbj3edqZcOXbx73KwoULGTZsGEuWLCEjI4MWLVrQsmVLADIyMpg/fz7jx4/nlVdeYdKkSQAsWbKExYsXExUVRYMGDXjggQeoXr164Wb3kaL8OokfgTlAA2PMNmPMXTiF61JjzDqgg/e0XwiPiGRH0wc4PXMTf/+lUS8REZGiMGPGDK677jpiYmIoVaoUHTt2/OeyLl26ANCyZUvi4+P/Ob99+/aULl2a6OhoGjVqxObNm30du9AU2YiXtbZ7Hhe1L6rHPFUtr+7FlqWfUGLu+9j2GvUSEZEgls/IlBuioqIACAsL+9ePVB87P7fLAo2+uT6biIhIdpzVl9MzN7F8yjC344iIiASdCy+8kFGjRnHkyBGSk5MZM2aM25F8SsUrhxZX380WU5nic97DZmW5HUdERCSotGjRgm7dutG0aVOuvPJKWrdu7XYknzLOtzr4t1atWtm4uDifPd7sXz/jvGXPsvyCL2jSvofPHldERKQorVq1ioYNG7odI6jkNk+NMQutta1yu75GvHLR6hpn1Ctmzrsa9RIREZFCo+KVi8jISLY26cPpGRtZNVXHeomIiEjhUPHKQ6tr72ErlSk2W6NeIiISPALhEKNAcTLzUsUrD1GRUcQ36UPtjI2snvaT23FEREROWXR0NImJiSpfhcBaS2JiItHR0Sd0O19/c31AaX3tPWxd/inRs96FdjeBMW5HEhEROWnVqlVj27ZtJCQkuB0lKERHR1OtWrUTuo2K13FER0WxqXEfLlzxAmum/USDdje5HUlEROSkRUREULt2bbdjhDTtaszH2R3vZQunETnrXdDQrIiIiJwCFa98REdFsanRfdROX8/a6T+7HUdEREQCmIpXAZzd8T62chqRM9/RqJeIiIicNBWvAigWHcWGhvdRK30962dq1EtEREROjopXAZ3dqTdbOY3w6Rr1EhERkZOj4lVAMdHRrD+jN7XS17Nh1gi344iIiEgAUvE6AWd3uo8tVCJs+v806iUiIiInTMXrBBQvFs26Br2pdXQdG2f/4nYcERERCTAqXieoTef72UIlPNPe1qiXiIiInBAVrxNUolg06+rfS62j64jXqJeIiIicABWvk9C6031spRJM07FeIiIiUnAqXiehVPEYVte7l1pH17J5zq9uxxEREZEAoeJ1ks7+Z9RLx3qJiIhIwah4naTSJWJYWfceaqatZeu8kW7HERERkQCg4nUKzul0P9tsRbKmvKVRLxEREcmXitcpKF0yhhXeUa9t80e7HUdERET8nIrXKWrT+X622opkTn5To14iIiJyXCpep6hMyeIsr3M3NdPWsH2BRr1EREQkbypehaBN5z5stRXJ0KiXiIiIHIeKVyEoV6o4f59+NzVT17Aj7je344iIiIifUvEqJG063882G0v6Xxr1EhERkdypeBWS8qVLsPT0u6mZupqdGvUSERGRXKh4FaKzO/XRqJeIiIjkScWrEMWWKcGSWr2okbqa3QvHuB1HRERE/IyKVyE7+zrnWK80jXqJiIhIDipehaximVIsqnUXNY6sYs+isW7HERERET+i4lUEnO/1iiV10hsa9RIREZF/qHgVgUplS7G4xp3UOLKKhMUa9RIRERGH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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "filenames": { + "image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter11_49_3.png" + }, + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "# The neural network with one input layer and one output layer,\n", + "# but with number of hidden layers specified by the user.\n", + "def deep_neural_network(deep_params, x):\n", + " # N_hidden is the number of hidden layers\n", + "\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consists of\n", + " # parameters to all the hidden\n", + " # layers AND the output layer.\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " # Due to multiple hidden layers, define a variable referencing to the\n", + " # output of the previous layer:\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "# The trial solution using the deep neural network:\n", + "def g_trial_deep(x,params, g0 = 10):\n", + " return g0 + x*deep_neural_network(params, x)\n", + "\n", + "# The right side of the ODE:\n", + "def g(x, g_trial, gamma = 2):\n", + " return -gamma*g_trial\n", + "\n", + "# The same cost function as before, but calls deep_neural_network instead.\n", + "def cost_function_deep(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial_deep(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the neural network\n", + " d_net_out = elementwise_grad(deep_neural_network,1)(P,x)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d_g_t = elementwise_grad(g_trial_deep,0)(x,P)\n", + "\n", + " # The right side of the ODE\n", + " func = g(x, g_t)\n", + "\n", + " err_sqr = (d_g_t - func)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum / np.size(err_sqr)\n", + "\n", + "# Solve the exponential decay ODE using neural network with one input and one output layer,\n", + "# but with specified number of hidden layers from the user.\n", + "def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb):\n", + " # num_hidden_neurons is now a list of number of neurons within each hidden layer\n", + "\n", + " # The number of elements in the list num_hidden_neurons thus represents\n", + " # the number of hidden layers.\n", + "\n", + " # Find the number of hidden layers:\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weights and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 )\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: %g'%cost_function_deep(P, x))\n", + "\n", + " ## Start finding the optimal weights using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_deep_grad = grad(cost_function_deep,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases\n", + " # in the hidden layers and output layers evaluated at x.\n", + " cost_deep_grad = cost_function_deep_grad(P, x)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_deep_grad[l]\n", + "\n", + " print('Final cost: %g'%cost_function_deep(P, x))\n", + "\n", + " return P\n", + "\n", + "def g_analytic(x, gamma = 2, g0 = 10):\n", + " return g0*np.exp(-gamma*x)\n", + "\n", + "# Solve the given problem\n", + "if __name__ == '__main__':\n", + " npr.seed(15)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " N = 10\n", + " x = np.linspace(0, 1, N)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = np.array([10,10])\n", + " num_iter = 10000\n", + " lmb = 0.001\n", + "\n", + " P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " res = g_trial_deep(x,P)\n", + " res_analytical = g_analytic(x)\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of a deep neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(x, res_analytical)\n", + " plt.plot(x, res[0,:])\n", + " plt.legend(['analytical','dnn'])\n", + " plt.ylabel('g(x)')\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example: Population growth\n", + "\n", + "A logistic model of population growth assumes that a population converges toward an equilibrium.\n", + "The population growth can be modeled by" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{log} \\tag{10}\n", + "\tg'(t) = \\alpha g(t)(A - g(t))\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $g(t)$ is the population density at time $t$, $\\alpha > 0$ the growth rate and $A > 0$ is the maximum population number in the environment.\n", + "Also, at $t = 0$ the population has the size $g(0) = g_0$, where $g_0$ is some chosen constant.\n", + "\n", + "In this example, similar network as for the exponential decay using Autograd has been used to solve the equation. However, as the implementation might suffer from e.g numerical instability\n", + "and high execution time (this might be more apparent in the examples solving PDEs),\n", + "using a library like TensorFlow is recommended.\n", + "Here, we stay with a more simple approach and implement for comparison, the simple forward Euler method.\n", + "\n", + "\n", + "\n", + "Here, we will model a population $g(t)$ in an environment having carrying capacity $A$.\n", + "The population follows the model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{solveode_population} \\tag{11}\n", + "g'(t) = \\alpha g(t)(A - g(t))\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $g(0) = g_0$.\n", + "\n", + "In this example, we let $\\alpha = 2$, $A = 1$, and $g_0 = 1.2$.\n", + "\n", + "\n", + "We will get a slightly different trial solution, as the boundary conditions are different\n", + "compared to the case for exponential decay.\n", + "\n", + "A possible trial solution satisfying the condition $g(0) = g_0$ could be\n", + "\n", + "$$\n", + "h_1(t) = g_0 + t \\cdot N(t,P)\n", + "$$\n", + "\n", + "with $N(t,P)$ being the output from the neural network with weights and biases for each layer collected in the set $P$.\n", + "\n", + "The analytical solution is\n", + "\n", + "$$\n", + "g(t) = \\frac{Ag_0}{g_0 + (A - g_0)\\exp(-\\alpha A t)}\n", + "$$\n", + "\n", + "\n", + "\n", + "The network will be the similar as for the exponential decay example, but with some small modifications for our problem." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial cost: 0.221805\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/numpy/core/_asarray.py:83: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n", + " return array(a, dtype, copy=False, order=order)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final cost: 0.000417932\n", + "The max absolute difference between the solutions is: 0.00424909\n" + ] + }, + { + "data": { + "image/png": "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P8fyWSq4iYiIiIQJBTcREREpcoYMGcKNN954xHHWrVv39/Orr76aBQsWHPV7jR07lh49ehz163Ki4CYiIiKSg+zB7Z133qFx48Y+VqTgJiIiImGmd+/etG7dmiZNmjB48GAASpUqxf3330/z5s1p3749GzduBGDUqFG0a9eOli1b0q1bt7+HH7Br1y5q165NWloaADt37qR27dp8/vnnTJs2jcsuu4wWLVqwb98+unbt+vctNH/44QdatWpF8+bNOfXUUwGYMmUKJ554Ii1btqRDhw4sWrQo3+dd3YGIiIjIUXtk1HwWrNuZr9NsXLU0D53T5Ijjvffee8THx7Nv3z5OOOEEzjvvPPbs2UP79u154oknuPvuu3n77bd54IEH6NixI5MmTcLMeOedd3jmmWd47rnn/p5WXFwcXbt25bvvvqN3794MGzaMPn36cMEFF/Daa6/x7LPP0qZNm0PePzk5mWuuuYbx48dTu3Zttm7dCkDDhg35/fffiYqK4pdffuG+++5jxIgR+foZKbiJiIhIWHn55ZcZOXIkAGvWrGHJkiXExMT8fR5Z69at+fnnnwGv77mLLrqI9evXs3///hz7TLv66qt55pln6N27N++//z5vv/32Yd9/0qRJdO7c+e9pxcfHA7Bjxw769evHkiVLMLO/9+LlJwU3EREROWp52TMWDGPHjuWXX35h4sSJlChRgq5du5KSkkJ0dPTf3WtERkaSnp4OwE033cTtt99Oz549GTt2LA8//PA/pnnSSSexcuVKxo4dS0ZGBk2bNj2m2v773/9y8sknM3LkSFauXEnXrl2PdTZzpXPcREREJGzs2LGDcuXKUaJECRYuXMikSZOOOH61atUA+OCDD3Id74orruDSSy/lyiuv/HtYXFwcu3bt+se47du3Z/z48axYsQLg70OlWd9ryJAhRzVfeaXgJiIiImGje/fupKen06hRI+69917at29/2PEffvhhLrjgAlq3bk2FChVyHe+yyy5j27ZtXHLJJX8P69+/P4MGDfr74oQDEhISGDx4MH369KF58+ZcdNFFANx999385z//oWXLln/v8ctv5pwLyoRDSZs2bdyBq0BERETk2Pz11180atTI7zKC4osvvuDrr7/mo48+KtD3zekzNbPpzrk2OY2vc9xERESkSLvpppv4/vvvGT16tN+lHJGCm4iIiBRp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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "filenames": { + "image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter11_55_3.png" + }, + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "# Function to get the parameters.\n", + "# Done such that one can easily change the paramaters after one's liking.\n", + "def get_parameters():\n", + " alpha = 2\n", + " A = 1\n", + " g0 = 1.2\n", + " return alpha, A, g0\n", + "\n", + "def deep_neural_network(P, x):\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(P) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " # Due to multiple hidden layers, define a variable referencing to the\n", + " # output of the previous layer:\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = P[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = P[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "\n", + "def cost_function_deep(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial_deep(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d_g_t = elementwise_grad(g_trial_deep,0)(x,P)\n", + "\n", + " # The right side of the ODE\n", + " func = f(x, g_t)\n", + "\n", + " err_sqr = (d_g_t - func)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum / np.size(err_sqr)\n", + "\n", + "# The right side of the ODE:\n", + "def f(x, g_trial):\n", + " alpha,A, g0 = get_parameters()\n", + " return alpha*g_trial*(A - g_trial)\n", + "\n", + "# The trial solution using the deep neural network:\n", + "def g_trial_deep(x, params):\n", + " alpha,A, g0 = get_parameters()\n", + " return g0 + x*deep_neural_network(params,x)\n", + "\n", + "# The analytical solution:\n", + "def g_analytic(t):\n", + " alpha,A, g0 = get_parameters()\n", + " return A*g0/(g0 + (A - g0)*np.exp(-alpha*A*t))\n", + "\n", + "def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb):\n", + " # num_hidden_neurons is now a list of number of neurons within each hidden layer\n", + "\n", + " # Find the number of hidden layers:\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 )\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: %g'%cost_function_deep(P, x))\n", + "\n", + " ## Start finding the optimal weigths using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_deep_grad = grad(cost_function_deep,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases\n", + " # in the hidden layers and output layers evaluated at x.\n", + " cost_deep_grad = cost_function_deep_grad(P, x)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_deep_grad[l]\n", + "\n", + " print('Final cost: %g'%cost_function_deep(P, x))\n", + "\n", + " return P\n", + "\n", + "if __name__ == '__main__':\n", + " npr.seed(4155)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nt = 10\n", + " T = 1\n", + " t = np.linspace(0,T, Nt)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = [100, 50, 25]\n", + " num_iter = 1000\n", + " lmb = 1e-3\n", + "\n", + " P = solve_ode_deep_neural_network(t, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " g_dnn_ag = g_trial_deep(t,P)\n", + " g_analytical = g_analytic(t)\n", + "\n", + " # Find the maximum absolute difference between the solutons:\n", + " diff_ag = np.max(np.abs(g_dnn_ag - g_analytical))\n", + " print(\"The max absolute difference between the solutions is: %g\"%diff_ag)\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(t, g_analytical)\n", + " plt.plot(t, g_dnn_ag[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('t')\n", + " plt.ylabel('g(t)')\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using forward Euler to solve the ODE\n", + "\n", + "A straightforward way of solving an ODE numerically, is to use Euler's method.\n", + "\n", + "Euler's method uses Taylor series to approximate the value at a function $f$ at a step $\\Delta x$ from $x$:\n", + "\n", + "$$\n", + "f(x + \\Delta x) \\approx f(x) + \\Delta x f'(x)\n", + "$$\n", + "\n", + "In our case, using Euler's method to approximate the value of $g$ at a step $\\Delta t$ from $t$ yields" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + " g(t + \\Delta t) &\\approx g(t) + \\Delta t g'(t) \\\\\n", + " &= g(t) + \\Delta t \\big(\\alpha g(t)(A - g(t))\\big)\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "along with the condition that $g(0) = g_0$.\n", + "\n", + "Let $t_i = i \\cdot \\Delta t$ where $\\Delta t = \\frac{T}{N_t-1}$ where $T$ is the final time our solver must solve for and $N_t$ the number of values for $t \\in [0, T]$ for $i = 0, \\dots, N_t-1$.\n", + "\n", + "For $i \\geq 1$, we have that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "t_i &= i\\Delta t \\\\\n", + "&= (i - 1)\\Delta t + \\Delta t \\\\\n", + "&= t_{i-1} + \\Delta t\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, if $g_i = g(t_i)$ then" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + " \\begin{aligned}\n", + " g_i &= g(t_i) \\\\\n", + " &= g(t_{i-1} + \\Delta t) \\\\\n", + " &\\approx g(t_{i-1}) + \\Delta t \\big(\\alpha g(t_{i-1})(A - g(t_{i-1}))\\big) \\\\\n", + " &= g_{i-1} + \\Delta t \\big(\\alpha g_{i-1}(A - g_{i-1})\\big)\n", + " \\end{aligned}\n", + "\\end{equation} \\label{odenum} \\tag{12}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "for $i \\geq 1$ and $g_0 = g(t_0) = g(0) = g_0$.\n", + "\n", + "Equation ([12](#odenum)) could be implemented in the following way,\n", + "extending the program that uses the network using Autograd:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial cost: 0.221805\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/numpy/core/_asarray.py:83: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n", + " return array(a, dtype, copy=False, order=order)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final cost: 0.000417932\n", + "The max absolute difference between the solutions is: 0.00424909\n", + "Max absolute difference between Euler method and analytical: 0.011225\n", + "Max absolute difference between deep neural network and analytical: 0.00424909\n" + ] + }, + { + "data": { + "image/png": "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P8fyWSq4iYiIiIQJBTcREREpcoYMGcKNN954xHHWrVv39/Orr76aBQsWHPV7jR07lh49ehz163Ki4CYiIiKSg+zB7Z133qFx48Y+VqTgJiIiImGmd+/etG7dmiZNmjB48GAASpUqxf3330/z5s1p3749GzduBGDUqFG0a9eOli1b0q1bt7+HH7Br1y5q165NWloaADt37qR27dp8/vnnTJs2jcsuu4wWLVqwb98+unbt+vctNH/44QdatWpF8+bNOfXUUwGYMmUKJ554Ii1btqRDhw4sWrQo3+dd3YGIiIjIUXtk1HwWrNuZr9NsXLU0D53T5Ijjvffee8THx7Nv3z5OOOEEzjvvPPbs2UP79u154oknuPvuu3n77bd54IEH6NixI5MmTcLMeOedd3jmmWd47rnn/p5WXFwcXbt25bvvvqN3794MGzaMPn36cMEFF/Daa6/x7LPP0qZNm0PePzk5mWuuuYbx48dTu3Zttm7dCkDDhg35/fffiYqK4pdffuG+++5jxIgR+foZKbiJiIhIWHn55ZcZOXIkAGvWrGHJkiXExMT8fR5Z69at+fnnnwGv77mLLrqI9evXs3///hz7TLv66qt55pln6N27N++//z5vv/32Yd9/0qRJdO7c+e9pxcfHA7Bjxw769evHkiVLMLO/9+LlJwU3EREROWp52TMWDGPHjuWXX35h4sSJlChRgq5du5KSkkJ0dPTf3WtERkaSnp4OwE033cTtt99Oz549GTt2LA8//PA/pnnSSSexcuVKxo4dS0ZGBk2bNj2m2v773/9y8sknM3LkSFauXEnXrl2PdTZzpXPcREREJGzs2LGDcuXKUaJECRYuXMikSZOOOH61atUA+OCDD3Id74orruDSSy/lyiuv/HtYXFwcu3bt+se47du3Z/z48axYsQLg70OlWd9ryJAhRzVfeaXgJiIiImGje/fupKen06hRI+69917at29/2PEffvhhLrjgAlq3bk2FChVyHe+yyy5j27ZtXHLJJX8P69+/P4MGDfr74oQDEhISGDx4MH369KF58+ZcdNFFANx999385z//oWXLln/v8ctv5pwLyoRDSZs2bdyBq0BERETk2Pz11180atTI7zKC4osvvuDrr7/mo48+KtD3zekzNbPpzrk2OY2vc9xERESkSLvpppv4/vvvGT16tN+lHJGCm4iIiBRp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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "filenames": { + "image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter11_63_3.png" + }, + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "filenames": { + "image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter11_63_4.png" + }, + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Assume that all function definitions from the example program using Autograd\n", + "# are located here.\n", + "\n", + "if __name__ == '__main__':\n", + " npr.seed(4155)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nt = 10\n", + " T = 1\n", + " t = np.linspace(0,T, Nt)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = [100,50,25]\n", + " num_iter = 1000\n", + " lmb = 1e-3\n", + "\n", + " P = solve_ode_deep_neural_network(t, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " g_dnn_ag = g_trial_deep(t,P)\n", + " g_analytical = g_analytic(t)\n", + "\n", + " # Find the maximum absolute difference between the solutons:\n", + " diff_ag = np.max(np.abs(g_dnn_ag - g_analytical))\n", + " print(\"The max absolute difference between the solutions is: %g\"%diff_ag)\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(t, g_analytical)\n", + " plt.plot(t, g_dnn_ag[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('t')\n", + " plt.ylabel('g(t)')\n", + "\n", + " ## Find an approximation to the funtion using forward Euler\n", + "\n", + " alpha, A, g0 = get_parameters()\n", + " dt = T/(Nt - 1)\n", + "\n", + " # Perform forward Euler to solve the ODE\n", + " g_euler = np.zeros(Nt)\n", + " g_euler[0] = g0\n", + "\n", + " for i in range(1,Nt):\n", + " g_euler[i] = g_euler[i-1] + dt*(alpha*g_euler[i-1]*(A - g_euler[i-1]))\n", + "\n", + " # Print the errors done by each method\n", + " diff1 = np.max(np.abs(g_euler - g_analytical))\n", + " diff2 = np.max(np.abs(g_dnn_ag[0,:] - g_analytical))\n", + "\n", + " print('Max absolute difference between Euler method and analytical: %g'%diff1)\n", + " print('Max absolute difference between deep neural network and analytical: %g'%diff2)\n", + "\n", + " # Plot results\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.plot(t,g_euler)\n", + " plt.plot(t,g_analytical)\n", + " plt.plot(t,g_dnn_ag[0,:])\n", + "\n", + " plt.legend(['euler','analytical','dnn'])\n", + " plt.xlabel('Time t')\n", + " plt.ylabel('g(t)')\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Solving the one dimensional Poisson equation\n", + "\n", + "The Poisson equation for $g(x)$ in one dimension is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{poisson} \\tag{13}\n", + " -g''(x) = f(x)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $f(x)$ is a given function for $x \\in (0,1)$.\n", + "\n", + "The conditions that $g(x)$ is chosen to fulfill, are" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + " g(0) &= 0 \\\\\n", + " g(1) &= 0\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This equation can be solved numerically using programs where e.g Autograd and TensorFlow are used.\n", + "The results from the networks can then be compared to the analytical solution.\n", + "In addition, it could be interesting to see how a typical method for numerically solving second order ODEs compares to the neural networks.\n", + "\n", + "\n", + "Here, the function $g(x)$ to solve for follows the equation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "-g''(x) = f(x),\\qquad x \\in (0,1)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $f(x)$ is a given function, along with the chosen conditions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "g(0) = g(1) = 0\n", + "\\end{aligned}\\label{cond} \\tag{14}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, we consider the case when $f(x) = (3x + x^2)\\exp(x)$.\n", + "\n", + "For this case, a possible trial solution satisfying the conditions could be" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "g_t(x) = x \\cdot (1-x) \\cdot N(P,x)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The analytical solution for this problem is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "g(x) = x(1 - x)\\exp(x)\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/numpy/core/_asarray.py:83: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n", + " return array(a, dtype, copy=False, order=order)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial cost: 457.256\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final cost: 0.00310113\n", + "The max absolute difference between the solutions is: 0.000464088\n" + ] + }, + { + "data": { + "image/png": "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REREjlxNTQ15eXlUVla6jhISYmNjSUtLIyoqqtm/oxImIiIShvLy8khMTCQzMxNjjOs4Qc1aS2FhIXl5eWRlZTX79/R1pIiISBiqrKykS5cuKmBtwBhDly5dWrxXUSVMREQkTKmAtZ3WPJcqYSIiIiIOqISJiIhIUHvqqae46aabDnud/Pz8b05fe+21rFmzpsX3NXfuXE477bQW/15TVMJEREQk5DUuYf/6178YMmSIw0QqYSIiIuLQmWeeydixYxk6dCiPPfYYAAkJCfzyl79k5MiRTJo0iV27dgEwe/ZsJk6cyOjRo5k+ffo35x+wf/9+srKyqKmpAaCkpISsrCxefvllFi9ezCWXXMKoUaOoqKhg6tSp30yD+O677zJmzBhGjhzJCSecAMDChQuZPHkyo0eP5qijjmL9+vVt/th1iAoREZEw9/vZq1mTX9KmtzmkV0d+e/rQw17vySefJDk5mYqKCsaPH88555xDWVkZkyZN4o9//CN33HEHjz/+OL/61a+YMmUK8+fPxxjDv/71L+6++27uueeeb24rMTGRqVOn8vbbb3PmmWfy4osvcvbZZ3Peeefx0EMP8be//Y1x48Z96/4LCgr4/ve/z2effUZWVhZFRUUADBo0iM8//5zIyEg+/PBDfvGLX/Dqq6+26XOkEiYiIiLO3H///bz++usA5ObmsnHjRqKjo78ZdzV27Fg++OADwHtsswsuuIAdO3ZQXV3d5DG5rr32Wu6++27OPPNM/v3vf/P4448f8v7nz5/Pscce+81tJScnA1BcXMwVV1zBxo0bMcZ8s3etLamEiYiIhLnm7LHyh7lz5/Lhhx/y1VdfERcXx9SpU6msrCQqKuqbQz5ERERQW1sLwI9+9CNuu+02Zs6cydy5c/nd7373nds8+uijyc7OZu7cudTV1TFs2LBWZfv1r3/N8ccfz+uvv052djZTp05t7cM8KI0JExERESeKi4vp3LkzcXFxrFu3jvnz5x/2+qmpqQA8/fTTB73e5ZdfzsUXX8xVV131zXmJiYns37//O9edNGkSn332GVu3bgX45uvIhvf11FNPtehxNZdKmIiIiDhx8sknU1tby+DBg/nZz37GpEmTDnn93/3ud5x33nmMHTuWrl27HvR6l1xyCXv37uWiiy765rwrr7ySG2644ZuB+QekpKTw2GOPcfbZZzNy5Egu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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "filenames": { + "image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter11_76_3.png" + }, + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " # Due to multiple hidden layers, define a variable referencing to the\n", + " # output of the previous layer:\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb):\n", + " # num_hidden_neurons is now a list of number of neurons within each hidden layer\n", + "\n", + " # Find the number of hidden layers:\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 )\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: %g'%cost_function_deep(P, x))\n", + "\n", + " ## Start finding the optimal weigths using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_deep_grad = grad(cost_function_deep,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases\n", + " # in the hidden layers and output layers evaluated at x.\n", + " cost_deep_grad = cost_function_deep_grad(P, x)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_deep_grad[l]\n", + "\n", + " print('Final cost: %g'%cost_function_deep(P, x))\n", + "\n", + " return P\n", + "\n", + "## Set up the cost function specified for this Poisson equation:\n", + "\n", + "# The right side of the ODE\n", + "def f(x):\n", + " return (3*x + x**2)*np.exp(x)\n", + "\n", + "def cost_function_deep(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial_deep(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d2_g_t = elementwise_grad(elementwise_grad(g_trial_deep,0))(x,P)\n", + "\n", + " right_side = f(x)\n", + "\n", + " err_sqr = (-d2_g_t - right_side)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum/np.size(err_sqr)\n", + "\n", + "# The trial solution:\n", + "def g_trial_deep(x,P):\n", + " return x*(1-x)*deep_neural_network(P,x)\n", + "\n", + "# The analytic solution;\n", + "def g_analytic(x):\n", + " return x*(1-x)*np.exp(x)\n", + "\n", + "if __name__ == '__main__':\n", + " npr.seed(4155)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nx = 10\n", + " x = np.linspace(0,1, Nx)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = [200,100]\n", + " num_iter = 1000\n", + " lmb = 1e-3\n", + "\n", + " P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " g_dnn_ag = g_trial_deep(x,P)\n", + " g_analytical = g_analytic(x)\n", + "\n", + " # Find the maximum absolute difference between the solutons:\n", + " max_diff = np.max(np.abs(g_dnn_ag - g_analytical))\n", + " print(\"The max absolute difference between the solutions is: %g\"%max_diff)\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(x, g_analytical)\n", + " plt.plot(x, g_dnn_ag[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('x')\n", + " plt.ylabel('g(x)')\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Comparing with a numerical scheme\n", + "\n", + "The Poisson equation is possible to solve using Taylor series to approximate the second derivative.\n", + "\n", + "Using Taylor series, the second derivative can be expressed as\n", + "\n", + "$$\n", + "g''(x) = \\frac{g(x + \\Delta x) - 2g(x) + g(x-\\Delta x)}{\\Delta x^2} + E_{\\Delta x}(x)\n", + "$$\n", + "\n", + "where $\\Delta x$ is a small step size and $E_{\\Delta x}(x)$ being the error term.\n", + "\n", + "Looking away from the error terms gives an approximation to the second derivative:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{approx} \\tag{15}\n", + "g''(x) \\approx \\frac{g(x + \\Delta x) - 2g(x) + g(x-\\Delta x)}{\\Delta x^2}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If $x_i = i \\Delta x = x_{i-1} + \\Delta x$ and $g_i = g(x_i)$ for $i = 1,\\dots N_x - 2$ with $N_x$ being the number of values for $x$, ([15](#approx)) becomes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "g''(x_i) &\\approx \\frac{g(x_i + \\Delta x) - 2g(x_i) + g(x_i -\\Delta x)}{\\Delta x^2} \\\\\n", + "&= \\frac{g_{i+1} - 2g_i + g_{i-1}}{\\Delta x^2}\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since we know from our problem that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "-g''(x) &= f(x) \\\\\n", + "&= (3x + x^2)\\exp(x)\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "along with the conditions $g(0) = g(1) = 0$,\n", + "the following scheme can be used to find an approximate solution for $g(x)$ numerically:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + " \\begin{aligned}\n", + " -\\Big( \\frac{g_{i+1} - 2g_i + g_{i-1}}{\\Delta x^2} \\Big) &= f(x_i) \\\\\n", + " -g_{i+1} + 2g_i - g_{i-1} &= \\Delta x^2 f(x_i)\n", + " \\end{aligned}\n", + "\\end{equation} \\label{odesys} \\tag{16}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "for $i = 1, \\dots, N_x - 2$ where $g_0 = g_{N_x - 1} = 0$ and $f(x_i) = (3x_i + x_i^2)\\exp(x_i)$, which is given for our specific problem.\n", + "\n", + "The equation can be rewritten into a matrix equation:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "\\begin{pmatrix}\n", + "2 & -1 & 0 & \\dots & 0 \\\\\n", + "-1 & 2 & -1 & \\dots & 0 \\\\\n", + "\\vdots & & \\ddots & & \\vdots \\\\\n", + "0 & \\dots & -1 & 2 & -1 \\\\\n", + "0 & \\dots & 0 & -1 & 2\\\\\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "g_1 \\\\\n", + "g_2 \\\\\n", + "\\vdots \\\\\n", + "g_{N_x - 3} \\\\\n", + "g_{N_x - 2}\n", + "\\end{pmatrix}\n", + "&=\n", + "\\Delta x^2\n", + "\\begin{pmatrix}\n", + "f(x_1) \\\\\n", + "f(x_2) \\\\\n", + "\\vdots \\\\\n", + "f(x_{N_x - 3}) \\\\\n", + "f(x_{N_x - 2})\n", + "\\end{pmatrix} \\\\\n", + "\\boldsymbol{A}\\boldsymbol{g} &= \\boldsymbol{f},\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "which makes it possible to solve for the vector $\\boldsymbol{g}$.\n", + "\n", + "\n", + "We can then compare the result from this numerical scheme with the output from our network using Autograd:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial cost: 457.256\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/numpy/core/_asarray.py:83: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n", + " return array(a, dtype, copy=False, order=order)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final cost: 0.00310113\n", + "The max absolute difference between the analytical solution and DNN Autograd: 0.000464088\n", + "The max absolute difference between the analytical solution and numerical scheme: 0.00266858\n" + ] + }, + { + "data": { + "image/png": "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REREjlxNTQ15eXlUVla6jhISYmNjSUtLIyoqqtm/oxImIiIShvLy8khMTCQzMxNjjOs4Qc1aS2FhIXl5eWRlZTX79/R1pIiISBiqrKykS5cuKmBtwBhDly5dWrxXUSVMREQkTKmAtZ3WPJcqYSIiIiIOqISJiIhIUHvqqae46aabDnud/Pz8b05fe+21rFmzpsX3NXfuXE477bQW/15TVMJEREQk5DUuYf/6178YMmSIw0QqYSIiIuLQmWeeydixYxk6dCiPPfYYAAkJCfzyl79k5MiRTJo0iV27dgEwe/ZsJk6cyOjRo5k+ffo35x+wf/9+srKyqKmpAaCkpISsrCxefvllFi9ezCWXXMKoUaOoqKhg6tSp30yD+O677zJmzBhGjhzJCSecAMDChQuZPHkyo0eP5qijjmL9+vVt/th1iAoREZEw9/vZq1mTX9KmtzmkV0d+e/rQw17vySefJDk5mYqKCsaPH88555xDWVkZkyZN4o9//CN33HEHjz/+OL/61a+YMmUK8+fPxxjDv/71L+6++27uueeeb24rMTGRqVOn8vbbb3PmmWfy4osvcvbZZ3Peeefx0EMP8be//Y1x48Z96/4LCgr4/ve/z2effUZWVhZFRUUADBo0iM8//5zIyEg+/PBDfvGLX/Dqq6+26XOkEiYiIiLO3H///bz++usA5ObmsnHjRqKjo78ZdzV27Fg++OADwHtsswsuuIAdO3ZQXV3d5DG5rr32Wu6++27OPPNM/v3vf/P4448f8v7nz5/Pscce+81tJScnA1BcXMwVV1zBxo0bMcZ8s3etLamEiYiIhLnm7LHyh7lz5/Lhhx/y1VdfERcXx9SpU6msrCQqKuqbQz5ERERQW1sLwI9+9CNuu+02Zs6cydy5c/nd7373nds8+uijyc7OZu7cudTV1TFs2LBWZfv1r3/N8ccfz+uvv052djZTp05t7cM8KI0JExERESeKi4vp3LkzcXFxrFu3jvnz5x/2+qmpqQA8/fTTB73e5ZdfzsUXX8xVV131zXmJiYns37//O9edNGkSn332GVu3bgX45uvIhvf11FNPtehxNZdKmIiIiDhx8sknU1tby+DBg/nZz37GpEmTDnn93/3ud5x33nmMHTuWrl27HvR6l1xyCXv37uWiiy765rwrr7ySG2644ZuB+QekpKTw2GOPcfbZZzNy5Egu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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "filenames": { + "image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter11_88_3.png" + }, + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "filenames": { + "image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/chapter11_88_4.png" + }, + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " # Due to multiple hidden layers, define a variable referencing to the\n", + " # output of the previous layer:\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb):\n", + " # num_hidden_neurons is now a list of number of neurons within each hidden layer\n", + "\n", + " # Find the number of hidden layers:\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 )\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: %g'%cost_function_deep(P, x))\n", + "\n", + " ## Start finding the optimal weigths using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_deep_grad = grad(cost_function_deep,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases\n", + " # in the hidden layers and output layers evaluated at x.\n", + " cost_deep_grad = cost_function_deep_grad(P, x)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_deep_grad[l]\n", + "\n", + " print('Final cost: %g'%cost_function_deep(P, x))\n", + "\n", + " return P\n", + "\n", + "## Set up the cost function specified for this Poisson equation:\n", + "\n", + "# The right side of the ODE\n", + "def f(x):\n", + " return (3*x + x**2)*np.exp(x)\n", + "\n", + "def cost_function_deep(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial_deep(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d2_g_t = elementwise_grad(elementwise_grad(g_trial_deep,0))(x,P)\n", + "\n", + " right_side = f(x)\n", + "\n", + " err_sqr = (-d2_g_t - right_side)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum/np.size(err_sqr)\n", + "\n", + "# The trial solution:\n", + "def g_trial_deep(x,P):\n", + " return x*(1-x)*deep_neural_network(P,x)\n", + "\n", + "# The analytic solution;\n", + "def g_analytic(x):\n", + " return x*(1-x)*np.exp(x)\n", + "\n", + "if __name__ == '__main__':\n", + " npr.seed(4155)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nx = 10\n", + " x = np.linspace(0,1, Nx)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = [200,100]\n", + " num_iter = 1000\n", + " lmb = 1e-3\n", + "\n", + " P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " g_dnn_ag = g_trial_deep(x,P)\n", + " g_analytical = g_analytic(x)\n", + "\n", + " # Find the maximum absolute difference between the solutons:\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(x, g_analytical)\n", + " plt.plot(x, g_dnn_ag[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('x')\n", + " plt.ylabel('g(x)')\n", + "\n", + " ## Perform the computation using the numerical scheme\n", + "\n", + " dx = 1/(Nx - 1)\n", + "\n", + " # Set up the matrix A\n", + " A = np.zeros((Nx-2,Nx-2))\n", + "\n", + " A[0,0] = 2\n", + " A[0,1] = -1\n", + "\n", + " for i in range(1,Nx-3):\n", + " A[i,i-1] = -1\n", + " A[i,i] = 2\n", + " A[i,i+1] = -1\n", + "\n", + " A[Nx - 3, Nx - 4] = -1\n", + " A[Nx - 3, Nx - 3] = 2\n", + "\n", + " # Set up the vector f\n", + " f_vec = dx**2 * f(x[1:-1])\n", + "\n", + " # Solve the equation\n", + " g_res = np.linalg.solve(A,f_vec)\n", + "\n", + " g_vec = np.zeros(Nx)\n", + " g_vec[1:-1] = g_res\n", + "\n", + " # Print the differences between each method\n", + " max_diff1 = np.max(np.abs(g_dnn_ag - g_analytical))\n", + " max_diff2 = np.max(np.abs(g_vec - g_analytical))\n", + " print(\"The max absolute difference between the analytical solution and DNN Autograd: %g\"%max_diff1)\n", + " print(\"The max absolute difference between the analytical solution and numerical scheme: %g\"%max_diff2)\n", + "\n", + " # Plot the results\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.plot(x,g_vec)\n", + " plt.plot(x,g_analytical)\n", + " plt.plot(x,g_dnn_ag[0,:])\n", + "\n", + " plt.legend(['numerical scheme','analytical','dnn'])\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Partial Differential Equations\n", + "\n", + "A partial differential equation (PDE) has a solution here the function\n", + "is defined by multiple variables. The equation may involve all kinds\n", + "of combinations of which variables the function is differentiated with\n", + "respect to.\n", + "\n", + "In general, a partial differential equation for a function $g(x_1,\\dots,x_N)$ with $N$ variables may be expressed as" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{PDE} \\tag{17}\n", + " f\\left(x_1, \\, \\dots \\, , x_N, \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_1}, \\dots , \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_N}, \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_1\\partial x_2}, \\, \\dots \\, , \\frac{\\partial^n g(x_1,\\dots,x_N) }{\\partial x_N^n} \\right) = 0\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $f$ is an expression involving all kinds of possible mixed derivatives of $g(x_1,\\dots,x_N)$ up to an order $n$. In order for the solution to be unique, some additional conditions must also be given.\n", + "\n", + "### Type of problem\n", + "\n", + "The problem our network must solve for, is similar to the ODE case.\n", + "We must have a trial solution $g_t$ at hand.\n", + "\n", + "For instance, the trial solution could be expressed as" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + " g_t(x_1,\\dots,x_N) = h_1(x_1,\\dots,x_N) + h_2(x_1,\\dots,x_N,N(x_1,\\dots,x_N,P))\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $h_1(x_1,\\dots,x_N)$ is a function that ensures $g_t(x_1,\\dots,x_N)$ satisfies some given conditions.\n", + "The neural network $N(x_1,\\dots,x_N,P)$ has weights and biases described by $P$ and $h_2(x_1,\\dots,x_N,N(x_1,\\dots,x_N,P))$ is an expression using the output from the neural network in some way.\n", + "\n", + "The role of the function $h_2(x_1,\\dots,x_N,N(x_1,\\dots,x_N,P))$, is to ensure that the output of $N(x_1,\\dots,x_N,P)$ is zero when $g_t(x_1,\\dots,x_N)$ is evaluated at the values of $x_1,\\dots,x_N$ where the given conditions must be satisfied. The function $h_1(x_1,\\dots,x_N)$ should alone make $g_t(x_1,\\dots,x_N)$ satisfy the conditions.\n", + "\n", + "\n", + "\n", + "### Network requirements\n", + "\n", + "The network tries then the minimize the cost function following the\n", + "same ideas as described for the ODE case, but now with more than one\n", + "variables to consider. The concept still remains the same; find a set\n", + "of parameters $P$ such that the expression $f$ in ([17](#PDE)) is as\n", + "close to zero as possible.\n", + "\n", + "As for the ODE case, the cost function is the mean squared error that\n", + "the network must try to minimize. The cost function for the network to\n", + "minimize is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C\\left(x_1, \\dots, x_N, P\\right) = \\left( f\\left(x_1, \\, \\dots \\, , x_N, \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_1}, \\dots , \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_N}, \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_1\\partial x_2}, \\, \\dots \\, , \\frac{\\partial^n g(x_1,\\dots,x_N) }{\\partial x_N^n} \\right) \\right)^2\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we let $\\boldsymbol{x} = \\big( x_1, \\dots, x_N \\big)$ be an array containing the values for $x_1, \\dots, x_N$ respectively, the cost function can be reformulated into the following:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C\\left(\\boldsymbol{x}, P\\right) = f\\left( \\left( \\boldsymbol{x}, \\frac{\\partial g(\\boldsymbol{x}) }{\\partial x_1}, \\dots , \\frac{\\partial g(\\boldsymbol{x}) }{\\partial x_N}, \\frac{\\partial g(\\boldsymbol{x}) }{\\partial x_1\\partial x_2}, \\, \\dots \\, , \\frac{\\partial^n g(\\boldsymbol{x}) }{\\partial x_N^n} \\right) \\right)^2\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we also have $M$ different sets of values for $x_1, \\dots, x_N$, that is $\\boldsymbol{x}_i = \\big(x_1^{(i)}, \\dots, x_N^{(i)}\\big)$ for $i = 1,\\dots,M$ being the rows in matrix $X$, the cost function can be generalized into" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C\\left(X, P \\right) = \\sum_{i=1}^M f\\left( \\left( \\boldsymbol{x}_i, \\frac{\\partial g(\\boldsymbol{x}_i) }{\\partial x_1}, \\dots , \\frac{\\partial g(\\boldsymbol{x}_i) }{\\partial x_N}, \\frac{\\partial g(\\boldsymbol{x}_i) }{\\partial x_1\\partial x_2}, \\, \\dots \\, , \\frac{\\partial^n g(\\boldsymbol{x}_i) }{\\partial x_N^n} \\right) \\right)^2.\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example: The diffusion equation\n", + "\n", + "In one spatial dimension, the equation reads" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\frac{\\partial g(x,t)}{\\partial t} = \\frac{\\partial^2 g(x,t)}{\\partial x^2}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where a possible choice of conditions are" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + "g(0,t) &= 0 ,\\qquad t \\geq 0 \\\\\n", + "g(1,t) &= 0, \\qquad t \\geq 0 \\\\\n", + "g(x,0) &= u(x),\\qquad x\\in [0,1]\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $u(x)$ being some given function.\n", + "\n", + "\n", + "\n", + "For this case, we want to find $g(x,t)$ such that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + " \\frac{\\partial g(x,t)}{\\partial t} = \\frac{\\partial^2 g(x,t)}{\\partial x^2}\n", + "\\end{equation} \\label{diffonedim} \\tag{18}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + "g(0,t) &= 0 ,\\qquad t \\geq 0 \\\\\n", + "g(1,t) &= 0, \\qquad t \\geq 0 \\\\\n", + "g(x,0) &= u(x),\\qquad x\\in [0,1]\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $u(x) = \\sin(\\pi x)$.\n", + "\n", + "First, let us set up the deep neural network.\n", + "The deep neural network will follow the same structure as discussed in the examples solving the ODEs.\n", + "First, we will look into how Autograd could be used in a network tailored to solve for bivariate functions.\n", + "\n", + "\n", + "\n", + "\n", + "The only change to do here, is to extend our network such that\n", + "functions of multiple parameters are correctly handled. In this case\n", + "we have two variables in our function to solve for, that is time $t$\n", + "and position $x$. The variables will be represented by a\n", + "one-dimensional array in the program. The program will evaluate the\n", + "network at each possible pair $(x,t)$, given an array for the desired\n", + "$x$-values and $t$-values to approximate the solution at." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # x is now a point and a 1D numpy array; make it a column vector\n", + " num_coordinates = np.size(x,0)\n", + " x = x.reshape(num_coordinates,-1)\n", + "\n", + " num_points = np.size(x,1)\n", + "\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output[0][0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The cost function must then iterate through the given arrays\n", + "containing values for $x$ and $t$, defines a point $(x,t)$ the deep\n", + "neural network and the trial solution is evaluated at, and then finds\n", + "the Jacobian of the trial solution.\n", + "\n", + "A possible trial solution for this PDE is\n", + "\n", + "$$\n", + "g_t(x,t) = h_1(x,t) + x(1-x)tN(x,t,P)\n", + "$$\n", + "\n", + "with $A(x,t)$ being a function ensuring that $g_t(x,t)$ satisfies our given conditions, and $N(x,t,P)$ being the output from the deep neural network using weights and biases for each layer from $P$.\n", + "\n", + "To fulfill the conditions, $A(x,t)$ could be:\n", + "\n", + "$$\n", + "h_1(x,t) = (1-t)\\Big(u(x) - \\big((1-x)u(0) + x u(1)\\big)\\Big) = (1-t)u(x) = (1-t)\\sin(\\pi x)\n", + "$$\n", + "since $(0) = u(1) = 0$ and $u(x) = \\sin(\\pi x)$.\n", + "\n", + "\n", + "\n", + "The Jacobian is used because the program must find the derivative of\n", + "the trial solution with respect to $x$ and $t$.\n", + "\n", + "This gives the necessity of computing the Jacobian matrix, as we want\n", + "to evaluate the gradient with respect to $x$ and $t$ (note that the\n", + "Jacobian of a scalar-valued multivariate function is simply its\n", + "gradient).\n", + "\n", + "In Autograd, the differentiation is by default done with respect to\n", + "the first input argument of your Python function. Since the points is\n", + "an array representing $x$ and $t$, the Jacobian is calculated using\n", + "the values of $x$ and $t$.\n", + "\n", + "To find the second derivative with respect to $x$ and $t$, the\n", + "Jacobian can be found for the second time. The result is a Hessian\n", + "matrix, which is the matrix containing all the possible second order\n", + "mixed derivatives of $g(x,t)$." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "# Set up the trial function:\n", + "def u(x):\n", + " return np.sin(np.pi*x)\n", + "\n", + "def g_trial(point,P):\n", + " x,t = point\n", + " return (1-t)*u(x) + x*(1-x)*t*deep_neural_network(P,point)\n", + "\n", + "# The right side of the ODE:\n", + "def f(point):\n", + " return 0.\n", + "\n", + "# The cost function:\n", + "def cost_function(P, x, t):\n", + " cost_sum = 0\n", + "\n", + " g_t_jacobian_func = jacobian(g_trial)\n", + " g_t_hessian_func = hessian(g_trial)\n", + "\n", + " for x_ in x:\n", + " for t_ in t:\n", + " point = np.array([x_,t_])\n", + "\n", + " g_t = g_trial(point,P)\n", + " g_t_jacobian = g_t_jacobian_func(point,P)\n", + " g_t_hessian = g_t_hessian_func(point,P)\n", + "\n", + " g_t_dt = g_t_jacobian[1]\n", + " g_t_d2x = g_t_hessian[0][0]\n", + "\n", + " func = f(point)\n", + "\n", + " err_sqr = ( (g_t_dt - g_t_d2x) - func)**2\n", + " cost_sum += err_sqr\n", + "\n", + " return cost_sum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setting up the network using Autograd; The full program\n", + "\n", + "Having set up the network, along with the trial solution and cost function, we can now see how the deep neural network performs by comparing the results to the analytical solution.\n", + "\n", + "The analytical solution of our problem is\n", + "\n", + "$$\n", + "g(x,t) = \\exp(-\\pi^2 t)\\sin(\\pi x)\n", + "$$\n", + "\n", + "A possible way to implement a neural network solving the PDE, is given below.\n", + "Be aware, though, that it is fairly slow for the parameters used.\n", + "A better result is possible, but requires more iterations, and thus longer time to complete.\n", + "\n", + "\n", + "Indeed, the program below is not optimal in its implementation, but rather serves as an example on how to implement and use a neural network to solve a PDE.\n", + "Using TensorFlow results in a much better execution time. Try it!" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/mhjensen/opt/anaconda3/lib/python3.8/site-packages/numpy/core/_asarray.py:83: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n", + " return array(a, dtype, copy=False, order=order)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial cost: 41.05505310046363\n" + ] + } + ], + "source": [ + "import autograd.numpy as np\n", + "from autograd import jacobian,hessian,grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import cm\n", + "from matplotlib import pyplot as plt\n", + "from mpl_toolkits.mplot3d import axes3d\n", + "\n", + "## Set up the network\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # x is now a point and a 1D numpy array; make it a column vector\n", + " num_coordinates = np.size(x,0)\n", + " x = x.reshape(num_coordinates,-1)\n", + "\n", + " num_points = np.size(x,1)\n", + "\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output[0][0]\n", + "\n", + "## Define the trial solution and cost function\n", + "def u(x):\n", + " return np.sin(np.pi*x)\n", + "\n", + "def g_trial(point,P):\n", + " x,t = point\n", + " return (1-t)*u(x) + x*(1-x)*t*deep_neural_network(P,point)\n", + "\n", + "# The right side of the ODE:\n", + "def f(point):\n", + " return 0.\n", + "\n", + "# The cost function:\n", + "def cost_function(P, x, t):\n", + " cost_sum = 0\n", + "\n", + " g_t_jacobian_func = jacobian(g_trial)\n", + " g_t_hessian_func = hessian(g_trial)\n", + "\n", + " for x_ in x:\n", + " for t_ in t:\n", + " point = np.array([x_,t_])\n", + "\n", + " g_t = g_trial(point,P)\n", + " g_t_jacobian = g_t_jacobian_func(point,P)\n", + " g_t_hessian = g_t_hessian_func(point,P)\n", + "\n", + " g_t_dt = g_t_jacobian[1]\n", + " g_t_d2x = g_t_hessian[0][0]\n", + "\n", + " func = f(point)\n", + "\n", + " err_sqr = ( (g_t_dt - g_t_d2x) - func)**2\n", + " cost_sum += err_sqr\n", + "\n", + " return cost_sum /( np.size(x)*np.size(t) )\n", + "\n", + "## For comparison, define the analytical solution\n", + "def g_analytic(point):\n", + " x,t = point\n", + " return np.exp(-np.pi**2*t)*np.sin(np.pi*x)\n", + "\n", + "## Set up a function for training the network to solve for the equation\n", + "def solve_pde_deep_neural_network(x,t, num_neurons, num_iter, lmb):\n", + " ## Set up initial weigths and biases\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 + 1 ) # 2 since we have two points, +1 to include bias\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: ',cost_function(P, x, t))\n", + "\n", + " cost_function_grad = grad(cost_function,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " cost_grad = cost_function_grad(P, x , t)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_grad[l]\n", + "\n", + " print('Final cost: ',cost_function(P, x, t))\n", + "\n", + " return P\n", + "\n", + "if __name__ == '__main__':\n", + " ### Use the neural network:\n", + " npr.seed(15)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nx = 10; Nt = 10\n", + " x = np.linspace(0, 1, Nx)\n", + " t = np.linspace(0,1,Nt)\n", + "\n", + " ## Set up the parameters for the network\n", + " num_hidden_neurons = [100, 25]\n", + " num_iter = 250\n", + " lmb = 0.01\n", + "\n", + " P = solve_pde_deep_neural_network(x,t, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " ## Store the results\n", + " g_dnn_ag = np.zeros((Nx, Nt))\n", + " G_analytical = np.zeros((Nx, Nt))\n", + " for i,x_ in enumerate(x):\n", + " for j, t_ in enumerate(t):\n", + " point = np.array([x_, t_])\n", + " g_dnn_ag[i,j] = g_trial(point,P)\n", + "\n", + " G_analytical[i,j] = g_analytic(point)\n", + "\n", + " # Find the map difference between the analytical and the computed solution\n", + " diff_ag = np.abs(g_dnn_ag - G_analytical)\n", + " print('Max absolute difference between the analytical solution and the network: %g'%np.max(diff_ag))\n", + "\n", + " ## Plot the solutions in two dimensions, that being in position and time\n", + "\n", + " T,X = np.meshgrid(t,x)\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Solution from the deep neural network w/ %d layer'%len(num_hidden_neurons))\n", + " s = ax.plot_surface(T,X,g_dnn_ag,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Analytical solution')\n", + " s = ax.plot_surface(T,X,G_analytical,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Difference')\n", + " s = ax.plot_surface(T,X,diff_ag,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + " ## Take some slices of the 3D plots just to see the solutions at particular times\n", + " indx1 = 0\n", + " indx2 = int(Nt/2)\n", + " indx3 = Nt-1\n", + "\n", + " t1 = t[indx1]\n", + " t2 = t[indx2]\n", + " t3 = t[indx3]\n", + "\n", + " # Slice the results from the DNN\n", + " res1 = g_dnn_ag[:,indx1]\n", + " res2 = g_dnn_ag[:,indx2]\n", + " res3 = g_dnn_ag[:,indx3]\n", + "\n", + " # Slice the analytical results\n", + " res_analytical1 = G_analytical[:,indx1]\n", + " res_analytical2 = G_analytical[:,indx2]\n", + " res_analytical3 = G_analytical[:,indx3]\n", + "\n", + " # Plot the slices\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t1)\n", + " plt.plot(x, res1)\n", + " plt.plot(x,res_analytical1)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t2)\n", + " plt.plot(x, res2)\n", + " plt.plot(x,res_analytical2)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t3)\n", + " plt.plot(x, res3)\n", + " plt.plot(x,res_analytical3)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Solving the wave equation with Neural Networks\n", + "\n", + "The wave equation is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\frac{\\partial^2 g(x,t)}{\\partial t^2} = c^2\\frac{\\partial^2 g(x,t)}{\\partial x^2}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $c$ being the specified wave speed.\n", + "\n", + "Here, the chosen conditions are" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + "\tg(0,t) &= 0 \\\\\n", + "\tg(1,t) &= 0 \\\\\n", + "\tg(x,0) &= u(x) \\\\\n", + "\t\\frac{\\partial g(x,t)}{\\partial t} \\Big |_{t = 0} &= v(x)\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $\\frac{\\partial g(x,t)}{\\partial t} \\Big |_{t = 0}$ means the derivative of $g(x,t)$ with respect to $t$ is evaluated at $t = 0$, and $u(x)$ and $v(x)$ being given functions.\n", + "\n", + "\n", + "The wave equation to solve for, is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{wave} \\tag{19}\n", + "\\frac{\\partial^2 g(x,t)}{\\partial t^2} = c^2 \\frac{\\partial^2 g(x,t)}{\\partial x^2}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $c$ is the given wave speed.\n", + "The chosen conditions for this equation are" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "g(0,t) &= 0, &t \\geq 0 \\\\\n", + "g(1,t) &= 0, &t \\geq 0 \\\\\n", + "g(x,0) &= u(x), &x\\in[0,1] \\\\\n", + "\\frac{\\partial g(x,t)}{\\partial t}\\Big |_{t = 0} &= v(x), &x \\in [0,1]\n", + "\\end{aligned} \\label{condwave} \\tag{20}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, let $c = 1$ and $u(x) = \\sin(\\pi x)$ and $v(x) = -\\pi\\sin(\\pi x)$.\n", + "\n", + "\n", + "\n", + "Setting up the network is done in similar matter as for the example of solving the diffusion equation.\n", + "The only things we have to change, is the trial solution such that it satisfies the conditions from ([20](#condwave)) and the cost function.\n", + "\n", + "The trial solution becomes slightly different since we have other conditions than in the example of solving the diffusion equation. Here, a possible trial solution $g_t(x,t)$ is\n", + "\n", + "$$\n", + "g_t(x,t) = h_1(x,t) + x(1-x)t^2N(x,t,P)\n", + "$$\n", + "\n", + "where\n", + "\n", + "$$\n", + "h_1(x,t) = (1-t^2)u(x) + tv(x)\n", + "$$\n", + "\n", + "Note that this trial solution satisfies the conditions only if $u(0) = v(0) = u(1) = v(1) = 0$, which is the case in this example.\n", + "\n", + "\n", + "The analytical solution for our specific problem, is\n", + "\n", + "$$\n", + "g(x,t) = \\sin(\\pi x)\\cos(\\pi t) - \\sin(\\pi x)\\sin(\\pi t)\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import hessian,grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import cm\n", + "from matplotlib import pyplot as plt\n", + "from mpl_toolkits.mplot3d import axes3d\n", + "\n", + "## Set up the trial function:\n", + "def u(x):\n", + " return np.sin(np.pi*x)\n", + "\n", + "def v(x):\n", + " return -np.pi*np.sin(np.pi*x)\n", + "\n", + "def h1(point):\n", + " x,t = point\n", + " return (1 - t**2)*u(x) + t*v(x)\n", + "\n", + "def g_trial(point,P):\n", + " x,t = point\n", + " return h1(point) + x*(1-x)*t**2*deep_neural_network(P,point)\n", + "\n", + "## Define the cost function\n", + "def cost_function(P, x, t):\n", + " cost_sum = 0\n", + "\n", + " g_t_hessian_func = hessian(g_trial)\n", + "\n", + " for x_ in x:\n", + " for t_ in t:\n", + " point = np.array([x_,t_])\n", + "\n", + " g_t_hessian = g_t_hessian_func(point,P)\n", + "\n", + " g_t_d2x = g_t_hessian[0][0]\n", + " g_t_d2t = g_t_hessian[1][1]\n", + "\n", + " err_sqr = ( (g_t_d2t - g_t_d2x) )**2\n", + " cost_sum += err_sqr\n", + "\n", + " return cost_sum / (np.size(t) * np.size(x))\n", + "\n", + "## The neural network\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # x is now a point and a 1D numpy array; make it a column vector\n", + " num_coordinates = np.size(x,0)\n", + " x = x.reshape(num_coordinates,-1)\n", + "\n", + " num_points = np.size(x,1)\n", + "\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output[0][0]\n", + "\n", + "## The analytical solution\n", + "def g_analytic(point):\n", + " x,t = point\n", + " return np.sin(np.pi*x)*np.cos(np.pi*t) - np.sin(np.pi*x)*np.sin(np.pi*t)\n", + "\n", + "def solve_pde_deep_neural_network(x,t, num_neurons, num_iter, lmb):\n", + " ## Set up initial weigths and biases\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 + 1 ) # 2 since we have two points, +1 to include bias\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: ',cost_function(P, x, t))\n", + "\n", + " cost_function_grad = grad(cost_function,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " cost_grad = cost_function_grad(P, x , t)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_grad[l]\n", + "\n", + "\n", + " print('Final cost: ',cost_function(P, x, t))\n", + "\n", + " return P\n", + "\n", + "if __name__ == '__main__':\n", + " ### Use the neural network:\n", + " npr.seed(15)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nx = 10; Nt = 10\n", + " x = np.linspace(0, 1, Nx)\n", + " t = np.linspace(0,1,Nt)\n", + "\n", + " ## Set up the parameters for the network\n", + " num_hidden_neurons = [50,20]\n", + " num_iter = 1000\n", + " lmb = 0.01\n", + "\n", + " P = solve_pde_deep_neural_network(x,t, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " ## Store the results\n", + " res = np.zeros((Nx, Nt))\n", + " res_analytical = np.zeros((Nx, Nt))\n", + " for i,x_ in enumerate(x):\n", + " for j, t_ in enumerate(t):\n", + " point = np.array([x_, t_])\n", + " res[i,j] = g_trial(point,P)\n", + "\n", + " res_analytical[i,j] = g_analytic(point)\n", + "\n", + " diff = np.abs(res - res_analytical)\n", + " print(\"Max difference between analytical and solution from nn: %g\"%np.max(diff))\n", + "\n", + " ## Plot the solutions in two dimensions, that being in position and time\n", + "\n", + " T,X = np.meshgrid(t,x)\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Solution from the deep neural network w/ %d layer'%len(num_hidden_neurons))\n", + " s = ax.plot_surface(T,X,res,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Analytical solution')\n", + " s = ax.plot_surface(T,X,res_analytical,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Difference')\n", + " s = ax.plot_surface(T,X,diff,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + " ## Take some slices of the 3D plots just to see the solutions at particular times\n", + " indx1 = 0\n", + " indx2 = int(Nt/2)\n", + " indx3 = Nt-1\n", + "\n", + " t1 = t[indx1]\n", + " t2 = t[indx2]\n", + " t3 = t[indx3]\n", + "\n", + " # Slice the results from the DNN\n", + " res1 = res[:,indx1]\n", + " res2 = res[:,indx2]\n", + " res3 = res[:,indx3]\n", + "\n", + " # Slice the analytical results\n", + " res_analytical1 = res_analytical[:,indx1]\n", + " res_analytical2 = res_analytical[:,indx2]\n", + " res_analytical3 = res_analytical[:,indx3]\n", + "\n", + " # Plot the slices\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t1)\n", + " plt.plot(x, res1)\n", + " plt.plot(x,res_analytical1)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t2)\n", + " plt.plot(x, res2)\n", + " plt.plot(x,res_analytical2)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t3)\n", + " plt.plot(x, res3)\n", + " plt.plot(x,res_analytical3)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Resources on differential equations and deep learning\n", + "\n", + "1. [Artificial neural networks for solving ordinary and partial differential equations by I.E. Lagaris et al](https://pdfs.semanticscholar.org/d061/df393e0e8fbfd0ea24976458b7d42419040d.pdf)\n", + "\n", + "2. [Neural networks for solving differential equations by A. Honchar](https://becominghuman.ai/neural-networks-for-solving-differential-equations-fa230ac5e04c)\n", + "\n", + "3. [Solving differential equations using neural networks by M.M Chiaramonte and M. Kiener](http://cs229.stanford.edu/proj2013/ChiaramonteKiener-SolvingDifferentialEquationsUsingNeuralNetworks.pdf)\n", + "\n", + "4. [Introduction to Partial Differential Equations by A. Tveito, R. Winther](https://www.springer.com/us/book/9783540225515)" + ] + } + ], + "metadata": { + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter11.py b/doc/LectureNotes/_build/jupyter_execute/chapter11.py new file mode 100644 index 000000000..17470c2a0 --- /dev/null +++ b/doc/LectureNotes/_build/jupyter_execute/chapter11.py @@ -0,0 +1,2345 @@ +# Solving Differential Equations with Deep Learning + +The Universal Approximation Theorem states that a neural network can +approximate any function at a single hidden layer along with one input +and output layer to any given precision. + + +An ordinary differential equation (ODE) is an equation involving functions having one variable. + +In general, an ordinary differential equation looks like + + +
+ +$$ +\begin{equation} \label{ode} \tag{1} +f\left(x, \, g(x), \, g'(x), \, g''(x), \, \dots \, , \, g^{(n)}(x)\right) = 0 +\end{equation} +$$ + +where $g(x)$ is the function to find, and $g^{(n)}(x)$ is the $n$-th derivative of $g(x)$. + +The $f\left(x, g(x), g'(x), g''(x), \, \dots \, , g^{(n)}(x)\right)$ is just a way to write that there is an expression involving $x$ and $g(x), \ g'(x), \ g''(x), \, \dots \, , \text{ and } g^{(n)}(x)$ on the left side of the equality sign in ([1](#ode)). +The highest order of derivative, that is the value of $n$, determines to the order of the equation. +The equation is referred to as a $n$-th order ODE. +Along with ([1](#ode)), some additional conditions of the function $g(x)$ are typically given +for the solution to be unique. + + + +Let the trial solution $g_t(x)$ be + + +
+ +$$ +\begin{equation} + g_t(x) = h_1(x) + h_2(x,N(x,P)) +\label{_auto1} \tag{2} +\end{equation} +$$ + +where $h_1(x)$ is a function that makes $g_t(x)$ satisfy a given set +of conditions, $N(x,P)$ a neural network with weights and biases +described by $P$ and $h_2(x, N(x,P))$ some expression involving the +neural network. The role of the function $h_2(x, N(x,P))$, is to +ensure that the output from $N(x,P)$ is zero when $g_t(x)$ is +evaluated at the values of $x$ where the given conditions must be +satisfied. The function $h_1(x)$ should alone make $g_t(x)$ satisfy +the conditions. + +But what about the network $N(x,P)$? + + +As described previously, an optimization method could be used to minimize the parameters of a neural network, that being its weights and biases, through backward propagation. + + + +For the minimization to be defined, we need to have a cost function at hand to minimize. + +It is given that $f\left(x, \, g(x), \, g'(x), \, g''(x), \, \dots \, , \, g^{(n)}(x)\right)$ should be equal to zero in ([1](#ode)). +We can choose to consider the mean squared error as the cost function for an input $x$. +Since we are looking at one input, the cost function is just $f$ squared. +The cost function $c\left(x, P \right)$ can therefore be expressed as + +$$ +C\left(x, P\right) = \big(f\left(x, \, g(x), \, g'(x), \, g''(x), \, \dots \, , \, g^{(n)}(x)\right)\big)^2 +$$ + +If $N$ inputs are given as a vector $\boldsymbol{x}$ with elements $x_i$ for $i = 1,\dots,N$, +the cost function becomes + + +
+ +$$ +\begin{equation} \label{cost} \tag{3} + C\left(\boldsymbol{x}, P\right) = \frac{1}{N} \sum_{i=1}^N \big(f\left(x_i, \, g(x_i), \, g'(x_i), \, g''(x_i), \, \dots \, , \, g^{(n)}(x_i)\right)\big)^2 +\end{equation} +$$ + +The neural net should then find the parameters $P$ that minimizes the cost function in +([3](#cost)) for a set of $N$ training samples $x_i$. + + + +To perform the minimization using gradient descent, the gradient of $C\left(\boldsymbol{x}, P\right)$ is needed. +It might happen so that finding an analytical expression of the gradient of $C(\boldsymbol{x}, P)$ from ([3](#cost)) gets too messy, depending on which cost function one desires to use. + +Luckily, there exists libraries that makes the job for us through automatic differentiation. +Automatic differentiation is a method of finding the derivatives numerically with very high precision. + + +### Example: Exponential decay + +An exponential decay of a quantity $g(x)$ is described by the equation + + +
+ +$$ +\begin{equation} \label{solve_expdec} \tag{4} + g'(x) = -\gamma g(x) +\end{equation} +$$ + +with $g(0) = g_0$ for some chosen initial value $g_0$. + +The analytical solution of ([4](#solve_expdec)) is + + +
+ +$$ +\begin{equation} + g(x) = g_0 \exp\left(-\gamma x\right) +\label{_auto2} \tag{5} +\end{equation} +$$ + +Having an analytical solution at hand, it is possible to use it to compare how well a neural network finds a solution of ([4](#solve_expdec)). + + + +The program will use a neural network to solve + + +
+ +$$ +\begin{equation} \label{solveode} \tag{6} +g'(x) = -\gamma g(x) +\end{equation} +$$ + +where $g(0) = g_0$ with $\gamma$ and $g_0$ being some chosen values. + +In this example, $\gamma = 2$ and $g_0 = 10$. + + +To begin with, a trial solution $g_t(t)$ must be chosen. A general trial solution for ordinary differential equations could be + +$$ +g_t(x, P) = h_1(x) + h_2(x, N(x, P)) +$$ + +with $h_1(x)$ ensuring that $g_t(x)$ satisfies some conditions and $h_2(x,N(x, P))$ an expression involving $x$ and the output from the neural network $N(x,P)$ with $P $ being the collection of the weights and biases for each layer. For now, it is assumed that the network consists of one input layer, one hidden layer, and one output layer. + + + +In this network, there are no weights and bias at the input layer, so $P = \{ P_{\text{hidden}}, P_{\text{output}} \}$. +If there are $N_{\text{hidden} }$ neurons in the hidden layer, then $P_{\text{hidden}}$ is a $N_{\text{hidden} } \times (1 + N_{\text{input}})$ matrix, given that there are $N_{\text{input}}$ neurons in the input layer. + +The first column in $P_{\text{hidden} }$ represents the bias for each neuron in the hidden layer and the second column represents the weights for each neuron in the hidden layer from the input layer. +If there are $N_{\text{output} }$ neurons in the output layer, then $P_{\text{output}} $ is a $N_{\text{output} } \times (1 + N_{\text{hidden} })$ matrix. + +Its first column represents the bias of each neuron and the remaining columns represents the weights to each neuron. + +It is given that $g(0) = g_0$. The trial solution must fulfill this condition to be a proper solution of ([6](#solveode)). A possible way to ensure that $g_t(0, P) = g_0$, is to let $F(N(x,P)) = x \cdot N(x,P)$ and $A(x) = g_0$. This gives the following trial solution: + + +
+ +$$ +\begin{equation} \label{trial} \tag{7} +g_t(x, P) = g_0 + x \cdot N(x, P) +\end{equation} +$$ + +### Reformulating the problem + +We wish that our neural network manages to minimize a given cost function. + +A reformulation of out equation, ([6](#solveode)), must therefore be done, +such that it describes the problem a neural network can solve for. + +The neural network must find the set of weights and biases $P$ such that the trial solution in ([7](#trial)) satisfies ([6](#solveode)). + +The trial solution + +$$ +g_t(x, P) = g_0 + x \cdot N(x, P) +$$ + +has been chosen such that it already solves the condition $g(0) = g_0$. What remains, is to find $P$ such that + + +
+ +$$ +\begin{equation} \label{nnmin} \tag{8} +g_t'(x, P) = - \gamma g_t(x, P) +\end{equation} +$$ + +is fulfilled as *best as possible*. + + +The left hand side and right hand side of ([8](#nnmin)) must be computed separately, and then the neural network must choose weights and biases, contained in $P$, such that the sides are equal as best as possible. +This means that the absolute or squared difference between the sides must be as close to zero, ideally equal to zero. +In this case, the difference squared shows to be an appropriate measurement of how erroneous the trial solution is with respect to $P$ of the neural network. + +This gives the following cost function our neural network must solve for: + +$$ +\min_{P}\Big\{ \big(g_t'(x, P) - ( -\gamma g_t(x, P) \big)^2 \Big\} +$$ + +(the notation $\min_{P}\{ f(x, P) \}$ means that we desire to find $P$ that yields the minimum of $f(x, P)$) + +or, in terms of weights and biases for the hidden and output layer in our network: + +$$ +\min_{P_{\text{hidden} }, \ P_{\text{output} }}\Big\{ \big(g_t'(x, \{ P_{\text{hidden} }, P_{\text{output} }\}) - ( -\gamma g_t(x, \{ P_{\text{hidden} }, P_{\text{output} }\}) \big)^2 \Big\} +$$ + +for an input value $x$. + + + +If the neural network evaluates $g_t(x, P)$ at more values for $x$, say $N$ values $x_i$ for $i = 1, \dots, N$, then the *total* error to minimize becomes + + +
+ +$$ +\begin{equation} \label{min} \tag{9} +\min_{P}\Big\{\frac{1}{N} \sum_{i=1}^N \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P) \big)^2 \Big\} +\end{equation} +$$ + +Letting $\boldsymbol{x}$ be a vector with elements $x_i$ and $C(\boldsymbol{x}, P) = \frac{1}{N} \sum_i \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P) \big)^2$ denote the cost function, the minimization problem that our network must solve, becomes + +$$ +\min_{P} C(\boldsymbol{x}, P) +$$ + +In terms of $P_{\text{hidden} }$ and $P_{\text{output} }$, this could also be expressed as + +$$ +\min_{P_{\text{hidden} }, \ P_{\text{output} }} C(\boldsymbol{x}, \{P_{\text{hidden} }, P_{\text{output} }\}) +$$ + + +For simplicity, it is assumed that the input is an array $\boldsymbol{x} = (x_1, \dots, x_N)$ with $N$ elements. It is at these points the neural network should find $P$ such that it fulfills ([9](#min)). + +First, the neural network must feed forward the inputs. +This means that $\boldsymbol{x}s$ must be passed through an input layer, a hidden layer and a output layer. The input layer in this case, does not need to process the data any further. +The input layer will consist of $N_{\text{input} }$ neurons, passing its element to each neuron in the hidden layer. The number of neurons in the hidden layer will be $N_{\text{hidden} }$. + + +For the $i$-th in the hidden layer with weight $w_i^{\text{hidden} }$ and bias $b_i^{\text{hidden} }$, the weighting from the $j$-th neuron at the input layer is: + +$$ +\begin{aligned} +z_{i,j}^{\text{hidden}} &= b_i^{\text{hidden}} + w_i^{\text{hidden}}x_j \\ +&= +\begin{pmatrix} +b_i^{\text{hidden}} & w_i^{\text{hidden}} +\end{pmatrix} +\begin{pmatrix} +1 \\ +x_j +\end{pmatrix} +\end{aligned} +$$ + +The result after weighting the inputs at the $i$-th hidden neuron can be written as a vector: + +$$ +\begin{aligned} +\boldsymbol{z}_{i}^{\text{hidden}} &= \Big( b_i^{\text{hidden}} + w_i^{\text{hidden}}x_1 , \ b_i^{\text{hidden}} + w_i^{\text{hidden}} x_2, \ \dots \, , \ b_i^{\text{hidden}} + w_i^{\text{hidden}} x_N\Big) \\ +&= +\begin{pmatrix} + b_i^{\text{hidden}} & w_i^{\text{hidden}} +\end{pmatrix} +\begin{pmatrix} +1 & 1 & \dots & 1 \\ +x_1 & x_2 & \dots & x_N +\end{pmatrix} \\ +&= \boldsymbol{p}_{i, \text{hidden}}^T X +\end{aligned} +$$ + +The vector $\boldsymbol{p}_{i, \text{hidden}}^T$ constitutes each row in $P_{\text{hidden} }$, which contains the weights for the neural network to minimize according to ([9](#min)). + +After having found $\boldsymbol{z}_{i}^{\text{hidden}} $ for every $i$-th neuron within the hidden layer, the vector will be sent to an activation function $a_i(\boldsymbol{z})$. + +In this example, the sigmoid function has been chosen to be the activation function for each hidden neuron: + +$$ +f(z) = \frac{1}{1 + \exp{(-z)}} +$$ + +It is possible to use other activations functions for the hidden layer also. + +The output $\boldsymbol{x}_i^{\text{hidden}}$ from each $i$-th hidden neuron is: + +$$ +\boldsymbol{x}_i^{\text{hidden} } = f\big( \boldsymbol{z}_{i}^{\text{hidden}} \big) +$$ + +The outputs $\boldsymbol{x}_i^{\text{hidden} } $ are then sent to the output layer. + +The output layer consists of one neuron in this case, and combines the +output from each of the neurons in the hidden layers. The output layer +combines the results from the hidden layer using some weights $w_i^{\text{output}}$ +and biases $b_i^{\text{output}}$. In this case, +it is assumes that the number of neurons in the output layer is one. + + + +The procedure of weighting the output neuron $j$ in the hidden layer to the $i$-th neuron in the output layer is similar as for the hidden layer described previously. + +$$ +\begin{aligned} +z_{1,j}^{\text{output}} & = +\begin{pmatrix} +b_1^{\text{output}} & \boldsymbol{w}_1^{\text{output}} +\end{pmatrix} +\begin{pmatrix} +1 \\ +\boldsymbol{x}_j^{\text{hidden}} +\end{pmatrix} +\end{aligned} +$$ + +Expressing $z_{1,j}^{\text{output}}$ as a vector gives the following way of weighting the inputs from the hidden layer: + +$$ +\boldsymbol{z}_{1}^{\text{output}} = +\begin{pmatrix} +b_1^{\text{output}} & \boldsymbol{w}_1^{\text{output}} +\end{pmatrix} +\begin{pmatrix} +1 & 1 & \dots & 1 \\ +\boldsymbol{x}_1^{\text{hidden}} & \boldsymbol{x}_2^{\text{hidden}} & \dots & \boldsymbol{x}_N^{\text{hidden}} +\end{pmatrix} +$$ + +In this case we seek a continuous range of values since we are approximating a function. This means that after computing $\boldsymbol{z}_{1}^{\text{output}}$ the neural network has finished its feed forward step, and $\boldsymbol{z}_{1}^{\text{output}}$ is the final output of the network. + + +The next step is to decide how the parameters should be changed such that they minimize the cost function. + +The chosen cost function for this problem is + +$$ +C(\boldsymbol{x}, P) = \frac{1}{N} \sum_i \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P) \big)^2 +$$ + +In order to minimize the cost function, an optimization method must be chosen. + +Here, gradient descent with a constant step size has been chosen. + +### Gradient descent + +The idea of the gradient descent algorithm is to update parameters in +a direction where the cost function decreases goes to a minimum. + +In general, the update of some parameters $\boldsymbol{\omega}$ given a cost +function defined by some weights $\boldsymbol{\omega}$, $C(\boldsymbol{x}, +\boldsymbol{\omega})$, goes as follows: + +$$ +\boldsymbol{\omega}_{\text{new} } = \boldsymbol{\omega} - \lambda \nabla_{\boldsymbol{\omega}} C(\boldsymbol{x}, \boldsymbol{\omega}) +$$ + +for a number of iterations or until $ \big|\big| \boldsymbol{\omega}_{\text{new} } - \boldsymbol{\omega} \big|\big|$ becomes smaller than some given tolerance. + +The value of $\lambda$ decides how large steps the algorithm must take +in the direction of $ \nabla_{\boldsymbol{\omega}} C(\boldsymbol{x}, \boldsymbol{\omega})$. +The notation $\nabla_{\boldsymbol{\omega}}$ express the gradient with respect +to the elements in $\boldsymbol{\omega}$. + +In our case, we have to minimize the cost function $C(\boldsymbol{x}, P)$ with +respect to the two sets of weights and biases, that is for the hidden +layer $P_{\text{hidden} }$ and for the output layer $P_{\text{output} +}$ . + +This means that $P_{\text{hidden} }$ and $P_{\text{output} }$ is updated by + +$$ +\begin{aligned} +P_{\text{hidden},\text{new}} &= P_{\text{hidden}} - \lambda \nabla_{P_{\text{hidden}}} C(\boldsymbol{x}, P) \\ +P_{\text{output},\text{new}} &= P_{\text{output}} - \lambda \nabla_{P_{\text{output}}} C(\boldsymbol{x}, P) +\end{aligned} +$$ + +### The code for solving the ODE + +%matplotlib inline + +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +# Assuming one input, hidden, and output layer +def neural_network(params, x): + + # Find the weights (including and biases) for the hidden and output layer. + # Assume that params is a list of parameters for each layer. + # The biases are the first element for each array in params, + # and the weights are the remaning elements in each array in params. + + w_hidden = params[0] + w_output = params[1] + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + ## Hidden layer: + + # Add a row of ones to include bias + x_input = np.concatenate((np.ones((1,num_values)), x_input ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_input) + x_hidden = sigmoid(z_hidden) + + ## Output layer: + + # Include bias: + x_hidden = np.concatenate((np.ones((1,num_values)), x_hidden ), axis = 0) + + z_output = np.matmul(w_output, x_hidden) + x_output = z_output + + return x_output + +# The trial solution using the deep neural network: +def g_trial(x,params, g0 = 10): + return g0 + x*neural_network(params,x) + +# The right side of the ODE: +def g(x, g_trial, gamma = 2): + return -gamma*g_trial + +# The cost function: +def cost_function(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial(x,P) + + # Find the derivative w.r.t x of the neural network + d_net_out = elementwise_grad(neural_network,1)(P,x) + + # Find the derivative w.r.t x of the trial function + d_g_t = elementwise_grad(g_trial,0)(x,P) + + # The right side of the ODE + func = g(x, g_t) + + err_sqr = (d_g_t - func)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum / np.size(err_sqr) + +# Solve the exponential decay ODE using neural network with one input, hidden, and output layer +def solve_ode_neural_network(x, num_neurons_hidden, num_iter, lmb): + ## Set up initial weights and biases + + # For the hidden layer + p0 = npr.randn(num_neurons_hidden, 2 ) + + # For the output layer + p1 = npr.randn(1, num_neurons_hidden + 1 ) # +1 since bias is included + + P = [p0, p1] + + print('Initial cost: %g'%cost_function(P, x)) + + ## Start finding the optimal weights using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_grad = grad(cost_function,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of two arrays; + # one for the gradient w.r.t P_hidden and + # one for the gradient w.r.t P_output + cost_grad = cost_function_grad(P, x) + + P[0] = P[0] - lmb * cost_grad[0] + P[1] = P[1] - lmb * cost_grad[1] + + print('Final cost: %g'%cost_function(P, x)) + + return P + +def g_analytic(x, gamma = 2, g0 = 10): + return g0*np.exp(-gamma*x) + +# Solve the given problem +if __name__ == '__main__': + # Set seed such that the weight are initialized + # with same weights and biases for every run. + npr.seed(15) + + ## Decide the vales of arguments to the function to solve + N = 10 + x = np.linspace(0, 1, N) + + ## Set up the initial parameters + num_hidden_neurons = 10 + num_iter = 10000 + lmb = 0.001 + + # Use the network + P = solve_ode_neural_network(x, num_hidden_neurons, num_iter, lmb) + + # Print the deviation from the trial solution and true solution + res = g_trial(x,P) + res_analytical = g_analytic(x) + + print('Max absolute difference: %g'%np.max(np.abs(res - res_analytical))) + + # Plot the results + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(x, res_analytical) + plt.plot(x, res[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('x') + plt.ylabel('g(x)') + plt.show() + +## The network with one input layer, specified number of hidden layers, and one output layer + +It is also possible to extend the construction of our network into a more general one, allowing the network to contain more than one hidden layers. + +The number of neurons within each hidden layer are given as a list of integers in the program below. + +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +# The neural network with one input layer and one output layer, +# but with number of hidden layers specified by the user. +def deep_neural_network(deep_params, x): + # N_hidden is the number of hidden layers + + N_hidden = np.size(deep_params) - 1 # -1 since params consists of + # parameters to all the hidden + # layers AND the output layer. + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + # Due to multiple hidden layers, define a variable referencing to the + # output of the previous layer: + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output + +# The trial solution using the deep neural network: +def g_trial_deep(x,params, g0 = 10): + return g0 + x*deep_neural_network(params, x) + +# The right side of the ODE: +def g(x, g_trial, gamma = 2): + return -gamma*g_trial + +# The same cost function as before, but calls deep_neural_network instead. +def cost_function_deep(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial_deep(x,P) + + # Find the derivative w.r.t x of the neural network + d_net_out = elementwise_grad(deep_neural_network,1)(P,x) + + # Find the derivative w.r.t x of the trial function + d_g_t = elementwise_grad(g_trial_deep,0)(x,P) + + # The right side of the ODE + func = g(x, g_t) + + err_sqr = (d_g_t - func)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum / np.size(err_sqr) + +# Solve the exponential decay ODE using neural network with one input and one output layer, +# but with specified number of hidden layers from the user. +def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb): + # num_hidden_neurons is now a list of number of neurons within each hidden layer + + # The number of elements in the list num_hidden_neurons thus represents + # the number of hidden layers. + + # Find the number of hidden layers: + N_hidden = np.size(num_neurons) + + ## Set up initial weights and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 ) + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: %g'%cost_function_deep(P, x)) + + ## Start finding the optimal weights using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_deep_grad = grad(cost_function_deep,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases + # in the hidden layers and output layers evaluated at x. + cost_deep_grad = cost_function_deep_grad(P, x) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_deep_grad[l] + + print('Final cost: %g'%cost_function_deep(P, x)) + + return P + +def g_analytic(x, gamma = 2, g0 = 10): + return g0*np.exp(-gamma*x) + +# Solve the given problem +if __name__ == '__main__': + npr.seed(15) + + ## Decide the vales of arguments to the function to solve + N = 10 + x = np.linspace(0, 1, N) + + ## Set up the initial parameters + num_hidden_neurons = np.array([10,10]) + num_iter = 10000 + lmb = 0.001 + + P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb) + + res = g_trial_deep(x,P) + res_analytical = g_analytic(x) + + plt.figure(figsize=(10,10)) + + plt.title('Performance of a deep neural network solving an ODE compared to the analytical solution') + plt.plot(x, res_analytical) + plt.plot(x, res[0,:]) + plt.legend(['analytical','dnn']) + plt.ylabel('g(x)') + plt.show() + +### Example: Population growth + +A logistic model of population growth assumes that a population converges toward an equilibrium. +The population growth can be modeled by + + +
+ +$$ +\begin{equation} \label{log} \tag{10} + g'(t) = \alpha g(t)(A - g(t)) +\end{equation} +$$ + +where $g(t)$ is the population density at time $t$, $\alpha > 0$ the growth rate and $A > 0$ is the maximum population number in the environment. +Also, at $t = 0$ the population has the size $g(0) = g_0$, where $g_0$ is some chosen constant. + +In this example, similar network as for the exponential decay using Autograd has been used to solve the equation. However, as the implementation might suffer from e.g numerical instability +and high execution time (this might be more apparent in the examples solving PDEs), +using a library like TensorFlow is recommended. +Here, we stay with a more simple approach and implement for comparison, the simple forward Euler method. + + + +Here, we will model a population $g(t)$ in an environment having carrying capacity $A$. +The population follows the model + + +
+ +$$ +\begin{equation} \label{solveode_population} \tag{11} +g'(t) = \alpha g(t)(A - g(t)) +\end{equation} +$$ + +where $g(0) = g_0$. + +In this example, we let $\alpha = 2$, $A = 1$, and $g_0 = 1.2$. + + +We will get a slightly different trial solution, as the boundary conditions are different +compared to the case for exponential decay. + +A possible trial solution satisfying the condition $g(0) = g_0$ could be + +$$ +h_1(t) = g_0 + t \cdot N(t,P) +$$ + +with $N(t,P)$ being the output from the neural network with weights and biases for each layer collected in the set $P$. + +The analytical solution is + +$$ +g(t) = \frac{Ag_0}{g_0 + (A - g_0)\exp(-\alpha A t)} +$$ + + + +The network will be the similar as for the exponential decay example, but with some small modifications for our problem. + +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +# Function to get the parameters. +# Done such that one can easily change the paramaters after one's liking. +def get_parameters(): + alpha = 2 + A = 1 + g0 = 1.2 + return alpha, A, g0 + +def deep_neural_network(P, x): + # N_hidden is the number of hidden layers + N_hidden = np.size(P) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + # Due to multiple hidden layers, define a variable referencing to the + # output of the previous layer: + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = P[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = P[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output + + +def cost_function_deep(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial_deep(x,P) + + # Find the derivative w.r.t x of the trial function + d_g_t = elementwise_grad(g_trial_deep,0)(x,P) + + # The right side of the ODE + func = f(x, g_t) + + err_sqr = (d_g_t - func)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum / np.size(err_sqr) + +# The right side of the ODE: +def f(x, g_trial): + alpha,A, g0 = get_parameters() + return alpha*g_trial*(A - g_trial) + +# The trial solution using the deep neural network: +def g_trial_deep(x, params): + alpha,A, g0 = get_parameters() + return g0 + x*deep_neural_network(params,x) + +# The analytical solution: +def g_analytic(t): + alpha,A, g0 = get_parameters() + return A*g0/(g0 + (A - g0)*np.exp(-alpha*A*t)) + +def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb): + # num_hidden_neurons is now a list of number of neurons within each hidden layer + + # Find the number of hidden layers: + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 ) + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: %g'%cost_function_deep(P, x)) + + ## Start finding the optimal weigths using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_deep_grad = grad(cost_function_deep,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases + # in the hidden layers and output layers evaluated at x. + cost_deep_grad = cost_function_deep_grad(P, x) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_deep_grad[l] + + print('Final cost: %g'%cost_function_deep(P, x)) + + return P + +if __name__ == '__main__': + npr.seed(4155) + + ## Decide the vales of arguments to the function to solve + Nt = 10 + T = 1 + t = np.linspace(0,T, Nt) + + ## Set up the initial parameters + num_hidden_neurons = [100, 50, 25] + num_iter = 1000 + lmb = 1e-3 + + P = solve_ode_deep_neural_network(t, num_hidden_neurons, num_iter, lmb) + + g_dnn_ag = g_trial_deep(t,P) + g_analytical = g_analytic(t) + + # Find the maximum absolute difference between the solutons: + diff_ag = np.max(np.abs(g_dnn_ag - g_analytical)) + print("The max absolute difference between the solutions is: %g"%diff_ag) + + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(t, g_analytical) + plt.plot(t, g_dnn_ag[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('t') + plt.ylabel('g(t)') + + plt.show() + +## Using forward Euler to solve the ODE + +A straightforward way of solving an ODE numerically, is to use Euler's method. + +Euler's method uses Taylor series to approximate the value at a function $f$ at a step $\Delta x$ from $x$: + +$$ +f(x + \Delta x) \approx f(x) + \Delta x f'(x) +$$ + +In our case, using Euler's method to approximate the value of $g$ at a step $\Delta t$ from $t$ yields + +$$ +\begin{aligned} + g(t + \Delta t) &\approx g(t) + \Delta t g'(t) \\ + &= g(t) + \Delta t \big(\alpha g(t)(A - g(t))\big) +\end{aligned} +$$ + +along with the condition that $g(0) = g_0$. + +Let $t_i = i \cdot \Delta t$ where $\Delta t = \frac{T}{N_t-1}$ where $T$ is the final time our solver must solve for and $N_t$ the number of values for $t \in [0, T]$ for $i = 0, \dots, N_t-1$. + +For $i \geq 1$, we have that + +$$ +\begin{aligned} +t_i &= i\Delta t \\ +&= (i - 1)\Delta t + \Delta t \\ +&= t_{i-1} + \Delta t +\end{aligned} +$$ + +Now, if $g_i = g(t_i)$ then + + +
+ +$$ +\begin{equation} + \begin{aligned} + g_i &= g(t_i) \\ + &= g(t_{i-1} + \Delta t) \\ + &\approx g(t_{i-1}) + \Delta t \big(\alpha g(t_{i-1})(A - g(t_{i-1}))\big) \\ + &= g_{i-1} + \Delta t \big(\alpha g_{i-1}(A - g_{i-1})\big) + \end{aligned} +\end{equation} \label{odenum} \tag{12} +$$ + +for $i \geq 1$ and $g_0 = g(t_0) = g(0) = g_0$. + +Equation ([12](#odenum)) could be implemented in the following way, +extending the program that uses the network using Autograd: + +# Assume that all function definitions from the example program using Autograd +# are located here. + +if __name__ == '__main__': + npr.seed(4155) + + ## Decide the vales of arguments to the function to solve + Nt = 10 + T = 1 + t = np.linspace(0,T, Nt) + + ## Set up the initial parameters + num_hidden_neurons = [100,50,25] + num_iter = 1000 + lmb = 1e-3 + + P = solve_ode_deep_neural_network(t, num_hidden_neurons, num_iter, lmb) + + g_dnn_ag = g_trial_deep(t,P) + g_analytical = g_analytic(t) + + # Find the maximum absolute difference between the solutons: + diff_ag = np.max(np.abs(g_dnn_ag - g_analytical)) + print("The max absolute difference between the solutions is: %g"%diff_ag) + + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(t, g_analytical) + plt.plot(t, g_dnn_ag[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('t') + plt.ylabel('g(t)') + + ## Find an approximation to the funtion using forward Euler + + alpha, A, g0 = get_parameters() + dt = T/(Nt - 1) + + # Perform forward Euler to solve the ODE + g_euler = np.zeros(Nt) + g_euler[0] = g0 + + for i in range(1,Nt): + g_euler[i] = g_euler[i-1] + dt*(alpha*g_euler[i-1]*(A - g_euler[i-1])) + + # Print the errors done by each method + diff1 = np.max(np.abs(g_euler - g_analytical)) + diff2 = np.max(np.abs(g_dnn_ag[0,:] - g_analytical)) + + print('Max absolute difference between Euler method and analytical: %g'%diff1) + print('Max absolute difference between deep neural network and analytical: %g'%diff2) + + # Plot results + plt.figure(figsize=(10,10)) + + plt.plot(t,g_euler) + plt.plot(t,g_analytical) + plt.plot(t,g_dnn_ag[0,:]) + + plt.legend(['euler','analytical','dnn']) + plt.xlabel('Time t') + plt.ylabel('g(t)') + + plt.show() + +## Solving the one dimensional Poisson equation + +The Poisson equation for $g(x)$ in one dimension is + + +
+ +$$ +\begin{equation} \label{poisson} \tag{13} + -g''(x) = f(x) +\end{equation} +$$ + +where $f(x)$ is a given function for $x \in (0,1)$. + +The conditions that $g(x)$ is chosen to fulfill, are + +$$ +\begin{align*} + g(0) &= 0 \\ + g(1) &= 0 +\end{align*} +$$ + +This equation can be solved numerically using programs where e.g Autograd and TensorFlow are used. +The results from the networks can then be compared to the analytical solution. +In addition, it could be interesting to see how a typical method for numerically solving second order ODEs compares to the neural networks. + + +Here, the function $g(x)$ to solve for follows the equation + +$$ +-g''(x) = f(x),\qquad x \in (0,1) +$$ + +where $f(x)$ is a given function, along with the chosen conditions + + +
+ +$$ +\begin{aligned} +g(0) = g(1) = 0 +\end{aligned}\label{cond} \tag{14} +$$ + +In this example, we consider the case when $f(x) = (3x + x^2)\exp(x)$. + +For this case, a possible trial solution satisfying the conditions could be + +$$ +g_t(x) = x \cdot (1-x) \cdot N(P,x) +$$ + +The analytical solution for this problem is + +$$ +g(x) = x(1 - x)\exp(x) +$$ + +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + # Due to multiple hidden layers, define a variable referencing to the + # output of the previous layer: + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output + +def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb): + # num_hidden_neurons is now a list of number of neurons within each hidden layer + + # Find the number of hidden layers: + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 ) + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: %g'%cost_function_deep(P, x)) + + ## Start finding the optimal weigths using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_deep_grad = grad(cost_function_deep,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases + # in the hidden layers and output layers evaluated at x. + cost_deep_grad = cost_function_deep_grad(P, x) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_deep_grad[l] + + print('Final cost: %g'%cost_function_deep(P, x)) + + return P + +## Set up the cost function specified for this Poisson equation: + +# The right side of the ODE +def f(x): + return (3*x + x**2)*np.exp(x) + +def cost_function_deep(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial_deep(x,P) + + # Find the derivative w.r.t x of the trial function + d2_g_t = elementwise_grad(elementwise_grad(g_trial_deep,0))(x,P) + + right_side = f(x) + + err_sqr = (-d2_g_t - right_side)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum/np.size(err_sqr) + +# The trial solution: +def g_trial_deep(x,P): + return x*(1-x)*deep_neural_network(P,x) + +# The analytic solution; +def g_analytic(x): + return x*(1-x)*np.exp(x) + +if __name__ == '__main__': + npr.seed(4155) + + ## Decide the vales of arguments to the function to solve + Nx = 10 + x = np.linspace(0,1, Nx) + + ## Set up the initial parameters + num_hidden_neurons = [200,100] + num_iter = 1000 + lmb = 1e-3 + + P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb) + + g_dnn_ag = g_trial_deep(x,P) + g_analytical = g_analytic(x) + + # Find the maximum absolute difference between the solutons: + max_diff = np.max(np.abs(g_dnn_ag - g_analytical)) + print("The max absolute difference between the solutions is: %g"%max_diff) + + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(x, g_analytical) + plt.plot(x, g_dnn_ag[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('x') + plt.ylabel('g(x)') + plt.show() + +### Comparing with a numerical scheme + +The Poisson equation is possible to solve using Taylor series to approximate the second derivative. + +Using Taylor series, the second derivative can be expressed as + +$$ +g''(x) = \frac{g(x + \Delta x) - 2g(x) + g(x-\Delta x)}{\Delta x^2} + E_{\Delta x}(x) +$$ + +where $\Delta x$ is a small step size and $E_{\Delta x}(x)$ being the error term. + +Looking away from the error terms gives an approximation to the second derivative: + + +
+ +$$ +\begin{equation} \label{approx} \tag{15} +g''(x) \approx \frac{g(x + \Delta x) - 2g(x) + g(x-\Delta x)}{\Delta x^2} +\end{equation} +$$ + +If $x_i = i \Delta x = x_{i-1} + \Delta x$ and $g_i = g(x_i)$ for $i = 1,\dots N_x - 2$ with $N_x$ being the number of values for $x$, ([15](#approx)) becomes + +$$ +\begin{aligned} +g''(x_i) &\approx \frac{g(x_i + \Delta x) - 2g(x_i) + g(x_i -\Delta x)}{\Delta x^2} \\ +&= \frac{g_{i+1} - 2g_i + g_{i-1}}{\Delta x^2} +\end{aligned} +$$ + +Since we know from our problem that + +$$ +\begin{aligned} +-g''(x) &= f(x) \\ +&= (3x + x^2)\exp(x) +\end{aligned} +$$ + +along with the conditions $g(0) = g(1) = 0$, +the following scheme can be used to find an approximate solution for $g(x)$ numerically: + + +
+ +$$ +\begin{equation} + \begin{aligned} + -\Big( \frac{g_{i+1} - 2g_i + g_{i-1}}{\Delta x^2} \Big) &= f(x_i) \\ + -g_{i+1} + 2g_i - g_{i-1} &= \Delta x^2 f(x_i) + \end{aligned} +\end{equation} \label{odesys} \tag{16} +$$ + +for $i = 1, \dots, N_x - 2$ where $g_0 = g_{N_x - 1} = 0$ and $f(x_i) = (3x_i + x_i^2)\exp(x_i)$, which is given for our specific problem. + +The equation can be rewritten into a matrix equation: + +$$ +\begin{aligned} +\begin{pmatrix} +2 & -1 & 0 & \dots & 0 \\ +-1 & 2 & -1 & \dots & 0 \\ +\vdots & & \ddots & & \vdots \\ +0 & \dots & -1 & 2 & -1 \\ +0 & \dots & 0 & -1 & 2\\ +\end{pmatrix} +\begin{pmatrix} +g_1 \\ +g_2 \\ +\vdots \\ +g_{N_x - 3} \\ +g_{N_x - 2} +\end{pmatrix} +&= +\Delta x^2 +\begin{pmatrix} +f(x_1) \\ +f(x_2) \\ +\vdots \\ +f(x_{N_x - 3}) \\ +f(x_{N_x - 2}) +\end{pmatrix} \\ +\boldsymbol{A}\boldsymbol{g} &= \boldsymbol{f}, +\end{aligned} +$$ + +which makes it possible to solve for the vector $\boldsymbol{g}$. + + +We can then compare the result from this numerical scheme with the output from our network using Autograd: + +import autograd.numpy as np +from autograd import grad, elementwise_grad +import autograd.numpy.random as npr +from matplotlib import pyplot as plt + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assumes input x being an one-dimensional array + num_values = np.size(x) + x = x.reshape(-1, num_values) + + # Assume that the input layer does nothing to the input x + x_input = x + + # Due to multiple hidden layers, define a variable referencing to the + # output of the previous layer: + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output + +def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb): + # num_hidden_neurons is now a list of number of neurons within each hidden layer + + # Find the number of hidden layers: + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 ) + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: %g'%cost_function_deep(P, x)) + + ## Start finding the optimal weigths using gradient descent + + # Find the Python function that represents the gradient of the cost function + # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer + cost_function_deep_grad = grad(cost_function_deep,0) + + # Let the update be done num_iter times + for i in range(num_iter): + # Evaluate the gradient at the current weights and biases in P. + # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases + # in the hidden layers and output layers evaluated at x. + cost_deep_grad = cost_function_deep_grad(P, x) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_deep_grad[l] + + print('Final cost: %g'%cost_function_deep(P, x)) + + return P + +## Set up the cost function specified for this Poisson equation: + +# The right side of the ODE +def f(x): + return (3*x + x**2)*np.exp(x) + +def cost_function_deep(P, x): + + # Evaluate the trial function with the current parameters P + g_t = g_trial_deep(x,P) + + # Find the derivative w.r.t x of the trial function + d2_g_t = elementwise_grad(elementwise_grad(g_trial_deep,0))(x,P) + + right_side = f(x) + + err_sqr = (-d2_g_t - right_side)**2 + cost_sum = np.sum(err_sqr) + + return cost_sum/np.size(err_sqr) + +# The trial solution: +def g_trial_deep(x,P): + return x*(1-x)*deep_neural_network(P,x) + +# The analytic solution; +def g_analytic(x): + return x*(1-x)*np.exp(x) + +if __name__ == '__main__': + npr.seed(4155) + + ## Decide the vales of arguments to the function to solve + Nx = 10 + x = np.linspace(0,1, Nx) + + ## Set up the initial parameters + num_hidden_neurons = [200,100] + num_iter = 1000 + lmb = 1e-3 + + P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb) + + g_dnn_ag = g_trial_deep(x,P) + g_analytical = g_analytic(x) + + # Find the maximum absolute difference between the solutons: + + plt.figure(figsize=(10,10)) + + plt.title('Performance of neural network solving an ODE compared to the analytical solution') + plt.plot(x, g_analytical) + plt.plot(x, g_dnn_ag[0,:]) + plt.legend(['analytical','nn']) + plt.xlabel('x') + plt.ylabel('g(x)') + + ## Perform the computation using the numerical scheme + + dx = 1/(Nx - 1) + + # Set up the matrix A + A = np.zeros((Nx-2,Nx-2)) + + A[0,0] = 2 + A[0,1] = -1 + + for i in range(1,Nx-3): + A[i,i-1] = -1 + A[i,i] = 2 + A[i,i+1] = -1 + + A[Nx - 3, Nx - 4] = -1 + A[Nx - 3, Nx - 3] = 2 + + # Set up the vector f + f_vec = dx**2 * f(x[1:-1]) + + # Solve the equation + g_res = np.linalg.solve(A,f_vec) + + g_vec = np.zeros(Nx) + g_vec[1:-1] = g_res + + # Print the differences between each method + max_diff1 = np.max(np.abs(g_dnn_ag - g_analytical)) + max_diff2 = np.max(np.abs(g_vec - g_analytical)) + print("The max absolute difference between the analytical solution and DNN Autograd: %g"%max_diff1) + print("The max absolute difference between the analytical solution and numerical scheme: %g"%max_diff2) + + # Plot the results + plt.figure(figsize=(10,10)) + + plt.plot(x,g_vec) + plt.plot(x,g_analytical) + plt.plot(x,g_dnn_ag[0,:]) + + plt.legend(['numerical scheme','analytical','dnn']) + plt.show() + +## Partial Differential Equations + +A partial differential equation (PDE) has a solution here the function +is defined by multiple variables. The equation may involve all kinds +of combinations of which variables the function is differentiated with +respect to. + +In general, a partial differential equation for a function $g(x_1,\dots,x_N)$ with $N$ variables may be expressed as + + +
+ +$$ +\begin{equation} \label{PDE} \tag{17} + f\left(x_1, \, \dots \, , x_N, \frac{\partial g(x_1,\dots,x_N) }{\partial x_1}, \dots , \frac{\partial g(x_1,\dots,x_N) }{\partial x_N}, \frac{\partial g(x_1,\dots,x_N) }{\partial x_1\partial x_2}, \, \dots \, , \frac{\partial^n g(x_1,\dots,x_N) }{\partial x_N^n} \right) = 0 +\end{equation} +$$ + +where $f$ is an expression involving all kinds of possible mixed derivatives of $g(x_1,\dots,x_N)$ up to an order $n$. In order for the solution to be unique, some additional conditions must also be given. + +### Type of problem + +The problem our network must solve for, is similar to the ODE case. +We must have a trial solution $g_t$ at hand. + +For instance, the trial solution could be expressed as + +$$ +\begin{align*} + g_t(x_1,\dots,x_N) = h_1(x_1,\dots,x_N) + h_2(x_1,\dots,x_N,N(x_1,\dots,x_N,P)) +\end{align*} +$$ + +where $h_1(x_1,\dots,x_N)$ is a function that ensures $g_t(x_1,\dots,x_N)$ satisfies some given conditions. +The neural network $N(x_1,\dots,x_N,P)$ has weights and biases described by $P$ and $h_2(x_1,\dots,x_N,N(x_1,\dots,x_N,P))$ is an expression using the output from the neural network in some way. + +The role of the function $h_2(x_1,\dots,x_N,N(x_1,\dots,x_N,P))$, is to ensure that the output of $N(x_1,\dots,x_N,P)$ is zero when $g_t(x_1,\dots,x_N)$ is evaluated at the values of $x_1,\dots,x_N$ where the given conditions must be satisfied. The function $h_1(x_1,\dots,x_N)$ should alone make $g_t(x_1,\dots,x_N)$ satisfy the conditions. + + + +### Network requirements + +The network tries then the minimize the cost function following the +same ideas as described for the ODE case, but now with more than one +variables to consider. The concept still remains the same; find a set +of parameters $P$ such that the expression $f$ in ([17](#PDE)) is as +close to zero as possible. + +As for the ODE case, the cost function is the mean squared error that +the network must try to minimize. The cost function for the network to +minimize is + +$$ +C\left(x_1, \dots, x_N, P\right) = \left( f\left(x_1, \, \dots \, , x_N, \frac{\partial g(x_1,\dots,x_N) }{\partial x_1}, \dots , \frac{\partial g(x_1,\dots,x_N) }{\partial x_N}, \frac{\partial g(x_1,\dots,x_N) }{\partial x_1\partial x_2}, \, \dots \, , \frac{\partial^n g(x_1,\dots,x_N) }{\partial x_N^n} \right) \right)^2 +$$ + +If we let $\boldsymbol{x} = \big( x_1, \dots, x_N \big)$ be an array containing the values for $x_1, \dots, x_N$ respectively, the cost function can be reformulated into the following: + +$$ +C\left(\boldsymbol{x}, P\right) = f\left( \left( \boldsymbol{x}, \frac{\partial g(\boldsymbol{x}) }{\partial x_1}, \dots , \frac{\partial g(\boldsymbol{x}) }{\partial x_N}, \frac{\partial g(\boldsymbol{x}) }{\partial x_1\partial x_2}, \, \dots \, , \frac{\partial^n g(\boldsymbol{x}) }{\partial x_N^n} \right) \right)^2 +$$ + +If we also have $M$ different sets of values for $x_1, \dots, x_N$, that is $\boldsymbol{x}_i = \big(x_1^{(i)}, \dots, x_N^{(i)}\big)$ for $i = 1,\dots,M$ being the rows in matrix $X$, the cost function can be generalized into + +$$ +C\left(X, P \right) = \sum_{i=1}^M f\left( \left( \boldsymbol{x}_i, \frac{\partial g(\boldsymbol{x}_i) }{\partial x_1}, \dots , \frac{\partial g(\boldsymbol{x}_i) }{\partial x_N}, \frac{\partial g(\boldsymbol{x}_i) }{\partial x_1\partial x_2}, \, \dots \, , \frac{\partial^n g(\boldsymbol{x}_i) }{\partial x_N^n} \right) \right)^2. +$$ + +## Example: The diffusion equation + +In one spatial dimension, the equation reads + +$$ +\frac{\partial g(x,t)}{\partial t} = \frac{\partial^2 g(x,t)}{\partial x^2} +$$ + +where a possible choice of conditions are + +$$ +\begin{align*} +g(0,t) &= 0 ,\qquad t \geq 0 \\ +g(1,t) &= 0, \qquad t \geq 0 \\ +g(x,0) &= u(x),\qquad x\in [0,1] +\end{align*} +$$ + +with $u(x)$ being some given function. + + + +For this case, we want to find $g(x,t)$ such that + + +
+ +$$ +\begin{equation} + \frac{\partial g(x,t)}{\partial t} = \frac{\partial^2 g(x,t)}{\partial x^2} +\end{equation} \label{diffonedim} \tag{18} +$$ + +and + +$$ +\begin{align*} +g(0,t) &= 0 ,\qquad t \geq 0 \\ +g(1,t) &= 0, \qquad t \geq 0 \\ +g(x,0) &= u(x),\qquad x\in [0,1] +\end{align*} +$$ + +with $u(x) = \sin(\pi x)$. + +First, let us set up the deep neural network. +The deep neural network will follow the same structure as discussed in the examples solving the ODEs. +First, we will look into how Autograd could be used in a network tailored to solve for bivariate functions. + + + + +The only change to do here, is to extend our network such that +functions of multiple parameters are correctly handled. In this case +we have two variables in our function to solve for, that is time $t$ +and position $x$. The variables will be represented by a +one-dimensional array in the program. The program will evaluate the +network at each possible pair $(x,t)$, given an array for the desired +$x$-values and $t$-values to approximate the solution at. + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # x is now a point and a 1D numpy array; make it a column vector + num_coordinates = np.size(x,0) + x = x.reshape(num_coordinates,-1) + + num_points = np.size(x,1) + + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assume that the input layer does nothing to the input x + x_input = x + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output[0][0] + +The cost function must then iterate through the given arrays +containing values for $x$ and $t$, defines a point $(x,t)$ the deep +neural network and the trial solution is evaluated at, and then finds +the Jacobian of the trial solution. + +A possible trial solution for this PDE is + +$$ +g_t(x,t) = h_1(x,t) + x(1-x)tN(x,t,P) +$$ + +with $A(x,t)$ being a function ensuring that $g_t(x,t)$ satisfies our given conditions, and $N(x,t,P)$ being the output from the deep neural network using weights and biases for each layer from $P$. + +To fulfill the conditions, $A(x,t)$ could be: + +$$ +h_1(x,t) = (1-t)\Big(u(x) - \big((1-x)u(0) + x u(1)\big)\Big) = (1-t)u(x) = (1-t)\sin(\pi x) +$$ +since $(0) = u(1) = 0$ and $u(x) = \sin(\pi x)$. + + + +The Jacobian is used because the program must find the derivative of +the trial solution with respect to $x$ and $t$. + +This gives the necessity of computing the Jacobian matrix, as we want +to evaluate the gradient with respect to $x$ and $t$ (note that the +Jacobian of a scalar-valued multivariate function is simply its +gradient). + +In Autograd, the differentiation is by default done with respect to +the first input argument of your Python function. Since the points is +an array representing $x$ and $t$, the Jacobian is calculated using +the values of $x$ and $t$. + +To find the second derivative with respect to $x$ and $t$, the +Jacobian can be found for the second time. The result is a Hessian +matrix, which is the matrix containing all the possible second order +mixed derivatives of $g(x,t)$. + +# Set up the trial function: +def u(x): + return np.sin(np.pi*x) + +def g_trial(point,P): + x,t = point + return (1-t)*u(x) + x*(1-x)*t*deep_neural_network(P,point) + +# The right side of the ODE: +def f(point): + return 0. + +# The cost function: +def cost_function(P, x, t): + cost_sum = 0 + + g_t_jacobian_func = jacobian(g_trial) + g_t_hessian_func = hessian(g_trial) + + for x_ in x: + for t_ in t: + point = np.array([x_,t_]) + + g_t = g_trial(point,P) + g_t_jacobian = g_t_jacobian_func(point,P) + g_t_hessian = g_t_hessian_func(point,P) + + g_t_dt = g_t_jacobian[1] + g_t_d2x = g_t_hessian[0][0] + + func = f(point) + + err_sqr = ( (g_t_dt - g_t_d2x) - func)**2 + cost_sum += err_sqr + + return cost_sum + +### Setting up the network using Autograd; The full program + +Having set up the network, along with the trial solution and cost function, we can now see how the deep neural network performs by comparing the results to the analytical solution. + +The analytical solution of our problem is + +$$ +g(x,t) = \exp(-\pi^2 t)\sin(\pi x) +$$ + +A possible way to implement a neural network solving the PDE, is given below. +Be aware, though, that it is fairly slow for the parameters used. +A better result is possible, but requires more iterations, and thus longer time to complete. + + +Indeed, the program below is not optimal in its implementation, but rather serves as an example on how to implement and use a neural network to solve a PDE. +Using TensorFlow results in a much better execution time. Try it! + +import autograd.numpy as np +from autograd import jacobian,hessian,grad +import autograd.numpy.random as npr +from matplotlib import cm +from matplotlib import pyplot as plt +from mpl_toolkits.mplot3d import axes3d + +## Set up the network + +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # x is now a point and a 1D numpy array; make it a column vector + num_coordinates = np.size(x,0) + x = x.reshape(num_coordinates,-1) + + num_points = np.size(x,1) + + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assume that the input layer does nothing to the input x + x_input = x + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output[0][0] + +## Define the trial solution and cost function +def u(x): + return np.sin(np.pi*x) + +def g_trial(point,P): + x,t = point + return (1-t)*u(x) + x*(1-x)*t*deep_neural_network(P,point) + +# The right side of the ODE: +def f(point): + return 0. + +# The cost function: +def cost_function(P, x, t): + cost_sum = 0 + + g_t_jacobian_func = jacobian(g_trial) + g_t_hessian_func = hessian(g_trial) + + for x_ in x: + for t_ in t: + point = np.array([x_,t_]) + + g_t = g_trial(point,P) + g_t_jacobian = g_t_jacobian_func(point,P) + g_t_hessian = g_t_hessian_func(point,P) + + g_t_dt = g_t_jacobian[1] + g_t_d2x = g_t_hessian[0][0] + + func = f(point) + + err_sqr = ( (g_t_dt - g_t_d2x) - func)**2 + cost_sum += err_sqr + + return cost_sum /( np.size(x)*np.size(t) ) + +## For comparison, define the analytical solution +def g_analytic(point): + x,t = point + return np.exp(-np.pi**2*t)*np.sin(np.pi*x) + +## Set up a function for training the network to solve for the equation +def solve_pde_deep_neural_network(x,t, num_neurons, num_iter, lmb): + ## Set up initial weigths and biases + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 + 1 ) # 2 since we have two points, +1 to include bias + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: ',cost_function(P, x, t)) + + cost_function_grad = grad(cost_function,0) + + # Let the update be done num_iter times + for i in range(num_iter): + cost_grad = cost_function_grad(P, x , t) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_grad[l] + + print('Final cost: ',cost_function(P, x, t)) + + return P + +if __name__ == '__main__': + ### Use the neural network: + npr.seed(15) + + ## Decide the vales of arguments to the function to solve + Nx = 10; Nt = 10 + x = np.linspace(0, 1, Nx) + t = np.linspace(0,1,Nt) + + ## Set up the parameters for the network + num_hidden_neurons = [100, 25] + num_iter = 250 + lmb = 0.01 + + P = solve_pde_deep_neural_network(x,t, num_hidden_neurons, num_iter, lmb) + + ## Store the results + g_dnn_ag = np.zeros((Nx, Nt)) + G_analytical = np.zeros((Nx, Nt)) + for i,x_ in enumerate(x): + for j, t_ in enumerate(t): + point = np.array([x_, t_]) + g_dnn_ag[i,j] = g_trial(point,P) + + G_analytical[i,j] = g_analytic(point) + + # Find the map difference between the analytical and the computed solution + diff_ag = np.abs(g_dnn_ag - G_analytical) + print('Max absolute difference between the analytical solution and the network: %g'%np.max(diff_ag)) + + ## Plot the solutions in two dimensions, that being in position and time + + T,X = np.meshgrid(t,x) + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Solution from the deep neural network w/ %d layer'%len(num_hidden_neurons)) + s = ax.plot_surface(T,X,g_dnn_ag,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Analytical solution') + s = ax.plot_surface(T,X,G_analytical,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Difference') + s = ax.plot_surface(T,X,diff_ag,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + ## Take some slices of the 3D plots just to see the solutions at particular times + indx1 = 0 + indx2 = int(Nt/2) + indx3 = Nt-1 + + t1 = t[indx1] + t2 = t[indx2] + t3 = t[indx3] + + # Slice the results from the DNN + res1 = g_dnn_ag[:,indx1] + res2 = g_dnn_ag[:,indx2] + res3 = g_dnn_ag[:,indx3] + + # Slice the analytical results + res_analytical1 = G_analytical[:,indx1] + res_analytical2 = G_analytical[:,indx2] + res_analytical3 = G_analytical[:,indx3] + + # Plot the slices + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t1) + plt.plot(x, res1) + plt.plot(x,res_analytical1) + plt.legend(['dnn','analytical']) + + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t2) + plt.plot(x, res2) + plt.plot(x,res_analytical2) + plt.legend(['dnn','analytical']) + + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t3) + plt.plot(x, res3) + plt.plot(x,res_analytical3) + plt.legend(['dnn','analytical']) + + plt.show() + +## Solving the wave equation with Neural Networks + +The wave equation is + +$$ +\frac{\partial^2 g(x,t)}{\partial t^2} = c^2\frac{\partial^2 g(x,t)}{\partial x^2} +$$ + +with $c$ being the specified wave speed. + +Here, the chosen conditions are + +$$ +\begin{align*} + g(0,t) &= 0 \\ + g(1,t) &= 0 \\ + g(x,0) &= u(x) \\ + \frac{\partial g(x,t)}{\partial t} \Big |_{t = 0} &= v(x) +\end{align*} +$$ + +where $\frac{\partial g(x,t)}{\partial t} \Big |_{t = 0}$ means the derivative of $g(x,t)$ with respect to $t$ is evaluated at $t = 0$, and $u(x)$ and $v(x)$ being given functions. + + +The wave equation to solve for, is + + +
+ +$$ +\begin{equation} \label{wave} \tag{19} +\frac{\partial^2 g(x,t)}{\partial t^2} = c^2 \frac{\partial^2 g(x,t)}{\partial x^2} +\end{equation} +$$ + +where $c$ is the given wave speed. +The chosen conditions for this equation are + + +
+ +$$ +\begin{aligned} +g(0,t) &= 0, &t \geq 0 \\ +g(1,t) &= 0, &t \geq 0 \\ +g(x,0) &= u(x), &x\in[0,1] \\ +\frac{\partial g(x,t)}{\partial t}\Big |_{t = 0} &= v(x), &x \in [0,1] +\end{aligned} \label{condwave} \tag{20} +$$ + +In this example, let $c = 1$ and $u(x) = \sin(\pi x)$ and $v(x) = -\pi\sin(\pi x)$. + + + +Setting up the network is done in similar matter as for the example of solving the diffusion equation. +The only things we have to change, is the trial solution such that it satisfies the conditions from ([20](#condwave)) and the cost function. + +The trial solution becomes slightly different since we have other conditions than in the example of solving the diffusion equation. Here, a possible trial solution $g_t(x,t)$ is + +$$ +g_t(x,t) = h_1(x,t) + x(1-x)t^2N(x,t,P) +$$ + +where + +$$ +h_1(x,t) = (1-t^2)u(x) + tv(x) +$$ + +Note that this trial solution satisfies the conditions only if $u(0) = v(0) = u(1) = v(1) = 0$, which is the case in this example. + + +The analytical solution for our specific problem, is + +$$ +g(x,t) = \sin(\pi x)\cos(\pi t) - \sin(\pi x)\sin(\pi t) +$$ + +import autograd.numpy as np +from autograd import hessian,grad +import autograd.numpy.random as npr +from matplotlib import cm +from matplotlib import pyplot as plt +from mpl_toolkits.mplot3d import axes3d + +## Set up the trial function: +def u(x): + return np.sin(np.pi*x) + +def v(x): + return -np.pi*np.sin(np.pi*x) + +def h1(point): + x,t = point + return (1 - t**2)*u(x) + t*v(x) + +def g_trial(point,P): + x,t = point + return h1(point) + x*(1-x)*t**2*deep_neural_network(P,point) + +## Define the cost function +def cost_function(P, x, t): + cost_sum = 0 + + g_t_hessian_func = hessian(g_trial) + + for x_ in x: + for t_ in t: + point = np.array([x_,t_]) + + g_t_hessian = g_t_hessian_func(point,P) + + g_t_d2x = g_t_hessian[0][0] + g_t_d2t = g_t_hessian[1][1] + + err_sqr = ( (g_t_d2t - g_t_d2x) )**2 + cost_sum += err_sqr + + return cost_sum / (np.size(t) * np.size(x)) + +## The neural network +def sigmoid(z): + return 1/(1 + np.exp(-z)) + +def deep_neural_network(deep_params, x): + # x is now a point and a 1D numpy array; make it a column vector + num_coordinates = np.size(x,0) + x = x.reshape(num_coordinates,-1) + + num_points = np.size(x,1) + + # N_hidden is the number of hidden layers + N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer + + # Assume that the input layer does nothing to the input x + x_input = x + x_prev = x_input + + ## Hidden layers: + + for l in range(N_hidden): + # From the list of parameters P; find the correct weigths and bias for this layer + w_hidden = deep_params[l] + + # Add a row of ones to include bias + x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0) + + z_hidden = np.matmul(w_hidden, x_prev) + x_hidden = sigmoid(z_hidden) + + # Update x_prev such that next layer can use the output from this layer + x_prev = x_hidden + + ## Output layer: + + # Get the weights and bias for this layer + w_output = deep_params[-1] + + # Include bias: + x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0) + + z_output = np.matmul(w_output, x_prev) + x_output = z_output + + return x_output[0][0] + +## The analytical solution +def g_analytic(point): + x,t = point + return np.sin(np.pi*x)*np.cos(np.pi*t) - np.sin(np.pi*x)*np.sin(np.pi*t) + +def solve_pde_deep_neural_network(x,t, num_neurons, num_iter, lmb): + ## Set up initial weigths and biases + N_hidden = np.size(num_neurons) + + ## Set up initial weigths and biases + + # Initialize the list of parameters: + P = [None]*(N_hidden + 1) # + 1 to include the output layer + + P[0] = npr.randn(num_neurons[0], 2 + 1 ) # 2 since we have two points, +1 to include bias + for l in range(1,N_hidden): + P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias + + # For the output layer + P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included + + print('Initial cost: ',cost_function(P, x, t)) + + cost_function_grad = grad(cost_function,0) + + # Let the update be done num_iter times + for i in range(num_iter): + cost_grad = cost_function_grad(P, x , t) + + for l in range(N_hidden+1): + P[l] = P[l] - lmb * cost_grad[l] + + + print('Final cost: ',cost_function(P, x, t)) + + return P + +if __name__ == '__main__': + ### Use the neural network: + npr.seed(15) + + ## Decide the vales of arguments to the function to solve + Nx = 10; Nt = 10 + x = np.linspace(0, 1, Nx) + t = np.linspace(0,1,Nt) + + ## Set up the parameters for the network + num_hidden_neurons = [50,20] + num_iter = 1000 + lmb = 0.01 + + P = solve_pde_deep_neural_network(x,t, num_hidden_neurons, num_iter, lmb) + + ## Store the results + res = np.zeros((Nx, Nt)) + res_analytical = np.zeros((Nx, Nt)) + for i,x_ in enumerate(x): + for j, t_ in enumerate(t): + point = np.array([x_, t_]) + res[i,j] = g_trial(point,P) + + res_analytical[i,j] = g_analytic(point) + + diff = np.abs(res - res_analytical) + print("Max difference between analytical and solution from nn: %g"%np.max(diff)) + + ## Plot the solutions in two dimensions, that being in position and time + + T,X = np.meshgrid(t,x) + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Solution from the deep neural network w/ %d layer'%len(num_hidden_neurons)) + s = ax.plot_surface(T,X,res,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Analytical solution') + s = ax.plot_surface(T,X,res_analytical,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + + fig = plt.figure(figsize=(10,10)) + ax = fig.gca(projection='3d') + ax.set_title('Difference') + s = ax.plot_surface(T,X,diff,linewidth=0,antialiased=False,cmap=cm.viridis) + ax.set_xlabel('Time $t$') + ax.set_ylabel('Position $x$'); + + ## Take some slices of the 3D plots just to see the solutions at particular times + indx1 = 0 + indx2 = int(Nt/2) + indx3 = Nt-1 + + t1 = t[indx1] + t2 = t[indx2] + t3 = t[indx3] + + # Slice the results from the DNN + res1 = res[:,indx1] + res2 = res[:,indx2] + res3 = res[:,indx3] + + # Slice the analytical results + res_analytical1 = res_analytical[:,indx1] + res_analytical2 = res_analytical[:,indx2] + res_analytical3 = res_analytical[:,indx3] + + # Plot the slices + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t1) + plt.plot(x, res1) + plt.plot(x,res_analytical1) + plt.legend(['dnn','analytical']) + + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t2) + plt.plot(x, res2) + plt.plot(x,res_analytical2) + plt.legend(['dnn','analytical']) + + plt.figure(figsize=(10,10)) + plt.title("Computed solutions at time = %g"%t3) + plt.plot(x, res3) + plt.plot(x,res_analytical3) + plt.legend(['dnn','analytical']) + + plt.show() + +## Resources on differential equations and deep learning + +1. [Artificial neural networks for solving ordinary and partial differential equations by I.E. Lagaris et al](https://pdfs.semanticscholar.org/d061/df393e0e8fbfd0ea24976458b7d42419040d.pdf) + +2. [Neural networks for solving differential equations by A. Honchar](https://becominghuman.ai/neural-networks-for-solving-differential-equations-fa230ac5e04c) + +3. [Solving differential equations using neural networks by M.M Chiaramonte and M. Kiener](http://cs229.stanford.edu/proj2013/ChiaramonteKiener-SolvingDifferentialEquationsUsingNeuralNetworks.pdf) + +4. [Introduction to Partial Differential Equations by A. Tveito, R. Winther](https://www.springer.com/us/book/9783540225515) \ No newline at end of file diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter11_47_2.png b/doc/LectureNotes/_build/jupyter_execute/chapter11_47_2.png new file mode 100644 index 0000000000000000000000000000000000000000..5667f33510ee727076ad0a2888ec3a6a662e37b1 GIT binary patch literal 23383 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 Vn);=#0FvuNI+}(zOVsZ@{U5ECvP}R0 literal 0 HcmV?d00001 diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter11_49_3.png b/doc/LectureNotes/_build/jupyter_execute/chapter11_49_3.png new file mode 100644 index 0000000000000000000000000000000000000000..d8fe671bbc3dbf58b8bb8e92eb10faf77d0837e3 GIT binary patch literal 23773 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 ARR910 literal 0 HcmV?d00001 diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter11_55_3.png b/doc/LectureNotes/_build/jupyter_execute/chapter11_55_3.png new file mode 100644 index 0000000000000000000000000000000000000000..25118b436989c9c35c2966ebab3763e331b74633 GIT binary patch literal 29269 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 E3oXa0h5!Hn literal 0 HcmV?d00001 diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter11_63_3.png b/doc/LectureNotes/_build/jupyter_execute/chapter11_63_3.png new file mode 100644 index 0000000000000000000000000000000000000000..25118b436989c9c35c2966ebab3763e331b74633 GIT binary patch literal 29269 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 E3oXa0h5!Hn literal 0 HcmV?d00001 diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter11_63_4.png b/doc/LectureNotes/_build/jupyter_execute/chapter11_63_4.png new file mode 100644 index 0000000000000000000000000000000000000000..7b1474c1bc4db4f06d93f7ec76da0751513559e9 GIT binary patch literal 34714 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 literal 0 HcmV?d00001 diff --git a/doc/LectureNotes/_build/jupyter_execute/chapter11_76_3.png b/doc/LectureNotes/_build/jupyter_execute/chapter11_76_3.png new file mode 100644 index 0000000000000000000000000000000000000000..40d7e881578b6ad5f4176054365e0c995d9da2ed GIT binary patch literal 27786 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 literal 0 HcmV?d00001 diff --git a/doc/LectureNotes/_toc.yml b/doc/LectureNotes/_toc.yml index 2754ecaff..52a203dfd 100644 --- a/doc/LectureNotes/_toc.yml +++ b/doc/LectureNotes/_toc.yml @@ -31,3 +31,5 @@ chapters: - file: chapter9.ipynb - file: chapter10.ipynb + - file: chapter11.ipynb + - file: chapter12.ipynb diff --git a/doc/LectureNotes/chapter11.ipynb b/doc/LectureNotes/chapter11.ipynb new file mode 100644 index 000000000..c03e4a368 --- /dev/null +++ b/doc/LectureNotes/chapter11.ipynb @@ -0,0 +1,3023 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Solving Differential Equations with Deep Learning\n", + "\n", + "The Universal Approximation Theorem states that a neural network can\n", + "approximate any function at a single hidden layer along with one input\n", + "and output layer to any given precision. \n", + "\n", + "\n", + "An ordinary differential equation (ODE) is an equation involving functions having one variable.\n", + "\n", + "In general, an ordinary differential equation looks like" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{ode} \\tag{1}\n", + "f\\left(x, \\, g(x), \\, g'(x), \\, g''(x), \\, \\dots \\, , \\, g^{(n)}(x)\\right) = 0\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $g(x)$ is the function to find, and $g^{(n)}(x)$ is the $n$-th derivative of $g(x)$.\n", + "\n", + "The $f\\left(x, g(x), g'(x), g''(x), \\, \\dots \\, , g^{(n)}(x)\\right)$ is just a way to write that there is an expression involving $x$ and $g(x), \\ g'(x), \\ g''(x), \\, \\dots \\, , \\text{ and } g^{(n)}(x)$ on the left side of the equality sign in ([1](#ode)).\n", + "The highest order of derivative, that is the value of $n$, determines to the order of the equation.\n", + "The equation is referred to as a $n$-th order ODE.\n", + "Along with ([1](#ode)), some additional conditions of the function $g(x)$ are typically given\n", + "for the solution to be unique.\n", + "\n", + "\n", + "\n", + "Let the trial solution $g_t(x)$ be" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + "\tg_t(x) = h_1(x) + h_2(x,N(x,P))\n", + "\\label{_auto1} \\tag{2}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $h_1(x)$ is a function that makes $g_t(x)$ satisfy a given set\n", + "of conditions, $N(x,P)$ a neural network with weights and biases\n", + "described by $P$ and $h_2(x, N(x,P))$ some expression involving the\n", + "neural network. The role of the function $h_2(x, N(x,P))$, is to\n", + "ensure that the output from $N(x,P)$ is zero when $g_t(x)$ is\n", + "evaluated at the values of $x$ where the given conditions must be\n", + "satisfied. The function $h_1(x)$ should alone make $g_t(x)$ satisfy\n", + "the conditions.\n", + "\n", + "But what about the network $N(x,P)$?\n", + "\n", + "\n", + "As described previously, an optimization method could be used to minimize the parameters of a neural network, that being its weights and biases, through backward propagation.\n", + "\n", + "\n", + "\n", + "For the minimization to be defined, we need to have a cost function at hand to minimize.\n", + "\n", + "It is given that $f\\left(x, \\, g(x), \\, g'(x), \\, g''(x), \\, \\dots \\, , \\, g^{(n)}(x)\\right)$ should be equal to zero in ([1](#ode)).\n", + "We can choose to consider the mean squared error as the cost function for an input $x$.\n", + "Since we are looking at one input, the cost function is just $f$ squared.\n", + "The cost function $c\\left(x, P \\right)$ can therefore be expressed as" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C\\left(x, P\\right) = \\big(f\\left(x, \\, g(x), \\, g'(x), \\, g''(x), \\, \\dots \\, , \\, g^{(n)}(x)\\right)\\big)^2\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If $N$ inputs are given as a vector $\\boldsymbol{x}$ with elements $x_i$ for $i = 1,\\dots,N$,\n", + "the cost function becomes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{cost} \\tag{3}\n", + "\tC\\left(\\boldsymbol{x}, P\\right) = \\frac{1}{N} \\sum_{i=1}^N \\big(f\\left(x_i, \\, g(x_i), \\, g'(x_i), \\, g''(x_i), \\, \\dots \\, , \\, g^{(n)}(x_i)\\right)\\big)^2\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The neural net should then find the parameters $P$ that minimizes the cost function in\n", + "([3](#cost)) for a set of $N$ training samples $x_i$.\n", + "\n", + "\n", + "\n", + "To perform the minimization using gradient descent, the gradient of $C\\left(\\boldsymbol{x}, P\\right)$ is needed.\n", + "It might happen so that finding an analytical expression of the gradient of $C(\\boldsymbol{x}, P)$ from ([3](#cost)) gets too messy, depending on which cost function one desires to use.\n", + "\n", + "Luckily, there exists libraries that makes the job for us through automatic differentiation.\n", + "Automatic differentiation is a method of finding the derivatives numerically with very high precision.\n", + "\n", + "\n", + "### Example: Exponential decay\n", + "\n", + "An exponential decay of a quantity $g(x)$ is described by the equation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{solve_expdec} \\tag{4}\n", + " g'(x) = -\\gamma g(x)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $g(0) = g_0$ for some chosen initial value $g_0$.\n", + "\n", + "The analytical solution of ([4](#solve_expdec)) is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + " g(x) = g_0 \\exp\\left(-\\gamma x\\right)\n", + "\\label{_auto2} \\tag{5}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Having an analytical solution at hand, it is possible to use it to compare how well a neural network finds a solution of ([4](#solve_expdec)).\n", + "\n", + "\n", + "\n", + "The program will use a neural network to solve" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{solveode} \\tag{6}\n", + "g'(x) = -\\gamma g(x)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $g(0) = g_0$ with $\\gamma$ and $g_0$ being some chosen values.\n", + "\n", + "In this example, $\\gamma = 2$ and $g_0 = 10$.\n", + "\n", + "\n", + "To begin with, a trial solution $g_t(t)$ must be chosen. A general trial solution for ordinary differential equations could be" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "g_t(x, P) = h_1(x) + h_2(x, N(x, P))\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $h_1(x)$ ensuring that $g_t(x)$ satisfies some conditions and $h_2(x,N(x, P))$ an expression involving $x$ and the output from the neural network $N(x,P)$ with $P $ being the collection of the weights and biases for each layer. For now, it is assumed that the network consists of one input layer, one hidden layer, and one output layer.\n", + "\n", + "\n", + "\n", + "In this network, there are no weights and bias at the input layer, so $P = \\{ P_{\\text{hidden}}, P_{\\text{output}} \\}$.\n", + "If there are $N_{\\text{hidden} }$ neurons in the hidden layer, then $P_{\\text{hidden}}$ is a $N_{\\text{hidden} } \\times (1 + N_{\\text{input}})$ matrix, given that there are $N_{\\text{input}}$ neurons in the input layer.\n", + "\n", + "The first column in $P_{\\text{hidden} }$ represents the bias for each neuron in the hidden layer and the second column represents the weights for each neuron in the hidden layer from the input layer.\n", + "If there are $N_{\\text{output} }$ neurons in the output layer, then $P_{\\text{output}} $ is a $N_{\\text{output} } \\times (1 + N_{\\text{hidden} })$ matrix.\n", + "\n", + "Its first column represents the bias of each neuron and the remaining columns represents the weights to each neuron.\n", + "\n", + "It is given that $g(0) = g_0$. The trial solution must fulfill this condition to be a proper solution of ([6](#solveode)). A possible way to ensure that $g_t(0, P) = g_0$, is to let $F(N(x,P)) = x \\cdot N(x,P)$ and $A(x) = g_0$. This gives the following trial solution:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{trial} \\tag{7}\n", + "g_t(x, P) = g_0 + x \\cdot N(x, P)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reformulating the problem\n", + "\n", + "We wish that our neural network manages to minimize a given cost function.\n", + "\n", + "A reformulation of out equation, ([6](#solveode)), must therefore be done,\n", + "such that it describes the problem a neural network can solve for.\n", + "\n", + "The neural network must find the set of weights and biases $P$ such that the trial solution in ([7](#trial)) satisfies ([6](#solveode)).\n", + "\n", + "The trial solution" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "g_t(x, P) = g_0 + x \\cdot N(x, P)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "has been chosen such that it already solves the condition $g(0) = g_0$. What remains, is to find $P$ such that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{nnmin} \\tag{8}\n", + "g_t'(x, P) = - \\gamma g_t(x, P)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "is fulfilled as *best as possible*.\n", + "\n", + "\n", + "The left hand side and right hand side of ([8](#nnmin)) must be computed separately, and then the neural network must choose weights and biases, contained in $P$, such that the sides are equal as best as possible.\n", + "This means that the absolute or squared difference between the sides must be as close to zero, ideally equal to zero.\n", + "In this case, the difference squared shows to be an appropriate measurement of how erroneous the trial solution is with respect to $P$ of the neural network.\n", + "\n", + "This gives the following cost function our neural network must solve for:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\min_{P}\\Big\\{ \\big(g_t'(x, P) - ( -\\gamma g_t(x, P) \\big)^2 \\Big\\}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(the notation $\\min_{P}\\{ f(x, P) \\}$ means that we desire to find $P$ that yields the minimum of $f(x, P)$)\n", + "\n", + "or, in terms of weights and biases for the hidden and output layer in our network:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\min_{P_{\\text{hidden} }, \\ P_{\\text{output} }}\\Big\\{ \\big(g_t'(x, \\{ P_{\\text{hidden} }, P_{\\text{output} }\\}) - ( -\\gamma g_t(x, \\{ P_{\\text{hidden} }, P_{\\text{output} }\\}) \\big)^2 \\Big\\}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "for an input value $x$.\n", + "\n", + "\n", + "\n", + "If the neural network evaluates $g_t(x, P)$ at more values for $x$, say $N$ values $x_i$ for $i = 1, \\dots, N$, then the *total* error to minimize becomes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{min} \\tag{9}\n", + "\\min_{P}\\Big\\{\\frac{1}{N} \\sum_{i=1}^N \\big(g_t'(x_i, P) - ( -\\gamma g_t(x_i, P) \\big)^2 \\Big\\}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Letting $\\boldsymbol{x}$ be a vector with elements $x_i$ and $C(\\boldsymbol{x}, P) = \\frac{1}{N} \\sum_i \\big(g_t'(x_i, P) - ( -\\gamma g_t(x_i, P) \\big)^2$ denote the cost function, the minimization problem that our network must solve, becomes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\min_{P} C(\\boldsymbol{x}, P)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In terms of $P_{\\text{hidden} }$ and $P_{\\text{output} }$, this could also be expressed as\n", + "\n", + "$$\n", + "\\min_{P_{\\text{hidden} }, \\ P_{\\text{output} }} C(\\boldsymbol{x}, \\{P_{\\text{hidden} }, P_{\\text{output} }\\})\n", + "$$\n", + "\n", + "\n", + "For simplicity, it is assumed that the input is an array $\\boldsymbol{x} = (x_1, \\dots, x_N)$ with $N$ elements. It is at these points the neural network should find $P$ such that it fulfills ([9](#min)).\n", + "\n", + "First, the neural network must feed forward the inputs.\n", + "This means that $\\boldsymbol{x}s$ must be passed through an input layer, a hidden layer and a output layer. The input layer in this case, does not need to process the data any further.\n", + "The input layer will consist of $N_{\\text{input} }$ neurons, passing its element to each neuron in the hidden layer. The number of neurons in the hidden layer will be $N_{\\text{hidden} }$.\n", + "\n", + "\n", + "For the $i$-th in the hidden layer with weight $w_i^{\\text{hidden} }$ and bias $b_i^{\\text{hidden} }$, the weighting from the $j$-th neuron at the input layer is:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "z_{i,j}^{\\text{hidden}} &= b_i^{\\text{hidden}} + w_i^{\\text{hidden}}x_j \\\\\n", + "&=\n", + "\\begin{pmatrix}\n", + "b_i^{\\text{hidden}} & w_i^{\\text{hidden}}\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "1 \\\\\n", + "x_j\n", + "\\end{pmatrix}\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The result after weighting the inputs at the $i$-th hidden neuron can be written as a vector:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "\\boldsymbol{z}_{i}^{\\text{hidden}} &= \\Big( b_i^{\\text{hidden}} + w_i^{\\text{hidden}}x_1 , \\ b_i^{\\text{hidden}} + w_i^{\\text{hidden}} x_2, \\ \\dots \\, , \\ b_i^{\\text{hidden}} + w_i^{\\text{hidden}} x_N\\Big) \\\\\n", + "&=\n", + "\\begin{pmatrix}\n", + " b_i^{\\text{hidden}} & w_i^{\\text{hidden}}\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "1 & 1 & \\dots & 1 \\\\\n", + "x_1 & x_2 & \\dots & x_N\n", + "\\end{pmatrix} \\\\\n", + "&= \\boldsymbol{p}_{i, \\text{hidden}}^T X\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The vector $\\boldsymbol{p}_{i, \\text{hidden}}^T$ constitutes each row in $P_{\\text{hidden} }$, which contains the weights for the neural network to minimize according to ([9](#min)).\n", + "\n", + "After having found $\\boldsymbol{z}_{i}^{\\text{hidden}} $ for every $i$-th neuron within the hidden layer, the vector will be sent to an activation function $a_i(\\boldsymbol{z})$.\n", + "\n", + "In this example, the sigmoid function has been chosen to be the activation function for each hidden neuron:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "f(z) = \\frac{1}{1 + \\exp{(-z)}}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is possible to use other activations functions for the hidden layer also.\n", + "\n", + "The output $\\boldsymbol{x}_i^{\\text{hidden}}$ from each $i$-th hidden neuron is:\n", + "\n", + "$$\n", + "\\boldsymbol{x}_i^{\\text{hidden} } = f\\big( \\boldsymbol{z}_{i}^{\\text{hidden}} \\big)\n", + "$$\n", + "\n", + "The outputs $\\boldsymbol{x}_i^{\\text{hidden} } $ are then sent to the output layer.\n", + "\n", + "The output layer consists of one neuron in this case, and combines the\n", + "output from each of the neurons in the hidden layers. The output layer\n", + "combines the results from the hidden layer using some weights $w_i^{\\text{output}}$\n", + "and biases $b_i^{\\text{output}}$. In this case,\n", + "it is assumes that the number of neurons in the output layer is one.\n", + "\n", + "\n", + "\n", + "The procedure of weighting the output neuron $j$ in the hidden layer to the $i$-th neuron in the output layer is similar as for the hidden layer described previously." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "z_{1,j}^{\\text{output}} & =\n", + "\\begin{pmatrix}\n", + "b_1^{\\text{output}} & \\boldsymbol{w}_1^{\\text{output}}\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "1 \\\\\n", + "\\boldsymbol{x}_j^{\\text{hidden}}\n", + "\\end{pmatrix}\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Expressing $z_{1,j}^{\\text{output}}$ as a vector gives the following way of weighting the inputs from the hidden layer:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\boldsymbol{z}_{1}^{\\text{output}} =\n", + "\\begin{pmatrix}\n", + "b_1^{\\text{output}} & \\boldsymbol{w}_1^{\\text{output}}\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "1 & 1 & \\dots & 1 \\\\\n", + "\\boldsymbol{x}_1^{\\text{hidden}} & \\boldsymbol{x}_2^{\\text{hidden}} & \\dots & \\boldsymbol{x}_N^{\\text{hidden}}\n", + "\\end{pmatrix}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case we seek a continuous range of values since we are approximating a function. This means that after computing $\\boldsymbol{z}_{1}^{\\text{output}}$ the neural network has finished its feed forward step, and $\\boldsymbol{z}_{1}^{\\text{output}}$ is the final output of the network.\n", + "\n", + "\n", + "The next step is to decide how the parameters should be changed such that they minimize the cost function.\n", + "\n", + "The chosen cost function for this problem is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C(\\boldsymbol{x}, P) = \\frac{1}{N} \\sum_i \\big(g_t'(x_i, P) - ( -\\gamma g_t(x_i, P) \\big)^2\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to minimize the cost function, an optimization method must be chosen.\n", + "\n", + "Here, gradient descent with a constant step size has been chosen.\n", + "\n", + "### Gradient descent\n", + "\n", + "The idea of the gradient descent algorithm is to update parameters in\n", + "a direction where the cost function decreases goes to a minimum.\n", + "\n", + "In general, the update of some parameters $\\boldsymbol{\\omega}$ given a cost\n", + "function defined by some weights $\\boldsymbol{\\omega}$, $C(\\boldsymbol{x},\n", + "\\boldsymbol{\\omega})$, goes as follows:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\boldsymbol{\\omega}_{\\text{new} } = \\boldsymbol{\\omega} - \\lambda \\nabla_{\\boldsymbol{\\omega}} C(\\boldsymbol{x}, \\boldsymbol{\\omega})\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "for a number of iterations or until $ \\big|\\big| \\boldsymbol{\\omega}_{\\text{new} } - \\boldsymbol{\\omega} \\big|\\big|$ becomes smaller than some given tolerance.\n", + "\n", + "The value of $\\lambda$ decides how large steps the algorithm must take\n", + "in the direction of $ \\nabla_{\\boldsymbol{\\omega}} C(\\boldsymbol{x}, \\boldsymbol{\\omega})$.\n", + "The notation $\\nabla_{\\boldsymbol{\\omega}}$ express the gradient with respect\n", + "to the elements in $\\boldsymbol{\\omega}$.\n", + "\n", + "In our case, we have to minimize the cost function $C(\\boldsymbol{x}, P)$ with\n", + "respect to the two sets of weights and biases, that is for the hidden\n", + "layer $P_{\\text{hidden} }$ and for the output layer $P_{\\text{output}\n", + "}$ .\n", + "\n", + "This means that $P_{\\text{hidden} }$ and $P_{\\text{output} }$ is updated by" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "P_{\\text{hidden},\\text{new}} &= P_{\\text{hidden}} - \\lambda \\nabla_{P_{\\text{hidden}}} C(\\boldsymbol{x}, P) \\\\\n", + "P_{\\text{output},\\text{new}} &= P_{\\text{output}} - \\lambda \\nabla_{P_{\\text{output}}} C(\\boldsymbol{x}, P)\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The code for solving the ODE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "# Assuming one input, hidden, and output layer\n", + "def neural_network(params, x):\n", + "\n", + " # Find the weights (including and biases) for the hidden and output layer.\n", + " # Assume that params is a list of parameters for each layer.\n", + " # The biases are the first element for each array in params,\n", + " # and the weights are the remaning elements in each array in params.\n", + "\n", + " w_hidden = params[0]\n", + " w_output = params[1]\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " ## Hidden layer:\n", + "\n", + " # Add a row of ones to include bias\n", + " x_input = np.concatenate((np.ones((1,num_values)), x_input ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_input)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " ## Output layer:\n", + "\n", + " # Include bias:\n", + " x_hidden = np.concatenate((np.ones((1,num_values)), x_hidden ), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_hidden)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "# The trial solution using the deep neural network:\n", + "def g_trial(x,params, g0 = 10):\n", + " return g0 + x*neural_network(params,x)\n", + "\n", + "# The right side of the ODE:\n", + "def g(x, g_trial, gamma = 2):\n", + " return -gamma*g_trial\n", + "\n", + "# The cost function:\n", + "def cost_function(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the neural network\n", + " d_net_out = elementwise_grad(neural_network,1)(P,x)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d_g_t = elementwise_grad(g_trial,0)(x,P)\n", + "\n", + " # The right side of the ODE\n", + " func = g(x, g_t)\n", + "\n", + " err_sqr = (d_g_t - func)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum / np.size(err_sqr)\n", + "\n", + "# Solve the exponential decay ODE using neural network with one input, hidden, and output layer\n", + "def solve_ode_neural_network(x, num_neurons_hidden, num_iter, lmb):\n", + " ## Set up initial weights and biases\n", + "\n", + " # For the hidden layer\n", + " p0 = npr.randn(num_neurons_hidden, 2 )\n", + "\n", + " # For the output layer\n", + " p1 = npr.randn(1, num_neurons_hidden + 1 ) # +1 since bias is included\n", + "\n", + " P = [p0, p1]\n", + "\n", + " print('Initial cost: %g'%cost_function(P, x))\n", + "\n", + " ## Start finding the optimal weights using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_grad = grad(cost_function,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of two arrays;\n", + " # one for the gradient w.r.t P_hidden and\n", + " # one for the gradient w.r.t P_output\n", + " cost_grad = cost_function_grad(P, x)\n", + "\n", + " P[0] = P[0] - lmb * cost_grad[0]\n", + " P[1] = P[1] - lmb * cost_grad[1]\n", + "\n", + " print('Final cost: %g'%cost_function(P, x))\n", + "\n", + " return P\n", + "\n", + "def g_analytic(x, gamma = 2, g0 = 10):\n", + " return g0*np.exp(-gamma*x)\n", + "\n", + "# Solve the given problem\n", + "if __name__ == '__main__':\n", + " # Set seed such that the weight are initialized\n", + " # with same weights and biases for every run.\n", + " npr.seed(15)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " N = 10\n", + " x = np.linspace(0, 1, N)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = 10\n", + " num_iter = 10000\n", + " lmb = 0.001\n", + "\n", + " # Use the network\n", + " P = solve_ode_neural_network(x, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " # Print the deviation from the trial solution and true solution\n", + " res = g_trial(x,P)\n", + " res_analytical = g_analytic(x)\n", + "\n", + " print('Max absolute difference: %g'%np.max(np.abs(res - res_analytical)))\n", + "\n", + " # Plot the results\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(x, res_analytical)\n", + " plt.plot(x, res[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('x')\n", + " plt.ylabel('g(x)')\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The network with one input layer, specified number of hidden layers, and one output layer\n", + "\n", + "It is also possible to extend the construction of our network into a more general one, allowing the network to contain more than one hidden layers.\n", + "\n", + "The number of neurons within each hidden layer are given as a list of integers in the program below." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "# The neural network with one input layer and one output layer,\n", + "# but with number of hidden layers specified by the user.\n", + "def deep_neural_network(deep_params, x):\n", + " # N_hidden is the number of hidden layers\n", + "\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consists of\n", + " # parameters to all the hidden\n", + " # layers AND the output layer.\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " # Due to multiple hidden layers, define a variable referencing to the\n", + " # output of the previous layer:\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "# The trial solution using the deep neural network:\n", + "def g_trial_deep(x,params, g0 = 10):\n", + " return g0 + x*deep_neural_network(params, x)\n", + "\n", + "# The right side of the ODE:\n", + "def g(x, g_trial, gamma = 2):\n", + " return -gamma*g_trial\n", + "\n", + "# The same cost function as before, but calls deep_neural_network instead.\n", + "def cost_function_deep(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial_deep(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the neural network\n", + " d_net_out = elementwise_grad(deep_neural_network,1)(P,x)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d_g_t = elementwise_grad(g_trial_deep,0)(x,P)\n", + "\n", + " # The right side of the ODE\n", + " func = g(x, g_t)\n", + "\n", + " err_sqr = (d_g_t - func)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum / np.size(err_sqr)\n", + "\n", + "# Solve the exponential decay ODE using neural network with one input and one output layer,\n", + "# but with specified number of hidden layers from the user.\n", + "def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb):\n", + " # num_hidden_neurons is now a list of number of neurons within each hidden layer\n", + "\n", + " # The number of elements in the list num_hidden_neurons thus represents\n", + " # the number of hidden layers.\n", + "\n", + " # Find the number of hidden layers:\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weights and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 )\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: %g'%cost_function_deep(P, x))\n", + "\n", + " ## Start finding the optimal weights using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_deep_grad = grad(cost_function_deep,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases\n", + " # in the hidden layers and output layers evaluated at x.\n", + " cost_deep_grad = cost_function_deep_grad(P, x)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_deep_grad[l]\n", + "\n", + " print('Final cost: %g'%cost_function_deep(P, x))\n", + "\n", + " return P\n", + "\n", + "def g_analytic(x, gamma = 2, g0 = 10):\n", + " return g0*np.exp(-gamma*x)\n", + "\n", + "# Solve the given problem\n", + "if __name__ == '__main__':\n", + " npr.seed(15)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " N = 10\n", + " x = np.linspace(0, 1, N)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = np.array([10,10])\n", + " num_iter = 10000\n", + " lmb = 0.001\n", + "\n", + " P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " res = g_trial_deep(x,P)\n", + " res_analytical = g_analytic(x)\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of a deep neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(x, res_analytical)\n", + " plt.plot(x, res[0,:])\n", + " plt.legend(['analytical','dnn'])\n", + " plt.ylabel('g(x)')\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example: Population growth\n", + "\n", + "A logistic model of population growth assumes that a population converges toward an equilibrium.\n", + "The population growth can be modeled by" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{log} \\tag{10}\n", + "\tg'(t) = \\alpha g(t)(A - g(t))\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $g(t)$ is the population density at time $t$, $\\alpha > 0$ the growth rate and $A > 0$ is the maximum population number in the environment.\n", + "Also, at $t = 0$ the population has the size $g(0) = g_0$, where $g_0$ is some chosen constant.\n", + "\n", + "In this example, similar network as for the exponential decay using Autograd has been used to solve the equation. However, as the implementation might suffer from e.g numerical instability\n", + "and high execution time (this might be more apparent in the examples solving PDEs),\n", + "using a library like TensorFlow is recommended.\n", + "Here, we stay with a more simple approach and implement for comparison, the simple forward Euler method.\n", + "\n", + "\n", + "\n", + "Here, we will model a population $g(t)$ in an environment having carrying capacity $A$.\n", + "The population follows the model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{solveode_population} \\tag{11}\n", + "g'(t) = \\alpha g(t)(A - g(t))\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $g(0) = g_0$.\n", + "\n", + "In this example, we let $\\alpha = 2$, $A = 1$, and $g_0 = 1.2$.\n", + "\n", + "\n", + "We will get a slightly different trial solution, as the boundary conditions are different\n", + "compared to the case for exponential decay.\n", + "\n", + "A possible trial solution satisfying the condition $g(0) = g_0$ could be\n", + "\n", + "$$\n", + "h_1(t) = g_0 + t \\cdot N(t,P)\n", + "$$\n", + "\n", + "with $N(t,P)$ being the output from the neural network with weights and biases for each layer collected in the set $P$.\n", + "\n", + "The analytical solution is\n", + "\n", + "$$\n", + "g(t) = \\frac{Ag_0}{g_0 + (A - g_0)\\exp(-\\alpha A t)}\n", + "$$\n", + "\n", + "\n", + "\n", + "The network will be the similar as for the exponential decay example, but with some small modifications for our problem." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "# Function to get the parameters.\n", + "# Done such that one can easily change the paramaters after one's liking.\n", + "def get_parameters():\n", + " alpha = 2\n", + " A = 1\n", + " g0 = 1.2\n", + " return alpha, A, g0\n", + "\n", + "def deep_neural_network(P, x):\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(P) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " # Due to multiple hidden layers, define a variable referencing to the\n", + " # output of the previous layer:\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = P[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = P[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "\n", + "def cost_function_deep(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial_deep(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d_g_t = elementwise_grad(g_trial_deep,0)(x,P)\n", + "\n", + " # The right side of the ODE\n", + " func = f(x, g_t)\n", + "\n", + " err_sqr = (d_g_t - func)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum / np.size(err_sqr)\n", + "\n", + "# The right side of the ODE:\n", + "def f(x, g_trial):\n", + " alpha,A, g0 = get_parameters()\n", + " return alpha*g_trial*(A - g_trial)\n", + "\n", + "# The trial solution using the deep neural network:\n", + "def g_trial_deep(x, params):\n", + " alpha,A, g0 = get_parameters()\n", + " return g0 + x*deep_neural_network(params,x)\n", + "\n", + "# The analytical solution:\n", + "def g_analytic(t):\n", + " alpha,A, g0 = get_parameters()\n", + " return A*g0/(g0 + (A - g0)*np.exp(-alpha*A*t))\n", + "\n", + "def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb):\n", + " # num_hidden_neurons is now a list of number of neurons within each hidden layer\n", + "\n", + " # Find the number of hidden layers:\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 )\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: %g'%cost_function_deep(P, x))\n", + "\n", + " ## Start finding the optimal weigths using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_deep_grad = grad(cost_function_deep,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases\n", + " # in the hidden layers and output layers evaluated at x.\n", + " cost_deep_grad = cost_function_deep_grad(P, x)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_deep_grad[l]\n", + "\n", + " print('Final cost: %g'%cost_function_deep(P, x))\n", + "\n", + " return P\n", + "\n", + "if __name__ == '__main__':\n", + " npr.seed(4155)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nt = 10\n", + " T = 1\n", + " t = np.linspace(0,T, Nt)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = [100, 50, 25]\n", + " num_iter = 1000\n", + " lmb = 1e-3\n", + "\n", + " P = solve_ode_deep_neural_network(t, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " g_dnn_ag = g_trial_deep(t,P)\n", + " g_analytical = g_analytic(t)\n", + "\n", + " # Find the maximum absolute difference between the solutons:\n", + " diff_ag = np.max(np.abs(g_dnn_ag - g_analytical))\n", + " print(\"The max absolute difference between the solutions is: %g\"%diff_ag)\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(t, g_analytical)\n", + " plt.plot(t, g_dnn_ag[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('t')\n", + " plt.ylabel('g(t)')\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using forward Euler to solve the ODE\n", + "\n", + "A straightforward way of solving an ODE numerically, is to use Euler's method.\n", + "\n", + "Euler's method uses Taylor series to approximate the value at a function $f$ at a step $\\Delta x$ from $x$:\n", + "\n", + "$$\n", + "f(x + \\Delta x) \\approx f(x) + \\Delta x f'(x)\n", + "$$\n", + "\n", + "In our case, using Euler's method to approximate the value of $g$ at a step $\\Delta t$ from $t$ yields" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + " g(t + \\Delta t) &\\approx g(t) + \\Delta t g'(t) \\\\\n", + " &= g(t) + \\Delta t \\big(\\alpha g(t)(A - g(t))\\big)\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "along with the condition that $g(0) = g_0$.\n", + "\n", + "Let $t_i = i \\cdot \\Delta t$ where $\\Delta t = \\frac{T}{N_t-1}$ where $T$ is the final time our solver must solve for and $N_t$ the number of values for $t \\in [0, T]$ for $i = 0, \\dots, N_t-1$.\n", + "\n", + "For $i \\geq 1$, we have that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "t_i &= i\\Delta t \\\\\n", + "&= (i - 1)\\Delta t + \\Delta t \\\\\n", + "&= t_{i-1} + \\Delta t\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, if $g_i = g(t_i)$ then" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + " \\begin{aligned}\n", + " g_i &= g(t_i) \\\\\n", + " &= g(t_{i-1} + \\Delta t) \\\\\n", + " &\\approx g(t_{i-1}) + \\Delta t \\big(\\alpha g(t_{i-1})(A - g(t_{i-1}))\\big) \\\\\n", + " &= g_{i-1} + \\Delta t \\big(\\alpha g_{i-1}(A - g_{i-1})\\big)\n", + " \\end{aligned}\n", + "\\end{equation} \\label{odenum} \\tag{12}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "for $i \\geq 1$ and $g_0 = g(t_0) = g(0) = g_0$.\n", + "\n", + "Equation ([12](#odenum)) could be implemented in the following way,\n", + "extending the program that uses the network using Autograd:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "# Assume that all function definitions from the example program using Autograd\n", + "# are located here.\n", + "\n", + "if __name__ == '__main__':\n", + " npr.seed(4155)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nt = 10\n", + " T = 1\n", + " t = np.linspace(0,T, Nt)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = [100,50,25]\n", + " num_iter = 1000\n", + " lmb = 1e-3\n", + "\n", + " P = solve_ode_deep_neural_network(t, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " g_dnn_ag = g_trial_deep(t,P)\n", + " g_analytical = g_analytic(t)\n", + "\n", + " # Find the maximum absolute difference between the solutons:\n", + " diff_ag = np.max(np.abs(g_dnn_ag - g_analytical))\n", + " print(\"The max absolute difference between the solutions is: %g\"%diff_ag)\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(t, g_analytical)\n", + " plt.plot(t, g_dnn_ag[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('t')\n", + " plt.ylabel('g(t)')\n", + "\n", + " ## Find an approximation to the funtion using forward Euler\n", + "\n", + " alpha, A, g0 = get_parameters()\n", + " dt = T/(Nt - 1)\n", + "\n", + " # Perform forward Euler to solve the ODE\n", + " g_euler = np.zeros(Nt)\n", + " g_euler[0] = g0\n", + "\n", + " for i in range(1,Nt):\n", + " g_euler[i] = g_euler[i-1] + dt*(alpha*g_euler[i-1]*(A - g_euler[i-1]))\n", + "\n", + " # Print the errors done by each method\n", + " diff1 = np.max(np.abs(g_euler - g_analytical))\n", + " diff2 = np.max(np.abs(g_dnn_ag[0,:] - g_analytical))\n", + "\n", + " print('Max absolute difference between Euler method and analytical: %g'%diff1)\n", + " print('Max absolute difference between deep neural network and analytical: %g'%diff2)\n", + "\n", + " # Plot results\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.plot(t,g_euler)\n", + " plt.plot(t,g_analytical)\n", + " plt.plot(t,g_dnn_ag[0,:])\n", + "\n", + " plt.legend(['euler','analytical','dnn'])\n", + " plt.xlabel('Time t')\n", + " plt.ylabel('g(t)')\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Solving the one dimensional Poisson equation\n", + "\n", + "The Poisson equation for $g(x)$ in one dimension is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{poisson} \\tag{13}\n", + " -g''(x) = f(x)\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $f(x)$ is a given function for $x \\in (0,1)$.\n", + "\n", + "The conditions that $g(x)$ is chosen to fulfill, are" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + " g(0) &= 0 \\\\\n", + " g(1) &= 0\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This equation can be solved numerically using programs where e.g Autograd and TensorFlow are used.\n", + "The results from the networks can then be compared to the analytical solution.\n", + "In addition, it could be interesting to see how a typical method for numerically solving second order ODEs compares to the neural networks.\n", + "\n", + "\n", + "Here, the function $g(x)$ to solve for follows the equation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "-g''(x) = f(x),\\qquad x \\in (0,1)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $f(x)$ is a given function, along with the chosen conditions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "g(0) = g(1) = 0\n", + "\\end{aligned}\\label{cond} \\tag{14}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, we consider the case when $f(x) = (3x + x^2)\\exp(x)$.\n", + "\n", + "For this case, a possible trial solution satisfying the conditions could be" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "g_t(x) = x \\cdot (1-x) \\cdot N(P,x)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The analytical solution for this problem is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "g(x) = x(1 - x)\\exp(x)\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " # Due to multiple hidden layers, define a variable referencing to the\n", + " # output of the previous layer:\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb):\n", + " # num_hidden_neurons is now a list of number of neurons within each hidden layer\n", + "\n", + " # Find the number of hidden layers:\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 )\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: %g'%cost_function_deep(P, x))\n", + "\n", + " ## Start finding the optimal weigths using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_deep_grad = grad(cost_function_deep,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases\n", + " # in the hidden layers and output layers evaluated at x.\n", + " cost_deep_grad = cost_function_deep_grad(P, x)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_deep_grad[l]\n", + "\n", + " print('Final cost: %g'%cost_function_deep(P, x))\n", + "\n", + " return P\n", + "\n", + "## Set up the cost function specified for this Poisson equation:\n", + "\n", + "# The right side of the ODE\n", + "def f(x):\n", + " return (3*x + x**2)*np.exp(x)\n", + "\n", + "def cost_function_deep(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial_deep(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d2_g_t = elementwise_grad(elementwise_grad(g_trial_deep,0))(x,P)\n", + "\n", + " right_side = f(x)\n", + "\n", + " err_sqr = (-d2_g_t - right_side)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum/np.size(err_sqr)\n", + "\n", + "# The trial solution:\n", + "def g_trial_deep(x,P):\n", + " return x*(1-x)*deep_neural_network(P,x)\n", + "\n", + "# The analytic solution;\n", + "def g_analytic(x):\n", + " return x*(1-x)*np.exp(x)\n", + "\n", + "if __name__ == '__main__':\n", + " npr.seed(4155)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nx = 10\n", + " x = np.linspace(0,1, Nx)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = [200,100]\n", + " num_iter = 1000\n", + " lmb = 1e-3\n", + "\n", + " P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " g_dnn_ag = g_trial_deep(x,P)\n", + " g_analytical = g_analytic(x)\n", + "\n", + " # Find the maximum absolute difference between the solutons:\n", + " max_diff = np.max(np.abs(g_dnn_ag - g_analytical))\n", + " print(\"The max absolute difference between the solutions is: %g\"%max_diff)\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(x, g_analytical)\n", + " plt.plot(x, g_dnn_ag[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('x')\n", + " plt.ylabel('g(x)')\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Comparing with a numerical scheme\n", + "\n", + "The Poisson equation is possible to solve using Taylor series to approximate the second derivative.\n", + "\n", + "Using Taylor series, the second derivative can be expressed as\n", + "\n", + "$$\n", + "g''(x) = \\frac{g(x + \\Delta x) - 2g(x) + g(x-\\Delta x)}{\\Delta x^2} + E_{\\Delta x}(x)\n", + "$$\n", + "\n", + "where $\\Delta x$ is a small step size and $E_{\\Delta x}(x)$ being the error term.\n", + "\n", + "Looking away from the error terms gives an approximation to the second derivative:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{approx} \\tag{15}\n", + "g''(x) \\approx \\frac{g(x + \\Delta x) - 2g(x) + g(x-\\Delta x)}{\\Delta x^2}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If $x_i = i \\Delta x = x_{i-1} + \\Delta x$ and $g_i = g(x_i)$ for $i = 1,\\dots N_x - 2$ with $N_x$ being the number of values for $x$, ([15](#approx)) becomes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "g''(x_i) &\\approx \\frac{g(x_i + \\Delta x) - 2g(x_i) + g(x_i -\\Delta x)}{\\Delta x^2} \\\\\n", + "&= \\frac{g_{i+1} - 2g_i + g_{i-1}}{\\Delta x^2}\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since we know from our problem that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "-g''(x) &= f(x) \\\\\n", + "&= (3x + x^2)\\exp(x)\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "along with the conditions $g(0) = g(1) = 0$,\n", + "the following scheme can be used to find an approximate solution for $g(x)$ numerically:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + " \\begin{aligned}\n", + " -\\Big( \\frac{g_{i+1} - 2g_i + g_{i-1}}{\\Delta x^2} \\Big) &= f(x_i) \\\\\n", + " -g_{i+1} + 2g_i - g_{i-1} &= \\Delta x^2 f(x_i)\n", + " \\end{aligned}\n", + "\\end{equation} \\label{odesys} \\tag{16}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "for $i = 1, \\dots, N_x - 2$ where $g_0 = g_{N_x - 1} = 0$ and $f(x_i) = (3x_i + x_i^2)\\exp(x_i)$, which is given for our specific problem.\n", + "\n", + "The equation can be rewritten into a matrix equation:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{aligned}\n", + "\\begin{pmatrix}\n", + "2 & -1 & 0 & \\dots & 0 \\\\\n", + "-1 & 2 & -1 & \\dots & 0 \\\\\n", + "\\vdots & & \\ddots & & \\vdots \\\\\n", + "0 & \\dots & -1 & 2 & -1 \\\\\n", + "0 & \\dots & 0 & -1 & 2\\\\\n", + "\\end{pmatrix}\n", + "\\begin{pmatrix}\n", + "g_1 \\\\\n", + "g_2 \\\\\n", + "\\vdots \\\\\n", + "g_{N_x - 3} \\\\\n", + "g_{N_x - 2}\n", + "\\end{pmatrix}\n", + "&=\n", + "\\Delta x^2\n", + "\\begin{pmatrix}\n", + "f(x_1) \\\\\n", + "f(x_2) \\\\\n", + "\\vdots \\\\\n", + "f(x_{N_x - 3}) \\\\\n", + "f(x_{N_x - 2})\n", + "\\end{pmatrix} \\\\\n", + "\\boldsymbol{A}\\boldsymbol{g} &= \\boldsymbol{f},\n", + "\\end{aligned}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "which makes it possible to solve for the vector $\\boldsymbol{g}$.\n", + "\n", + "\n", + "We can then compare the result from this numerical scheme with the output from our network using Autograd:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad, elementwise_grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import pyplot as plt\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assumes input x being an one-dimensional array\n", + " num_values = np.size(x)\n", + " x = x.reshape(-1, num_values)\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + "\n", + " # Due to multiple hidden layers, define a variable referencing to the\n", + " # output of the previous layer:\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_values)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output\n", + "\n", + "def solve_ode_deep_neural_network(x, num_neurons, num_iter, lmb):\n", + " # num_hidden_neurons is now a list of number of neurons within each hidden layer\n", + "\n", + " # Find the number of hidden layers:\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 )\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: %g'%cost_function_deep(P, x))\n", + "\n", + " ## Start finding the optimal weigths using gradient descent\n", + "\n", + " # Find the Python function that represents the gradient of the cost function\n", + " # w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer\n", + " cost_function_deep_grad = grad(cost_function_deep,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " # Evaluate the gradient at the current weights and biases in P.\n", + " # The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases\n", + " # in the hidden layers and output layers evaluated at x.\n", + " cost_deep_grad = cost_function_deep_grad(P, x)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_deep_grad[l]\n", + "\n", + " print('Final cost: %g'%cost_function_deep(P, x))\n", + "\n", + " return P\n", + "\n", + "## Set up the cost function specified for this Poisson equation:\n", + "\n", + "# The right side of the ODE\n", + "def f(x):\n", + " return (3*x + x**2)*np.exp(x)\n", + "\n", + "def cost_function_deep(P, x):\n", + "\n", + " # Evaluate the trial function with the current parameters P\n", + " g_t = g_trial_deep(x,P)\n", + "\n", + " # Find the derivative w.r.t x of the trial function\n", + " d2_g_t = elementwise_grad(elementwise_grad(g_trial_deep,0))(x,P)\n", + "\n", + " right_side = f(x)\n", + "\n", + " err_sqr = (-d2_g_t - right_side)**2\n", + " cost_sum = np.sum(err_sqr)\n", + "\n", + " return cost_sum/np.size(err_sqr)\n", + "\n", + "# The trial solution:\n", + "def g_trial_deep(x,P):\n", + " return x*(1-x)*deep_neural_network(P,x)\n", + "\n", + "# The analytic solution;\n", + "def g_analytic(x):\n", + " return x*(1-x)*np.exp(x)\n", + "\n", + "if __name__ == '__main__':\n", + " npr.seed(4155)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nx = 10\n", + " x = np.linspace(0,1, Nx)\n", + "\n", + " ## Set up the initial parameters\n", + " num_hidden_neurons = [200,100]\n", + " num_iter = 1000\n", + " lmb = 1e-3\n", + "\n", + " P = solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " g_dnn_ag = g_trial_deep(x,P)\n", + " g_analytical = g_analytic(x)\n", + "\n", + " # Find the maximum absolute difference between the solutons:\n", + "\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.title('Performance of neural network solving an ODE compared to the analytical solution')\n", + " plt.plot(x, g_analytical)\n", + " plt.plot(x, g_dnn_ag[0,:])\n", + " plt.legend(['analytical','nn'])\n", + " plt.xlabel('x')\n", + " plt.ylabel('g(x)')\n", + "\n", + " ## Perform the computation using the numerical scheme\n", + "\n", + " dx = 1/(Nx - 1)\n", + "\n", + " # Set up the matrix A\n", + " A = np.zeros((Nx-2,Nx-2))\n", + "\n", + " A[0,0] = 2\n", + " A[0,1] = -1\n", + "\n", + " for i in range(1,Nx-3):\n", + " A[i,i-1] = -1\n", + " A[i,i] = 2\n", + " A[i,i+1] = -1\n", + "\n", + " A[Nx - 3, Nx - 4] = -1\n", + " A[Nx - 3, Nx - 3] = 2\n", + "\n", + " # Set up the vector f\n", + " f_vec = dx**2 * f(x[1:-1])\n", + "\n", + " # Solve the equation\n", + " g_res = np.linalg.solve(A,f_vec)\n", + "\n", + " g_vec = np.zeros(Nx)\n", + " g_vec[1:-1] = g_res\n", + "\n", + " # Print the differences between each method\n", + " max_diff1 = np.max(np.abs(g_dnn_ag - g_analytical))\n", + " max_diff2 = np.max(np.abs(g_vec - g_analytical))\n", + " print(\"The max absolute difference between the analytical solution and DNN Autograd: %g\"%max_diff1)\n", + " print(\"The max absolute difference between the analytical solution and numerical scheme: %g\"%max_diff2)\n", + "\n", + " # Plot the results\n", + " plt.figure(figsize=(10,10))\n", + "\n", + " plt.plot(x,g_vec)\n", + " plt.plot(x,g_analytical)\n", + " plt.plot(x,g_dnn_ag[0,:])\n", + "\n", + " plt.legend(['numerical scheme','analytical','dnn'])\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Partial Differential Equations\n", + "\n", + "A partial differential equation (PDE) has a solution here the function\n", + "is defined by multiple variables. The equation may involve all kinds\n", + "of combinations of which variables the function is differentiated with\n", + "respect to.\n", + "\n", + "In general, a partial differential equation for a function $g(x_1,\\dots,x_N)$ with $N$ variables may be expressed as" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{PDE} \\tag{17}\n", + " f\\left(x_1, \\, \\dots \\, , x_N, \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_1}, \\dots , \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_N}, \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_1\\partial x_2}, \\, \\dots \\, , \\frac{\\partial^n g(x_1,\\dots,x_N) }{\\partial x_N^n} \\right) = 0\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $f$ is an expression involving all kinds of possible mixed derivatives of $g(x_1,\\dots,x_N)$ up to an order $n$. In order for the solution to be unique, some additional conditions must also be given.\n", + "\n", + "### Type of problem\n", + "\n", + "The problem our network must solve for, is similar to the ODE case.\n", + "We must have a trial solution $g_t$ at hand.\n", + "\n", + "For instance, the trial solution could be expressed as" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + " g_t(x_1,\\dots,x_N) = h_1(x_1,\\dots,x_N) + h_2(x_1,\\dots,x_N,N(x_1,\\dots,x_N,P))\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $h_1(x_1,\\dots,x_N)$ is a function that ensures $g_t(x_1,\\dots,x_N)$ satisfies some given conditions.\n", + "The neural network $N(x_1,\\dots,x_N,P)$ has weights and biases described by $P$ and $h_2(x_1,\\dots,x_N,N(x_1,\\dots,x_N,P))$ is an expression using the output from the neural network in some way.\n", + "\n", + "The role of the function $h_2(x_1,\\dots,x_N,N(x_1,\\dots,x_N,P))$, is to ensure that the output of $N(x_1,\\dots,x_N,P)$ is zero when $g_t(x_1,\\dots,x_N)$ is evaluated at the values of $x_1,\\dots,x_N$ where the given conditions must be satisfied. The function $h_1(x_1,\\dots,x_N)$ should alone make $g_t(x_1,\\dots,x_N)$ satisfy the conditions.\n", + "\n", + "\n", + "\n", + "### Network requirements\n", + "\n", + "The network tries then the minimize the cost function following the\n", + "same ideas as described for the ODE case, but now with more than one\n", + "variables to consider. The concept still remains the same; find a set\n", + "of parameters $P$ such that the expression $f$ in ([17](#PDE)) is as\n", + "close to zero as possible.\n", + "\n", + "As for the ODE case, the cost function is the mean squared error that\n", + "the network must try to minimize. The cost function for the network to\n", + "minimize is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C\\left(x_1, \\dots, x_N, P\\right) = \\left( f\\left(x_1, \\, \\dots \\, , x_N, \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_1}, \\dots , \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_N}, \\frac{\\partial g(x_1,\\dots,x_N) }{\\partial x_1\\partial x_2}, \\, \\dots \\, , \\frac{\\partial^n g(x_1,\\dots,x_N) }{\\partial x_N^n} \\right) \\right)^2\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we let $\\boldsymbol{x} = \\big( x_1, \\dots, x_N \\big)$ be an array containing the values for $x_1, \\dots, x_N$ respectively, the cost function can be reformulated into the following:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C\\left(\\boldsymbol{x}, P\\right) = f\\left( \\left( \\boldsymbol{x}, \\frac{\\partial g(\\boldsymbol{x}) }{\\partial x_1}, \\dots , \\frac{\\partial g(\\boldsymbol{x}) }{\\partial x_N}, \\frac{\\partial g(\\boldsymbol{x}) }{\\partial x_1\\partial x_2}, \\, \\dots \\, , \\frac{\\partial^n g(\\boldsymbol{x}) }{\\partial x_N^n} \\right) \\right)^2\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we also have $M$ different sets of values for $x_1, \\dots, x_N$, that is $\\boldsymbol{x}_i = \\big(x_1^{(i)}, \\dots, x_N^{(i)}\\big)$ for $i = 1,\\dots,M$ being the rows in matrix $X$, the cost function can be generalized into" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "C\\left(X, P \\right) = \\sum_{i=1}^M f\\left( \\left( \\boldsymbol{x}_i, \\frac{\\partial g(\\boldsymbol{x}_i) }{\\partial x_1}, \\dots , \\frac{\\partial g(\\boldsymbol{x}_i) }{\\partial x_N}, \\frac{\\partial g(\\boldsymbol{x}_i) }{\\partial x_1\\partial x_2}, \\, \\dots \\, , \\frac{\\partial^n g(\\boldsymbol{x}_i) }{\\partial x_N^n} \\right) \\right)^2.\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example: The diffusion equation\n", + "\n", + "In one spatial dimension, the equation reads" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\frac{\\partial g(x,t)}{\\partial t} = \\frac{\\partial^2 g(x,t)}{\\partial x^2}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where a possible choice of conditions are" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + "g(0,t) &= 0 ,\\qquad t \\geq 0 \\\\\n", + "g(1,t) &= 0, \\qquad t \\geq 0 \\\\\n", + "g(x,0) &= u(x),\\qquad x\\in [0,1]\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $u(x)$ being some given function.\n", + "\n", + "\n", + "\n", + "For this case, we want to find $g(x,t)$ such that" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation}\n", + " \\frac{\\partial g(x,t)}{\\partial t} = \\frac{\\partial^2 g(x,t)}{\\partial x^2}\n", + "\\end{equation} \\label{diffonedim} \\tag{18}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + "g(0,t) &= 0 ,\\qquad t \\geq 0 \\\\\n", + "g(1,t) &= 0, \\qquad t \\geq 0 \\\\\n", + "g(x,0) &= u(x),\\qquad x\\in [0,1]\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $u(x) = \\sin(\\pi x)$.\n", + "\n", + "First, let us set up the deep neural network.\n", + "The deep neural network will follow the same structure as discussed in the examples solving the ODEs.\n", + "First, we will look into how Autograd could be used in a network tailored to solve for bivariate functions.\n", + "\n", + "\n", + "\n", + "\n", + "The only change to do here, is to extend our network such that\n", + "functions of multiple parameters are correctly handled. In this case\n", + "we have two variables in our function to solve for, that is time $t$\n", + "and position $x$. The variables will be represented by a\n", + "one-dimensional array in the program. The program will evaluate the\n", + "network at each possible pair $(x,t)$, given an array for the desired\n", + "$x$-values and $t$-values to approximate the solution at." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # x is now a point and a 1D numpy array; make it a column vector\n", + " num_coordinates = np.size(x,0)\n", + " x = x.reshape(num_coordinates,-1)\n", + "\n", + " num_points = np.size(x,1)\n", + "\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output[0][0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The cost function must then iterate through the given arrays\n", + "containing values for $x$ and $t$, defines a point $(x,t)$ the deep\n", + "neural network and the trial solution is evaluated at, and then finds\n", + "the Jacobian of the trial solution.\n", + "\n", + "A possible trial solution for this PDE is\n", + "\n", + "$$\n", + "g_t(x,t) = h_1(x,t) + x(1-x)tN(x,t,P)\n", + "$$\n", + "\n", + "with $A(x,t)$ being a function ensuring that $g_t(x,t)$ satisfies our given conditions, and $N(x,t,P)$ being the output from the deep neural network using weights and biases for each layer from $P$.\n", + "\n", + "To fulfill the conditions, $A(x,t)$ could be:\n", + "\n", + "$$\n", + "h_1(x,t) = (1-t)\\Big(u(x) - \\big((1-x)u(0) + x u(1)\\big)\\Big) = (1-t)u(x) = (1-t)\\sin(\\pi x)\n", + "$$\n", + "since $(0) = u(1) = 0$ and $u(x) = \\sin(\\pi x)$.\n", + "\n", + "\n", + "\n", + "The Jacobian is used because the program must find the derivative of\n", + "the trial solution with respect to $x$ and $t$.\n", + "\n", + "This gives the necessity of computing the Jacobian matrix, as we want\n", + "to evaluate the gradient with respect to $x$ and $t$ (note that the\n", + "Jacobian of a scalar-valued multivariate function is simply its\n", + "gradient).\n", + "\n", + "In Autograd, the differentiation is by default done with respect to\n", + "the first input argument of your Python function. Since the points is\n", + "an array representing $x$ and $t$, the Jacobian is calculated using\n", + "the values of $x$ and $t$.\n", + "\n", + "To find the second derivative with respect to $x$ and $t$, the\n", + "Jacobian can be found for the second time. The result is a Hessian\n", + "matrix, which is the matrix containing all the possible second order\n", + "mixed derivatives of $g(x,t)$." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "# Set up the trial function:\n", + "def u(x):\n", + " return np.sin(np.pi*x)\n", + "\n", + "def g_trial(point,P):\n", + " x,t = point\n", + " return (1-t)*u(x) + x*(1-x)*t*deep_neural_network(P,point)\n", + "\n", + "# The right side of the ODE:\n", + "def f(point):\n", + " return 0.\n", + "\n", + "# The cost function:\n", + "def cost_function(P, x, t):\n", + " cost_sum = 0\n", + "\n", + " g_t_jacobian_func = jacobian(g_trial)\n", + " g_t_hessian_func = hessian(g_trial)\n", + "\n", + " for x_ in x:\n", + " for t_ in t:\n", + " point = np.array([x_,t_])\n", + "\n", + " g_t = g_trial(point,P)\n", + " g_t_jacobian = g_t_jacobian_func(point,P)\n", + " g_t_hessian = g_t_hessian_func(point,P)\n", + "\n", + " g_t_dt = g_t_jacobian[1]\n", + " g_t_d2x = g_t_hessian[0][0]\n", + "\n", + " func = f(point)\n", + "\n", + " err_sqr = ( (g_t_dt - g_t_d2x) - func)**2\n", + " cost_sum += err_sqr\n", + "\n", + " return cost_sum" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setting up the network using Autograd; The full program\n", + "\n", + "Having set up the network, along with the trial solution and cost function, we can now see how the deep neural network performs by comparing the results to the analytical solution.\n", + "\n", + "The analytical solution of our problem is\n", + "\n", + "$$\n", + "g(x,t) = \\exp(-\\pi^2 t)\\sin(\\pi x)\n", + "$$\n", + "\n", + "A possible way to implement a neural network solving the PDE, is given below.\n", + "Be aware, though, that it is fairly slow for the parameters used.\n", + "A better result is possible, but requires more iterations, and thus longer time to complete.\n", + "\n", + "\n", + "Indeed, the program below is not optimal in its implementation, but rather serves as an example on how to implement and use a neural network to solve a PDE.\n", + "Using TensorFlow results in a much better execution time. Try it!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import jacobian,hessian,grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import cm\n", + "from matplotlib import pyplot as plt\n", + "from mpl_toolkits.mplot3d import axes3d\n", + "\n", + "## Set up the network\n", + "\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # x is now a point and a 1D numpy array; make it a column vector\n", + " num_coordinates = np.size(x,0)\n", + " x = x.reshape(num_coordinates,-1)\n", + "\n", + " num_points = np.size(x,1)\n", + "\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output[0][0]\n", + "\n", + "## Define the trial solution and cost function\n", + "def u(x):\n", + " return np.sin(np.pi*x)\n", + "\n", + "def g_trial(point,P):\n", + " x,t = point\n", + " return (1-t)*u(x) + x*(1-x)*t*deep_neural_network(P,point)\n", + "\n", + "# The right side of the ODE:\n", + "def f(point):\n", + " return 0.\n", + "\n", + "# The cost function:\n", + "def cost_function(P, x, t):\n", + " cost_sum = 0\n", + "\n", + " g_t_jacobian_func = jacobian(g_trial)\n", + " g_t_hessian_func = hessian(g_trial)\n", + "\n", + " for x_ in x:\n", + " for t_ in t:\n", + " point = np.array([x_,t_])\n", + "\n", + " g_t = g_trial(point,P)\n", + " g_t_jacobian = g_t_jacobian_func(point,P)\n", + " g_t_hessian = g_t_hessian_func(point,P)\n", + "\n", + " g_t_dt = g_t_jacobian[1]\n", + " g_t_d2x = g_t_hessian[0][0]\n", + "\n", + " func = f(point)\n", + "\n", + " err_sqr = ( (g_t_dt - g_t_d2x) - func)**2\n", + " cost_sum += err_sqr\n", + "\n", + " return cost_sum /( np.size(x)*np.size(t) )\n", + "\n", + "## For comparison, define the analytical solution\n", + "def g_analytic(point):\n", + " x,t = point\n", + " return np.exp(-np.pi**2*t)*np.sin(np.pi*x)\n", + "\n", + "## Set up a function for training the network to solve for the equation\n", + "def solve_pde_deep_neural_network(x,t, num_neurons, num_iter, lmb):\n", + " ## Set up initial weigths and biases\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 + 1 ) # 2 since we have two points, +1 to include bias\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: ',cost_function(P, x, t))\n", + "\n", + " cost_function_grad = grad(cost_function,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " cost_grad = cost_function_grad(P, x , t)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_grad[l]\n", + "\n", + " print('Final cost: ',cost_function(P, x, t))\n", + "\n", + " return P\n", + "\n", + "if __name__ == '__main__':\n", + " ### Use the neural network:\n", + " npr.seed(15)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nx = 10; Nt = 10\n", + " x = np.linspace(0, 1, Nx)\n", + " t = np.linspace(0,1,Nt)\n", + "\n", + " ## Set up the parameters for the network\n", + " num_hidden_neurons = [100, 25]\n", + " num_iter = 250\n", + " lmb = 0.01\n", + "\n", + " P = solve_pde_deep_neural_network(x,t, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " ## Store the results\n", + " g_dnn_ag = np.zeros((Nx, Nt))\n", + " G_analytical = np.zeros((Nx, Nt))\n", + " for i,x_ in enumerate(x):\n", + " for j, t_ in enumerate(t):\n", + " point = np.array([x_, t_])\n", + " g_dnn_ag[i,j] = g_trial(point,P)\n", + "\n", + " G_analytical[i,j] = g_analytic(point)\n", + "\n", + " # Find the map difference between the analytical and the computed solution\n", + " diff_ag = np.abs(g_dnn_ag - G_analytical)\n", + " print('Max absolute difference between the analytical solution and the network: %g'%np.max(diff_ag))\n", + "\n", + " ## Plot the solutions in two dimensions, that being in position and time\n", + "\n", + " T,X = np.meshgrid(t,x)\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Solution from the deep neural network w/ %d layer'%len(num_hidden_neurons))\n", + " s = ax.plot_surface(T,X,g_dnn_ag,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Analytical solution')\n", + " s = ax.plot_surface(T,X,G_analytical,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Difference')\n", + " s = ax.plot_surface(T,X,diff_ag,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + " ## Take some slices of the 3D plots just to see the solutions at particular times\n", + " indx1 = 0\n", + " indx2 = int(Nt/2)\n", + " indx3 = Nt-1\n", + "\n", + " t1 = t[indx1]\n", + " t2 = t[indx2]\n", + " t3 = t[indx3]\n", + "\n", + " # Slice the results from the DNN\n", + " res1 = g_dnn_ag[:,indx1]\n", + " res2 = g_dnn_ag[:,indx2]\n", + " res3 = g_dnn_ag[:,indx3]\n", + "\n", + " # Slice the analytical results\n", + " res_analytical1 = G_analytical[:,indx1]\n", + " res_analytical2 = G_analytical[:,indx2]\n", + " res_analytical3 = G_analytical[:,indx3]\n", + "\n", + " # Plot the slices\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t1)\n", + " plt.plot(x, res1)\n", + " plt.plot(x,res_analytical1)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t2)\n", + " plt.plot(x, res2)\n", + " plt.plot(x,res_analytical2)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t3)\n", + " plt.plot(x, res3)\n", + " plt.plot(x,res_analytical3)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Solving the wave equation with Neural Networks\n", + "\n", + "The wave equation is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\frac{\\partial^2 g(x,t)}{\\partial t^2} = c^2\\frac{\\partial^2 g(x,t)}{\\partial x^2}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "with $c$ being the specified wave speed.\n", + "\n", + "Here, the chosen conditions are" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align*}\n", + "\tg(0,t) &= 0 \\\\\n", + "\tg(1,t) &= 0 \\\\\n", + "\tg(x,0) &= u(x) \\\\\n", + "\t\\frac{\\partial g(x,t)}{\\partial t} \\Big |_{t = 0} &= v(x)\n", + "\\end{align*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $\\frac{\\partial g(x,t)}{\\partial t} \\Big |_{t = 0}$ means the derivative of $g(x,t)$ with respect to $t$ is evaluated at $t = 0$, and $u(x)$ and $v(x)$ being given functions.\n", + "\n", + "\n", + "The wave equation to solve for, is" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{equation} \\label{wave} \\tag{19}\n", + "\\frac{\\partial^2 g(x,t)}{\\partial t^2} = c^2 \\frac{\\partial^2 g(x,t)}{\\partial x^2}\n", + "\\end{equation}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "where $c$ is the given wave speed.\n", + "The chosen conditions for this equation are" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{aligned}\n", + "g(0,t) &= 0, &t \\geq 0 \\\\\n", + "g(1,t) &= 0, &t \\geq 0 \\\\\n", + "g(x,0) &= u(x), &x\\in[0,1] \\\\\n", + "\\frac{\\partial g(x,t)}{\\partial t}\\Big |_{t = 0} &= v(x), &x \\in [0,1]\n", + "\\end{aligned} \\label{condwave} \\tag{20}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, let $c = 1$ and $u(x) = \\sin(\\pi x)$ and $v(x) = -\\pi\\sin(\\pi x)$.\n", + "\n", + "\n", + "\n", + "Setting up the network is done in similar matter as for the example of solving the diffusion equation.\n", + "The only things we have to change, is the trial solution such that it satisfies the conditions from ([20](#condwave)) and the cost function.\n", + "\n", + "The trial solution becomes slightly different since we have other conditions than in the example of solving the diffusion equation. Here, a possible trial solution $g_t(x,t)$ is\n", + "\n", + "$$\n", + "g_t(x,t) = h_1(x,t) + x(1-x)t^2N(x,t,P)\n", + "$$\n", + "\n", + "where\n", + "\n", + "$$\n", + "h_1(x,t) = (1-t^2)u(x) + tv(x)\n", + "$$\n", + "\n", + "Note that this trial solution satisfies the conditions only if $u(0) = v(0) = u(1) = v(1) = 0$, which is the case in this example.\n", + "\n", + "\n", + "The analytical solution for our specific problem, is\n", + "\n", + "$$\n", + "g(x,t) = \\sin(\\pi x)\\cos(\\pi t) - \\sin(\\pi x)\\sin(\\pi t)\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import hessian,grad\n", + "import autograd.numpy.random as npr\n", + "from matplotlib import cm\n", + "from matplotlib import pyplot as plt\n", + "from mpl_toolkits.mplot3d import axes3d\n", + "\n", + "## Set up the trial function:\n", + "def u(x):\n", + " return np.sin(np.pi*x)\n", + "\n", + "def v(x):\n", + " return -np.pi*np.sin(np.pi*x)\n", + "\n", + "def h1(point):\n", + " x,t = point\n", + " return (1 - t**2)*u(x) + t*v(x)\n", + "\n", + "def g_trial(point,P):\n", + " x,t = point\n", + " return h1(point) + x*(1-x)*t**2*deep_neural_network(P,point)\n", + "\n", + "## Define the cost function\n", + "def cost_function(P, x, t):\n", + " cost_sum = 0\n", + "\n", + " g_t_hessian_func = hessian(g_trial)\n", + "\n", + " for x_ in x:\n", + " for t_ in t:\n", + " point = np.array([x_,t_])\n", + "\n", + " g_t_hessian = g_t_hessian_func(point,P)\n", + "\n", + " g_t_d2x = g_t_hessian[0][0]\n", + " g_t_d2t = g_t_hessian[1][1]\n", + "\n", + " err_sqr = ( (g_t_d2t - g_t_d2x) )**2\n", + " cost_sum += err_sqr\n", + "\n", + " return cost_sum / (np.size(t) * np.size(x))\n", + "\n", + "## The neural network\n", + "def sigmoid(z):\n", + " return 1/(1 + np.exp(-z))\n", + "\n", + "def deep_neural_network(deep_params, x):\n", + " # x is now a point and a 1D numpy array; make it a column vector\n", + " num_coordinates = np.size(x,0)\n", + " x = x.reshape(num_coordinates,-1)\n", + "\n", + " num_points = np.size(x,1)\n", + "\n", + " # N_hidden is the number of hidden layers\n", + " N_hidden = np.size(deep_params) - 1 # -1 since params consist of parameters to all the hidden layers AND the output layer\n", + "\n", + " # Assume that the input layer does nothing to the input x\n", + " x_input = x\n", + " x_prev = x_input\n", + "\n", + " ## Hidden layers:\n", + "\n", + " for l in range(N_hidden):\n", + " # From the list of parameters P; find the correct weigths and bias for this layer\n", + " w_hidden = deep_params[l]\n", + "\n", + " # Add a row of ones to include bias\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev ), axis = 0)\n", + "\n", + " z_hidden = np.matmul(w_hidden, x_prev)\n", + " x_hidden = sigmoid(z_hidden)\n", + "\n", + " # Update x_prev such that next layer can use the output from this layer\n", + " x_prev = x_hidden\n", + "\n", + " ## Output layer:\n", + "\n", + " # Get the weights and bias for this layer\n", + " w_output = deep_params[-1]\n", + "\n", + " # Include bias:\n", + " x_prev = np.concatenate((np.ones((1,num_points)), x_prev), axis = 0)\n", + "\n", + " z_output = np.matmul(w_output, x_prev)\n", + " x_output = z_output\n", + "\n", + " return x_output[0][0]\n", + "\n", + "## The analytical solution\n", + "def g_analytic(point):\n", + " x,t = point\n", + " return np.sin(np.pi*x)*np.cos(np.pi*t) - np.sin(np.pi*x)*np.sin(np.pi*t)\n", + "\n", + "def solve_pde_deep_neural_network(x,t, num_neurons, num_iter, lmb):\n", + " ## Set up initial weigths and biases\n", + " N_hidden = np.size(num_neurons)\n", + "\n", + " ## Set up initial weigths and biases\n", + "\n", + " # Initialize the list of parameters:\n", + " P = [None]*(N_hidden + 1) # + 1 to include the output layer\n", + "\n", + " P[0] = npr.randn(num_neurons[0], 2 + 1 ) # 2 since we have two points, +1 to include bias\n", + " for l in range(1,N_hidden):\n", + " P[l] = npr.randn(num_neurons[l], num_neurons[l-1] + 1) # +1 to include bias\n", + "\n", + " # For the output layer\n", + " P[-1] = npr.randn(1, num_neurons[-1] + 1 ) # +1 since bias is included\n", + "\n", + " print('Initial cost: ',cost_function(P, x, t))\n", + "\n", + " cost_function_grad = grad(cost_function,0)\n", + "\n", + " # Let the update be done num_iter times\n", + " for i in range(num_iter):\n", + " cost_grad = cost_function_grad(P, x , t)\n", + "\n", + " for l in range(N_hidden+1):\n", + " P[l] = P[l] - lmb * cost_grad[l]\n", + "\n", + "\n", + " print('Final cost: ',cost_function(P, x, t))\n", + "\n", + " return P\n", + "\n", + "if __name__ == '__main__':\n", + " ### Use the neural network:\n", + " npr.seed(15)\n", + "\n", + " ## Decide the vales of arguments to the function to solve\n", + " Nx = 10; Nt = 10\n", + " x = np.linspace(0, 1, Nx)\n", + " t = np.linspace(0,1,Nt)\n", + "\n", + " ## Set up the parameters for the network\n", + " num_hidden_neurons = [50,20]\n", + " num_iter = 1000\n", + " lmb = 0.01\n", + "\n", + " P = solve_pde_deep_neural_network(x,t, num_hidden_neurons, num_iter, lmb)\n", + "\n", + " ## Store the results\n", + " res = np.zeros((Nx, Nt))\n", + " res_analytical = np.zeros((Nx, Nt))\n", + " for i,x_ in enumerate(x):\n", + " for j, t_ in enumerate(t):\n", + " point = np.array([x_, t_])\n", + " res[i,j] = g_trial(point,P)\n", + "\n", + " res_analytical[i,j] = g_analytic(point)\n", + "\n", + " diff = np.abs(res - res_analytical)\n", + " print(\"Max difference between analytical and solution from nn: %g\"%np.max(diff))\n", + "\n", + " ## Plot the solutions in two dimensions, that being in position and time\n", + "\n", + " T,X = np.meshgrid(t,x)\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Solution from the deep neural network w/ %d layer'%len(num_hidden_neurons))\n", + " s = ax.plot_surface(T,X,res,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Analytical solution')\n", + " s = ax.plot_surface(T,X,res_analytical,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + "\n", + " fig = plt.figure(figsize=(10,10))\n", + " ax = fig.gca(projection='3d')\n", + " ax.set_title('Difference')\n", + " s = ax.plot_surface(T,X,diff,linewidth=0,antialiased=False,cmap=cm.viridis)\n", + " ax.set_xlabel('Time $t$')\n", + " ax.set_ylabel('Position $x$');\n", + "\n", + " ## Take some slices of the 3D plots just to see the solutions at particular times\n", + " indx1 = 0\n", + " indx2 = int(Nt/2)\n", + " indx3 = Nt-1\n", + "\n", + " t1 = t[indx1]\n", + " t2 = t[indx2]\n", + " t3 = t[indx3]\n", + "\n", + " # Slice the results from the DNN\n", + " res1 = res[:,indx1]\n", + " res2 = res[:,indx2]\n", + " res3 = res[:,indx3]\n", + "\n", + " # Slice the analytical results\n", + " res_analytical1 = res_analytical[:,indx1]\n", + " res_analytical2 = res_analytical[:,indx2]\n", + " res_analytical3 = res_analytical[:,indx3]\n", + "\n", + " # Plot the slices\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t1)\n", + " plt.plot(x, res1)\n", + " plt.plot(x,res_analytical1)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t2)\n", + " plt.plot(x, res2)\n", + " plt.plot(x,res_analytical2)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.figure(figsize=(10,10))\n", + " plt.title(\"Computed solutions at time = %g\"%t3)\n", + " plt.plot(x, res3)\n", + " plt.plot(x,res_analytical3)\n", + " plt.legend(['dnn','analytical'])\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Resources on differential equations and deep learning\n", + "\n", + "1. [Artificial neural networks for solving ordinary and partial differential equations by I.E. Lagaris et al](https://pdfs.semanticscholar.org/d061/df393e0e8fbfd0ea24976458b7d42419040d.pdf)\n", + "\n", + "2. [Neural networks for solving differential equations by A. Honchar](https://becominghuman.ai/neural-networks-for-solving-differential-equations-fa230ac5e04c)\n", + "\n", + "3. [Solving differential equations using neural networks by M.M Chiaramonte and M. Kiener](http://cs229.stanford.edu/proj2013/ChiaramonteKiener-SolvingDifferentialEquationsUsingNeuralNetworks.pdf)\n", + "\n", + "4. [Introduction to Partial Differential Equations by A. Tveito, R. Winther](https://www.springer.com/us/book/9783540225515)" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/doc/LectureNotes/chapter12.ipynb b/doc/LectureNotes/chapter12.ipynb new file mode 100644 index 000000000..d88cef4d1 --- /dev/null +++ b/doc/LectureNotes/chapter12.ipynb @@ -0,0 +1,732 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Convolutional Neural Networks (recognizing images)\n", + "\n", + "\n", + "Convolutional neural networks (CNNs) were developed during the last\n", + "decade of the previous century, with a focus on character recognition\n", + "tasks. Nowadays, CNNs are a central element in the spectacular success\n", + "of deep learning methods. The success in for example image\n", + "classifications have made them a central tool for most machine\n", + "learning practitioners.\n", + "\n", + "CNNs are very similar to ordinary Neural Networks.\n", + "They are made up of neurons that have learnable weights and\n", + "biases. Each neuron receives some inputs, performs a dot product and\n", + "optionally follows it with a non-linearity. The whole network still\n", + "expresses a single differentiable score function: from the raw image\n", + "pixels on one end to class scores at the other. And they still have a\n", + "loss function (for example Softmax) on the last (fully-connected) layer\n", + "and all the tips/tricks we developed for learning regular Neural\n", + "Networks still apply (back propagation, gradient descent etc etc).\n", + "\n", + "What is the difference? **CNN architectures make the explicit assumption that\n", + "the inputs are images, which allows us to encode certain properties\n", + "into the architecture. These then make the forward function more\n", + "efficient to implement and vastly reduce the amount of parameters in\n", + "the network.**\n", + "\n", + "Here we provide only a superficial overview, for the more interested, we recommend highly the course\n", + "[IN5400 – Machine Learning for Image Analysis](https://www.uio.no/studier/emner/matnat/ifi/IN5400/index-eng.html)\n", + "and the slides of [CS231](http://cs231n.github.io/convolutional-networks/).\n", + "\n", + "Another good read is the article here . \n", + "\n", + "\n", + "As an example, consider\n", + "an image of size $32\\times 32\\times 3$ (32 wide, 32 high, 3 color channels), so a\n", + "single fully-connected neuron in a first hidden layer of a regular\n", + "Neural Network would have $32\\times 32\\times 3 = 3072$ weights. This amount still\n", + "seems manageable, but clearly this fully-connected structure does not\n", + "scale to larger images. For example, an image of more respectable\n", + "size, say $200\\times 200\\times 3$, would lead to neurons that have \n", + "$200\\times 200\\times 3 = 120,000$ weights. \n", + "\n", + "We could have\n", + "several such neurons, and the parameters would add up quickly! Clearly,\n", + "this full connectivity is wasteful and the huge number of parameters\n", + "would quickly lead to possible overfitting.\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Convolutional Neural Networks take advantage of the fact that the\n", + "input consists of images and they constrain the architecture in a more\n", + "sensible way. \n", + "\n", + "In particular, unlike a regular Neural Network, the\n", + "layers of a CNN have neurons arranged in 3 dimensions: width,\n", + "height, depth. (Note that the word depth here refers to the third\n", + "dimension of an activation volume, not to the depth of a full Neural\n", + "Network, which can refer to the total number of layers in a network.)\n", + "\n", + "To understand it better, the above example of an image \n", + "with an input volume of\n", + "activations has dimensions $32\\times 32\\times 3$ (width, height,\n", + "depth respectively). \n", + "\n", + "The neurons in a layer will\n", + "only be connected to a small region of the layer before it, instead of\n", + "all of the neurons in a fully-connected manner. Moreover, the final\n", + "output layer could for this specific image have dimensions $1\\times 1 \\times 10$, \n", + "because by the\n", + "end of the CNN architecture we will reduce the full image into a\n", + "single vector of class scores, arranged along the depth\n", + "dimension. \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "A simple CNN is a sequence of layers, and every layer of a CNN\n", + "transforms one volume of activations to another through a\n", + "differentiable function. We use three main types of layers to build\n", + "CNN architectures: Convolutional Layer, Pooling Layer, and\n", + "Fully-Connected Layer (exactly as seen in regular Neural Networks). We\n", + "will stack these layers to form a full CNN architecture.\n", + "\n", + "A simple CNN for image classification could have the architecture:\n", + "\n", + "* **INPUT** ($32\\times 32 \\times 3$) will hold the raw pixel values of the image, in this case an image of width 32, height 32, and with three color channels R,G,B.\n", + "\n", + "* **CONV** (convolutional )layer will compute the output of neurons that are connected to local regions in the input, each computing a dot product between their weights and a small region they are connected to in the input volume. This may result in volume such as $[32\\times 32\\times 12]$ if we decided to use 12 filters.\n", + "\n", + "* **RELU** layer will apply an elementwise activation function, such as the $max(0,x)$ thresholding at zero. This leaves the size of the volume unchanged ($[32\\times 32\\times 12]$).\n", + "\n", + "* **POOL** (pooling) layer will perform a downsampling operation along the spatial dimensions (width, height), resulting in volume such as $[16\\times 16\\times 12]$.\n", + "\n", + "* **FC** (i.e. fully-connected) layer will compute the class scores, resulting in volume of size $[1\\times 1\\times 10]$, where each of the 10 numbers correspond to a class score, such as among the 10 categories of the MNIST images we considered above . As with ordinary Neural Networks and as the name implies, each neuron in this layer will be connected to all the numbers in the previous volume.\n", + "\n", + "CNNs transform the original image layer by layer from the original\n", + "pixel values to the final class scores. \n", + "\n", + "Observe that some layers contain\n", + "parameters and other don’t. In particular, the CNN layers perform\n", + "transformations that are a function of not only the activations in the\n", + "input volume, but also of the parameters (the weights and biases of\n", + "the neurons). On the other hand, the RELU/POOL layers will implement a\n", + "fixed function. The parameters in the CONV/FC layers will be trained\n", + "with gradient descent so that the class scores that the CNN computes\n", + "are consistent with the labels in the training set for each image.\n", + "\n", + "\n", + "\n", + "### CNNs in brief\n", + "\n", + "In summary:\n", + "\n", + "* A CNN architecture is in the simplest case a list of Layers that transform the image volume into an output volume (e.g. holding the class scores)\n", + "\n", + "* There are a few distinct types of Layers (e.g. CONV/FC/RELU/POOL are by far the most popular)\n", + "\n", + "* Each Layer accepts an input 3D volume and transforms it to an output 3D volume through a differentiable function\n", + "\n", + "* Each Layer may or may not have parameters (e.g. CONV/FC do, RELU/POOL don’t)\n", + "\n", + "* Each Layer may or may not have additional hyperparameters (e.g. CONV/FC/POOL do, RELU doesn’t)\n", + "\n", + "For more material on convolutional networks, we strongly recommend\n", + "the course\n", + "[IN5400 – Machine Learning for Image Analysis](https://www.uio.no/studier/emner/matnat/ifi/IN5400/index-eng.html)\n", + "and the slides of [CS231](http://cs231n.github.io/convolutional-networks/) which is taught at Stanford University (consistently ranked as one of the top computer science programs in the world). [Michael Nielsen's book is a must read, in particular chapter 6 which deals with CNNs](http://neuralnetworksanddeeplearning.com/chap6.html).\n", + "\n", + "\n", + "\n", + "\n", + "## CNNs in more detail, building convolutional neural networks in Tensorflow and Keras\n", + "\n", + "\n", + "As discussed above, CNNs are neural networks built from the assumption that the inputs\n", + "to the network are 2D images. This is important because the number of features or pixels in images\n", + "grows very fast with the image size, and an enormous number of weights and biases are needed in order to build an accurate network. \n", + "\n", + "As before, we still have our input, a hidden layer and an output. What's novel about convolutional networks\n", + "are the **convolutional** and **pooling** layers stacked in pairs between the input and the hidden layer.\n", + "In addition, the data is no longer represented as a 2D feature matrix, instead each input is a number of 2D\n", + "matrices, typically 1 for each color dimension (Red, Green, Blue). \n", + "\n", + "\n", + "\n", + "It means that to represent the entire\n", + "dataset of images, we require a 4D matrix or **tensor**. This tensor has the dimensions:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "(n_{inputs},\\, n_{pixels, width},\\, n_{pixels, height},\\, depth) .\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The MNIST dataset consists of grayscale images with a pixel size of\n", + "$28\\times 28$, meaning we require $28 \\times 28 = 724$ weights to each\n", + "neuron in the first hidden layer.\n", + "\n", + "If we were to analyze images of size $128\\times 128$ we would require\n", + "$128 \\times 128 = 16384$ weights to each neuron. Even worse if we were\n", + "dealing with color images, as most images are, we have an image matrix\n", + "of size $128\\times 128$ for each color dimension (Red, Green, Blue),\n", + "meaning 3 times the number of weights $= 49152$ are required for every\n", + "single neuron in the first hidden layer.\n", + "\n", + "\n", + "\n", + "Images typically have strong local correlations, meaning that a small\n", + "part of the image varies little from its neighboring regions. If for\n", + "example we have an image of a blue car, we can roughly assume that a\n", + "small blue part of the image is surrounded by other blue regions.\n", + "\n", + "Therefore, instead of connecting every single pixel to a neuron in the\n", + "first hidden layer, as we have previously done with deep neural\n", + "networks, we can instead connect each neuron to a small part of the\n", + "image (in all 3 RGB depth dimensions). The size of each small area is\n", + "fixed, and known as a [receptive](https://en.wikipedia.org/wiki/Receptive_field).\n", + "\n", + "\n", + "\n", + "The layers of a convolutional neural network arrange neurons in 3D: width, height and depth. \n", + "The input image is typically a square matrix of depth 3. \n", + "\n", + "A **convolution** is performed on the image which outputs\n", + "a 3D volume of neurons. The weights to the input are arranged in a number of 2D matrices, known as **filters**.\n", + "\n", + "\n", + "Each filter slides along the input image, taking the dot product\n", + "between each small part of the image and the filter, in all depth\n", + "dimensions. This is then passed through a non-linear function,\n", + "typically the **Rectified Linear (ReLu)** function, which serves as the\n", + "activation of the neurons in the first convolutional layer. This is\n", + "further passed through a **pooling layer**, which reduces the size of the\n", + "convolutional layer, e.g. by taking the maximum or average across some\n", + "small regions, and this serves as input to the next convolutional\n", + "layer.\n", + "\n", + "\n", + "\n", + "By systematically reducing the size of the input volume, through\n", + "convolution and pooling, the network should create representations of\n", + "small parts of the input, and then from them assemble representations\n", + "of larger areas. The final pooling layer is flattened to serve as\n", + "input to a hidden layer, such that each neuron in the final pooling\n", + "layer is connected to every single neuron in the hidden layer. This\n", + "then serves as input to the output layer, e.g. a softmax output for\n", + "classification.\n", + "\n", + "\n", + "\n", + "### Prerequisites: Collect and pre-process data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "# import necessary packages\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from sklearn import datasets\n", + "\n", + "\n", + "# ensure the same random numbers appear every time\n", + "np.random.seed(0)\n", + "\n", + "# display images in notebook\n", + "%matplotlib inline\n", + "plt.rcParams['figure.figsize'] = (12,12)\n", + "\n", + "\n", + "# download MNIST dataset\n", + "digits = datasets.load_digits()\n", + "\n", + "# define inputs and labels\n", + "inputs = digits.images\n", + "labels = digits.target\n", + "\n", + "# RGB images have a depth of 3\n", + "# our images are grayscale so they should have a depth of 1\n", + "inputs = inputs[:,:,:,np.newaxis]\n", + "\n", + "print(\"inputs = (n_inputs, pixel_width, pixel_height, depth) = \" + str(inputs.shape))\n", + "print(\"labels = (n_inputs) = \" + str(labels.shape))\n", + "\n", + "\n", + "# choose some random images to display\n", + "n_inputs = len(inputs)\n", + "indices = np.arange(n_inputs)\n", + "random_indices = np.random.choice(indices, size=5)\n", + "\n", + "for i, image in enumerate(digits.images[random_indices]):\n", + " plt.subplot(1, 5, i+1)\n", + " plt.axis('off')\n", + " plt.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')\n", + " plt.title(\"Label: %d\" % digits.target[random_indices[i]])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Importing Keras and Tensorflow" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "from tensorflow.keras import datasets, layers, models\n", + "from tensorflow.keras.layers import Input\n", + "from tensorflow.keras.models import Sequential #This allows appending layers to existing models\n", + "from tensorflow.keras.layers import Dense #This allows defining the characteristics of a particular layer\n", + "from tensorflow.keras import optimizers #This allows using whichever optimiser we want (sgd,adam,RMSprop)\n", + "from tensorflow.keras import regularizers #This allows using whichever regularizer we want (l1,l2,l1_l2)\n", + "from tensorflow.keras.utils import to_categorical #This allows using categorical cross entropy as the cost function\n", + "#from tensorflow.keras import Conv2D\n", + "#from tensorflow.keras import MaxPooling2D\n", + "#from tensorflow.keras import Flatten\n", + "\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "# representation of labels\n", + "labels = to_categorical(labels)\n", + "\n", + "# split into train and test data\n", + "# one-liner from scikit-learn library\n", + "train_size = 0.8\n", + "test_size = 1 - train_size\n", + "X_train, X_test, Y_train, Y_test = train_test_split(inputs, labels, train_size=train_size,\n", + " test_size=test_size)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "def create_convolutional_neural_network_keras(input_shape, receptive_field,\n", + " n_filters, n_neurons_connected, n_categories,\n", + " eta, lmbd):\n", + " model = Sequential()\n", + " model.add(layers.Conv2D(n_filters, (receptive_field, receptive_field), input_shape=input_shape, padding='same',\n", + " activation='relu', kernel_regularizer=regularizers.l2(lmbd)))\n", + " model.add(layers.MaxPooling2D(pool_size=(2, 2)))\n", + " model.add(layers.Flatten())\n", + " model.add(layers.Dense(n_neurons_connected, activation='relu', kernel_regularizer=regularizers.l2(lmbd)))\n", + " model.add(layers.Dense(n_categories, activation='softmax', kernel_regularizer=regularizers.l2(lmbd)))\n", + " \n", + " sgd = optimizers.SGD(lr=eta)\n", + " model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])\n", + " \n", + " return model\n", + "\n", + "epochs = 100\n", + "batch_size = 100\n", + "input_shape = X_train.shape[1:4]\n", + "receptive_field = 3\n", + "n_filters = 10\n", + "n_neurons_connected = 50\n", + "n_categories = 10\n", + "\n", + "eta_vals = np.logspace(-5, 1, 7)\n", + "lmbd_vals = np.logspace(-5, 1, 7)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "CNN_keras = np.zeros((len(eta_vals), len(lmbd_vals)), dtype=object)\n", + " \n", + "for i, eta in enumerate(eta_vals):\n", + " for j, lmbd in enumerate(lmbd_vals):\n", + " CNN = create_convolutional_neural_network_keras(input_shape, receptive_field,\n", + " n_filters, n_neurons_connected, n_categories,\n", + " eta, lmbd)\n", + " CNN.fit(X_train, Y_train, epochs=epochs, batch_size=batch_size, verbose=0)\n", + " scores = CNN.evaluate(X_test, Y_test)\n", + " \n", + " CNN_keras[i][j] = CNN\n", + " \n", + " print(\"Learning rate = \", eta)\n", + " print(\"Lambda = \", lmbd)\n", + " print(\"Test accuracy: %.3f\" % scores[1])\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Final visualization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "# visual representation of grid search\n", + "# uses seaborn heatmap, could probably do this in matplotlib\n", + "import seaborn as sns\n", + "\n", + "sns.set()\n", + "\n", + "train_accuracy = np.zeros((len(eta_vals), len(lmbd_vals)))\n", + "test_accuracy = np.zeros((len(eta_vals), len(lmbd_vals)))\n", + "\n", + "for i in range(len(eta_vals)):\n", + " for j in range(len(lmbd_vals)):\n", + " CNN = CNN_keras[i][j]\n", + "\n", + " train_accuracy[i][j] = CNN.evaluate(X_train, Y_train)[1]\n", + " test_accuracy[i][j] = CNN.evaluate(X_test, Y_test)[1]\n", + "\n", + " \n", + "fig, ax = plt.subplots(figsize = (10, 10))\n", + "sns.heatmap(train_accuracy, annot=True, ax=ax, cmap=\"viridis\")\n", + "ax.set_title(\"Training Accuracy\")\n", + "ax.set_ylabel(\"$\\eta$\")\n", + "ax.set_xlabel(\"$\\lambda$\")\n", + "plt.show()\n", + "\n", + "fig, ax = plt.subplots(figsize = (10, 10))\n", + "sns.heatmap(test_accuracy, annot=True, ax=ax, cmap=\"viridis\")\n", + "ax.set_title(\"Test Accuracy\")\n", + "ax.set_ylabel(\"$\\eta$\")\n", + "ax.set_xlabel(\"$\\lambda$\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The CIFAR01 data set\n", + "\n", + "The CIFAR10 dataset contains 60,000 color images in 10 classes, with\n", + "6,000 images in each class. The dataset is divided into 50,000\n", + "training images and 10,000 testing images. The classes are mutually\n", + "exclusive and there is no overlap between them." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "\n", + "from tensorflow.keras import datasets, layers, models\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# We import the data set\n", + "(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()\n", + "\n", + "# Normalize pixel values to be between 0 and 1 by dividing by 255. \n", + "train_images, test_images = train_images / 255.0, test_images / 255.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To verify that the dataset looks correct, let's plot the first 25 images from the training set and display the class name below each image." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',\n", + " 'dog', 'frog', 'horse', 'ship', 'truck']\n", + "​\n", + "plt.figure(figsize=(10,10))\n", + "for i in range(25):\n", + " plt.subplot(5,5,i+1)\n", + " plt.xticks([])\n", + " plt.yticks([])\n", + " plt.grid(False)\n", + " plt.imshow(train_images[i], cmap=plt.cm.binary)\n", + " # The CIFAR labels happen to be arrays, \n", + " # which is why you need the extra index\n", + " plt.xlabel(class_names[train_labels[i][0]])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The 6 lines of code below define the convolutional base using a common pattern: a stack of Conv2D and MaxPooling2D layers.\n", + "\n", + "As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to these dimensions, color_channels refers to (R,G,B). In this example, you will configure our CNN to process inputs of shape (32, 32, 3), which is the format of CIFAR images. You can do this by passing the argument input_shape to our first layer." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "model = models.Sequential()\n", + "model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))\n", + "model.add(layers.MaxPooling2D((2, 2)))\n", + "model.add(layers.Conv2D(64, (3, 3), activation='relu'))\n", + "model.add(layers.MaxPooling2D((2, 2)))\n", + "model.add(layers.Conv2D(64, (3, 3), activation='relu'))\n", + "\n", + "# Let's display the architecture of our model so far.\n", + "\n", + "model.summary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can see that the output of every Conv2D and MaxPooling2D layer is a 3D tensor of shape (height, width, channels). The width and height dimensions tend to shrink as you go deeper in the network. The number of output channels for each Conv2D layer is controlled by the first argument (e.g., 32 or 64). Typically, as the width and height shrink, you can afford (computationally) to add more output channels in each Conv2D layer.\n", + "\n", + "\n", + "\n", + "To complete our model, you will feed the last output tensor from the\n", + "convolutional base (of shape (4, 4, 64)) into one or more Dense layers\n", + "to perform classification. Dense layers take vectors as input (which\n", + "are 1D), while the current output is a 3D tensor. First, you will\n", + "flatten (or unroll) the 3D output to 1D, then add one or more Dense\n", + "layers on top. CIFAR has 10 output classes, so you use a final Dense\n", + "layer with 10 outputs and a softmax activation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "model.add(layers.Flatten())\n", + "model.add(layers.Dense(64, activation='relu'))\n", + "model.add(layers.Dense(10))\n", + "Here's the complete architecture of our model.\n", + "\n", + "model.summary()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As you can see, our (4, 4, 64) outputs were flattened into vectors of shape (1024) before going through two Dense layers.\n", + "\n", + "Compile and train the model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "model.compile(optimizer='adam',\n", + " loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n", + " metrics=['accuracy'])\n", + "​\n", + "history = model.fit(train_images, train_labels, epochs=10, \n", + " validation_data=(test_images, test_labels))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we evaluate the model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "plt.plot(history.history['accuracy'], label='accuracy')\n", + "plt.plot(history.history['val_accuracy'], label = 'val_accuracy')\n", + "plt.xlabel('Epoch')\n", + "plt.ylabel('Accuracy')\n", + "plt.ylim([0.5, 1])\n", + "plt.legend(loc='lower right')\n", + "\n", + "test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)\n", + "\n", + "print(test_acc)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Recurrent neural networks: Overarching view\n", + "\n", + "Till now our focus has been, including convolutional neural networks\n", + "as well, on feedforward neural networks. The output or the activations\n", + "flow only in one direction, from the input layer to the output layer.\n", + "\n", + "A recurrent neural network (RNN) looks very much like a feedforward\n", + "neural network, except that it also has connections pointing\n", + "backward. \n", + "\n", + "RNNs are used to analyze time series data such as stock prices, and\n", + "tell you when to buy or sell. In autonomous driving systems, they can\n", + "anticipate car trajectories and help avoid accidents. More generally,\n", + "they can work on sequences of arbitrary lengths, rather than on\n", + "fixed-sized inputs like all the nets we have discussed so far. For\n", + "example, they can take sentences, documents, or audio samples as\n", + "input, making them extremely useful for natural language processing\n", + "systems such as automatic translation and speech-to-text.\n", + "\n", + "\n", + "\n", + "\n", + "### A simple example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], + "source": [ + "# Start importing packages\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import tensorflow as tf\n", + "from tensorflow.keras import datasets, layers, models\n", + "from tensorflow.keras.layers import Input\n", + "from tensorflow.keras.models import Model, Sequential \n", + "from tensorflow.keras.layers import Dense, SimpleRNN, LSTM, GRU\n", + "from tensorflow.keras import optimizers \n", + "from tensorflow.keras import regularizers \n", + "from tensorflow.keras.utils import to_categorical \n", + "\n", + "\n", + "\n", + "# convert into dataset matrix\n", + "def convertToMatrix(data, step):\n", + " X, Y =[], []\n", + " for i in range(len(data)-step):\n", + " d=i+step \n", + " X.append(data[i:d,])\n", + " Y.append(data[d,])\n", + " return np.array(X), np.array(Y)\n", + "\n", + "step = 4\n", + "N = 1000 \n", + "Tp = 800 \n", + "\n", + "t=np.arange(0,N)\n", + "x=np.sin(0.02*t)+2*np.random.rand(N)\n", + "df = pd.DataFrame(x)\n", + "df.head()\n", + "\n", + "plt.plot(df)\n", + "plt.show()\n", + "\n", + "values=df.values\n", + "train,test = values[0:Tp,:], values[Tp:N,:]\n", + "\n", + "# add step elements into train and test\n", + "test = np.append(test,np.repeat(test[-1,],step))\n", + "train = np.append(train,np.repeat(train[-1,],step))\n", + " \n", + "trainX,trainY =convertToMatrix(train,step)\n", + "testX,testY =convertToMatrix(test,step)\n", + "trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))\n", + "testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1]))\n", + "\n", + "model = Sequential()\n", + "model.add(SimpleRNN(units=32, input_shape=(1,step), activation=\"relu\"))\n", + "model.add(Dense(8, activation=\"relu\")) \n", + "model.add(Dense(1))\n", + "model.compile(loss='mean_squared_error', optimizer='rmsprop')\n", + "model.summary()\n", + "\n", + "model.fit(trainX,trainY, epochs=100, batch_size=16, verbose=2)\n", + "trainPredict = model.predict(trainX)\n", + "testPredict= model.predict(testX)\n", + "predicted=np.concatenate((trainPredict,testPredict),axis=0)\n", + "\n", + "trainScore = model.evaluate(trainX, trainY, verbose=0)\n", + "print(trainScore)\n", + "\n", + "index = df.index.values\n", + "plt.plot(index,df)\n", + "plt.plot(index,predicted)\n", + "plt.axvline(df.index[Tp], c=\"r\")\n", + "plt.show()" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 +}