Source code for pinnicle.nn.nn

import deepxde as dde
import deepxde.backend as bkd
import numpy as np
from deepxde.backend import tf
from .helper import minmax_scale, up_scale, fourier_feature
from ..utils import default_float_type
from ..parameter import NNParameter

[docs] class FNN: def __init__(self, parameters=NNParameter()): """ general class for constructing nerual network """ self.parameters = parameters # update necesarry parameters for fourier feature transform # NOTE: these changes will not be saved to the param file, # so that the change will not accumulate and loading the previous param file will create the same nn if self.parameters.fft : # Then add an additional layer before the output node self.num_neurons = parameters.num_neurons + [parameters.num_fourier_feature*parameters.sigma_size] self.num_layers = len(self.num_neurons) # append linear transform for the output self.activation = self.parameters.activation + [None] else: # just to avoid modify parameters self.num_neurons = self.parameters.num_neurons self.num_layers = self.parameters.num_layers self.activation = self.parameters.activation # create new NN if self.parameters.is_parallel: self.net = self.createPFNN() else: self.net = self.createFNN() # by default, use min-max scale for the input if self.parameters.is_input_scaling(): # force the input and output lb and ub to be tensors if bkd.backend_name == "pytorch" or bkd.backend_name == "paddle": self.parameters.input_lb = bkd.as_tensor(self.parameters.input_lb, dtype=default_float_type()) self.parameters.input_ub = bkd.as_tensor(self.parameters.input_ub, dtype=default_float_type()) if self.parameters.fft : print(f"add Fourier feature transform to input transform") if self.parameters.B is not None: self.B = bkd.as_tensor(self.parameters.B, dtype=default_float_type()) else: self.B = bkd.as_tensor( np.reshape(np.random.normal(0.0, self.parameters.sigma, [len(self.parameters.input_variables), self.parameters.num_fourier_feature, self.parameters.sigma_size]), [len(self.parameters.input_variables), self.parameters.num_fourier_feature*self.parameters.sigma_size]), dtype=default_float_type()) def wrapper(x): """a wrapper function to add fourier feature transform to the input """ return fourier_feature(minmax_scale(x, self.parameters.input_lb, self.parameters.input_ub), self.B) # add to input transform self.net.apply_feature_transform(wrapper) else: print(f"add input transform with {self.parameters.input_lb} and {self.parameters.input_ub}") # add input transform self._add_input_transform(minmax_scale) # upscale the output by min-max if self.parameters.is_output_scaling(): print(f"add output transform with {self.parameters.output_lb} and {self.parameters.output_ub}") # force the input and output lb and ub to be tensors if bkd.backend_name == "pytorch": self.parameters.output_lb = bkd.as_tensor(self.parameters.output_lb, dtype=default_float_type()) self.parameters.output_ub = bkd.as_tensor(self.parameters.output_ub, dtype=default_float_type()) # add output transform self._add_output_transform(up_scale)
[docs] def createFNN(self): """ create a fully connected neural network """ if isinstance(self.num_neurons, list): # directly use the given list of num_neurons layer_size = [self.parameters.input_size] + \ self.num_neurons + \ [self.parameters.output_size] else: # repeat num_layers times layer_size = [self.parameters.input_size] + \ [self.num_neurons] * self.num_layers + \ [self.parameters.output_size] return dde.nn.FNN(layer_size, self.activation, self.parameters.initializer)
[docs] def createPFNN(self): """ create a parallel fully connected neural network """ if isinstance(self.num_neurons, list): layer_size = [self.parameters.input_size] + \ [[n]*self.parameters.output_size for n in self.num_neurons] + \ [self.parameters.output_size] else: layer_size = [self.parameters.input_size] + \ [[self.num_neurons]*self.parameters.output_size] * self.num_layers + \ [self.parameters.output_size] return dde.nn.PFNN(layer_size, self.activation, self.parameters.initializer)
def _add_input_transform(self, func): """ a wrapper function to add scaling at the input """ def _wrapper(x): return func(x, self.parameters.input_lb, self.parameters.input_ub) self.net.apply_feature_transform(_wrapper) def _add_output_transform(self, func): """ a wrapper function to add scaling at the output """ def _wrapper(dummy, x): return func(x, self.parameters.output_lb, self.parameters.output_ub) self.net.apply_output_transform(_wrapper)