cMHN 1.0
C++ library for learning MHNs with pRC
learn_theta.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-2-Clause
2
3#ifndef cMHN_TT_LEARN_THETA_H
4#define cMHN_TT_LEARN_THETA_H
5
6#include <iostream>
7#include <map>
8#include <string>
9#include <tuple>
10
12#include <cmhn/tt/als.hpp>
13#include <cmhn/tt/mamen.hpp>
15#include <cmhn/tt/utility.hpp>
19
20#include <prc.hpp>
21
22namespace cMHN::TT
23{
56 template<pRC::Size RP, pRC::Size RQ, class T, pRC::Size D, class S>
57 std::tuple<pRC::Tensor<T, D, D>,
58 std::map<std::string, std::string>,
59 std::map<std::string, double>>
60 learnTheta(pRC::Tensor<T, D, D> const &theta,
61 std::string const &header, std::string const &output,
62 std::map<S, T> const &pD, cMHN::Score<T> const &Score,
63 cMHN::Regulator<T, D> const &Regulator, T const &toleranceOptimizer,
64 T const &toleranceSolverP, T const &toleranceSolverQ)
65 {
66 using ModeSizes = decltype(getModeSizes<D>());
67
68 auto tempTheta = theta;
69
70 T score = pRC::zero();
71
72 pRC::Index at_iter = 0;
73
74 pRC::Float<64> startTime = pRC::getTimeInSeconds();
75
76 std::map<std::string, double> logInfoNumbers{{"Score", score()},
77 {"Iterations", at_iter},
78 {"Time", pRC::getTimeInSeconds()() - startTime()},
79 {"Lambda", Regulator.lambda()()}};
80
81 std::map<std::string, std::string> logInfoNames{
82 {"Score Name", Score.name()}, {"Regulator Name", Regulator.name()}};
83
84 writeTheta(output, header, tempTheta, logInfoNames, logInfoNumbers);
85
86 std::cout << "cMHN learning started (TT):" << std::endl;
87 std::cout << "\tScore Name:\t" << logInfoNames["Score Name"]
88 << std::endl;
89 std::cout << "\tRegulator Name:\t" << logInfoNames["Regulator Name"]
90 << std::endl
91 << std::endl;
92
93 // get first pInit
94 pRC::SeedSequence seq(8, 16);
95 pRC::RandomEngine rng(seq);
96 pRC::GaussianDistribution<pRC::Float<>> dist;
97 auto pInit = round<decltype(getRanks<D, RP>())>(pRC::random<pRC::TensorTrain::Tensor
98 <T, ModeSizes, decltype(getRanks<D, RP>())>>(rng, dist));
99 pInit = pInit / norm(pInit);
100
101 tempTheta = pRC::optimize<pRC::Optimizer::BFGS<>>(
102 tempTheta,
103 [&output, &at_iter, &score, &pD, &Score, &Regulator, &pInit,
104 &toleranceOptimizer, &toleranceSolverP, &toleranceSolverQ](
105 pRC::Tensor<T, D, D> const &tempTheta, pRC::Tensor<T, D, D> &g)
106 {
107 MHNOperator<T, D> op(tempTheta);
108
109 auto const pTheta =
110 ::cMHN::calculatePTheta<RP>(op, pInit, toleranceSolverP);
111
112 // use this pTheta as the next pInit
113 pInit = pTheta;
114
115 g = pRC::zero();
116 score = pRC::zero();
117
118 T scoreT = pRC::zero();
119 pRC::Tensor<T, D, D> gT = pRC::zero();
120#if defined(_OPENMP)
121 #pragma omp declare reduction(+: T, pRC::Tensor<T, D, D>: omp_out = omp_in + omp_out) \
122 initializer (omp_priv(pRC::Zero()))
123 #pragma omp parallel for schedule(dynamic, 10) reduction(+ : scoreT, gT)
124#endif // _OPENMP
125 for(pRC::Index s = 0; s < pD.size(); ++s)
126 {
127 auto it = pD.cbegin();
128 std::advance(it, s);
129 auto const [k, v] = *it;
130 auto const pThetaE = pTheta(k);
131
132 scoreT += Score.pointwiseScore(v, pThetaE);
133
134 auto const rhs =
135 pRC::TensorTrain::Tensor<T, ModeSizes>::Single(
136 pRC::identity<T>(), k);
137
138 // solve (1-Q)T * q = rhs
139 auto const q = ALS<RQ, pRC::Operator::Transform::Transpose>(
140 op, rhs, toleranceSolverQ);
141
142 pRC::Tensor<T, D, D> tmp = pRC::zero();
143 for(pRC::Index i = 0; i < D; ++i)
144 {
145 for(pRC::Index j = 0; j < D; ++j)
146 {
147 tmp(i, j) = -Score.pointwiseDSDP(v, pThetaE) *
148 scalarProduct(q,
149 op.derivative(i, j) * pTheta)();
150 }
151 }
152
153 gT += tmp;
154 }
155
156 score += scoreT;
157 g += gT;
158
159 // signs b/c pRC::Optimmizer::BFGS minimizes the score function
160 g = Regulator.grad(tempTheta) - g;
161 return Regulator.score(tempTheta) - score;
162 },
163 [&output, &header, &score, &at_iter, &startTime, &logInfoNames,
164 &logInfoNumbers](auto const &tempTheta)
165 {
166 logInfoNumbers["Iterations"] = at_iter;
167 logInfoNumbers["Score"] = score();
168 logInfoNumbers["Time"] =
169 pRC::getTimeInSeconds()() - startTime();
170
171 std::cout << "cMHN learning in progress (TT):" << std::endl;
172 std::cout << std::defaultfloat;
173 std::cout << "\tIteration:\t" << logInfoNumbers["Iterations"]
174 << std::endl;
175 std::cout << std::scientific;
176 std::cout << "\tLambda:\t\t" << logInfoNumbers["Lambda"]
177 << std::endl;
178 std::cout << "\tScore:\t\t" << logInfoNumbers["Score"]
179 << std::endl;
180 std::cout << "\tTime:\t\t" << logInfoNumbers["Time"]
181 << std::endl;
182 std::cout << std::defaultfloat;
183
184 writeTheta(output, header, tempTheta, logInfoNames,
185 logInfoNumbers);
186 at_iter++;
187 },
188 toleranceOptimizer);
189
190 return std::make_tuple(tempTheta, logInfoNames, logInfoNumbers);
191 }
192}
193
194#endif // cMHN_TT_LEARN_THETA_H
pRC::Size const D
Definition: CalculatePThetaTests.cpp:9
Class storing all relevant information for a regulator.
Definition: regulator.hpp:30
auto & lambda()
Definition: regulator.hpp:58
auto grad(pRC::Tensor< T, D, D > const &theta) const
Definition: regulator.hpp:53
auto name() const
Definition: regulator.hpp:68
auto score(pRC::Tensor< T, D, D > const &theta) const
Definition: regulator.hpp:48
Class storing all relevant information for a score.
Definition: score.hpp:27
auto pointwiseScore(T const &pDE, T const &pThetaE) const
Definition: score.hpp:44
auto name() const
Definition: score.hpp:54
auto pointwiseDSDP(T const &pDE, T const &pThetaE) const
Definition: score.hpp:49
Class storing an MHN operator represented by a theta matrix (for TT calculations)
Definition: mhn_operator.hpp:23
constexpr auto derivative(pRC::Index const i, pRC::Index const j) const
Definition: mhn_operator.hpp:76
pRC::Float<> T
Definition: externs_nonTT.hpp:1
Definition: als.hpp:12
std::tuple< pRC::Tensor< T, D, D >, std::map< std::string, std::string >, std::map< std::string, double > > learnTheta(pRC::Tensor< T, D, D > const &theta, std::string const &header, std::string const &output, std::map< S, T > const &pD, cMHN::Score< T > const &Score, cMHN::Regulator< T, D > const &Regulator, T const &toleranceOptimizer, T const &toleranceSolverP, T const &toleranceSolverQ)
Optimizes an MHN represented by a theta matrix to best describe a given data distribution using the T...
Definition: learn_theta.hpp:60
static auto writeTheta(std::string const &filename, std::string const &header, pRC::Tensor< T, D, D > const &theta, std::map< std::string, std::string > const &logInfoNames={}, std::map< std::string, double > const &logInfoNumbers={})
Writes a theta matrix to file, including additional logging information at the bottom.
Definition: write_theta.hpp:29