correcting typos
This commit is contained in:
@@ -199,7 +199,35 @@ div { text-align: justify; text-justify: inter-word; }
|
||||
('Running with Keras', 2, None, '___sec83'),
|
||||
('Final part', 2, None, '___sec84'),
|
||||
('Final visualization', 2, None, '___sec85'),
|
||||
('Fun links', 2, None, '___sec86')]}
|
||||
('Fun links', 2, None, '___sec86'),
|
||||
('Applications: solving ordinary differential equations with '
|
||||
'Neural Networks',
|
||||
2,
|
||||
None,
|
||||
'___sec87'),
|
||||
('Trial solution', 2, None, '___sec88'),
|
||||
('More details', 2, None, '___sec89'),
|
||||
('Reformulating the problem', 2, None, '___sec90'),
|
||||
('Estimating errors', 2, None, '___sec91'),
|
||||
('Creating a simple Deep Neural Net', 2, None, '___sec92'),
|
||||
('Feedforward', 2, None, '___sec93'),
|
||||
('Result after weighting', 2, None, '___sec94'),
|
||||
('Output', 2, None, '___sec95'),
|
||||
('Setting up the code, feed forward part', 2, None, '___sec96'),
|
||||
('Backpropagation', 2, None, '___sec97'),
|
||||
('Gradient Descent', 2, None, '___sec98'),
|
||||
('More on GD and cost function', 2, None, '___sec99'),
|
||||
('An implementation of a Deep Neural Network',
|
||||
2,
|
||||
None,
|
||||
'___sec100'),
|
||||
('Feed forward again', 2, None, '___sec101'),
|
||||
('The final parts of the code', 2, None, '___sec102'),
|
||||
('And adding Back propagation', 2, None, '___sec103'),
|
||||
('Solving the ODE', 2, None, '___sec104'),
|
||||
('Using neural network', 2, None, '___sec105'),
|
||||
('Using a deep neural network', 2, None, '___sec106'),
|
||||
('Wrapping it up', 2, None, '___sec107')]}
|
||||
end of tocinfo -->
|
||||
|
||||
<body>
|
||||
@@ -3632,6 +3660,824 @@ plt.show()
|
||||
<li> <a href="https://deepdreamgenerator.com/" target="_blank">Abstract art using convolutional neural networks</a></li>
|
||||
</ol>
|
||||
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec87">Applications: solving ordinary differential equations with Neural Networks </h2>
|
||||
|
||||
<p>
|
||||
We end our discussion on neural networks with a discussion on how to solve differential equations. Here we focus
|
||||
first on the classical exponential decay in one dimension. Thereafter we switch to the Poisson equation in one dimension.
|
||||
|
||||
<p>
|
||||
The aim is to see if we can use a neural network to solve
|
||||
|
||||
$$
|
||||
\begin{equation}
|
||||
\label{eq:ode}
|
||||
g'(x) = -\gamma g(x)
|
||||
\end{equation}
|
||||
$$
|
||||
|
||||
<p>
|
||||
where \( g(0) = g_0 \) with \( \gamma \) and \( g_0 \) being some chosen
|
||||
values. This equation is an ordinary differential equation since the
|
||||
function we have to solve for, \( g(x) \), is of one variable.
|
||||
|
||||
<p>
|
||||
Here we set \( \gamma = 2 \) and \( g_0 = 10 \) but feel free to change
|
||||
them and see how the neural network performs.
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec88">Trial solution </h2>
|
||||
|
||||
<p>
|
||||
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)),
|
||||
$$
|
||||
|
||||
<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.
|
||||
|
||||
<p>
|
||||
It is assumed that 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 an \( N_{\text{hidden} }
|
||||
\times 2 \) matrix.
|
||||
|
||||
<p>
|
||||
The first column in \( P_{\text{hidden} } \) represents
|
||||
the bias for each neuron in the hidden layer and the second column
|
||||
represents the weigths for each neuron. 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.
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec89">More details </h2>
|
||||
|
||||
<p>
|
||||
We have \( g(0) = g_0 \). The trial solution must fulfill this
|
||||
condition to be a proper solution of \eqref{eq:ode}.
|
||||
|
||||
<p>
|
||||
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}
|
||||
g_t(x, P) = g_0 + x \cdot N(x, P).
|
||||
\label{_auto11}
|
||||
\end{equation}
|
||||
$$
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec90">Reformulating the problem </h2>
|
||||
|
||||
<p>
|
||||
Often, the role of a neural network is to minimize its parameters with
|
||||
respect to some given error criteria. This criteria, the cost or loss
|
||||
function, is a measure of how much error the output of the network has
|
||||
compared to some given known answers. A reformulation of
|
||||
\eqref{eq:ode} must therefore be done, such that it describes the
|
||||
problem a neural network can solve.
|
||||
|
||||
<p>
|
||||
The neural network must find the set of weigths and biases \( P \) such
|
||||
that the trial solution in satisfies
|
||||
\eqref{eq:ode}. The trial solution has been chosen such that it
|
||||
already solves the condition \( g(0) = g_0 \). What remains, is to find
|
||||
\( P \) such that
|
||||
|
||||
$$
|
||||
\begin{equation}
|
||||
g_t'(x, P) = - \gamma g_t(x, P)
|
||||
\label{_auto12}
|
||||
\end{equation}
|
||||
$$
|
||||
|
||||
<p>
|
||||
is fulfilled as <em>best as possible</em>.
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec91">Estimating errors </h2>
|
||||
|
||||
<p>
|
||||
Having two sides of an equation as equal as
|
||||
possible, means that the absolute or squared difference between the
|
||||
sides must be as close to zero as small. In this case, the difference
|
||||
squared is an appropiate measurement of how errorneous the trial
|
||||
solution is with respect to \( P \) of the neural network. Therefore, the
|
||||
problem our network must solve, is
|
||||
|
||||
$$
|
||||
\min_{P}\Big\{ \big(g_t'(x, P) - ( -\gamma g_t(x, P) \big)^2 \Big\}
|
||||
$$
|
||||
|
||||
<p>
|
||||
or, in terms of weights and biases for each layer:
|
||||
|
||||
$$
|
||||
\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\}
|
||||
$$
|
||||
|
||||
<p>
|
||||
for an input value \( x \).
|
||||
If the neural network evaluates \( g_t(x, P) \) at more avalues for \( x \), say \( N \) values \( x_i \) for \( i = 1, \dots, N \), then the <em>total</em> error to minimize is
|
||||
|
||||
$$
|
||||
\begin{equation}
|
||||
\label{eq:min}
|
||||
\min_{P}\Big\{\sum_i \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P) \big)^2 \Big\}
|
||||
\end{equation}
|
||||
$$
|
||||
|
||||
<p>
|
||||
Letting \( c(x, P) = \sum_i \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P)
|
||||
\big)^2 \) denote the cost function, the minimization problem of which
|
||||
our network must solve, is
|
||||
|
||||
$$
|
||||
\min_{P} c(x, P)
|
||||
$$
|
||||
|
||||
<p>
|
||||
or in terms of \( P_{\text{hidden} } \) and \( P_{\text{output} } \)
|
||||
|
||||
$$
|
||||
\min_{P_{\text{hidden} }, \ P_{\text{output} }} c(x, \{P_{\text{hidden} }, P_{\text{output} }\})
|
||||
$$
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec92">Creating a simple Deep Neural Net </h2>
|
||||
|
||||
<p>
|
||||
The next step is to decide how the neural net \( N(x, P) \)
|
||||
should be. In this case, the neural network is made
|
||||
from scratch to understand better how a neural network works, gain
|
||||
more control over its architecture, and see how Autograd can be used
|
||||
to simplify the implementation.
|
||||
|
||||
<p>
|
||||
Since a deep neural network (DNN) is a neural network with more than
|
||||
one hidden layer, we can first look on how to implement a neural
|
||||
network. Having an implementation of a neural network at hand, an
|
||||
extension of it into a deep neural network would (hopefully) be
|
||||
painless.
|
||||
|
||||
<p>
|
||||
For simplicity, we assume that the input is an array \( \vec x =
|
||||
(x_1, \dots, x_N) \) with \( N \) elements. It is at these points the neural
|
||||
network should find \( P \) such that it fulfills \eqref{eq:min}.
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec93">Feedforward </h2>
|
||||
|
||||
<p>
|
||||
First, a feedforward of the inputs must be done. This means that \( \vec
|
||||
x \) 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} } \).
|
||||
|
||||
<p>
|
||||
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}
|
||||
$$
|
||||
|
||||
<p>
|
||||
<!-- !split -->
|
||||
|
||||
<h2 id="___sec94">Result after weighting </h2>
|
||||
|
||||
<p>
|
||||
The result after weighting the input at the \( i \)-th hidden neuron can be written as a vector:
|
||||
$$
|
||||
\begin{aligned}
|
||||
\vec{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} \\
|
||||
&= \vec{p}_{i, \text{hidden}}^T X
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
<p>
|
||||
It is the vector \( \vec{p}_{i, \text{hidden}}^T \) that defines each row
|
||||
in \( P_{\text{hidden} } \), which contains the weights for the neural
|
||||
network to minimize according to \eqref{eq:min}.
|
||||
|
||||
<p>
|
||||
After having found \( \vec{z}_{i}^{\text{hidden}} \) for every neuron \( i \)
|
||||
in the hidden layer, the vector will be sent to an activation function
|
||||
\( a_i(\vec{z}) \). In this example, the sigmoid function has been used:
|
||||
|
||||
$$
|
||||
f(z) = \frac{1}{1 + \exp{(-z)}}.
|
||||
$$
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec95">Output </h2>
|
||||
|
||||
<p>
|
||||
The output $\vec{x}_i^{\text{hidden} }$from each \( i \)-th hidden neuron is:
|
||||
|
||||
$$
|
||||
\vec{x}_i^{\text{hidden} } = f\big( \vec{z}_{i}^{\text{hidden}} \big).
|
||||
$$
|
||||
|
||||
<p>
|
||||
The outputs \( \vec{x}_i^{\text{hidden} } \) are then sent to the output layer.
|
||||
|
||||
<p>
|
||||
The output layer consist 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.
|
||||
|
||||
<p>
|
||||
The procedure of weigthing 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}} & \vec{w}_1^{\text{output}}
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
1 \\
|
||||
\vec{x}_j^{\text{hidden}}
|
||||
\end{pmatrix}
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
<p>
|
||||
Expressing \( z_{1,j}^{\text{output}} \) as a vector gives the following procedure of weighting the inputs from the hidden layer:
|
||||
|
||||
$$
|
||||
\vec{z}_{1}^{\text{output}} =
|
||||
\begin{pmatrix}
|
||||
b_1^{\text{output}} & \vec{w}_1^{\text{output}}
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
1 & 1 & \dots & 1 \\
|
||||
\vec{x}_1^{\text{hidden}} & \vec{x}_2^{\text{hidden}} & \dots & \vec{x}_N^{\text{hidden}}
|
||||
\end{pmatrix}
|
||||
$$
|
||||
|
||||
<p>
|
||||
In this case we seek a continous range of values since we are
|
||||
approximating a function. This means that after computing
|
||||
\( \vec{z}_{1}^{\text{output}} \) the neural network has finished its
|
||||
feedforward step, and \( \vec{z}_{1}^{\text{output}} \) is the final
|
||||
output of the network.
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec96">Setting up the code, feed forward part </h2>
|
||||
<p>
|
||||
|
||||
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #408080; font-style: italic"># Note that we use the numpy wrapper for Autograd (see the gradient descent slides)</span>
|
||||
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">autograd.numpy</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">np</span>
|
||||
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">autograd</span> <span style="color: #008000; font-weight: bold">import</span> grad, elementwise_grad
|
||||
<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">autograd.numpy.random</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #0000FF; font-weight: bold">npr</span>
|
||||
<span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">matplotlib</span> <span style="color: #008000; font-weight: bold">import</span> pyplot <span style="color: #008000; font-weight: bold">as</span> plt
|
||||
|
||||
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">sigmoid</span>(z):
|
||||
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">1/</span>(<span style="color: #666666">1</span> <span style="color: #666666">+</span> np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>z))
|
||||
|
||||
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">neural_network</span>(params, x):
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Find the weights (including and biases) for the hidden and output layer.</span>
|
||||
<span style="color: #408080; font-style: italic"># Assume that params is a list of parameters for each layer. </span>
|
||||
<span style="color: #408080; font-style: italic"># The biases are the first element for each array in params, </span>
|
||||
<span style="color: #408080; font-style: italic"># and the weights are the remaning elements in each array in params. </span>
|
||||
|
||||
w_hidden <span style="color: #666666">=</span> params[<span style="color: #666666">0</span>]
|
||||
w_output <span style="color: #666666">=</span> params[<span style="color: #666666">1</span>]
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Assumes input x being an one-dimensional array</span>
|
||||
num_values <span style="color: #666666">=</span> np<span style="color: #666666">.</span>size(x)
|
||||
x <span style="color: #666666">=</span> x<span style="color: #666666">.</span>reshape(<span style="color: #666666">-1</span>, num_values)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Assume that the input layer does nothing to the input x</span>
|
||||
x_input <span style="color: #666666">=</span> x
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Hidden layer:</span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Add a row of ones to include bias</span>
|
||||
x_input <span style="color: #666666">=</span> np<span style="color: #666666">.</span>concatenate((np<span style="color: #666666">.</span>ones((<span style="color: #666666">1</span>,num_values)), x_input ), axis <span style="color: #666666">=</span> <span style="color: #666666">0</span>)
|
||||
|
||||
z_hidden <span style="color: #666666">=</span> np<span style="color: #666666">.</span>matmul(w_hidden, x_input)
|
||||
x_hidden <span style="color: #666666">=</span> sigmoid(z_hidden)
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Output layer:</span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Include bias:</span>
|
||||
x_hidden <span style="color: #666666">=</span> np<span style="color: #666666">.</span>concatenate((np<span style="color: #666666">.</span>ones((<span style="color: #666666">1</span>,num_values)), x_hidden ), axis <span style="color: #666666">=</span> <span style="color: #666666">0</span>)
|
||||
|
||||
z_output <span style="color: #666666">=</span> np<span style="color: #666666">.</span>matmul(w_output, x_hidden)
|
||||
x_output <span style="color: #666666">=</span> z_output
|
||||
|
||||
<span style="color: #008000; font-weight: bold">return</span> x_output
|
||||
</pre></div>
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec97">Backpropagation </h2>
|
||||
|
||||
<p>
|
||||
Now that feedforward can be done, the next step is to decide how the
|
||||
parameters should change such that they minimize the cost function.
|
||||
|
||||
<p>
|
||||
Recall that the chosen cost function for this problem is
|
||||
|
||||
$$
|
||||
c(x, P) = \sum_i \big(g_t'(x_i, P) - ( -\gamma g_t(x_i, P) \big)^2
|
||||
$$
|
||||
|
||||
<p>
|
||||
In order to minimize it, an optimalization method must be chosen.
|
||||
|
||||
<p>
|
||||
Here, gradient descent with a constant step size has been chosen.
|
||||
|
||||
<p>
|
||||
Before looking at the gradient descent method, let us set up the cost
|
||||
function along with the right ride of the ODE and trial solution.
|
||||
|
||||
<p>
|
||||
|
||||
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #408080; font-style: italic"># The trial solution using the deep neural network:</span>
|
||||
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">g_trial</span>(x,params, g0 <span style="color: #666666">=</span> <span style="color: #666666">10</span>):
|
||||
<span style="color: #008000; font-weight: bold">return</span> g0 <span style="color: #666666">+</span> x<span style="color: #666666">*</span>neural_network(params,x)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># The right side of the ODE:</span>
|
||||
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">g</span>(x, g_trial, gamma <span style="color: #666666">=</span> <span style="color: #666666">2</span>):
|
||||
<span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">-</span>gamma<span style="color: #666666">*</span>g_trial
|
||||
|
||||
<span style="color: #408080; font-style: italic"># The cost function:</span>
|
||||
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">cost_function</span>(P, x):
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Evaluate the trial function with the current parameters P</span>
|
||||
g_t <span style="color: #666666">=</span> g_trial(x,P)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Find the derivative w.r.t x of the neural network</span>
|
||||
d_net_out <span style="color: #666666">=</span> elementwise_grad(neural_network,<span style="color: #666666">1</span>)(P,x)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Find the derivative w.r.t x of the trial function</span>
|
||||
d_g_t <span style="color: #666666">=</span> elementwise_grad(g_trial,<span style="color: #666666">0</span>)(x,P)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># The right side of the ODE </span>
|
||||
func <span style="color: #666666">=</span> g(x, g_t)
|
||||
|
||||
err_sqr <span style="color: #666666">=</span> (d_g_t <span style="color: #666666">-</span> func)<span style="color: #666666">**2</span>
|
||||
cost_sum <span style="color: #666666">=</span> np<span style="color: #666666">.</span>sum(err_sqr)
|
||||
|
||||
<span style="color: #008000; font-weight: bold">return</span> cost_sum
|
||||
</pre></div>
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec98">Gradient Descent </h2>
|
||||
|
||||
<p>
|
||||
The idea of the gradient descent algorithm is to update parameters in
|
||||
direction where the cost function decreases goes to a minimum.
|
||||
|
||||
<p>
|
||||
In general, the update of some parameters \( \vec \omega \) given a cost
|
||||
function defined by some weights \( \vec \omega \), \( c(x, \vec \omega) \),
|
||||
goes as follows:
|
||||
|
||||
$$
|
||||
\vec \omega_{\text{new} } = \vec \omega - \lambda \nabla_{\vec \omega} c(x, \vec \omega),
|
||||
$$
|
||||
|
||||
<p>
|
||||
for a number of iterations or until $ \big|\big| \vec
|
||||
\omega_{\text{new} } - \vec \omega \big|\big|$ is smaller than some
|
||||
given tolerance.
|
||||
|
||||
<p>
|
||||
The value of \( \lambda \) decides how large steps the algorithm must take
|
||||
in the direction of $ \nabla_{\vec \omega} c(x, \vec \omega)$. The
|
||||
notatation \( \nabla_{\vec \omega} \) denotes the gradient with respect to
|
||||
the elements in \( \vec \omega \).
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec99">More on GD and cost function </h2>
|
||||
|
||||
<p>
|
||||
In our case, we have to minimize the cost function \( c(x, P) \) with
|
||||
respect to the two sets of weights and bisases, that is for the hidden
|
||||
layer \( P_{\text{hidden} } \) and for the ouput layer \( P_{\text{output}
|
||||
} \) .
|
||||
|
||||
<p>
|
||||
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(x, P) \\
|
||||
P_{\text{output},\text{new}} &= P_{\text{output}} - \lambda \nabla_{P_{\text{output}}} c(x, P)
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
<p>
|
||||
This might look like a cumberstone to set up the correct expression
|
||||
for finding the gradients. Luckily, Autograd comes to the rescue.
|
||||
|
||||
<p>
|
||||
|
||||
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">solve_ode_neural_network</span>(x, num_neurons_hidden, num_iter, lmb):
|
||||
<span style="color: #408080; font-style: italic">## Set up initial weigths and biases </span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># For the hidden layer</span>
|
||||
p0 <span style="color: #666666">=</span> npr<span style="color: #666666">.</span>randn(num_neurons_hidden, <span style="color: #666666">2</span> )
|
||||
|
||||
<span style="color: #408080; font-style: italic"># For the output layer</span>
|
||||
p1 <span style="color: #666666">=</span> npr<span style="color: #666666">.</span>randn(<span style="color: #666666">1</span>, num_neurons_hidden <span style="color: #666666">+</span> <span style="color: #666666">1</span> ) <span style="color: #408080; font-style: italic"># +1 since bias is included</span>
|
||||
|
||||
P <span style="color: #666666">=</span> [p0, p1]
|
||||
|
||||
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Initial cost: </span><span style="color: #BB6688; font-weight: bold">%g</span><span style="color: #BA2121">'</span><span style="color: #666666">%</span>cost_function(P, x))
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Start finding the optimal weigths using gradient descent</span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Find the Python function that represents the gradient of the cost function</span>
|
||||
<span style="color: #408080; font-style: italic"># w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer</span>
|
||||
cost_function_grad <span style="color: #666666">=</span> grad(cost_function,<span style="color: #666666">0</span>)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Let the update be done num_iter times</span>
|
||||
<span style="color: #008000; font-weight: bold">for</span> i <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(num_iter):
|
||||
<span style="color: #408080; font-style: italic"># Evaluate the gradient at the current weights and biases in P. </span>
|
||||
<span style="color: #408080; font-style: italic"># The cost_grad consist now of two arrays; </span>
|
||||
<span style="color: #408080; font-style: italic"># one for the gradient w.r.t P_hidden and </span>
|
||||
<span style="color: #408080; font-style: italic"># one for the gradient w.r.t P_output</span>
|
||||
cost_grad <span style="color: #666666">=</span> cost_function_grad(P, x)
|
||||
|
||||
P[<span style="color: #666666">0</span>] <span style="color: #666666">=</span> P[<span style="color: #666666">0</span>] <span style="color: #666666">-</span> lmb <span style="color: #666666">*</span> cost_grad[<span style="color: #666666">0</span>]
|
||||
P[<span style="color: #666666">1</span>] <span style="color: #666666">=</span> P[<span style="color: #666666">1</span>] <span style="color: #666666">-</span> lmb <span style="color: #666666">*</span> cost_grad[<span style="color: #666666">1</span>]
|
||||
|
||||
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Final cost: </span><span style="color: #BB6688; font-weight: bold">%g</span><span style="color: #BA2121">'</span><span style="color: #666666">%</span>cost_function(P, x))
|
||||
|
||||
<span style="color: #008000; font-weight: bold">return</span> P
|
||||
</pre></div>
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec100">An implementation of a Deep Neural Network </h2>
|
||||
|
||||
<p>
|
||||
As previously stated, a Deep Neural Network (DNN) follows the same
|
||||
concept of a neural network, but having more than one hidden
|
||||
layer. Suppose that the network has \( N_{\text{hidden}} \) hidden layers
|
||||
where the \( l \)-th layer has \( N_{\text{hidden}}^{(l)} \) neurons. The
|
||||
input is still assumed to be an array of size \( 1 \times N \). The
|
||||
network must now try to optimalize its output with respect to the
|
||||
collection of weigths and biases \( P = \big\{P_{\text{input} }, \
|
||||
P_{\text{hidden} }^{(1)}, \ P_{\text{hidden} }^{(2)}, \ \dots , \
|
||||
P_{\text{hidden} }^{(N_{\text{hidden}})}, \ P_{\text{output} }\big\} \).
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec101">Feed forward again </h2>
|
||||
|
||||
<p>
|
||||
The feedforward step is similar to as for the neural netowork, but now considering more than one hidden layer.
|
||||
|
||||
<p>
|
||||
The \( i \)-th neuron at layer \( l \) recieves the result
|
||||
\( \vec{x}_j^{(l-1),\text{hidden} } \) from the \( j \)-th neuron at layer
|
||||
\( l-1 \). The \( i \)-th neuron at layer \( l \) weights all of the elements in
|
||||
\( \vec{x}_j^{(l-1),\text{hidden} } \) with a weight vector \( \vec
|
||||
w_{i,j}^{(l), \ \text{hidden} } \) with as many weigths as there are
|
||||
elements in$\vec{x}_j^{(l-1),\text{hidden} }$, and adds a bias
|
||||
\( b_i^{(l), \ \text{hidden} } \):
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
z_{i,j}^{(l),\ \text{hidden}} &= b_i^{(l), \ \text{hidden}} + \big(\vec{w}_{i}^{(l), \ \text{hidden}}\big)^T\vec{x}_j^{(l-1),\text{hidden} } \\
|
||||
&=
|
||||
\begin{pmatrix}
|
||||
b_i^{(l), \ \text{hidden}} & \big(\vec{w}_{i}^{(l), \ \text{hidden}}\big)^T
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
1 \\
|
||||
\vec{x}_j^{(l-1),\text{hidden} }
|
||||
\end{pmatrix}
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
<p>
|
||||
The output from the \( i \)-th neuron at the hidden layer \( l \) becomes a vector \( \vec{z}_{i}^{(l),\ \text{hidden}} \):
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
\vec{z}_{i}^{(l),\ \text{hidden}} &= \Big( b_i^{(l), \ \text{hidden}} + \big(\vec{w}_{i}^{(l), \ \text{hidden}}\big)^T\vec{x}_1^{(l-1),\text{hidden} }, \ \dots \ , \ b_i^{(l), \ \text{hidden}} + \big(\vec{w}_{i}^{(l), \ \text{hidden}}\big)^T\vec{x}_{N_{hidden}^{(l-1)}}^{(l-1),\text{hidden} } \Big) \\
|
||||
&=
|
||||
\begin{pmatrix}
|
||||
b_i^{(l), \ \text{hidden}} & \big(\vec{w}_{i}^{(l), \ \text{hidden}}\big)^T
|
||||
\end{pmatrix}
|
||||
\begin{pmatrix}
|
||||
1 & 1 & \dots & 1 \\
|
||||
\vec{x}_{1}^{(l-1),\text{hidden} } & \vec{x}_{2}^{(l-1),\text{hidden} } & \dots & \vec{x}_{N_{hidden}^{(l-1)}}^{(l-1),\text{hidden} }
|
||||
\end{pmatrix}
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec102">The final parts of the code </h2>
|
||||
<p>
|
||||
|
||||
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">deep_neural_network</span>(deep_params, x):
|
||||
<span style="color: #408080; font-style: italic"># N_hidden is the number of hidden layers </span>
|
||||
N_hidden <span style="color: #666666">=</span> np<span style="color: #666666">.</span>size(deep_params) <span style="color: #666666">-</span> <span style="color: #666666">1</span> <span style="color: #408080; font-style: italic"># -1 since params consist of parameters to all the hidden layers AND the output layer</span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Assumes input x being an one-dimensional array</span>
|
||||
num_values <span style="color: #666666">=</span> np<span style="color: #666666">.</span>size(x)
|
||||
x <span style="color: #666666">=</span> x<span style="color: #666666">.</span>reshape(<span style="color: #666666">-1</span>, num_values)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Assume that the input layer does nothing to the input x</span>
|
||||
x_input <span style="color: #666666">=</span> x
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Due to multiple hidden layers, define a variable referencing to the</span>
|
||||
<span style="color: #408080; font-style: italic"># output of the previous layer:</span>
|
||||
x_prev <span style="color: #666666">=</span> x_input
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Hidden layers:</span>
|
||||
|
||||
<span style="color: #008000; font-weight: bold">for</span> l <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(N_hidden):
|
||||
<span style="color: #408080; font-style: italic"># From the list of parameters P; find the correct weigths and bias for this layer</span>
|
||||
w_hidden <span style="color: #666666">=</span> deep_params[l]
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Add a row of ones to include bias</span>
|
||||
x_prev <span style="color: #666666">=</span> np<span style="color: #666666">.</span>concatenate((np<span style="color: #666666">.</span>ones((<span style="color: #666666">1</span>,num_values)), x_prev ), axis <span style="color: #666666">=</span> <span style="color: #666666">0</span>)
|
||||
|
||||
z_hidden <span style="color: #666666">=</span> np<span style="color: #666666">.</span>matmul(w_hidden, x_prev)
|
||||
x_hidden <span style="color: #666666">=</span> sigmoid(z_hidden)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Update x_prev such that next layer can use the output from this layer</span>
|
||||
x_prev <span style="color: #666666">=</span> x_hidden
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Output layer:</span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Get the weights and bias for this layer</span>
|
||||
w_output <span style="color: #666666">=</span> deep_params[<span style="color: #666666">-1</span>]
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Include bias:</span>
|
||||
x_prev <span style="color: #666666">=</span> np<span style="color: #666666">.</span>concatenate((np<span style="color: #666666">.</span>ones((<span style="color: #666666">1</span>,num_values)), x_prev), axis <span style="color: #666666">=</span> <span style="color: #666666">0</span>)
|
||||
|
||||
z_output <span style="color: #666666">=</span> np<span style="color: #666666">.</span>matmul(w_output, x_prev)
|
||||
x_output <span style="color: #666666">=</span> z_output
|
||||
|
||||
<span style="color: #008000; font-weight: bold">return</span> x_output
|
||||
</pre></div>
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec103">And adding Back propagation </h2>
|
||||
|
||||
<p>
|
||||
This step is very similar for the neural network. The idea in this
|
||||
step is the same as for the neural network, but with more parameters
|
||||
to update for. Again there is no need for computing the gradients
|
||||
analytically since Autograd does the work for us.
|
||||
|
||||
<p>
|
||||
|
||||
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #408080; font-style: italic"># The trial solution using the deep neural network:</span>
|
||||
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">g_trial_deep</span>(x,params, g0 <span style="color: #666666">=</span> <span style="color: #666666">10</span>):
|
||||
<span style="color: #008000; font-weight: bold">return</span> g0 <span style="color: #666666">+</span> x<span style="color: #666666">*</span>deep_neural_network(params,x)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># The same cost function as for the neural network, but calls deep_neural_network instead.</span>
|
||||
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">cost_function_deep</span>(P, x):
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Evaluate the trial function with the current parameters P</span>
|
||||
g_t <span style="color: #666666">=</span> g_trial_deep(x,P)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Find the derivative w.r.t x of the neural network</span>
|
||||
d_net_out <span style="color: #666666">=</span> elementwise_grad(deep_neural_network,<span style="color: #666666">1</span>)(P,x)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Find the derivative w.r.t x of the trial function</span>
|
||||
d_g_t <span style="color: #666666">=</span> elementwise_grad(g_trial_deep,<span style="color: #666666">0</span>)(x,P)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># The right side of the ODE </span>
|
||||
func <span style="color: #666666">=</span> g(x, g_t)
|
||||
|
||||
err_sqr <span style="color: #666666">=</span> (d_g_t <span style="color: #666666">-</span> func)<span style="color: #666666">**2</span>
|
||||
cost_sum <span style="color: #666666">=</span> np<span style="color: #666666">.</span>sum(err_sqr)
|
||||
|
||||
<span style="color: #008000; font-weight: bold">return</span> cost_sum
|
||||
|
||||
<span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">solve_ode_deep_neural_network</span>(x, num_neurons, num_iter, lmb):
|
||||
<span style="color: #408080; font-style: italic"># num_hidden_neurons is now a list of number of neurons within each hidden layer</span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Find the number of hidden layers:</span>
|
||||
N_hidden <span style="color: #666666">=</span> np<span style="color: #666666">.</span>size(num_neurons)
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Set up initial weigths and biases </span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Initialize the list of parameters:</span>
|
||||
P <span style="color: #666666">=</span> [<span style="color: #008000">None</span>]<span style="color: #666666">*</span>(N_hidden <span style="color: #666666">+</span> <span style="color: #666666">1</span>) <span style="color: #408080; font-style: italic"># + 1 to include the output layer</span>
|
||||
|
||||
P[<span style="color: #666666">0</span>] <span style="color: #666666">=</span> npr<span style="color: #666666">.</span>randn(num_neurons[<span style="color: #666666">0</span>], <span style="color: #666666">2</span> )
|
||||
<span style="color: #008000; font-weight: bold">for</span> l <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(<span style="color: #666666">1</span>,N_hidden):
|
||||
P[l] <span style="color: #666666">=</span> npr<span style="color: #666666">.</span>randn(num_neurons[l], num_neurons[l<span style="color: #666666">-1</span>] <span style="color: #666666">+</span> <span style="color: #666666">1</span>) <span style="color: #408080; font-style: italic"># +1 to include bias </span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># For the output layer</span>
|
||||
P[<span style="color: #666666">-1</span>] <span style="color: #666666">=</span> npr<span style="color: #666666">.</span>randn(<span style="color: #666666">1</span>, num_neurons[<span style="color: #666666">-1</span>] <span style="color: #666666">+</span> <span style="color: #666666">1</span> ) <span style="color: #408080; font-style: italic"># +1 since bias is included</span>
|
||||
|
||||
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Initial cost: </span><span style="color: #BB6688; font-weight: bold">%g</span><span style="color: #BA2121">'</span><span style="color: #666666">%</span>cost_function_deep(P, x))
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Start finding the optimal weigths using gradient descent</span>
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Find the Python function that represents the gradient of the cost function</span>
|
||||
<span style="color: #408080; font-style: italic"># w.r.t the 0-th input argument -- that is the weights and biases in the hidden and output layer</span>
|
||||
cost_function_deep_grad <span style="color: #666666">=</span> grad(cost_function_deep,<span style="color: #666666">0</span>)
|
||||
|
||||
<span style="color: #408080; font-style: italic"># Let the update be done num_iter times</span>
|
||||
<span style="color: #008000; font-weight: bold">for</span> i <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(num_iter):
|
||||
<span style="color: #408080; font-style: italic"># Evaluate the gradient at the current weights and biases in P. </span>
|
||||
<span style="color: #408080; font-style: italic"># The cost_grad consist now of N_hidden + 1 arrays; the gradient w.r.t the weights and biases</span>
|
||||
<span style="color: #408080; font-style: italic"># in the hidden layers and output layers evaluated at x.</span>
|
||||
cost_deep_grad <span style="color: #666666">=</span> cost_function_deep_grad(P, x)
|
||||
|
||||
<span style="color: #008000; font-weight: bold">for</span> l <span style="color: #AA22FF; font-weight: bold">in</span> <span style="color: #008000">range</span>(N_hidden<span style="color: #666666">+1</span>):
|
||||
P[l] <span style="color: #666666">=</span> P[l] <span style="color: #666666">-</span> lmb <span style="color: #666666">*</span> cost_deep_grad[l]
|
||||
|
||||
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Final cost: </span><span style="color: #BB6688; font-weight: bold">%g</span><span style="color: #BA2121">'</span><span style="color: #666666">%</span>cost_function_deep(P, x))
|
||||
|
||||
<span style="color: #008000; font-weight: bold">return</span> P
|
||||
</pre></div>
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec104">Solving the ODE </h2>
|
||||
|
||||
<p>
|
||||
Finally, having set up the networks we are ready to use them to solve the ODE problem.
|
||||
We add the analytical solution
|
||||
|
||||
<p>
|
||||
|
||||
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">g_analytic</span>(x, gamma <span style="color: #666666">=</span> <span style="color: #666666">2</span>, g0 <span style="color: #666666">=</span> <span style="color: #666666">10</span>):
|
||||
<span style="color: #008000; font-weight: bold">return</span> g0<span style="color: #666666">*</span>np<span style="color: #666666">.</span>exp(<span style="color: #666666">-</span>gamma<span style="color: #666666">*</span>x)
|
||||
</pre></div>
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec105">Using neural network </h2>
|
||||
|
||||
<p>
|
||||
The code below solves the ODE using a neural network. The number of
|
||||
values for the input \( \vec x \) is 10, number of hidden neurons in the
|
||||
hidden layer being 10 and th step size used in gradien descent
|
||||
\( \lambda = 0.001 \). The program updates the weights and biases in the
|
||||
network <em>num_iter</em> times. Finally, it plots the results from using the
|
||||
neural network along with the analytical solution.
|
||||
|
||||
<p>
|
||||
|
||||
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>npr<span style="color: #666666">.</span>seed(<span style="color: #666666">15</span>)
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Decide the vales of arguments to the function to solve</span>
|
||||
N <span style="color: #666666">=</span> <span style="color: #666666">10</span>
|
||||
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linspace(<span style="color: #666666">0</span>, <span style="color: #666666">1</span>, N)
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Set up the initial parameters</span>
|
||||
num_hidden_neurons <span style="color: #666666">=</span> <span style="color: #666666">10</span>
|
||||
num_iter <span style="color: #666666">=</span> <span style="color: #666666">10000</span>
|
||||
lmb <span style="color: #666666">=</span> <span style="color: #666666">0.001</span>
|
||||
|
||||
P <span style="color: #666666">=</span> solve_ode_neural_network(x, num_hidden_neurons, num_iter, lmb)
|
||||
|
||||
res <span style="color: #666666">=</span> g_trial(x,P)
|
||||
res_analytical <span style="color: #666666">=</span> g_analytic(x)
|
||||
|
||||
<span style="color: #008000; font-weight: bold">print</span>(<span style="color: #BA2121">'Max absolute difference: </span><span style="color: #BB6688; font-weight: bold">%g</span><span style="color: #BA2121">'</span><span style="color: #666666">%</span>np<span style="color: #666666">.</span>max(np<span style="color: #666666">.</span>abs(res <span style="color: #666666">-</span> res_analytical)))
|
||||
|
||||
plt<span style="color: #666666">.</span>figure(figsize<span style="color: #666666">=</span>(<span style="color: #666666">10</span>,<span style="color: #666666">10</span>))
|
||||
|
||||
plt<span style="color: #666666">.</span>title(<span style="color: #BA2121">'Performance of neural network solving an ODE compared to the analytical solution'</span>)
|
||||
plt<span style="color: #666666">.</span>plot(x, res_analytical)
|
||||
plt<span style="color: #666666">.</span>plot(x, res[<span style="color: #666666">0</span>,:])
|
||||
plt<span style="color: #666666">.</span>legend([<span style="color: #BA2121">'analytical'</span>,<span style="color: #BA2121">'nn'</span>])
|
||||
plt<span style="color: #666666">.</span>xlabel(<span style="color: #BA2121">'x'</span>)
|
||||
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">'g(x)'</span>)
|
||||
plt<span style="color: #666666">.</span>show()
|
||||
</pre></div>
|
||||
<p>
|
||||
<!-- !split -->
|
||||
|
||||
<h2 id="___sec106">Using a deep neural network </h2>
|
||||
|
||||
<p>
|
||||
|
||||
<!-- code=python (!bc pycod) typeset with pygments style "default" -->
|
||||
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span></span>npr<span style="color: #666666">.</span>seed(<span style="color: #666666">15</span>)
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Decide the vales of arguments to the function to solve</span>
|
||||
N <span style="color: #666666">=</span> <span style="color: #666666">10</span>
|
||||
x <span style="color: #666666">=</span> np<span style="color: #666666">.</span>linspace(<span style="color: #666666">0</span>, <span style="color: #666666">1</span>, N)
|
||||
|
||||
<span style="color: #408080; font-style: italic">## Set up the initial parameters</span>
|
||||
num_hidden_neurons <span style="color: #666666">=</span> np<span style="color: #666666">.</span>array([<span style="color: #666666">10</span>,<span style="color: #666666">10</span>])
|
||||
num_iter <span style="color: #666666">=</span> <span style="color: #666666">10000</span>
|
||||
lmb <span style="color: #666666">=</span> <span style="color: #666666">0.001</span>
|
||||
|
||||
P <span style="color: #666666">=</span> solve_ode_deep_neural_network(x, num_hidden_neurons, num_iter, lmb)
|
||||
|
||||
res <span style="color: #666666">=</span> g_trial_deep(x,P)
|
||||
res_analytical <span style="color: #666666">=</span> g_analytic(x)
|
||||
|
||||
plt<span style="color: #666666">.</span>figure(figsize<span style="color: #666666">=</span>(<span style="color: #666666">10</span>,<span style="color: #666666">10</span>))
|
||||
|
||||
plt<span style="color: #666666">.</span>title(<span style="color: #BA2121">'Performance of a deep neural network solving an ODE compared to the analytical solution'</span>)
|
||||
plt<span style="color: #666666">.</span>plot(x, res_analytical)
|
||||
plt<span style="color: #666666">.</span>plot(x, res[<span style="color: #666666">0</span>,:])
|
||||
plt<span style="color: #666666">.</span>legend([<span style="color: #BA2121">'analytical'</span>,<span style="color: #BA2121">'dnn'</span>])
|
||||
plt<span style="color: #666666">.</span>ylabel(<span style="color: #BA2121">'g(x)'</span>)
|
||||
plt<span style="color: #666666">.</span>show()
|
||||
</pre></div>
|
||||
<p>
|
||||
<!-- !split --><br><br><br><br><br><br><br><br><br><br>
|
||||
|
||||
<h2 id="___sec107">Wrapping it up </h2>
|
||||
|
||||
<p>
|
||||
By rewriting the ODE as a minimization problem, it was possible to
|
||||
solve equation using either a neural network (one hidden layer) or a
|
||||
deep neural network (more than one hidden layers). How well the
|
||||
network performed is measured by a specified cost function, which is
|
||||
the function the network tries to minimize. Using a trial solution
|
||||
which satisfies the additional condition and being defined by using
|
||||
the output from the network in some way, the minimization problem
|
||||
could be explicitly defined for out network to solve. The proposed
|
||||
solution from the network is then the trial solution with parameters,
|
||||
that is weights and biases within each layer in the network, such that
|
||||
the solution minimizes the cost function.
|
||||
|
||||
<!-- ------------------- end of main content --------------- -->
|
||||
|
||||
|
||||
Reference in New Issue
Block a user