Line data Source code
1 : /************************************************************************* 2 : * 3 : * Project 4 : * _____ _____ __ __ _____ 5 : * / ____| __ \| \/ | __ \ 6 : * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) | 7 : * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/ 8 : *| (_) | |_) | __/ | | | |__| | | | | | | | 9 : * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_| 10 : * | | 11 : * |_| 12 : * 13 : * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al. 14 : * 15 : * This software is licensed as described in the file LICENSE, which 16 : * you should have received as part of this distribution. The terms 17 : * among other details are referenced in the official documentation 18 : * seen here : https://akielaries.github.io/openGPMP/ along with 19 : * important files seen in this project. 20 : * 21 : * You may opt to use, copy, modify, merge, publish, distribute 22 : * and/or sell copies of the Software, and permit persons to whom 23 : * the Software is furnished to do so, under the terms of the 24 : * LICENSE file. As this is an Open Source effort, all implementations 25 : * must be of the same methodology. 26 : * 27 : * 28 : * 29 : * This software is distributed on an AS IS basis, WITHOUT 30 : * WARRANTY OF ANY KIND, either express or implied. 31 : * 32 : ************************************************************************/ 33 : #include <cmath> 34 : #include <cstdlib> 35 : #include <iostream> 36 : #include <openGPMP/ml/kohonen_net.hpp> 37 : 38 0 : gpmp::ml::KohonenNet::KohonenNet(int in_size, int m_size) 39 0 : : input_size(in_size), map_size(m_size) { 40 0 : initialize_weights(); 41 0 : } 42 : 43 0 : gpmp::ml::KohonenNet::~KohonenNet() { 44 0 : } 45 : 46 0 : void gpmp::ml::KohonenNet::initialize_weights() { 47 0 : weights.resize(map_size, std::vector<double>(input_size)); 48 : 49 : // Initialize weights randomly or using some other strategy 50 : // For simplicity, we initialize them with random values between 0 and 1 51 0 : for (int i = 0; i < map_size; ++i) { 52 0 : for (int j = 0; j < input_size; ++j) { 53 0 : weights[i][j] = static_cast<double>(rand()) / RAND_MAX; 54 : } 55 : } 56 0 : } 57 : 58 0 : void gpmp::ml::KohonenNet::train( 59 : const std::vector<std::vector<double>> &inputData, 60 : int epochs) { 61 0 : for (int epoch = 0; epoch < epochs; ++epoch) { 62 0 : for (const auto &inputVector : inputData) { 63 0 : int bmu = best_matching_unit(inputVector); 64 0 : double learningRate = 1.0 - static_cast<double>(epoch) / epochs; 65 0 : update_weights(bmu, inputVector, learningRate); 66 : } 67 : } 68 0 : } 69 : 70 0 : int gpmp::ml::KohonenNet::classify(const std::vector<double> &inputVector) { 71 0 : return best_matching_unit(inputVector); 72 : } 73 : 74 0 : int gpmp::ml::KohonenNet::best_matching_unit( 75 : const std::vector<double> &inputVector) { 76 0 : int bmu = 0; 77 0 : double minDistance = euclidean_distance(inputVector, weights[0]); 78 : 79 0 : for (int i = 1; i < map_size; ++i) { 80 0 : double distance = euclidean_distance(inputVector, weights[i]); 81 0 : if (distance < minDistance) { 82 0 : minDistance = distance; 83 0 : bmu = i; 84 : } 85 : } 86 : 87 0 : return bmu; 88 : } 89 : 90 0 : void gpmp::ml::KohonenNet::update_weights( 91 : int bmu, 92 : const std::vector<double> &inputVector, 93 : double learningRate) { 94 0 : for (int i = 0; i < input_size; ++i) { 95 0 : double delta = inputVector[i] - weights[bmu][i]; 96 0 : weights[bmu][i] += learningRate * delta; 97 : } 98 0 : } 99 : 100 : double 101 0 : gpmp::ml::KohonenNet::euclidean_distance(const std::vector<double> &vec1, 102 : const std::vector<double> &vec2) { 103 0 : double distance = 0.0; 104 0 : for (size_t i = 0; i < vec1.size(); ++i) { 105 0 : double diff = vec1[i] - vec2[i]; 106 0 : distance += diff * diff; 107 : } 108 0 : return sqrt(distance); 109 : }