Compare commits

..

2 Commits

Author SHA1 Message Date
Brett 7b2bd7679a parker is a little bitch :3
i love him so much
2024-11-06 01:33:28 -05:00
Brett 062956f7d5 silly 2024-11-06 01:22:52 -05:00
12 changed files with 334 additions and 178 deletions

View File

@ -1,164 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="CMakePresetLoader">{
&quot;useNewFormat&quot;: true
}</component>
<component name="CMakeReloadState">
<option name="reloaded" value="true" />
</component>
<component name="CMakeRunConfigurationManager">
<generated>
<config projectName="COSC-4P80-Assignment-3" targetName="BLT_WITH_GRAPHICS" />
<config projectName="COSC-4P80-Assignment-3" targetName="freetype" />
<config projectName="COSC-4P80-Assignment-3" targetName="BLT" />
<config projectName="COSC-4P80-Assignment-3" targetName="COSC-4P80-Assignment-3" />
</generated>
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" />
<configuration PROFILE_NAME="Release" ENABLED="true" CONFIG_NAME="Release" />
<configuration PROFILE_NAME="RelWithDebInfo" ENABLED="true" CONFIG_NAME="RelWithDebInfo" />
<configuration PROFILE_NAME="RelWithDebInfo Addrsan" ENABLED="true" CONFIG_NAME="RelWithDebInfo" GENERATION_OPTIONS="-DENABLE_ADDRSAN=ON -DENABLE_UBSAN=ON" />
<configuration PROFILE_NAME="RelWithDebInfo ubsan" ENABLED="true" CONFIG_NAME="RelWithDebInfo" GENERATION_OPTIONS="-DENABLE_UBSAN=ON" />
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="df4fb81f-8c9e-43af-9712-6ff8baeb587a" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/include/assign3/functions.h" afterDir="false" />
<change afterPath="$PROJECT_DIR$/include/assign3/fwdecl.h" afterDir="false" />
<change afterPath="$PROJECT_DIR$/include/assign3/neuron.h" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/functions.cpp" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/neuron.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/commit.py" beforeDir="false" afterPath="$PROJECT_DIR$/commit.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/include/assign3/file.h" beforeDir="false" afterPath="$PROJECT_DIR$/include/assign3/file.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/build_emscript.sh" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/build_emscript.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/cloc.sh" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/cloc.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/commit.py" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/commit.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/cloc.sh" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/cloc.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/commit.py" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/commit.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/commit.py.save" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/commit.py.save" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/gen-llil.pl" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/gen-llil.pl" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/gen_files" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/gen_files" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/run_llil4map" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/examples/llil_utils/run_llil4map" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/phmap_lldb.py" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/libraries/parallel-hashmap/phmap_lldb.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/py_commit_helper.sh" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/py_commit_helper.sh" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/src/blt/std/assert.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/libraries/BLT/src/blt/std/assert.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/lib/blt-with-graphics/resources/fonts/a.out" beforeDir="false" afterPath="$PROJECT_DIR$/lib/blt-with-graphics/resources/fonts/a.out" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.cpp" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
<option name="indexerUseModules" value="false" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="CMakeBuildProfile:RelWithDebInfo" />
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectApplicationVersion">
<option name="ide" value="CLion" />
<option name="majorVersion" value="2024" />
<option name="minorVersion" value="1.3" />
<option name="productBranch" value="Classic" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 7
}</component>
<component name="ProjectId" id="2oG5NNX4GedKhxLJDuzQ5OR5kr5" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;CMake Application.COSC-4P80-Assignment-3.executor&quot;: &quot;Run&quot;,
&quot;NIXITCH_NIXPKGS_CONFIG&quot;: &quot;/etc/nix/nixpkgs-config.nix&quot;,
&quot;NIXITCH_NIX_CONF_DIR&quot;: &quot;&quot;,
&quot;NIXITCH_NIX_OTHER_STORES&quot;: &quot;&quot;,
&quot;NIXITCH_NIX_PATH&quot;: &quot;/home/brett/.nix-defexpr/channels:nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels&quot;,
&quot;NIXITCH_NIX_PROFILES&quot;: &quot;/run/current-system/sw /nix/var/nix/profiles/default /etc/profiles/per-user/brett /home/brett/.local/state/nix/profile /nix/profile /home/brett/.nix-profile&quot;,
&quot;NIXITCH_NIX_REMOTE&quot;: &quot;&quot;,
&quot;NIXITCH_NIX_USER_PROFILE_DIR&quot;: &quot;/nix/var/nix/profiles/per-user/brett&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;RunOnceActivity.readMode.enableVisualFormatting&quot;: &quot;true&quot;,
&quot;cf.first.check.clang-format&quot;: &quot;false&quot;,
&quot;cidr.known.project.marker&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/brett/Documents/Brock/CS 4P80/COSC-4P80-Assignment-3&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;CMakeSettings&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="RunManager" selected="CMake Application.COSC-4P80-Assignment-3">
<configuration default="true" type="CLionExternalRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true">
<method v="2">
<option name="CLION.EXTERNAL.BUILD" enabled="true" />
</method>
</configuration>
<configuration name="BLT" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="BLT" CONFIG_NAME="Debug">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="BLT_WITH_GRAPHICS" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="BLT_WITH_GRAPHICS" CONFIG_NAME="Debug">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="COSC-4P80-Assignment-3" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="COSC-4P80-Assignment-3" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="COSC-4P80-Assignment-3" RUN_TARGET_NAME="COSC-4P80-Assignment-3">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="freetype" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="COSC-4P80-Assignment-3" TARGET_NAME="freetype" CONFIG_NAME="Debug">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
<list>
<item itemvalue="CMake Application.COSC-4P80-Assignment-3" />
<item itemvalue="CMake Application.BLT_WITH_GRAPHICS" />
<item itemvalue="CMake Application.BLT" />
<item itemvalue="CMake Application.freetype" />
</list>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="df4fb81f-8c9e-43af-9712-6ff8baeb587a" name="Changes" comment="" />
<created>1730483030448</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1730483030448</updated>
<workItem from="1730483031471" duration="57000" />
<workItem from="1730483139508" duration="22719000" />
<workItem from="1730760265254" duration="6300000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="VCPKGProject">
<isAutomaticCheckingOnLaunch value="false" />
<isAutomaticFoundErrors value="true" />
<isAutomaticReloadCMake value="true" />
</component>
</project>

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(COSC-4P80-Assignment-3 VERSION 0.0.5)
project(COSC-4P80-Assignment-3 VERSION 0.0.7)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

