Compare commits
2 Commits
b9a8d3ffbc
...
0dd9cade42
Author | SHA1 | Date |
---|---|---|
Brett | 0dd9cade42 | |
Brett | 2cb87c6b08 |
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(COSC-4P80-Assignment-3 VERSION 0.0.22)
|
project(COSC-4P80-Assignment-3 VERSION 0.0.24)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
||||||
|
@ -14,12 +14,6 @@ FetchContent_Declare(implot
|
||||||
FIND_PACKAGE_ARGS)
|
FIND_PACKAGE_ARGS)
|
||||||
FetchContent_MakeAvailable(implot)
|
FetchContent_MakeAvailable(implot)
|
||||||
|
|
||||||
FetchContent_Declare(matplotplusplus
|
|
||||||
GIT_REPOSITORY https://github.com/alandefreitas/matplotplusplus
|
|
||||||
GIT_TAG v1.2.1
|
|
||||||
FIND_PACKAGE_ARGS)
|
|
||||||
FetchContent_MakeAvailable(matplotplusplus)
|
|
||||||
|
|
||||||
add_subdirectory(lib/blt-with-graphics)
|
add_subdirectory(lib/blt-with-graphics)
|
||||||
|
|
||||||
include_directories(include/)
|
include_directories(include/)
|
||||||
|
@ -32,7 +26,7 @@ add_executable(COSC-4P80-Assignment-3 ${PROJECT_BUILD_FILES} ${IM_PLOT_FILES})
|
||||||
target_compile_options(COSC-4P80-Assignment-3 PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
target_compile_options(COSC-4P80-Assignment-3 PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
||||||
target_link_options(COSC-4P80-Assignment-3 PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
target_link_options(COSC-4P80-Assignment-3 PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
||||||
|
|
||||||
target_link_libraries(COSC-4P80-Assignment-3 PRIVATE BLT_WITH_GRAPHICS matplot)
|
target_link_libraries(COSC-4P80-Assignment-3 PRIVATE BLT_WITH_GRAPHICS)
|
||||||
|
|
||||||
if (${ENABLE_ADDRSAN} MATCHES ON)
|
if (${ENABLE_ADDRSAN} MATCHES ON)
|
||||||
target_compile_options(COSC-4P80-Assignment-3 PRIVATE -fsanitize=address)
|
target_compile_options(COSC-4P80-Assignment-3 PRIVATE -fsanitize=address)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -94,7 +94,6 @@ namespace assign3
|
||||||
som = std::make_unique<som_t>(motor_data.files[currently_selected_network], som_width, som_height, max_epochs,
|
som = std::make_unique<som_t>(motor_data.files[currently_selected_network], som_width, som_height, max_epochs,
|
||||||
distance_function.get(), topology_function.get(), static_cast<shape_t>(selected_som_mode),
|
distance_function.get(), topology_function.get(), static_cast<shape_t>(selected_som_mode),
|
||||||
static_cast<init_t>(selected_init_type), normalize_init);
|
static_cast<init_t>(selected_init_type), normalize_init);
|
||||||
som->compute_neuron_activations();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -44,6 +44,8 @@ namespace assign3
|
||||||
|
|
||||||
Scalar quantization_error();
|
Scalar quantization_error();
|
||||||
|
|
||||||
|
void compute_errors();
|
||||||
|
|
||||||
void compute_neuron_activations(Scalar distance = 2, Scalar activation = 0.5);
|
void compute_neuron_activations(Scalar distance = 2, Scalar activation = 0.5);
|
||||||
|
|
||||||
void write_activations(std::ostream& out);
|
void write_activations(std::ostream& out);
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib
|
||||||
|
import matplotlib as mpl
|
||||||
|
import sys
|
||||||
|
|
||||||
|
filename = sys.argv[1]
|
||||||
|
size = sys.argv[2]
|
||||||
|
|
||||||
|
df = pd.read_csv(filename, header=None)
|
||||||
|
|
||||||
|
height, width = df.shape
|
||||||
|
|
||||||
|
data = df.to_numpy()
|
||||||
|
|
||||||
|
plt.imshow(data, cmap='coolwarm_r', interpolation='nearest')
|
||||||
|
|
||||||
|
plt.xticks(np.arange(width), np.arange(width))
|
||||||
|
plt.yticks(np.arange(height), np.arange(height))
|
||||||
|
|
||||||
|
plt.xlabel('X Pos')
|
||||||
|
plt.ylabel('Y Pos')
|
||||||
|
plt.title('Heatmap of Motor Data (Bins: {})'.format(size))
|
||||||
|
|
||||||
|
plt.gca().invert_yaxis()
|
||||||
|
|
||||||
|
plt.colorbar()
|
||||||
|
|
||||||
|
plt.savefig("heatmap.png")
|
|
@ -0,0 +1,61 @@
|
||||||
|
import pandas as pd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import sys
|
||||||
|
|
||||||
|
file1 = sys.argv[1]
|
||||||
|
file2 = sys.argv[2]
|
||||||
|
bins = sys.argv[3]
|
||||||
|
split = sys.argv[4]
|
||||||
|
|
||||||
|
df1 = pd.read_csv(file1)
|
||||||
|
df2 = pd.read_csv(file2)
|
||||||
|
|
||||||
|
data1 = df1.to_numpy()
|
||||||
|
data2 = df2.to_numpy()
|
||||||
|
|
||||||
|
y_min = np.min(data2)
|
||||||
|
y_max = np.max(data2)
|
||||||
|
|
||||||
|
if split.lower() == "false":
|
||||||
|
fig, ax1 = plt.subplots()
|
||||||
|
|
||||||
|
ax1.plot(data1, color='b', label='Topological Error')
|
||||||
|
ax1.set_xlabel('Epoch')
|
||||||
|
ax1.set_ylabel('Error %', color='b')
|
||||||
|
ax1.tick_params(axis='y', labelcolor='b')
|
||||||
|
ax1.set_ylim(0, 1)
|
||||||
|
#ax1.set_xlim(0, data1.size)
|
||||||
|
|
||||||
|
ax2 = ax1.twinx()
|
||||||
|
|
||||||
|
ax2.plot(data2, color='r', label='Quantization Error')
|
||||||
|
ax2.set_ylabel('Incorrect BMU', color='r')
|
||||||
|
ax2.tick_params(axis='y', labelcolor='r')
|
||||||
|
ax2.set_ylim(y_min, y_max)
|
||||||
|
|
||||||
|
ax1.set_title('Topological and Quantization Error (Bins: {})'.format(bins))
|
||||||
|
|
||||||
|
plt.savefig("errors{}.png".format(bins))
|
||||||
|
else:
|
||||||
|
plt.plot(data1, color='b', label='Topological Error')
|
||||||
|
plt.xlabel('Epoch')
|
||||||
|
plt.ylabel('Error %', color='b')
|
||||||
|
plt.tick_params(axis='y', labelcolor='b')
|
||||||
|
plt.ylim(0, 1)
|
||||||
|
|
||||||
|
plt.title("Topological Error (Bins: {})".format(bins))
|
||||||
|
|
||||||
|
plt.savefig("errors-topological{}.png".format(bins))
|
||||||
|
|
||||||
|
plt.plot(data2, color='b', label='Quantization Error')
|
||||||
|
plt.xlabel('Epoch')
|
||||||
|
plt.ylabel('Incorrect BMU', color='b')
|
||||||
|
plt.tick_params(axis='y', labelcolor='b')
|
||||||
|
plt.ylim(y_min, y_max)
|
||||||
|
|
||||||
|
plt.title("Quantization Error (Bins: {})".format(bins))
|
||||||
|
|
||||||
|
plt.savefig("errors-quantization{}.png".format(bins))
|
||||||
|
|
||||||
|
|
66
src/main.cpp
66
src/main.cpp
|
@ -10,7 +10,6 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <matplot/matplot.h>
|
|
||||||
|
|
||||||
using namespace assign3;
|
using namespace assign3;
|
||||||
|
|
||||||
|
@ -78,11 +77,6 @@ void action_start_graphics(const std::vector<std::string>& argv_vector)
|
||||||
blt::gfx::init(blt::gfx::window_data{"My Sexy Window", init, update, destroy}.setSyncInterval(1).setMaximized(true));
|
blt::gfx::init(blt::gfx::window_data{"My Sexy Window", init, update, destroy}.setSyncInterval(1).setMaximized(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct activation
|
|
||||||
{
|
|
||||||
Scalar x, y, act;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct task_t // NOLINT
|
struct task_t // NOLINT
|
||||||
{
|
{
|
||||||
data_file_t* file;
|
data_file_t* file;
|
||||||
|
@ -101,7 +95,7 @@ struct task_t // NOLINT
|
||||||
gaussian_function_t topology_func{};
|
gaussian_function_t topology_func{};
|
||||||
std::vector<std::vector<Scalar>> topological_errors{};
|
std::vector<std::vector<Scalar>> topological_errors{};
|
||||||
std::vector<std::vector<Scalar>> quantization_errors{};
|
std::vector<std::vector<Scalar>> quantization_errors{};
|
||||||
std::vector<std::vector<activation>> activations{};
|
std::vector<std::vector<Scalar>> activations{};
|
||||||
};
|
};
|
||||||
|
|
||||||
void action_test(const std::vector<std::string>& argv_vector)
|
void action_test(const std::vector<std::string>& argv_vector)
|
||||||
|
@ -125,7 +119,7 @@ void action_test(const std::vector<std::string>& argv_vector)
|
||||||
|
|
||||||
static blt::size_t runs = 30;
|
static blt::size_t runs = 30;
|
||||||
|
|
||||||
for (blt::size_t i = 0; i < std::thread::hardware_concurrency(); i++)
|
for (blt::size_t _ = 0; _ < std::thread::hardware_concurrency(); _++)
|
||||||
{
|
{
|
||||||
threads.emplace_back([&task_mutex, &tasks]() {
|
threads.emplace_back([&task_mutex, &tasks]() {
|
||||||
do
|
do
|
||||||
|
@ -139,7 +133,7 @@ void action_test(const std::vector<std::string>& argv_vector)
|
||||||
tasks.pop_back();
|
tasks.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (blt::size_t i = 0; i < runs; i++)
|
for (blt::size_t run = 0; run < runs; run++)
|
||||||
{
|
{
|
||||||
gaussian_function_t func{};
|
gaussian_function_t func{};
|
||||||
auto dist = distance_function_t::from_shape(task.shape, task.width, task.height);
|
auto dist = distance_function_t::from_shape(task.shape, task.width, task.height);
|
||||||
|
@ -147,13 +141,13 @@ void action_test(const std::vector<std::string>& argv_vector)
|
||||||
&task.topology_func, task.shape, task.init, false);
|
&task.topology_func, task.shape, task.init, false);
|
||||||
while (som->get_current_epoch() < som->get_max_epochs())
|
while (som->get_current_epoch() < som->get_max_epochs())
|
||||||
som->train_epoch(task.initial_learn_rate);
|
som->train_epoch(task.initial_learn_rate);
|
||||||
som->compute_neuron_activations();
|
|
||||||
|
|
||||||
task.topological_errors.push_back(som->get_topological_errors());
|
task.topological_errors.push_back(som->get_topological_errors());
|
||||||
task.quantization_errors.push_back(som->get_quantization_errors());
|
task.quantization_errors.push_back(som->get_quantization_errors());
|
||||||
std::vector<activation> acts;
|
|
||||||
for (const auto& neuron : som->get_array().get_map())
|
std::vector<Scalar> acts;
|
||||||
acts.push_back({neuron.get_x(), neuron.get_y(), neuron.get_activation()});
|
for (const auto& v : som->get_array().get_map())
|
||||||
|
acts.push_back(v.get_activation());
|
||||||
task.activations.emplace_back(std::move(acts));
|
task.activations.emplace_back(std::move(acts));
|
||||||
}
|
}
|
||||||
std::stringstream paths;
|
std::stringstream paths;
|
||||||
|
@ -170,7 +164,7 @@ void action_test(const std::vector<std::string>& argv_vector)
|
||||||
|
|
||||||
std::vector<Scalar> average_topological_errors;
|
std::vector<Scalar> average_topological_errors;
|
||||||
std::vector<Scalar> average_quantization_errors;
|
std::vector<Scalar> average_quantization_errors;
|
||||||
std::vector<activation> average_activations;
|
std::vector<Scalar> average_activations;
|
||||||
|
|
||||||
average_topological_errors.resize(task.topological_errors.begin()->size());
|
average_topological_errors.resize(task.topological_errors.begin()->size());
|
||||||
average_quantization_errors.resize(task.quantization_errors.begin()->size());
|
average_quantization_errors.resize(task.quantization_errors.begin()->size());
|
||||||
|
@ -184,30 +178,30 @@ void action_test(const std::vector<std::string>& argv_vector)
|
||||||
average_quantization_errors[index] += v;
|
average_quantization_errors[index] += v;
|
||||||
for (const auto& vec : task.activations)
|
for (const auto& vec : task.activations)
|
||||||
for (auto [index, v] : blt::enumerate(vec))
|
for (auto [index, v] : blt::enumerate(vec))
|
||||||
average_activations[index].act += v.act;
|
average_activations[index] += v;
|
||||||
|
|
||||||
for (auto& v : average_topological_errors)
|
std::ofstream topological{path + "topological_avg.csv"};
|
||||||
v /= static_cast<Scalar>(runs);
|
std::ofstream quantization{path + "quantization_avg.csv"};
|
||||||
for (auto& v : average_quantization_errors)
|
std::ofstream activations{path + "activations_avg.csv"};
|
||||||
v /= static_cast<Scalar>(runs);
|
|
||||||
for (auto& v : average_activations)
|
|
||||||
v.act /= static_cast<Scalar>(runs);
|
|
||||||
|
|
||||||
auto f = matplot::figure();
|
topological << "error\n";
|
||||||
f->tiledlayout(2, 1);
|
quantization << "error\n";
|
||||||
auto axis = f->add_axes();
|
for (auto [i, v] : blt::enumerate(average_topological_errors))
|
||||||
axis->hold(true);
|
{
|
||||||
axis->plot(matplot::linspace(0, static_cast<double>(task.max_epochs)), average_topological_errors)->display_name("Topological Error");
|
topological << v / static_cast<Scalar>(runs) << '\n';
|
||||||
axis->title("Error");
|
}
|
||||||
axis->xlabel("Epoch");
|
for (auto [i, v] : blt::enumerate(average_quantization_errors))
|
||||||
axis->ylabel("Error");
|
{
|
||||||
axis->grid(true);
|
quantization << v / static_cast<Scalar>(runs) << '\n';
|
||||||
axis->plot(matplot::linspace(0, static_cast<double>(task.max_epochs)), average_quantization_errors)->display_name("Quantization Error");
|
}
|
||||||
f->title("Topological and Quantization Errors, " + std::to_string(runs) + " Runs");
|
for (auto [i, v] : blt::enumerate(average_activations))
|
||||||
|
{
|
||||||
f->save((path + "errors_plot.eps"), "postscript");
|
activations << v / static_cast<Scalar>(runs);
|
||||||
f->save((path + "errors_plot.tex"), "epslatex");
|
if (i % task.width == task.width-1)
|
||||||
f->save((path + "errors_plot.png"), "png");
|
activations << '\n';
|
||||||
|
else
|
||||||
|
activations << ',';
|
||||||
|
}
|
||||||
|
|
||||||
BLT_INFO("Task '%s' Complete", path.c_str());
|
BLT_INFO("Task '%s' Complete", path.c_str());
|
||||||
|
|
||||||
|
|
|
@ -242,10 +242,7 @@ namespace assign3
|
||||||
if (running)
|
if (running)
|
||||||
{
|
{
|
||||||
if (som->get_current_epoch() < som->get_max_epochs())
|
if (som->get_current_epoch() < som->get_max_epochs())
|
||||||
{
|
|
||||||
som->train_epoch(initial_learn_rate);
|
som->train_epoch(initial_learn_rate);
|
||||||
som->compute_neuron_activations();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
13
src/som.cpp
13
src/som.cpp
|
@ -34,8 +34,7 @@ namespace assign3
|
||||||
{
|
{
|
||||||
for (auto& v : array.get_map())
|
for (auto& v : array.get_map())
|
||||||
v.randomize(std::random_device{}(), init, normalize, file);
|
v.randomize(std::random_device{}(), init, normalize, file);
|
||||||
topological_errors.push_back(topological_error());
|
compute_errors();
|
||||||
quantization_errors.push_back(quantization_error());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void som_t::train_epoch(Scalar initial_learn_rate)
|
void som_t::train_epoch(Scalar initial_learn_rate)
|
||||||
|
@ -67,8 +66,7 @@ namespace assign3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_epoch++;
|
current_epoch++;
|
||||||
topological_errors.push_back(topological_error());
|
compute_errors();
|
||||||
quantization_errors.push_back(quantization_error());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blt::size_t som_t::get_closest_neuron(const std::vector<Scalar>& data)
|
blt::size_t som_t::get_closest_neuron(const std::vector<Scalar>& data)
|
||||||
|
@ -269,5 +267,12 @@ namespace assign3
|
||||||
return incorrect;
|
return incorrect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void som_t::compute_errors()
|
||||||
|
{
|
||||||
|
compute_neuron_activations();
|
||||||
|
topological_errors.push_back(topological_error());
|
||||||
|
quantization_errors.push_back(quantization_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue