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 514 : GaussianProcessTrainer::validParams()
26 : {
27 514 : InputParameters params = SurrogateTrainer::validParams();
28 514 : params.addClassDescription("Provides data preperation and training for a single- or multi-output "
29 : "Gaussian Process surrogate model.");
30 :
31 1028 : params.addRequiredParam<UserObjectName>("covariance_function", "Name of covariance function.");
32 1028 : params.addParam<bool>(
33 1028 : "standardize_params", true, "Standardize (center and scale) training parameters (x values)");
34 1028 : params.addParam<bool>(
35 1028 : "standardize_data", true, "Standardize (center and scale) training data (y values)");
36 : // Already preparing to use Adam here
37 1028 : params.addParam<unsigned int>("num_iters", 1000, "Tolerance value for Adam optimization");
38 1028 : params.addParam<unsigned int>("batch_size", 0, "The batch size for Adam optimization");
39 1028 : params.addParam<Real>("learning_rate", 0.001, "The learning rate for Adam optimization");
40 1028 : params.addParam<unsigned int>(
41 : "show_every_nth_iteration",
42 1028 : 0,
43 : "Switch to show Adam optimization loss values at every nth step. If 0, nothing is showed.");
44 1028 : params.addParam<std::vector<std::string>>("tune_parameters",
45 : "Select hyperparameters to be tuned");
46 1028 : params.addParam<std::vector<Real>>("tuning_min", "Minimum allowable tuning value");
47 1028 : params.addParam<std::vector<Real>>("tuning_max", "Maximum allowable tuning value");
48 514 : return params;
49 0 : }
50 :
51 259 : GaussianProcessTrainer::GaussianProcessTrainer(const InputParameters & parameters)
52 : : SurrogateTrainer(parameters),
53 : CovarianceInterface(parameters),
54 259 : _predictor_row(getPredictorData()),
55 518 : _gp(declareModelData<StochasticTools::GaussianProcess>("_gp")),
56 518 : _training_params(declareModelData<RealEigenMatrix>("_training_params")),
57 518 : _standardize_params(getParam<bool>("standardize_params")),
58 518 : _standardize_data(getParam<bool>("standardize_data")),
59 518 : _do_tuning(isParamValid("tune_parameters")),
60 1295 : _optimization_opts(StochasticTools::GaussianProcess::GPOptimizerOptions(
61 777 : getParam<unsigned int>("show_every_nth_iteration"),
62 518 : getParam<unsigned int>("num_iters"),
63 518 : getParam<unsigned int>("batch_size"),
64 518 : getParam<Real>("learning_rate"))),
65 259 : _sampler_row(getSamplerData())
66 : {
67 : // Error Checking
68 518 : if (parameters.isParamSetByUser("batch_size"))
69 123 : 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 255 : _do_tuning ? getParam<std::vector<std::string>>("tune_parameters")
74 238 : : std::vector<std::string>{});
75 :
76 816 : if (isParamValid("tuning_min") &&
77 357 : (getParam<std::vector<Real>>("tuning_min").size() != tune_parameters.size()))
78 0 : mooseError("tuning_min size does not match tune_parameters");
79 816 : if (isParamValid("tuning_max") &&
80 357 : (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 510 : if (isParamValid("tuning_min"))
85 153 : lower_bounds = getParam<std::vector<Real>>("tuning_min");
86 510 : if (isParamValid("tuning_max"))
87 153 : upper_bounds = getParam<std::vector<Real>>("tuning_max");
88 :
89 255 : _gp.initialize(getCovarianceFunctionByName(parameters.get<UserObjectName>("covariance_function")),
90 : tune_parameters,
91 : lower_bounds,
92 : upper_bounds);
93 :
94 255 : _n_outputs = _gp.getCovarFunction().numOutputs();
95 255 : }
96 :
97 : void
98 357 : GaussianProcessTrainer::preTrain()
99 : {
100 357 : _params_buffer.clear();
101 357 : _data_buffer.clear();
102 357 : _params_buffer.reserve(getLocalSampleSize());
103 357 : _data_buffer.reserve(getLocalSampleSize());
104 357 : }
105 :
106 : void
107 3212 : GaussianProcessTrainer::train()
108 : {
109 3212 : _params_buffer.push_back(_predictor_row);
110 :
111 3212 : 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 3212 : _data_buffer.push_back(_rvecval ? (*_rvecval) : std::vector<Real>(1, *_rval));
119 3212 : }
120 :
121 : void
122 357 : GaussianProcessTrainer::postTrain()
123 : {
124 : // Instead of gatherSum, we have to allgather.
125 357 : _communicator.allgather(_params_buffer);
126 357 : _communicator.allgather(_data_buffer);
127 :
128 357 : _training_params.resize(_params_buffer.size(), _n_dims);
129 357 : _training_data.resize(_data_buffer.size(), _n_outputs);
130 :
131 5321 : for (auto ii : make_range(_training_params.rows()))
132 : {
133 16048 : for (auto jj : make_range(_n_dims))
134 11084 : _training_params(ii, jj) = _params_buffer[ii][jj];
135 10268 : for (auto jj : make_range(_n_outputs))
136 5304 : _training_data(ii, jj) = _data_buffer[ii][jj];
137 : }
138 :
139 : // Standardize (center and scale) training params
140 357 : if (_standardize_params)
141 357 : _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 357 : if (_standardize_data)
148 357 : _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 357 : _gp.setupCovarianceMatrix(_training_params, _training_data, _optimization_opts);
155 357 : }
|