Line data Source code
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 : #include "GaussianProcessTrainer.h"
11 : #include "Sampler.h"
12 : #include "CartesianProduct.h"
13 :
14 : #include <petsctao.h>
15 : #include <petscdmda.h>
16 :
17 : #include "libmesh/petsc_vector.h"
18 : #include "libmesh/petsc_matrix.h"
19 :
20 : #include <cmath>
21 :
22 : registerMooseObject("StochasticToolsApp", GaussianProcessTrainer);
23 :
24 : InputParameters
25 484 : GaussianProcessTrainer::validParams()
26 : {
27 484 : InputParameters params = SurrogateTrainer::validParams();
28 484 : params.addClassDescription("Provides data preperation and training for a single- or multi-output "
29 : "Gaussian Process surrogate model.");
30 :
31 968 : params.addRequiredParam<UserObjectName>("covariance_function", "Name of covariance function.");
32 968 : params.addParam<bool>(
33 968 : "standardize_params", true, "Standardize (center and scale) training parameters (x values)");
34 968 : params.addParam<bool>(
35 968 : "standardize_data", true, "Standardize (center and scale) training data (y values)");
36 : // Already preparing to use Adam here
37 968 : params.addParam<unsigned int>("num_iters", 1000, "Tolerance value for Adam optimization");
38 968 : params.addParam<unsigned int>("batch_size", 0, "The batch size for Adam optimization");
39 968 : params.addParam<Real>("learning_rate", 0.001, "The learning rate for Adam optimization");
40 968 : params.addParam<unsigned int>(
41 : "show_every_nth_iteration",
42 968 : 0,
43 : "Switch to show Adam optimization loss values at every nth step. If 0, nothing is showed.");
44 968 : params.addParam<std::vector<std::string>>("tune_parameters",
45 : "Select hyperparameters to be tuned");
46 968 : params.addParam<std::vector<Real>>("tuning_min", "Minimum allowable tuning value");
47 968 : params.addParam<std::vector<Real>>("tuning_max", "Maximum allowable tuning value");
48 484 : return params;
49 0 : }
50 :
51 244 : GaussianProcessTrainer::GaussianProcessTrainer(const InputParameters & parameters)
52 : : SurrogateTrainer(parameters),
53 : CovarianceInterface(parameters),
54 244 : _predictor_row(getPredictorData()),
55 488 : _gp(declareModelData<StochasticTools::GaussianProcess>("_gp")),
56 488 : _training_params(declareModelData<RealEigenMatrix>("_training_params")),
57 488 : _standardize_params(getParam<bool>("standardize_params")),
58 488 : _standardize_data(getParam<bool>("standardize_data")),
59 488 : _do_tuning(isParamValid("tune_parameters")),
60 1220 : _optimization_opts(StochasticTools::GaussianProcess::GPOptimizerOptions(
61 732 : getParam<unsigned int>("show_every_nth_iteration"),
62 488 : getParam<unsigned int>("num_iters"),
63 488 : getParam<unsigned int>("batch_size"),
64 488 : getParam<Real>("learning_rate"))),
65 488 : _sampler_row(getSamplerData())
66 : {
67 : // Error Checking
68 488 : if (parameters.isParamSetByUser("batch_size"))
69 116 : if (_sampler.getNumberOfRows() < _optimization_opts.batch_size)
70 4 : paramError("batch_size", "Batch size cannot be greater than the training data set size.");
71 :
72 : std::vector<std::string> tune_parameters(
73 240 : _do_tuning ? getParam<std::vector<std::string>>("tune_parameters")
74 224 : : std::vector<std::string>{});
75 :
76 768 : if (isParamValid("tuning_min") &&
77 336 : (getParam<std::vector<Real>>("tuning_min").size() != tune_parameters.size()))
78 0 : mooseError("tuning_min size does not match tune_parameters");
79 768 : if (isParamValid("tuning_max") &&
80 336 : (getParam<std::vector<Real>>("tuning_max").size() != tune_parameters.size()))
81 0 : mooseError("tuning_max size does not match tune_parameters");
82 :
83 : std::vector<Real> lower_bounds, upper_bounds;
84 480 : if (isParamValid("tuning_min"))
85 144 : lower_bounds = getParam<std::vector<Real>>("tuning_min");
86 480 : if (isParamValid("tuning_max"))
87 144 : upper_bounds = getParam<std::vector<Real>>("tuning_max");
88 :
89 240 : _gp.initialize(getCovarianceFunctionByName(parameters.get<UserObjectName>("covariance_function")),
90 : tune_parameters,
91 : lower_bounds,
92 : upper_bounds);
93 :
94 240 : _n_outputs = _gp.getCovarFunction().numOutputs();
95 240 : }
96 :
97 : void
98 336 : GaussianProcessTrainer::preTrain()
99 : {
100 336 : _params_buffer.clear();
101 336 : _data_buffer.clear();
102 336 : _params_buffer.reserve(getLocalSampleSize());
103 336 : _data_buffer.reserve(getLocalSampleSize());
104 336 : }
105 :
106 : void
107 2920 : GaussianProcessTrainer::train()
108 : {
109 2920 : _params_buffer.push_back(_predictor_row);
110 :
111 2920 : if (_rvecval && _rvecval->size() != _n_outputs)
112 0 : mooseError("The size of the provided response (",
113 0 : _rvecval->size(),
114 : ") does not match the number of expected outputs from the covariance (",
115 : _n_outputs,
116 : ")!");
117 :
118 2920 : _data_buffer.push_back(_rvecval ? (*_rvecval) : std::vector<Real>(1, *_rval));
119 2920 : }
120 :
121 : void
122 336 : GaussianProcessTrainer::postTrain()
123 : {
124 : // Instead of gatherSum, we have to allgather.
125 336 : _communicator.allgather(_params_buffer);
126 336 : _communicator.allgather(_data_buffer);
127 :
128 336 : _training_params.resize(_params_buffer.size(), _n_dims);
129 336 : _training_data.resize(_data_buffer.size(), _n_outputs);
130 :
131 5008 : for (auto ii : make_range(_training_params.rows()))
132 : {
133 15104 : for (auto jj : make_range(_n_dims))
134 10432 : _training_params(ii, jj) = _params_buffer[ii][jj];
135 9664 : for (auto jj : make_range(_n_outputs))
136 4992 : _training_data(ii, jj) = _data_buffer[ii][jj];
137 : }
138 :
139 : // Standardize (center and scale) training params
140 336 : if (_standardize_params)
141 336 : _gp.standardizeParameters(_training_params);
142 : // if not standardizing data set mean=0, std=1 for use in surrogate
143 : else
144 0 : _gp.paramStandardizer().set(0, 1, _n_dims);
145 :
146 : // Standardize (center and scale) training data
147 336 : if (_standardize_data)
148 336 : _gp.standardizeData(_training_data);
149 : // if not standardizing data set mean=0, std=1 for use in surrogate
150 : else
151 0 : _gp.dataStandardizer().set(0, 1, _n_outputs);
152 :
153 : // Setup the covariance
154 336 : _gp.setupCovarianceMatrix(_training_params, _training_data, _optimization_opts);
155 336 : }
|