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 "Standardizer.h"
12 :
13 : namespace StochasticTools
14 : {
15 :
16 : namespace
17 : {
18 :
19 : void
20 402809 : checkInputCompatibility(const torch::Tensor & input, const torch::Tensor & reference)
21 : {
22 402809 : if (input.dim() != 2)
23 0 : mooseError("Standardizer input must be a rank-2 tensor.");
24 402809 : if (reference.dim() != 1)
25 0 : mooseError("Standardizer moments must be stored as feature vectors.");
26 402809 : if (input.size(1) != reference.size(0))
27 0 : mooseError("Standardizer input dimension mismatch.");
28 402809 : }
29 :
30 : torch::Tensor
31 671617 : toStandardizerOptions(const torch::Tensor & tensor, const torch::TensorOptions & options)
32 : {
33 671617 : auto result = tensor.to(options.device());
34 671617 : if (result.scalar_type() != at::kDouble)
35 0 : result = result.to(at::kDouble);
36 671617 : return result;
37 : }
38 :
39 : torch::Tensor
40 671617 : asFeatureVector(const torch::Tensor & feature_vector, const torch::Tensor & input)
41 : {
42 671617 : return toStandardizerOptions(feature_vector, input.options().dtype(at::kDouble));
43 : }
44 :
45 : } // namespace
46 :
47 : void
48 176 : Standardizer::set(const Real & n)
49 : {
50 352 : _mean = torch::zeros({long(n)}, at::kDouble);
51 176 : _stdev = torch::ones({long(n)}, at::kDouble);
52 176 : }
53 :
54 : void
55 0 : Standardizer::set(const Real & mean, const Real & stdev)
56 : {
57 0 : _mean = torch::full({1}, mean, at::kDouble);
58 0 : _stdev = torch::full({1}, stdev, at::kDouble);
59 0 : }
60 :
61 : void
62 0 : Standardizer::set(const Real & mean, const Real & stdev, const Real & n)
63 : {
64 : auto options = torch::TensorOptions().dtype(at::kDouble);
65 0 : _mean = torch::full({long(n)}, mean, options);
66 0 : _stdev = torch::full({long(n)}, stdev, options);
67 0 : }
68 :
69 : void
70 80 : Standardizer::set(const std::vector<Real> & mean, const std::vector<Real> & stdev)
71 : {
72 : mooseAssert(mean.size() == stdev.size(),
73 : "Provided mean and standard deviation vectors are of differing size.");
74 160 : _mean = LibtorchUtils::vectorToTensorCopy(mean, {long(mean.size())});
75 80 : _stdev = LibtorchUtils::vectorToTensorCopy(stdev, {long(stdev.size())});
76 80 : }
77 :
78 : void
79 806 : Standardizer::computeSet(const torch::Tensor & input)
80 : {
81 806 : if (input.dim() != 2)
82 0 : mooseError("Standardizer input must be a rank-2 tensor.");
83 : // Compute mean and standard deviation
84 806 : _mean = torch::mean(input, 0, false);
85 806 : _stdev = torch::std(input, 0, 0, false);
86 806 : }
87 :
88 : void
89 134807 : Standardizer::getStandardized(torch::Tensor & input) const
90 : {
91 134807 : checkInputCompatibility(input, _mean);
92 539228 : input.sub_(asFeatureVector(_mean, input)).div_(asFeatureVector(_stdev, input));
93 134807 : }
94 :
95 : void
96 134001 : Standardizer::getDestandardized(torch::Tensor & input) const
97 : {
98 134001 : checkInputCompatibility(input, _mean);
99 402003 : input.mul_(asFeatureVector(_stdev, input)).add_(asFeatureVector(_mean, input));
100 134001 : }
101 :
102 : void
103 134001 : Standardizer::getDescaled(torch::Tensor & input) const
104 : {
105 134001 : checkInputCompatibility(input, _stdev);
106 134001 : input.mul_(asFeatureVector(_stdev, input));
107 134001 : }
108 :
109 : void
110 0 : Standardizer::getScaled(torch::Tensor & input) const
111 : {
112 0 : checkInputCompatibility(input, _stdev);
113 0 : input.div_(asFeatureVector(_stdev, input));
114 0 : }
115 :
116 : /// Helper for dataStore
117 : void
118 116 : Standardizer::storeHelper(std::ostream & stream, void * context) const
119 : {
120 116 : const auto mean = LibtorchUtils::toCPUContiguous(_mean);
121 116 : const auto stdev = LibtorchUtils::toCPUContiguous(_stdev);
122 116 : auto mean_accessor = mean.accessor<Real, 1>();
123 116 : auto stdev_accessor = stdev.accessor<Real, 1>();
124 116 : unsigned int n = mean.size(0);
125 : dataStore(stream, n, context);
126 320 : for (unsigned int ii = 0; ii < n; ++ii)
127 204 : dataStore(stream, mean_accessor[ii], context);
128 320 : for (unsigned int ii = 0; ii < n; ++ii)
129 204 : dataStore(stream, stdev_accessor[ii], context);
130 116 : }
131 :
132 : } // StochasticTools namespace
133 :
134 : template <>
135 : void
136 116 : dataStore(std::ostream & stream, StochasticTools::Standardizer & standardizer, void * context)
137 : {
138 116 : standardizer.storeHelper(stream, context);
139 116 : }
140 :
141 : template <>
142 : void
143 64 : dataLoad(std::istream & stream, StochasticTools::Standardizer & standardizer, void * context)
144 : {
145 : unsigned int n;
146 : dataLoad(stream, n, context);
147 64 : std::vector<Real> mean(n);
148 64 : std::vector<Real> stdev(n);
149 184 : for (unsigned int ii = 0; ii < n; ++ii)
150 120 : dataLoad(stream, mean[ii], context);
151 184 : for (unsigned int ii = 0; ii < n; ++ii)
152 120 : dataLoad(stream, stdev[ii], context);
153 64 : standardizer.set(mean, stdev);
154 64 : }
155 :
156 : #endif
|