https://mooseframework.inl.gov
Loading...
Searching...
No Matches
LibtorchANNTrainer.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#ifdef MOOSE_LIBTORCH_ENABLED
11
12#include "LibtorchANNTrainer.h"
13#include "LibtorchDataset.h"
14#include "Sampler.h"
15
17
20{
22
23 params.addClassDescription("Trains a simple neural network using libtorch.");
24
25 params.addRangeCheckedParam<unsigned int>(
26 "num_batches", 1, "1<=num_batches", "Number of batches.");
27 params.addRangeCheckedParam<unsigned int>(
28 "num_epochs", 1, "0<num_epochs", "Number of training epochs.");
29 params.addRangeCheckedParam<Real>(
30 "rel_loss_tol",
31 0,
32 "0<=rel_loss_tol<=1",
33 "The relative loss where we stop the training of the neural net.");
34 params.addParam<std::vector<unsigned int>>(
35 "num_neurons_per_layer", std::vector<unsigned int>(), "Number of neurons per layer.");
36 params.addParam<std::vector<std::string>>(
37 "activation_function",
38 std::vector<std::string>({"relu"}),
39 "The type of activation functions to use. It is either one value "
40 "or one value per hidden layer.");
41 params.addParam<std::string>(
42 "nn_filename", "net.pt", "Filename used to output the neural net parameters.");
43 params.addParam<bool>("read_from_file",
44 false,
45 "Switch to allow reading old trained neural nets for further training.");
46 params.addParam<Real>("learning_rate", 0.001, "Learning rate (relaxation).");
47 params.addRangeCheckedParam<unsigned int>(
48 "print_epoch_loss",
49 0,
50 "0<=print_epoch_loss",
51 "Epoch training loss printing. 0 - no printing, 1 - every epoch, 10 - every 10th epoch.");
52 params.addParam<unsigned int>(
53 "seed", 11, "Random number generator seed for stochastic optimizers.");
54 params.addParam<unsigned int>(
55 "max_processes", 1, "The maximum number of parallel processes that the trainer will use.");
56
57 params.addParam<bool>(
58 "standardize_input", true, "Standardize (center and scale) training inputs (x values)");
59 params.addParam<bool>(
60 "standardize_output", true, "Standardize (center and scale) training outputs (y values)");
61
62 params.suppressParameter<MooseEnum>("response_type");
63 return params;
64}
65
67 : SurrogateTrainer(parameters),
68 _predictor_row(getPredictorData()),
69 _num_neurons_per_layer(declareModelData<std::vector<unsigned int>>(
70 "num_neurons_per_layer", getParam<std::vector<unsigned int>>("num_neurons_per_layer"))),
71 _activation_function(declareModelData<std::vector<std::string>>(
72 "activation_function", getParam<std::vector<std::string>>("activation_function"))),
73 _nn_filename(getParam<std::string>("nn_filename")),
74 _read_from_file(getParam<bool>("read_from_file")),
75 _nn(declareModelData<std::shared_ptr<Moose::LibtorchArtificialNeuralNet>>("nn")),
76 _standardize_input(getParam<bool>("standardize_input")),
77 _standardize_output(getParam<bool>("standardize_output")),
78 _input_standardizer(declareModelData<StochasticTools::Standardizer>("input_standardizer")),
79 _output_standardizer(declareModelData<StochasticTools::Standardizer>("output_standardizer"))
80{
81 // Fixing the RNG seed to make sure every experiment is the same.
82 // Otherwise sampling / stochastic gradient descent would be different.
83 torch::manual_seed(getParam<unsigned int>("seed"));
84
86 _optim_options.learning_rate = getParam<Real>("learning_rate");
87 _optim_options.num_epochs = getParam<unsigned int>("num_epochs");
88 _optim_options.num_batches = getParam<unsigned int>("num_batches");
89 _optim_options.rel_loss_tol = getParam<Real>("rel_loss_tol");
90 _optim_options.print_loss = getParam<unsigned int>("print_epoch_loss") > 0;
91 _optim_options.print_epoch_loss = getParam<unsigned int>("print_epoch_loss");
92 _optim_options.parallel_processes = getParam<unsigned int>("max_processes");
93}
94
95void
97{
98 // Resize to number of sample points
99 _flattened_data.clear();
100 _flattened_response.clear();
103}
104
105void
107{
108 for (auto & p : _predictor_row)
109 _flattened_data.push_back(p);
110
111 _flattened_response.push_back(*_rval);
112}
113
114void
116{
119
120 // Then, we create and load our Tensors
121 unsigned int num_samples = _flattened_response.size();
122 unsigned int num_inputs = _n_dims;
123
124 // We create a neural net (for the definition of the net see the header file)
125 _nn = std::make_shared<Moose::LibtorchArtificialNeuralNet>(
127
128 if (_read_from_file)
129 try
130 {
131 torch::load(_nn, _nn_filename);
132 _console << "Loaded requested .pt file." << std::endl;
133 }
134 catch (const c10::Error & e)
135 {
136 mooseError("The requested pytorch file could not be loaded.\n", e.msg());
137 }
138
139 // The default data type in pytorch is float, while we use double in MOOSE.
140 // Therefore, in some cases we have to convert Tensors to double.
141 auto options = torch::TensorOptions().dtype(at::kDouble);
142 torch::Tensor data_tensor =
143 torch::from_blob(_flattened_data.data(), {num_samples, num_inputs}, options).to(at::kDouble);
144 torch::Tensor response_tensor =
145 torch::from_blob(_flattened_response.data(), {num_samples, 1}, options).to(at::kDouble);
146
147 // We standardize the input/output pairs if the user requested it
149 {
150 auto data_std_mean = torch::std_mean(data_tensor, 0);
151 auto & data_std = std::get<0>(data_std_mean);
152 auto & data_mean = std::get<1>(data_std_mean);
153
154 data_tensor = (data_tensor - data_mean) / data_std;
155
156 std::vector<Real> converted_data_mean;
157 LibtorchUtils::tensorToVector(data_mean, converted_data_mean);
158 std::vector<Real> converted_data_std;
159 LibtorchUtils::tensorToVector(data_std, converted_data_std);
160 _input_standardizer.set(converted_data_mean, converted_data_std);
161 }
162 else
164
166 {
167 auto response_std_mean = torch::std_mean(response_tensor, 0);
168 auto & response_std = std::get<0>(response_std_mean);
169 auto & response_mean = std::get<1>(response_std_mean);
170
171 response_tensor = (response_tensor - response_mean) / response_std;
172
173 std::vector<Real> converted_response_mean;
174 LibtorchUtils::tensorToVector(response_mean, converted_response_mean);
175 std::vector<Real> converted_response_std;
176 LibtorchUtils::tensorToVector(response_std, converted_response_std);
177 _output_standardizer.set(converted_response_mean, converted_response_std);
178 }
179 else
181
182 // We create a custom data set from our converted data
183 Moose::LibtorchDataset my_data(data_tensor, response_tensor);
184
185 // We create atrainer for our neral net and train it with the dataset
187 trainer.train(my_data, _optim_options);
188}
189
190#endif
const Real p
registerMooseObject("StochasticToolsApp", LibtorchANNTrainer)
void ErrorVector unsigned int
const ConsoleStream _console
void suppressParameter(const std::string &name)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Trainer responsible of fitting a neural network on predefined data.
std::vector< std::string > & _activation_function
Activation functions for each hidden layer.
StochasticTools::Standardizer & _output_standardizer
Standardizer for use with output response (y)
virtual void postTrain() override
Contains processes which are executed after the training loop.
std::vector< Real > _flattened_data
The gathered data in a flattened form to be able to convert easily to torch::Tensor.
std::vector< unsigned int > & _num_neurons_per_layer
Number of neurons within the hidden layers (the length of this vector should be the same as _num_hidd...
StochasticTools::Standardizer & _input_standardizer
Standardizer for use with input (x)
std::vector< Real > _flattened_response
The gathered response in a flattened form to be able to convert easily to torch::Tensor.
const std::string _nn_filename
Name of the pytorch output file.
const std::vector< Real > & _predictor_row
Data from the current predictor row.
LibtorchANNTrainer(const InputParameters &parameters)
Construct using input parameters.
const bool _standardize_output
If the training output should be standardized (scaled and shifted)
virtual void preTrain() override
Contains processes which are executed before the training loop.
static InputParameters validParams()
virtual void train() override
Contains processes which are executed for every sample in the training loop.
Moose::LibtorchTrainingOptions _optim_options
The struct which contains the information for the training of the neural net.
std::shared_ptr< Moose::LibtorchArtificialNeuralNet > & _nn
Pointer to the neural net object (initialized as null)
const bool _read_from_file
Switch indicating if an already existing neural net should be read from a file or not.
const bool _standardize_input
If the training output should be standardized (scaled and shifted)
void mooseError(Args &&... args) const
virtual void train(LibtorchDataset &dataset, const LibtorchTrainingOptions &options)
void set(const Real &n)
Methods for setting mean and standard deviation directly Sets mean=0, std=1 for n variables.
This is the main trainer base class.
unsigned int getLocalSampleSize() const
const Real * _rval
Response value.
static InputParameters validParams()
unsigned int _n_dims
Dimension of predictor data - either _sampler.getNumberOfCols() or _pvals.size() + _pcols....
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
const Parallel::Communicator & _communicator
const Parallel::Communicator & comm() const
void tensorToVector(torch::Tensor &tensor, std::vector< DataType > &vector)
Enum for batch type in stochastic tools MultiApp.