0
commit.py Normal file → Executable file
View File

70
include/assign3/array.h Normal file
View File

@ -0,0 +1,70 @@
#pragma once
/*
* Copyright (C) 2024 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef COSC_4P80_ASSIGNMENT_3_ARRAY_H
#define COSC_4P80_ASSIGNMENT_3_ARRAY_H
#include <assign3/fwdecl.h>
#include <assign3/neuron.h>
namespace assign3
{
class array_t
{
public:
explicit array_t(blt::size_t dimensions, blt::size_t width, blt::size_t height):
width(static_cast<blt::i64>(width)), height(static_cast<blt::i64>(height))
{
for (blt::size_t i = 0; i < width; i++)
for (blt::size_t j = 0; j < height; j++)
map.emplace_back(dimensions, i, j);
}
inline neuron_t& get(blt::size_t x, blt::size_t y)
{ return map[y * width + x]; }
[[nodiscard]] inline const neuron_t& get(blt::size_t x, blt::size_t y) const
{ return map[y * width + x]; }
[[nodiscard]] inline blt::size_t get_width() const
{ return width; }
[[nodiscard]] inline blt::size_t get_height() const
{ return height; }
[[nodiscard]] inline std::vector<neuron_t>& get_map()
{ return map; }
[[nodiscard]] inline const std::vector<neuron_t>& get_map() const
{ return map; }
private:
[[nodiscard]] inline blt::i64 wrap_width(blt::i64 x) const;
[[nodiscard]] inline blt::i64 wrap_height(blt::i64 y) const;
private:
blt::i64 width, height;
std::vector<neuron_t> map;
};
}
#endif //COSC_4P80_ASSIGNMENT_3_ARRAY_H

View File

@ -26,6 +26,11 @@ namespace assign3
struct topology_function_t
{
/**
* @param dist input - usually the distance
* @param r time ratio - t / max_t
* @return basis results
*/
[[nodiscard]] virtual Scalar call(Scalar dist, Scalar r) const = 0;
};

