silly functions
parent
a69e3274dc
commit
3b13e48f36
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(COSC-4P80-Assignment-3 VERSION 0.0.8)
|
project(COSC-4P80-Assignment-3 VERSION 0.0.9)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H
|
#define COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H
|
||||||
|
|
||||||
#include <assign3/fwdecl.h>
|
#include <assign3/fwdecl.h>
|
||||||
|
#include <blt/std/ranges.h>
|
||||||
|
|
||||||
namespace assign3
|
namespace assign3
|
||||||
{
|
{
|
||||||
|
@ -39,6 +40,16 @@ namespace assign3
|
||||||
[[nodiscard]] Scalar call(Scalar dist, Scalar r) const final;
|
[[nodiscard]] Scalar call(Scalar dist, Scalar r) const final;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct distance_function_t
|
||||||
|
{
|
||||||
|
[[nodiscard]] virtual Scalar distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct euclidean_distance_function_t : public distance_function_t
|
||||||
|
{
|
||||||
|
[[nodiscard]] Scalar distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const final;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H
|
#endif //COSC_4P80_ASSIGNMENT_3_FUNCTIONS_H
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#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_UI_H
|
||||||
|
#define COSC_4P80_ASSIGNMENT_3_UI_H
|
||||||
|
|
||||||
|
namespace assign3 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //COSC_4P80_ASSIGNMENT_3_UI_H
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
#include <assign3/functions.h>
|
#include <assign3/functions.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include "blt/iterator/zip.h"
|
||||||
|
|
||||||
namespace assign3
|
namespace assign3
|
||||||
{
|
{
|
||||||
|
@ -26,4 +27,15 @@ namespace assign3
|
||||||
auto dist_sq = dist * dist;
|
auto dist_sq = dist * dist;
|
||||||
return std::exp(-r * dist_sq);
|
return std::exp(-r * dist_sq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scalar euclidean_distance_function_t::distance(blt::span<const Scalar> x, blt::span<const Scalar> y) const
|
||||||
|
{
|
||||||
|
Scalar dist = 0;
|
||||||
|
for (auto [a, b] : blt::in_pairs(x, y))
|
||||||
|
{
|
||||||
|
auto d = a - b;
|
||||||
|
dist += d * d;
|
||||||
|
}
|
||||||
|
return std::sqrt(dist);
|
||||||
|
}
|
||||||
}
|
}
|
84
src/main.cpp
84
src/main.cpp
|
@ -21,9 +21,26 @@ blt::gfx::first_person_camera_2d camera;
|
||||||
|
|
||||||
blt::size_t som_width = 7;
|
blt::size_t som_width = 7;
|
||||||
blt::size_t som_height = 7;
|
blt::size_t som_height = 7;
|
||||||
blt::size_t max_epochs = 100;
|
blt::size_t max_epochs = 1000;
|
||||||
Scalar initial_learn_rate = 0.1;
|
Scalar initial_learn_rate = 0.1;
|
||||||
|
|
||||||
|
int currently_selected_network = 0;
|
||||||
|
std::vector<std::string> map_files_names;
|
||||||
|
|
||||||
|
float neuron_scale = 35;
|
||||||
|
float draw_width = neuron_scale * static_cast<float>(som_width);
|
||||||
|
float draw_height = neuron_scale * static_cast<float>(som_height);
|
||||||
|
|
||||||
|
void generate_network(int selection)
|
||||||
|
{
|
||||||
|
som = std::make_unique<som_t>(files[selection].normalize(), som_width, som_height, max_epochs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* get_selection_string(void*, int selection)
|
||||||
|
{
|
||||||
|
return map_files_names[selection].c_str();
|
||||||
|
}
|
||||||
|
|
||||||
void init(const blt::gfx::window_data&)
|
void init(const blt::gfx::window_data&)
|
||||||
{
|
{
|
||||||
using namespace blt::gfx;
|
using namespace blt::gfx;
|
||||||
|
@ -33,15 +50,16 @@ void init(const blt::gfx::window_data&)
|
||||||
resources.load_resources();
|
resources.load_resources();
|
||||||
renderer_2d.create();
|
renderer_2d.create();
|
||||||
|
|
||||||
som = std::make_unique<som_t>(
|
for (const auto& data : files)
|
||||||
*std::find_if(files.begin(), files.end(), [](const data_file_t& v) { return v.data_points.begin()->bins.size() == 32; }),
|
map_files_names.emplace_back(std::to_string(data.data_points.begin()->bins.size()));
|
||||||
som_width, som_height, max_epochs);
|
|
||||||
|
generate_network(currently_selected_network);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const blt::gfx::window_data& data)
|
void update(const blt::gfx::window_data& window_data)
|
||||||
{
|
{
|
||||||
using namespace blt::gfx;
|
using namespace blt::gfx;
|
||||||
global_matrices.update_perspectives(data.width, data.height, 90, 0.1, 2000);
|
global_matrices.update_perspectives(window_data.width, window_data.height, 90, 0.1, 2000);
|
||||||
|
|
||||||
camera.update();
|
camera.update();
|
||||||
camera.update_view(global_matrices);
|
camera.update_view(global_matrices);
|
||||||
|
@ -49,6 +67,10 @@ void update(const blt::gfx::window_data& data)
|
||||||
|
|
||||||
if (ImGui::Begin("Controls"))
|
if (ImGui::Begin("Controls"))
|
||||||
{
|
{
|
||||||
|
ImGui::Text("Network Select");
|
||||||
|
if (ImGui::ListBox("##Network Select", ¤tly_selected_network, get_selection_string, nullptr, static_cast<int>(map_files_names.size())))
|
||||||
|
generate_network(currently_selected_network);
|
||||||
|
|
||||||
if (ImGui::Button("Run Epoch"))
|
if (ImGui::Button("Run Epoch"))
|
||||||
{
|
{
|
||||||
static gaussian_function_t func;
|
static gaussian_function_t func;
|
||||||
|
@ -71,8 +93,8 @@ void update(const blt::gfx::window_data& data)
|
||||||
activations.clear();
|
activations.clear();
|
||||||
activations.resize(som->get_array().get_map().size());
|
activations.resize(som->get_array().get_map().size());
|
||||||
|
|
||||||
auto& meow = *std::find_if(files.begin(), files.end(), [](const data_file_t& v) { return v.data_points.begin()->bins.size() == 32; });
|
auto current_data_file = files[currently_selected_network].normalize();
|
||||||
for (auto& v : meow.data_points)
|
for (auto& v : current_data_file.data_points)
|
||||||
{
|
{
|
||||||
auto nearest = som->get_closest_neuron(v.bins);
|
auto nearest = som->get_closest_neuron(v.bins);
|
||||||
activations[nearest] += v.is_bad ? -1 : 1;
|
activations[nearest] += v.is_bad ? -1 : 1;
|
||||||
|
@ -83,8 +105,6 @@ void update(const blt::gfx::window_data& data)
|
||||||
|
|
||||||
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
|
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
|
||||||
{
|
{
|
||||||
float scale = 35;
|
|
||||||
|
|
||||||
auto activation = activations[i];
|
auto activation = activations[i];
|
||||||
|
|
||||||
blt::vec4 color = blt::make_color(1, 1, 1);
|
blt::vec4 color = blt::make_color(1, 1, 1);
|
||||||
|
@ -93,10 +113,50 @@ void update(const blt::gfx::window_data& data)
|
||||||
else if (activation < 0)
|
else if (activation < 0)
|
||||||
color = blt::make_color(std::abs(static_cast<Scalar>(activation) / static_cast<Scalar>(min)), 0, 0);
|
color = blt::make_color(std::abs(static_cast<Scalar>(activation) / static_cast<Scalar>(min)), 0, 0);
|
||||||
|
|
||||||
renderer_2d.drawPointInternal(color, point2d_t{v.get_x() * scale + scale, v.get_y() * scale + scale, scale});
|
renderer_2d.drawPointInternal(color,
|
||||||
|
point2d_t{v.get_x() * neuron_scale + neuron_scale, v.get_y() * neuron_scale + neuron_scale, neuron_scale});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer_2d.render(data.width, data.height);
|
static std::vector<float> closest_type;
|
||||||
|
closest_type.clear();
|
||||||
|
closest_type.resize(som->get_array().get_map().size());
|
||||||
|
|
||||||
|
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
|
||||||
|
{
|
||||||
|
Scalar lowest_distance = std::numeric_limits<Scalar>::max();
|
||||||
|
bool is_bad = false;
|
||||||
|
for (const auto& data : current_data_file.data_points)
|
||||||
|
{
|
||||||
|
auto dist = v.dist(data.bins);
|
||||||
|
if (dist < lowest_distance)
|
||||||
|
{
|
||||||
|
lowest_distance = dist;
|
||||||
|
is_bad = data.is_bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// BLT_TRACE(is_bad ? -lowest_distance : lowest_distance);
|
||||||
|
closest_type[i] = is_bad ? -lowest_distance : lowest_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto min_dist = *std::min_element(closest_type.begin(), closest_type.end());
|
||||||
|
auto max_dist = *std::max_element(closest_type.begin(), closest_type.end());
|
||||||
|
|
||||||
|
for (auto [i, v] : blt::enumerate(som->get_array().get_map()))
|
||||||
|
{
|
||||||
|
auto type = closest_type[i];
|
||||||
|
|
||||||
|
blt::vec4 color = blt::make_color(1, 1, 1);
|
||||||
|
if (type >= 0)
|
||||||
|
color = blt::make_color(0, 1 - (type / max_dist) + 0.1f, 0);
|
||||||
|
else if (type < 0)
|
||||||
|
color = blt::make_color(1 - (type / min_dist) + 0.1f, 0, 0);
|
||||||
|
|
||||||
|
renderer_2d.drawPointInternal(color,
|
||||||
|
point2d_t{draw_width + neuron_scale * 2 + v.get_x() * neuron_scale + neuron_scale,
|
||||||
|
v.get_y() * neuron_scale + neuron_scale, neuron_scale});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer_2d.render(window_data.width, window_data.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy(const blt::gfx::window_data&)
|
void destroy(const blt::gfx::window_data&)
|
||||||
|
|
|
@ -49,19 +49,13 @@ namespace assign3
|
||||||
|
|
||||||
Scalar neuron_t::dist(const std::vector<Scalar>& X) const
|
Scalar neuron_t::dist(const std::vector<Scalar>& X) const
|
||||||
{
|
{
|
||||||
Scalar dist = 0;
|
euclidean_distance_function_t dist_func;
|
||||||
for (auto [v, x] : blt::zip(data, X))
|
return dist_func.distance(data, X);
|
||||||
{
|
|
||||||
auto loc = (v - x);
|
|
||||||
dist += loc * loc;
|
|
||||||
}
|
|
||||||
return std::sqrt(dist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scalar neuron_t::distance(const neuron_t& n1, const neuron_t& n2)
|
Scalar neuron_t::distance(const neuron_t& n1, const neuron_t& n2)
|
||||||
{
|
{
|
||||||
auto dx = n1.get_x() - n2.get_x();
|
euclidean_distance_function_t dist_func;
|
||||||
auto dy = n1.get_y() - n2.get_y();
|
return dist_func.distance({n1.get_x(), n1.get_y()}, {n2.get_x(), n2.get_y()});
|
||||||
return std::sqrt(dx * dx + dy * dy);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue