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