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 "ActiveLearningGPDecision.h"
11 : #include "Sampler.h"
12 : #include "AdaptiveMonteCarloUtils.h"
13 :
14 : #include <math.h>
15 :
16 : registerMooseObject("StochasticToolsApp", ActiveLearningGPDecision);
17 :
18 : InputParameters
19 228 : ActiveLearningGPDecision::validParams()
20 : {
21 228 : InputParameters params = ActiveLearningReporterTempl<Real>::validParams();
22 228 : params.addClassDescription(
23 : "Evaluates a GP surrogate model, determines its prediction quality, "
24 : "launches full model if GP prediction is inadequate, and retrains GP.");
25 456 : MooseEnum learning_function("Ufunction COV");
26 456 : params.addRequiredParam<MooseEnum>(
27 : "learning_function", learning_function, "The learning function for active learning.");
28 456 : params.addRequiredParam<Real>("learning_function_threshold", "The learning function threshold.");
29 456 : params.addParam<Real>("learning_function_parameter",
30 456 : std::numeric_limits<Real>::max(),
31 : "The learning function parameter.");
32 456 : params.addRequiredParam<UserObjectName>("al_gp", "Active learning GP trainer.");
33 456 : params.addRequiredParam<UserObjectName>("gp_evaluator", "Evaluate the trained GP.");
34 456 : params.addRequiredParam<SamplerName>("sampler", "The sampler object.");
35 456 : params.addParam<ReporterValueName>("flag_sample", "flag_sample", "Flag samples.");
36 456 : params.addRequiredParam<int>("n_train", "Number of training steps.");
37 456 : params.addParam<ReporterValueName>("inputs", "inputs", "The inputs.");
38 456 : params.addParam<ReporterValueName>("gp_mean", "gp_mean", "The GP mean prediction.");
39 456 : params.addParam<ReporterValueName>("gp_std", "gp_std", "The GP standard deviation.");
40 228 : return params;
41 228 : }
42 :
43 114 : ActiveLearningGPDecision::ActiveLearningGPDecision(const InputParameters & parameters)
44 : : ActiveLearningReporterTempl<Real>(parameters),
45 : SurrogateModelInterface(this),
46 114 : _learning_function(getParam<MooseEnum>("learning_function")),
47 228 : _learning_function_threshold(getParam<Real>("learning_function_threshold")),
48 228 : _learning_function_parameter(getParam<Real>("learning_function_parameter")),
49 114 : _al_gp(getUserObject<ActiveLearningGaussianProcess>("al_gp")),
50 114 : _gp_eval(getSurrogateModel<GaussianProcessSurrogate>("gp_evaluator")),
51 114 : _flag_sample(declareValue<std::vector<bool>>(
52 114 : "flag_sample", std::vector<bool>(sampler().getNumberOfRows(), false))),
53 228 : _n_train(getParam<int>("n_train")),
54 114 : _inputs(declareValue<std::vector<std::vector<Real>>>(
55 : "inputs",
56 228 : std::vector<std::vector<Real>>(sampler().getNumberOfRows(),
57 228 : std::vector<Real>(sampler().getNumberOfCols())))),
58 114 : _gp_mean(
59 228 : declareValue<std::vector<Real>>("gp_mean", std::vector<Real>(sampler().getNumberOfRows()))),
60 114 : _gp_std(
61 228 : declareValue<std::vector<Real>>("gp_std", std::vector<Real>(sampler().getNumberOfRows()))),
62 114 : _decision(true),
63 114 : _inputs_global(getGlobalInputData()),
64 228 : _outputs_global(getGlobalOutputData())
65 : {
66 212 : if (_learning_function == "Ufunction" &&
67 310 : !parameters.isParamSetByUser("learning_function_parameter"))
68 0 : paramError("learning_function",
69 : "The Ufunction requires the model failure threshold ('learning_function_parameter') "
70 : "to be specified.");
71 114 : }
72 :
73 : bool
74 2294 : ActiveLearningGPDecision::learningFunction(const Real & gp_mean, const Real & gp_std) const
75 : {
76 2294 : if (_learning_function == "Ufunction")
77 2054 : return (std::abs(gp_mean - _learning_function_parameter) / gp_std) >
78 2054 : _learning_function_threshold;
79 240 : else if (_learning_function == "COV")
80 240 : return (gp_std / std::abs(gp_mean)) < _learning_function_threshold;
81 : else
82 0 : mooseError("Invalid learning function ", std::string(_learning_function));
83 : return false;
84 : }
85 :
86 : void
87 870 : ActiveLearningGPDecision::setupData(const std::vector<std::vector<Real>> & inputs,
88 : const std::vector<Real> & outputs)
89 : {
90 870 : _inputs_batch.insert(_inputs_batch.end(), inputs.begin(), inputs.end());
91 870 : _outputs_batch.insert(_outputs_batch.end(), outputs.begin(), outputs.end());
92 870 : }
93 :
94 : bool
95 1324 : ActiveLearningGPDecision::facilitateDecision()
96 : {
97 2948 : for (dof_id_type i = 0; i < _inputs.size(); ++i)
98 : {
99 1624 : _gp_mean[i] = _gp_eval.evaluate(_inputs[i], _gp_std[i]);
100 1624 : _flag_sample[i] = !learningFunction(_gp_mean[i], _gp_std[i]);
101 : }
102 :
103 1324 : for (const auto & fs : _flag_sample)
104 1344 : if (!fs)
105 : return false;
106 : return true;
107 : }
108 :
109 : void
110 1828 : ActiveLearningGPDecision::preNeedSample()
111 : {
112 : // Accumulate inputs and outputs if we previously decided we needed a sample
113 1828 : if (_t_step > 1 && _decision)
114 : {
115 : // Accumulate data into _batch members
116 600 : setupData(_inputs, _outputs_global);
117 :
118 : // Retrain if we are outside the training phase
119 600 : if (_t_step > _n_train)
120 196 : _al_gp.reTrain(_inputs_batch, _outputs_batch);
121 : }
122 :
123 : // Gather inputs for the current step
124 1828 : _inputs = _inputs_global;
125 :
126 : // Evaluate GP and decide if we need more data if outside training phase
127 1828 : if (_t_step > _n_train)
128 1324 : _decision = facilitateDecision();
129 1828 : }
130 :
131 : bool
132 1300 : ActiveLearningGPDecision::needSample(const std::vector<Real> &,
133 : dof_id_type,
134 : dof_id_type global_ind,
135 : Real & val)
136 : {
137 1300 : if (!_decision)
138 870 : val = _gp_mean[global_ind];
139 1300 : return _decision;
140 : }
|