Krotos Modules 3
Loading...
Searching...
No Matches
LinearModel.cpp
Go to the documentation of this file.
1
2#include "LinearModel.h"
3
4namespace krotos
5{
6
7 LinearModel::LinearModel(const std::vector<Eigen::MatrixXf>& weights, const std::vector<Eigen::VectorXf>& biases,
8 const Eigen::MatrixXf& weightsOutput, const Eigen::VectorXf& biasOutput,
9 const StringArray& categories)
10 : m_weights(weights), m_bias(biases), m_weightsOutput(weightsOutput), m_biasOutput(biasOutput),
11 m_outputCategories(categories)
12 {
13 // get number of layers
14 m_numLayers = m_weights.size();
15
16 // get the size of each layer
17 m_layerSize = m_weights[0].rows();
18
19 // resize layer outputs
21
22 for (auto& layerOut : m_layerOutput)
23 {
24 layerOut.resize(m_layerSize);
25 }
26 // resize outputs to the size of output categories
27 m_outputs.resize(categories.size());
28
29 // resize working buffer
31 }
32
34
35Eigen::VectorXf LinearModel::infer(const Eigen::VectorXf& input)
36{
37 // input should be same size as the input layer weights
38 jassert(input.size() == m_layerSize);
39
40 // add activation here if needed (use working buffer):
41 m_workingBuffer = m_weights[0].transpose() * input + m_bias[0];
43
44 for (int i = 1; i < m_numLayers; i++)
45 {
46 m_layerOutput[i] = m_weights[0] * m_layerOutput[i - 1] + m_bias[i];
47 }
48
49 // // calculate output layer
51
52 // apply activation
54
55 // get index of the max element
56 auto maxElementIter = std::max_element(m_outputs.data(), m_outputs.data() + m_outputs.size());
57 int maxIdx = std::distance(m_outputs.data(), maxElementIter);
58
60
61 return m_outputs;
62}
63
64Eigen::VectorXf LinearModel::inferSingle(const Eigen::VectorXf& input)
65{
66 // input should be same size as the input layer weights
67 jassert(input.size() == m_layerSize);
68
69 m_workingBuffer = m_weights[0] * input + m_bias[0];
71
72 // get index of the max element
73 auto maxElementIter = std::max_element(m_outputs.data(), m_outputs.data() + m_outputs.size());
74 int maxIdx = std::distance(m_outputs.data(), maxElementIter);
75
77
78 return m_outputs;
79}
80
82{
83 // load json from binary data
84 const char* jsonBinaryData = reinterpret_cast<const char*>(KrotosBinaryData::logistic_regression_json);
85
86 // convert to string
87 String jsonString(jsonBinaryData);
88
89 // and parse it
90 auto parsedData = JSON::parse(jsonString);
91
92 if (!parsedData.isVoid())
93 {
94 auto* object = parsedData.getDynamicObject();
95
96 // keep weights in a var
97 Array<var> weightsAllLayers;
98 Array<var> biasesAllLayers;
99
100 // keys for bias and weights
101 StringArray weightKeys;
102 StringArray biasKeys;
103
104 // iterate to get layer key
105 for (auto& prop : object->getProperties())
106 {
107 // property name to string
108 String propertyName = prop.name.toString();
109 if (propertyName.contains("weight"))
110 {
111 weightKeys.add(propertyName);
112 }
113 else if (propertyName.contains("bias"))
114 {
115 biasKeys.add(propertyName);
116 }
117 }
118
119 // the number of layers is equal to the weight keys size
120 m_numLayers = weightKeys.size();
121
122 // load weights and biases for each layer
123 for (auto& weightLayerName : weightKeys)
124 {
125 // array to keep the current layer from json data
126 m_weightsVar = object->getProperty(weightLayerName);
127
128 if (m_weightsVar.isArray())
129 {
130 weightsAllLayers.add(m_weightsVar);
131 }
132 }
133
134 // load biases for each layer
135 for (auto& biasLayerName : biasKeys)
136 {
137 // array to keep the current layer from json data
138 juce::var bias = object->getProperty(biasLayerName);
139
140 if (bias.isArray())
141 {
142 // get size
143 int biasVecSize = bias.size();
144
145 // the temporary eigen vector
146 Eigen::VectorXf biasVec(biasVecSize);
147 for (int i = 0; i < biasVecSize; i++)
148 {
149 biasVec[i] = bias[i];
150 }
151 // add to m_bias
152 m_bias.push_back(biasVec);
153 }
154 }
155
156 // Weights ..
157 for (const auto& weights : weightsAllLayers)
158 {
159 if (weights.isArray())
160 {
161 // convert to eigen representations and pass it to member variable
162 int numRows = weights.getArray()->size();
163 int numCols = weights.getArray()->begin()->getArray()->size();
164 if (numCols == 0 || numRows == 0)
165 {
166 continue;
167 }
168 m_layerSize = numCols;
169 // Create an Eigen matrix with the appropriate size
170 Eigen::MatrixXf weightsMatrix(numRows, numCols);
171 for (int i = 0; i < numRows; i++)
172 {
173 for (int j = 0; j < numCols; j++)
174 {
175 weightsMatrix(i, j) =
176 static_cast<double>(weights.getArray()->getUnchecked(i).getArray()->getUnchecked(j));
177 }
178 }
179 // // and push it back to m_weights
180 m_weights.push_back(weightsMatrix);
181 }
182 }
183
184 // get categories
185 auto categories = object->getProperty("classes");
186 for (auto& cat : *categories.getArray())
187 {
188 m_outputCategories.add(cat.toString());
189 }
190 }
191}
192
194{
195 return m_outputCategories;
196}
197
198Eigen::VectorXf LinearModel::sigmoid(const Eigen::VectorXf& lOut) { return 1.0 / (1.0 + (-lOut.array()).exp()); }
199
200Eigen::VectorXf LinearModel::relu(const Eigen::VectorXf& lOut) { return lOut.array().max(0.0); }
201
206
207
208} // namespace krotos
Eigen::VectorXf relu(const Eigen::VectorXf &lOut)
relu activation function
Definition LinearModel.cpp:200
Eigen::VectorXf m_outputs
Definition LinearModel.h:72
void loadModelData()
Definition LinearModel.cpp:81
Eigen::VectorXf m_workingBuffer
Definition LinearModel.h:88
Eigen::VectorXf infer(const Eigen::VectorXf &input)
infers the model to predict output
Definition LinearModel.cpp:35
std::vector< Eigen::VectorXf > m_layerOutput
Definition LinearModel.h:69
int m_layerSize
Definition LinearModel.h:78
std::vector< Eigen::VectorXf > m_bias
Definition LinearModel.h:60
Eigen::MatrixXf m_weightsOutput
Definition LinearModel.h:57
Eigen::VectorXf inferSingle(const Eigen::VectorXf &input)
Definition LinearModel.cpp:64
Eigen::VectorXf m_biasOutput
Definition LinearModel.h:63
StringArray m_outputCategories
Definition LinearModel.h:66
std::vector< Eigen::MatrixXf > m_weights
Definition LinearModel.h:54
LinearModel()
Constructor for the linear model, this will automatically load a model that is expected to exist in t...
Definition LinearModel.cpp:33
StringArray getOutputCategories()
returns the output categories
Definition LinearModel.cpp:193
int m_numLayers
Definition LinearModel.h:75
String getProminentCategory()
returns the prominent category name
Definition LinearModel.cpp:202
var m_weightsVar
Definition LinearModel.h:84
Eigen::VectorXf sigmoid(const Eigen::VectorXf &lOut)
sigmoid activation function
Definition LinearModel.cpp:198
int m_prominentCategoryIndex
Definition LinearModel.h:91
Definition AirAbsorptionFilter.cpp:2