View File

@ -22,6 +22,11 @@
namespace assign3
{
using Scalar = float;
enum class shape
{
GRID, HONEYCOMB
};
}
#endif //COSC_4P80_ASSIGNMENT_3_FWDECL_H

View File

@ -36,9 +36,11 @@ namespace assign3
neuron_t& randomize(blt::size_t seed);
neuron_t& update(const std::vector<Scalar>& new_data, const topology_function_t* basis_func, Scalar eta, Scalar r);
neuron_t& update(const std::vector<Scalar>& new_data, Scalar dist, Scalar eta);
static Scalar distance(const neuron_t& n1, const neuron_t& n2, Scalar time_ratio);
static Scalar distance(const neuron_t& n1, const neuron_t& n2);
[[nodiscard]] Scalar dist(const std::vector<Scalar>& X) const;
[[nodiscard]] inline const std::vector<Scalar>& get_data() const
{ return data; }
@ -48,9 +50,8 @@ namespace assign3
[[nodiscard]] inline Scalar get_y() const
{ return y_pos; }
private:
[[nodiscard]] Scalar dist(const std::vector<Scalar>& X) const;
private:
Scalar x_pos, y_pos;
std::vector<Scalar> data;
};

56
include/assign3/som.h Normal file
View File

@ -0,0 +1,56 @@
#pragma once
/*
* Copyright (C) 2024 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef COSC_4P80_ASSIGNMENT_3_SOM_H
#define COSC_4P80_ASSIGNMENT_3_SOM_H
#include <assign3/array.h>
#include <assign3/file.h>
#include <assign3/functions.h>
namespace assign3
{
class som_t
{
public:
som_t(const data_file_t& file, blt::size_t width, blt::size_t height, blt::size_t max_epochs);
blt::size_t get_closest_neuron(const std::vector<Scalar>& data);
void train_epoch(Scalar initial_learn_rate, topology_function_t* basis_func);
[[nodiscard]] const array_t& get_array() const
{ return array; }
[[nodiscard]] blt::size_t get_current_epoch() const
{ return current_epoch; }
[[nodiscard]] blt::size_t get_max_epochs() const
{ return max_epochs; }
private:
array_t array;
data_file_t file;
blt::size_t current_epoch = 0;
blt::size_t max_epochs;
};
}
#endif //COSC_4P80_ASSIGNMENT_3_SOM_H

43
src/array.cpp Normal file
View File

@ -0,0 +1,43 @@
/*
* <Short Description>
* Copyright (C) 2024 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <assign3/array.h>
#include <cmath>
namespace assign3
{
blt::i64 array_t::wrap_height(blt::i64 y) const
{
if (y >= height)
return y - height;
else if (y < 0)
return height + y;
else
return y;
}
blt::i64 array_t::wrap_width(blt::i64 x) const
{
if (x >= width)
return x - width;
else if (x < 0)
return width + x;
else
return x;
}
}

View File

@ -6,9 +6,13 @@
#include "blt/gfx/renderer/batch_2d_renderer.h"
#include "blt/gfx/renderer/camera.h"
#include <assign3/file.h>
#include <assign3/som.h>
#include <imgui.h>
std::vector<assign3::data_file_t> files;
using namespace assign3;
std::vector<data_file_t> files;
std::unique_ptr<som_t> som;
blt::gfx::matrix_state_manager global_matrices;
blt::gfx::resource_manager resources;
@ -23,16 +27,67 @@ void init(const blt::gfx::window_data&)
global_matrices.create_internals();
resources.load_resources();
renderer_2d.create();
blt::size_t size = 5;
som = std::make_unique<som_t>(
*std::find_if(files.begin(), files.end(), [](const data_file_t& v) { return v.data_points.begin()->bins.size() == 32; }),
size, size, 100);
}
void update(const blt::gfx::window_data& data)
{
using namespace blt::gfx;
global_matrices.update_perspectives(data.width, data.height, 90, 0.1, 2000);
camera.update();
camera.update_view(global_matrices);
global_matrices.update();
if (ImGui::Begin("Controls"))
{
ImGui::Button("Run Epoch");
if (ImGui::IsItemClicked())
{
static gaussian_function_t func;
som->train_epoch(0.1, &func);
}
}
ImGui::End();
auto& meow = *std::find_if(files.begin(), files.end(), [](const data_file_t& v) { return v.data_points.begin()->bins.size() == 32; });
for (auto& v : som->get_array().get_map())
{
float scale = 35;
float total_good_distance = 0;
float total_bad_distance = 0;
float total_goods = 0;
float total_bads = 0;
for (auto& point : meow.data_points)
{
auto dist = v.dist(point.bins);
if (point.is_bad)
{
total_bads++;
total_bad_distance += dist;
} else
{
total_goods++;
total_good_distance += dist;
}
}
float good_ratio = total_goods > 0 ? total_good_distance / total_goods : 0;
float bad_ratio = total_bads > 0 ? total_bad_distance / total_bads : 0;
float good_to_bad = total_good_distance / total_bad_distance;
BLT_TRACE("%f %f %f", good_ratio, bad_ratio, good_to_bad);
renderer_2d.drawPointInternal(blt::make_color(good_ratio, bad_ratio, good_to_bad),
point2d_t{v.get_x() * scale + scale, v.get_y() * scale + scale, scale});
}
renderer_2d.render(data.width, data.height);
}

View File

@ -32,11 +32,17 @@ namespace assign3
return *this;
}
neuron_t& neuron_t::update(const std::vector<Scalar>& new_data, const topology_function_t* basis_func, Scalar eta, Scalar r)
neuron_t& neuron_t::update(const std::vector<Scalar>& new_data, Scalar dist, Scalar eta)
{
auto d = dist(new_data);
for (auto& v : data)
v = eta * basis_func->call(d, r);
static thread_local std::vector<Scalar> diff;
diff.clear();
for (auto [x, v] : blt::in_pairs(new_data, data))
diff.push_back(v - x);
for (auto [v, d] : blt::in_pairs(data, diff))
v += eta * dist * d;
return *this;
}
@ -51,10 +57,10 @@ namespace assign3
return std::sqrt(dist);
}
Scalar neuron_t::distance(const neuron_t& n1, const neuron_t& n2, Scalar time_ratio)
Scalar neuron_t::distance(const neuron_t& n1, const neuron_t& n2)
{
auto dist = n1.dist(n2.data);
auto dist_sq = dist * dist;
return std::exp(-time_ratio * dist_sq);
auto dx = n1.get_x() - n2.get_x();
auto dy = n1.get_y() - n2.get_y();
return std::sqrt(dx * dx + dy * dy);
}
}

79
src/som.cpp Normal file
View File

@ -0,0 +1,79 @@
/*
* <Short Description>
* Copyright (C) 2024 Brett Terpstra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <assign3/som.h>
#include <random>
#include <algorithm>
#include <blt/std/random.h>
#include <blt/iterator/enumerate.h>
namespace assign3
{
som_t::som_t(const data_file_t& file, blt::size_t width, blt::size_t height, blt::size_t max_epochs):
array(file.data_points.begin()->bins.size(), width, height), file(file), max_epochs(max_epochs)
{
for (auto& v : array.get_map())
v.randomize(std::random_device{}());
}
void som_t::train_epoch(Scalar initial_learn_rate, topology_function_t* basis_func)
{
blt::random::random_t rand{std::random_device{}()};
std::shuffle(file.data_points.begin(), file.data_points.end(), rand);
auto time_ratio = static_cast<Scalar>(current_epoch) / static_cast<Scalar>(max_epochs);
auto eta = initial_learn_rate * std::exp(-2 * time_ratio);
for (auto& current_data : file.data_points)
{
auto v0_idx = get_closest_neuron(current_data.bins);
auto v0 = array.get_map()[v0_idx];
v0.update(current_data.bins, 1, eta);
for (auto [i, n] : blt::enumerate(array.get_map()))
{
if (i == v0_idx)
continue;
auto dist = basis_func->call(neuron_t::distance(v0, n), time_ratio);
n.update(current_data.bins, dist, eta);
}
}
current_epoch++;
}
blt::size_t som_t::get_closest_neuron(const std::vector<Scalar>& data)
{
blt::size_t index = 0;
Scalar distance = std::numeric_limits<Scalar>::max();
for (auto [i, d] : blt::enumerate(array.get_map()))
{
auto dist = d.dist(data);
if (dist < distance)
{
index = i;
distance = dist;
}
}
return index;
}
}