https://mooseframework.inl.gov
PolynomialRegressionTrainer.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 
11 #include "Sampler.h"
12 
14 
17 {
19 
20  params.addClassDescription("Computes coefficients for polynomial regession model.");
21 
22  MooseEnum rtype("ols=0 ridge=1");
24  "regression_type", rtype, "The type of regression to perform.");
25  params.addRequiredParam<unsigned int>("max_degree",
26  "Maximum polynomial degree to use for the regression.");
27  params.addParam<Real>("penalty", 0.0, "Penalty for Ridge regularization.");
28 
29  return params;
30 }
31 
33  : SurrogateTrainer(parameters), // SurrogateTrainer(parameters),
34  _predictor_row(getPredictorData()),
35  _regression_type(getParam<MooseEnum>("regression_type")),
36  _penalty(getParam<Real>("penalty")),
37  _coeff(declareModelData<std::vector<std::vector<Real>>>("_coeff")),
38  _max_degree(
39  declareModelData<unsigned int>("_max_degree", getParam<unsigned int>("max_degree"))),
40  _power_matrix(declareModelData<std::vector<std::vector<unsigned int>>>(
41  "_power_matrix",
42  StochasticTools::MultiDimPolynomialGenerator::generateTuple(_n_dims, _max_degree + 1))),
43  _n_poly_terms(_power_matrix.size()),
44  _matrix(_n_poly_terms, _n_poly_terms),
45  _rhs(1, DenseVector<Real>(_n_poly_terms, 0.0)),
46  _r_sum(1, 0.0)
47 {
48  _coeff.resize(_n_poly_terms);
49 
50  // Throwing a warning if the penalty parameter is set with OLS regression
51  if (_regression_type == "ols" && _penalty != 0)
52  mooseWarning("Penalty parameter is not used for OLS regression, found penalty=", _penalty);
53 
54  // Check if we have enough data points to solve the problem
56  mooseError("Number of data points must be greater than the number of terms in the polynomial.");
57 
58  // Creating calculators needed for feature standardization.
59  _calculators.resize(_n_poly_terms * 3);
60  for (const auto & term : make_range(_n_poly_terms))
61  {
63  _calculators[3 * term + 1] = StochasticTools::makeCalculator(MooseEnumItem("stddev"), *this);
64  _calculators[3 * term + 2] = StochasticTools::makeCalculator(MooseEnumItem("sum"), *this);
65  }
66 }
67 
68 void
70 {
71  _matrix.zero();
72  for (unsigned int r = 0; r < _rhs.size(); ++r)
73  _rhs[r].zero();
74 
76  for (auto & calc : _calculators)
77  calc->initializeCalculator();
78 
79  _r_sum.assign(_rhs.size(), 0.0);
80 }
81 
82 void
84 {
85  // Caching the different powers of data to accelerate the assembly of the
86  // system
87  DenseMatrix<Real> data_pow(_n_dims, _max_degree + 1);
88  for (unsigned int d = 0; d < _n_dims; ++d)
89  for (unsigned int i = 0; i <= _max_degree; ++i)
90  data_pow(d, i) = pow(_predictor_row[d], i);
91 
92  // Emplace new values if necessary
93  if (_rvecval)
94  for (unsigned int r = _rhs.size(); r < _rvecval->size(); ++r)
95  {
96  _rhs.emplace_back(_n_poly_terms, 0.0);
97  _r_sum.emplace_back(0.0);
98  }
99 
100  for (unsigned int i = 0; i < _n_poly_terms; ++i)
101  {
102  Real i_value(1.0);
103  for (unsigned int ii = 0; ii < _n_dims; ++ii)
104  i_value *= data_pow(ii, _power_matrix[i][ii]);
105 
106  for (unsigned int j = 0; j < _n_poly_terms; ++j)
107  {
108  Real j_value(1.0);
109  for (unsigned int jj = 0; jj < _n_dims; ++jj)
110  j_value *= data_pow(jj, _power_matrix[j][jj]);
111 
112  _matrix(i, j) += i_value * j_value;
113  }
114 
115  // Update calculators.
116  for (unsigned int c = i * 3; c < (i + 1) * 3; ++c)
117  _calculators[c]->updateCalculator(i_value);
118 
119  if (_rval)
120  _rhs[0](i) += i_value * (*_rval);
121  else if (_rvecval)
122  for (unsigned int r = 0; r < _rvecval->size(); ++r)
123  _rhs[r](i) += i_value * (*_rvecval)[r];
124  }
125 
126  if (_rval)
127  _r_sum[0] += (*_rval);
128  else if (_rvecval)
129  for (unsigned int r = 0; r < _rvecval->size(); ++r)
130  _r_sum[r] += (*_rvecval)[r];
131 
132  // Adding penalty term for Ridge regularization
133  if (_regression_type == "ridge")
134  for (unsigned int i = 0; i < _n_poly_terms; ++i)
135  _matrix(i, i) += _penalty;
136 }
137 
138 void
140 {
141  // Make sure _rhs are all the same size
142  unsigned int nrval = _rhs.size();
143  gatherMax(nrval);
144  for (unsigned int r = _rhs.size(); r < nrval; ++r)
145  {
146  _rhs.emplace_back(_n_poly_terms, 0.0);
147  _r_sum.emplace_back(0.0);
148  }
149 
150  // Gather regression data
152  for (auto & it : _rhs)
153  gatherSum(it.get_values());
154 
155  // Gather response sums.
156  gatherSum(_r_sum);
157 
158  // Finalize calculators.
159  for (auto & calc : _calculators)
160  calc->finalizeCalculator(true);
161 
162  std::vector<Real> mu(_n_poly_terms);
163  std::vector<Real> sig(_n_poly_terms);
164  std::vector<Real> sum_pf(_n_poly_terms);
165 
166  for (unsigned int i = 0; i < _n_poly_terms; ++i)
167  {
168  // To handle intercept, use mu = 0, sig = 1.
169  mu[i] = i > 0 ? _calculators[3 * i]->getValue() : 0.0;
170  sig[i] = i > 0 ? _calculators[3 * i + 1]->getValue() : 1.0;
171  sum_pf[i] = _calculators[3 * i + 2]->getValue();
172  }
173 
174  // Transform _matrix and _rhs to match standardized features.
175  const Real n = sum_pf[0]; // Sum of intercept term = n.
176  for (unsigned int i = 0; i < _n_poly_terms; ++i)
177  {
178  for (unsigned int j = 0; j < _n_poly_terms; ++j)
179  {
180  _matrix(i, j) -= (mu[j] * sum_pf[i] + mu[i] * sum_pf[j]);
181  _matrix(i, j) += n * mu[i] * mu[j];
182  _matrix(i, j) /= (sig[i] * sig[j]);
183  }
184  for (unsigned int r = 0; r < _rhs.size(); ++r)
185  _rhs[r](i) = (_rhs[r](i) - mu[i] * _r_sum[r]) / sig[i];
186  }
187 
188  DenseVector<Real> sol;
189 
190  _coeff.resize(_rhs.size());
191  for (unsigned int r = 0; r < _rhs.size(); ++r)
192  {
193  _matrix.lu_solve(_rhs[r], sol);
194  _coeff[r] = sol.get_values();
195 
196  // Transform coefficients to match unstandardized features.
197  for (unsigned int i = 1; i < _n_poly_terms; ++i)
198  {
199  _coeff[r][i] /= sig[i];
200  _coeff[r][0] -= _coeff[r][i] * mu[i];
201  }
202  }
203 }
const unsigned int _n_poly_terms
Number of terms in the polynomial expression.
const Real * _rval
Response value.
unsigned int _n_dims
Dimension of predictor data - either _sampler.getNumberOfCols() or _pvals.size() + _pcols...
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
virtual void zero() override final
const std::vector< Real > * _rvecval
Vector response value.
void gatherMax(T &value)
const std::vector< Real > & _predictor_row
Data from the current predictor row.
std::vector< std::unique_ptr< RealCalculator > > _calculators
Calculators used in standardizing polynomial features.
std::vector< std::vector< Real > > & _coeff
Coefficients of regression model.
const Real & _penalty
The penalty parameter for Ridge regularization.
const Number zero
std::vector< Real > _r_sum
Calculator used to sum response values.
void mooseWarning(Args &&... args) const
void addRequiredParam(const std::string &name, const std::string &doc_string)
PolynomialRegressionTrainer(const InputParameters &parameters)
std::unique_ptr< Calculator< InType, OutType > > makeCalculator(const MooseEnumItem &item, const libMesh::ParallelObject &other)
Definition: Calculators.h:335
void gatherSum(T &value)
const std::vector< std::vector< unsigned int > > & _power_matrix
Matirx co containing the touples of the powers for each term.
Enum for batch type in stochastic tools MultiApp.
static const std::string mu
Definition: NS.h:123
const unsigned int & _max_degree
Maximum polynomial degree, limiting the sum of constituent polynomial degrees.
std::vector< Real > & get_values()
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
dof_id_type getNumberOfRows() const
void lu_solve(const DenseVector< Real > &b, DenseVector< Real > &x)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
This is the main trainer base class.
std::vector< DenseVector< Real > > _rhs
const MooseEnum & _regression_type
Types for the polynomial regression.
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
static InputParameters validParams()
static InputParameters validParams()
void ErrorVector unsigned int
registerMooseObject("StochasticToolsApp", PolynomialRegressionTrainer)