Skip to content

Commit

Permalink
[neural-networks] several fixes and restructures according to reviews
Browse files Browse the repository at this point in the history
  • Loading branch information
HenKlei committed Jul 8, 2020
1 parent 4d8e44c commit 0d4ad06
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 187 deletions.
10 changes: 10 additions & 0 deletions src/pymor/core/exceptions.py
Expand Up @@ -56,12 +56,22 @@ def __init__(self, op):
self.op = op


class NeuralNetworkTrainingFailed(Exception):
"""Is raised when training of a neural network fails."""


class QtMissing(ImportError):
"""Raise me where having importable Qt bindings is non-optional"""
def __init__(self, msg=None):
msg = msg or 'cannot visualize: import of Qt bindings failed'
super().__init__(msg)

class TorchMissing(ImportError):
"""Raise me where having importable torch version is non-optional"""
def __init__(self, msg=None):
msg = msg or 'cannot use neural networks: import of torch failed'
super().__init__(msg)


class RuleNotMatchingError(NotImplementedError):
pass
Expand Down
62 changes: 58 additions & 4 deletions src/pymor/models/neural_network.py
Expand Up @@ -7,7 +7,9 @@

if config.HAVE_TORCH:
import torch
import torch.nn as nn

from pymor.core.base import BasicObject
from pymor.models.interface import Model
from pymor.vectorarrays.numpy import NumpyVectorSpace

Expand Down Expand Up @@ -64,13 +66,65 @@ def _solve(self, mu=None, return_output=False):
# convert the parameter `mu` into a form that is usable in PyTorch
converted_input = torch.from_numpy(mu.to_numpy()).double()
# obtain (reduced) coordinates by forward pass of the parameter values through the neural network
u = self.neural_network(converted_input).data.numpy()
U = self.neural_network(converted_input).data.numpy()
# convert plain numpy array to element of the actual solution space
u = self.solution_space.make_array(u)
U = self.solution_space.make_array(U)

if return_output:
if self.output_functional is None:
raise ValueError('Model has no output')
return u, self.output_functional.apply(u, mu=mu)
return U, self.output_functional.apply(U, mu=mu)
else:
return u
return U


class FullyConnectedNN(nn.Module, BasicObject):
"""Class for neural networks with fully connected layers.
This class implements neural networks consisting of linear and fully connected layers.
Furthermore, the same activation function is used between each layer, except for the
last one where no activation function is applied.
Parameters
----------
layers_sizes
List of sizes (i.e. number of neurons) for the layers of the neural network.
activation_function
Function to use as activation function between the single layers.
"""

def __init__(self, layers_sizes, activation_function=torch.tanh):
super().__init__()

if layers_sizes is None or not len(layers_sizes) > 1 or not all(size >= 1 for size in layers_sizes):
raise ValueError

self.input_dimension = layers_sizes[0]
self.output_dimension = layers_sizes[-1]

self.layers = nn.ModuleList()
self.layers.extend([nn.Linear(int(layers_sizes[i]), int(layers_sizes[i+1])) for i in range(len(layers_sizes) - 1)])

self.activation_function = activation_function

if not self.logging_disabled:
self.logger.info(f'Architecture of the neural network:\n{self}')

def forward(self, x):
"""Performs the forward pass through the neural network.
Applies the weights in the linear layers and passes the outcomes to the
activation function.
Parameters
----------
x
Input for the neural network.
Returns
-------
The output of the neural network for the input x.
"""
for i in range(len(self.layers) - 1):
x = self.activation_function(self.layers[i](x))
return self.layers[len(self.layers)-1](x)

0 comments on commit 0d4ad06

Please sign in to comment.