MeLOn
Loading...
Searching...
No Matches
svm.h
Go to the documentation of this file.
1/**********************************************************************************
2* Copyright (c) 2020 Process Systems Engineering (AVT.SVT), RWTH Aachen University
3*
4* This program and the accompanying materials are made available under the
5* terms of the Eclipse Public License 2.0 which is available at
6* http://www.eclipse.org/legal/epl-2.0.
7*
8* SPDX-License-Identifier: EPL-2.0
9*
10* @file svm.h
11*
12* @brief File containing declaration of the support vector machine class.
13*
14**********************************************************************************/
15
16#include <vector>
17#include <string>
18#include <cmath>
19#include <memory>
20
21#include "MeLOn.h"
22#include "exceptions.h"
23#include "kernel.h"
24#include "scaler.h"
25#include "vectorarithmetics.h"
26#include "svmData.h"
27#include "svmParser.h"
28
29namespace melon {
30
35 template<typename T>
36 class SupportVectorMachine : public MelonModel<T> {
37 protected:
38 std::shared_ptr<const SvmData> _data;
39 std::unique_ptr<kernel::StationaryKernel<double, T>> _kernel;
41 std::unique_ptr<Scaler<T>> _inputScaler;
42 std::unique_ptr<Scaler<T>> _outputScaler;
49 void _set_data_object(std::shared_ptr<const ModelData> modelData) override;
50
64 T _calculate_prediction(std::vector<T> input, std::vector<T> internalVariables, const bool fullSpace, std::vector<T>& constraints);
65
69 void _update_kernel();
70
78 virtual T _decision_function(std::vector<T> kernelValues) = 0;
79
80 public:
81
85 SupportVectorMachine() : MelonModel<T>(std::make_shared<SvmParserFactory>()) {};
86
92 SupportVectorMachine(std::string modelName) : SupportVectorMachine() { this->load_model(modelName, MODEL_FILE_TYPE::JSON); };
93
101 SupportVectorMachine(std::string modelPath, std::string modelName) : SupportVectorMachine() { this->load_model(modelPath, modelName, MODEL_FILE_TYPE::JSON); };
102
108 SupportVectorMachine(std::shared_ptr<const SvmData> modelData) : SupportVectorMachine() { this->load_model(modelData); };
109
119 void get_fullspace_variables(size_t& variableNumber, std::vector<std::string>& variableNames, std::vector<std::pair<double, double>>& variableBounds);
120
132 T calculate_prediction_full_space(std::vector<T> input, std::vector<T> internalVariables, std::vector<T>& constraints);
133
141 T calculate_prediction_reduced_space(std::vector<T> input);
142
149 };
150
155 template<typename T>
157 private:
158
166 T _decision_function(std::vector<T> input) override;
167 public:
168 // Inherit SupportVectorMachine constructors
170 };
171
176 template<typename T>
178 private:
179
187 T _decision_function(std::vector<T> input) override;
188 public:
189 // Inherit SupportVectorMachine constructors
191
193 // Sets data object containing model parameters.
194 template<typename T>
195 void SupportVectorMachine<T>::_set_data_object(std::shared_ptr<const ModelData> modelData) {
196 // Downcast the ModelData pointer to a SvmData pointer
197 _data = std::dynamic_pointer_cast<const SvmData>(modelData);
198 if (_data == nullptr) {
199 throw(MelonException(" Error while loading support vector machine: Incorrect type of passed data object. The data object must be of type SvmData."));
200 }
201
202 _inputScaler = ScalerFactory<T>::create_scaler(_data->inputScalerData);
203 _outputScaler = ScalerFactory<T>::create_scaler(_data->outputScalerData);
204 _update_kernel();
205 }
206
207
209 // Loads kernel according to loaded internal parameters
210 template<typename T>
212 switch (_data->kernelFunction) {
214 _kernel = std::unique_ptr<kernel::KernelRBF<double, T>>(new kernel::KernelRBF<double, T>(_data->kernelParameters.front()));
215 }
216 }
217
218
220 // Calculates prediction based on inputs and set constraints for fullspace formulation
221 template<typename T>
222 T SupportVectorMachine<T>::calculate_prediction_full_space(std::vector<T> input, std::vector<T> internalVariables, std::vector<T>& constraints) {
223 try{
224 return _calculate_prediction(input, internalVariables, true, constraints);
225 }
226 catch (const std::exception& e) {
227 throw(MelonException(" Encountered a fatal error while evaluating support vector machine. Terminating.", e));
228 }
229 catch (...) {
230 throw(MelonException(" Encountered a fatal error while evaluating support vector machine. Terminating."));
231 }
232
233 }
234
235
237 // Calculates prediction based on inputs in reduced space
238 template<typename T>
240 std::vector<T> dummyInternalVariables;
241 std::vector<T> dummyConstraints;
242 try{
243 return _calculate_prediction(input, dummyInternalVariables, false, dummyConstraints);
244 }
245 catch (const std::exception& e) {
246 throw(MelonException(" Encountered a fatal error while evaluating support vector machine. Terminating.", e));
247 }
248 catch (...) {
249 throw(MelonException(" Encountered a fatal error while evaluating support vector machine. Terminating."));
250 }
251 }
252
253
255 // Calculates prediction
256 template<typename T>
257 T SupportVectorMachine<T>::_calculate_prediction(std::vector<T> input, std::vector<T> internalVariables, const bool fullSpace, std::vector<T>& constraints) {
258
259 // ---------------------------------------------------------------------------------
260 // 0: Check input dimensions
261 // ---------------------------------------------------------------------------------
262
263 if (input.size() != _data->supportVectors.at(0).size()) {
264 throw MelonException(" Error while calculating svm prediction: Incorrect input dimension. In reduced space mode evaluation the size of the variables vector must be equal to the input dimension of the svm.");
265 }
266 if (fullSpace) {
267 size_t variablesSize = get_number_of_full_space_variables();
268 if (internalVariables.size() != variablesSize) {
269 throw MelonException(" Error while calculating svm prediction: Incorrect input dimension. In full space mode evaluation the size of the variables vector be equal to the number of internal variables.");
270 }
271 }
272
273 auto variableIterator = internalVariables.begin();
274 if (this->_modelLoaded) {
275
276 // ---------------------------------------------------------------------------------
277 // 1: Scale inputs
278 // ---------------------------------------------------------------------------------
279
280 std::vector<T> scaledInput = _inputScaler->scale(input);
281 if (fullSpace) {
282 this->_set_constraints(constraints, scaledInput, variableIterator);
283 }
284
285 // ---------------------------------------------------------------------------------
286 // 2: Evaluate kernel for support vectors and input
287 // ---------------------------------------------------------------------------------
288
289 std::vector<T> kernelValues;
290 kernelValues.reserve(_data->supportVectors.size());
291 for (auto& iSupportVector: _data->supportVectors) {
292 T distance = _kernel->calculate_distance(iSupportVector, scaledInput);
293 if (fullSpace) {
294 this->_set_constraints(constraints, distance, variableIterator);
295 }
296
297 T kernelValue = _kernel->evaluate_kernel(distance);
298 if (fullSpace) {
299 this->_set_constraints(constraints, kernelValue, variableIterator);
300 }
301
302 kernelValues.push_back(kernelValue);
303 }
304
305 // ---------------------------------------------------------------------------------
306 // 3: Evaluate decision function
307 // ---------------------------------------------------------------------------------
308
309 T result = _decision_function(kernelValues);
310 if (fullSpace) {
311 this->_set_constraints(constraints, result, variableIterator);
312 }
313
314 // ---------------------------------------------------------------------------------
315 // 4: Descale ouput
316 // ---------------------------------------------------------------------------------
317
318 T output = _outputScaler->descale({ result }).front();
319 if (fullSpace) {
320 this->_set_constraints(constraints, output, variableIterator);
321 }
322
323 return output;
324 }
325 else {
326 throw MelonException{ " Error while calculating support vector machine prediction: No model was loaded yet." };
327 }
328 }
329
330
332 // Decision function for support vector regression.
333 template<typename T>
335 return dot_product(this->_data->dualCoefficients, input) + this->_data->rho;
336 }
337
338
340 // Decision function for one class support vector machine.
341 template<typename T>
343 return dot_product(this->_data->dualCoefficients, input) + this->_data->rho;
344 }
345
346
348 // Calculates the number of full space variables.
349 template<typename T>
351 size_t variableNumber;
352 std::vector<std::string> variableNames;
353 std::vector<std::pair<double, double>> variableBounds;
354 get_fullspace_variables(variableNumber, variableNames, variableBounds);
355 return variableNumber;
356 }
357
358
360 // Creates variables for the full space formulation in MAiNGO.
361 template<typename T>
362 void SupportVectorMachine<T>::get_fullspace_variables(size_t& variableNumber, std::vector<std::string>& variableNames, std::vector<std::pair<double, double>>& variableBounds) {
363
364 variableNumber = 0;
365 variableNames.clear();
366 variableBounds.clear();
367
368
369 // get max squared distance between support vectors
370 auto n = this->_data->supportVectors.at(0).size();
371 auto lbs = std::vector<double>(n, 1e6);
372 auto ubs = std::vector<double>(n, -1e6);
373 for (auto iSupportVector : this->_data->supportVectors) {
374 for (int i = 0; i < iSupportVector.size(); i++) {
375 auto xi = iSupportVector[i];
376 if (xi < lbs[i]) lbs[i] = xi;
377 if (xi > ubs[i]) ubs[i] = xi;
378 }
379 }
380 double maxSquaredDistance = 0;
381 for (size_t i = 0; i < lbs.size(); i++) {
382 maxSquaredDistance = maxSquaredDistance + (ubs[i] - lbs[i])*(ubs[i] - lbs[i]);
383 }
384
385 //std::cout << "Hint: Using max squared distance = " << maxSquaredDistance << "\n\n\n";
386
387 variableNumber += 2 * _data->dualCoefficients.size();
388 for (int i = 0; i < _data->dualCoefficients.size(); i++) {
389 variableNames.push_back("squared_distance_" + std::to_string(i));
390 variableNames.push_back("kernel_value_" + std::to_string(i));
391 variableBounds.push_back(std::make_pair(0., maxSquaredDistance));
392 variableBounds.push_back(std::make_pair(0., 1.0));
393 }
394
395 double sum_alpha = 0;
396 for (auto alpha : this->_data->dualCoefficients) {
397 sum_alpha = sum_alpha + alpha;
398 }
399
400 variableNames.push_back("prediction");
401 if (this->_data->kernelFunction == RBF) {
402 variableBounds.push_back(std::make_pair(0, (sum_alpha - this->_data->rho)));
403 }
404 else {
405 variableBounds.push_back(std::make_pair(-1e6, 1e6));
406
407 }
408 variableNumber++;
409 }
410}
This class defines the exceptions thrown by FeedForwardNet.
Definition exceptions.h:32
Definition MeLOn.h:32
void load_model(std::string modelName, MODEL_FILE_TYPE fileType)
Loads new model from file.
Definition MeLOn.h:114
static std::unique_ptr< Scaler< T > > create_scaler(const std::shared_ptr< const ScalerData > scalerData)
Factory function for creating a instance of a scaler object.
Definition scaler.h:208
Class defining support vector machine to be used in the MAiNGO solver.
Definition svm.h:36
size_t get_number_of_full_space_variables()
Calculates the number of full space variables.
Definition svm.h:350
SupportVectorMachine()
Default Constructor.
Definition svm.h:85
SupportVectorMachine(std::string modelName)
Constructor.
Definition svm.h:92
void get_fullspace_variables(size_t &variableNumber, std::vector< std::string > &variableNames, std::vector< std::pair< double, double > > &variableBounds)
Creates variables for the full space formulation in MAiNGO.
Definition svm.h:362
SupportVectorMachine(std::string modelPath, std::string modelName)
Constructor.
Definition svm.h:101
void _update_kernel()
Loads kernel according to loaded internal parameters.
Definition svm.h:211
std::unique_ptr< Scaler< T > > _outputScaler
Definition svm.h:42
T calculate_prediction_full_space(std::vector< T > input, std::vector< T > internalVariables, std::vector< T > &constraints)
Calculates prediction based on inputs and set constraints for fullspace formulation.
Definition svm.h:222
std::shared_ptr< const SvmData > _data
Definition svm.h:38
virtual T _decision_function(std::vector< T > kernelValues)=0
Decision function used by the different types of svms.
T _calculate_prediction(std::vector< T > input, std::vector< T > internalVariables, const bool fullSpace, std::vector< T > &constraints)
Calculates prediction.
Definition svm.h:257
void _set_data_object(std::shared_ptr< const ModelData > modelData) override
Sets data object containing model parameters.
Definition svm.h:195
std::unique_ptr< Scaler< T > > _inputScaler
Definition svm.h:41
std::unique_ptr< kernel::StationaryKernel< double, T > > _kernel
Definition svm.h:39
T calculate_prediction_reduced_space(std::vector< T > input)
Calculates prediction based on inputs in reduced space.
Definition svm.h:239
SupportVectorMachine(std::shared_ptr< const SvmData > modelData)
Constructor.
Definition svm.h:108
Class defining support vector machine for one class classification to be used in the MAiNGO solver.
Definition svm.h:177
T _decision_function(std::vector< T > input) override
Decision function for one class support vector machine.
Definition svm.h:342
Class defining support vector machine for regression to be used in the MAiNGO solver.
Definition svm.h:156
T _decision_function(std::vector< T > input) override
Decision function for support vector regression.
Definition svm.h:334
This class is a factory class for creating child instances of SvmParser.
Definition svmParser.h:74
Implementation of Radial Basis Function kernel.
Definition kernel.h:230
Definition kernel.h:21
@ JSON
Definition modelParser.h:33
auto dot_product(const std::vector< T > &v1, const std::vector< U > &v2)
Overloaded operator for vector class allowing the calulation of dot product of two vectors.
Definition vectorarithmetics.h:155
@ RBF
Definition svmData.h:32