Compare commits
No commits in common. "0dd9cade424673717b67c4063c8377002f9a6bc3" and "b9a8d3ffbc11407b66d60369ff17c3a8b572089b" have entirely different histories.
0dd9cade42
...
b9a8d3ffbc
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
project(COSC-4P80-Assignment-3 VERSION 0.0.24)
|
||||
project(COSC-4P80-Assignment-3 VERSION 0.0.22)
|
||||
include(FetchContent)
|
||||
|
||||
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
||||
|
@ -14,6 +14,12 @@ FetchContent_Declare(implot
|
|||
FIND_PACKAGE_ARGS)
|
||||
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)
|
||||
|
||||
include_directories(include/)
|
||||
|
@ -26,7 +32,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_link_options(COSC-4P80-Assignment-3 PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
|
||||
|
||||
target_link_libraries(COSC-4P80-Assignment-3 PRIVATE BLT_WITH_GRAPHICS)
|
||||
target_link_libraries(COSC-4P80-Assignment-3 PRIVATE BLT_WITH_GRAPHICS matplot)
|
||||
|
||||
if (${ENABLE_ADDRSAN} MATCHES ON)
|
||||
target_compile_options(COSC-4P80-Assignment-3 PRIVATE -fsanitize=address)
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
Before Width: | Height: | Size: 19 KiB |
BIN
errors25.png
BIN
errors25.png
Binary file not shown.
Before Width: | Height: | Size: 36 KiB |
BIN
heatmap.png
BIN
heatmap.png
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
|
@ -94,6 +94,7 @@ namespace assign3
|
|||
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),
|
||||
static_cast<init_t>(selected_init_type), normalize_init);
|
||||
som->compute_neuron_activations();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -44,8 +44,6 @@ namespace assign3
|
|||
|
||||
Scalar quantization_error();
|
||||
|
||||
void compute_errors();
|
||||
|
||||
void compute_neuron_activations(Scalar distance = 2, Scalar activation = 0.5);
|
||||
|
||||
void write_activations(std::ostream& out);
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
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")
|
|
@ -1,61 +0,0 @@
|
|||
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,6 +10,7 @@
|
|||
#include <mutex>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <matplot/matplot.h>
|
||||
|
||||
using namespace assign3;
|
||||
|
||||
|
@ -77,6 +78,11 @@ 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));
|
||||
}
|
||||
|
||||
struct activation
|
||||
{
|
||||
Scalar x, y, act;
|
||||
};
|
||||
|
||||
struct task_t // NOLINT
|
||||
{
|
||||
data_file_t* file;
|
||||
|
@ -95,7 +101,7 @@ struct task_t // NOLINT
|
|||
gaussian_function_t topology_func{};
|
||||
std::vector<std::vector<Scalar>> topological_errors{};
|
||||
std::vector<std::vector<Scalar>> quantization_errors{};
|
||||
std::vector<std::vector<Scalar>> activations{};
|
||||
std::vector<std::vector<activation>> activations{};
|
||||
};
|
||||
|
||||
void action_test(const std::vector<std::string>& argv_vector)
|
||||
|
@ -119,7 +125,7 @@ void action_test(const std::vector<std::string>& argv_vector)
|
|||
|
||||
static blt::size_t runs = 30;
|
||||
|
||||
for (blt::size_t _ = 0; _ < std::thread::hardware_concurrency(); _++)
|
||||
for (blt::size_t i = 0; i < std::thread::hardware_concurrency(); i++)
|
||||
{
|
||||
threads.emplace_back([&task_mutex, &tasks]() {
|
||||
do
|
||||
|
@ -133,7 +139,7 @@ void action_test(const std::vector<std::string>& argv_vector)
|
|||
tasks.pop_back();
|
||||
}
|
||||
|
||||
for (blt::size_t run = 0; run < runs; run++)
|
||||
for (blt::size_t i = 0; i < runs; i++)
|
||||
{
|
||||
gaussian_function_t func{};
|
||||
auto dist = distance_function_t::from_shape(task.shape, task.width, task.height);
|
||||
|
@ -141,13 +147,13 @@ void action_test(const std::vector<std::string>& argv_vector)
|
|||
&task.topology_func, task.shape, task.init, false);
|
||||
while (som->get_current_epoch() < som->get_max_epochs())
|
||||
som->train_epoch(task.initial_learn_rate);
|
||||
som->compute_neuron_activations();
|
||||
|
||||
task.topological_errors.push_back(som->get_topological_errors());
|
||||
task.quantization_errors.push_back(som->get_quantization_errors());
|
||||
|
||||
std::vector<Scalar> acts;
|
||||
for (const auto& v : som->get_array().get_map())
|
||||
acts.push_back(v.get_activation());
|
||||
std::vector<activation> acts;
|
||||
for (const auto& neuron : som->get_array().get_map())
|
||||
acts.push_back({neuron.get_x(), neuron.get_y(), neuron.get_activation()});
|
||||
task.activations.emplace_back(std::move(acts));
|
||||
}
|
||||
std::stringstream paths;
|
||||
|
@ -164,7 +170,7 @@ void action_test(const std::vector<std::string>& argv_vector)
|
|||
|
||||
std::vector<Scalar> average_topological_errors;
|
||||
std::vector<Scalar> average_quantization_errors;
|
||||
std::vector<Scalar> average_activations;
|
||||
std::vector<activation> average_activations;
|
||||
|
||||
average_topological_errors.resize(task.topological_errors.begin()->size());
|
||||
average_quantization_errors.resize(task.quantization_errors.begin()->size());
|
||||
|
@ -178,30 +184,30 @@ void action_test(const std::vector<std::string>& argv_vector)
|
|||
average_quantization_errors[index] += v;
|
||||
for (const auto& vec : task.activations)
|
||||
for (auto [index, v] : blt::enumerate(vec))
|
||||
average_activations[index] += v;
|
||||
average_activations[index].act += v.act;
|
||||
|
||||
std::ofstream topological{path + "topological_avg.csv"};
|
||||
std::ofstream quantization{path + "quantization_avg.csv"};
|
||||
std::ofstream activations{path + "activations_avg.csv"};
|
||||
for (auto& v : average_topological_errors)
|
||||
v /= static_cast<Scalar>(runs);
|
||||
for (auto& v : average_quantization_errors)
|
||||
v /= static_cast<Scalar>(runs);
|
||||
for (auto& v : average_activations)
|
||||
v.act /= static_cast<Scalar>(runs);
|
||||
|
||||
topological << "error\n";
|
||||
quantization << "error\n";
|
||||
for (auto [i, v] : blt::enumerate(average_topological_errors))
|
||||
{
|
||||
topological << v / static_cast<Scalar>(runs) << '\n';
|
||||
}
|
||||
for (auto [i, v] : blt::enumerate(average_quantization_errors))
|
||||
{
|
||||
quantization << v / static_cast<Scalar>(runs) << '\n';
|
||||
}
|
||||
for (auto [i, v] : blt::enumerate(average_activations))
|
||||
{
|
||||
activations << v / static_cast<Scalar>(runs);
|
||||
if (i % task.width == task.width-1)
|
||||
activations << '\n';
|
||||
else
|
||||
activations << ',';
|
||||
}
|
||||
auto f = matplot::figure();
|
||||
f->tiledlayout(2, 1);
|
||||
auto axis = f->add_axes();
|
||||
axis->hold(true);
|
||||
axis->plot(matplot::linspace(0, static_cast<double>(task.max_epochs)), average_topological_errors)->display_name("Topological Error");
|
||||
axis->title("Error");
|
||||
axis->xlabel("Epoch");
|
||||
axis->ylabel("Error");
|
||||
axis->grid(true);
|
||||
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");
|
||||
|
||||
f->save((path + "errors_plot.eps"), "postscript");
|
||||
f->save((path + "errors_plot.tex"), "epslatex");
|
||||
f->save((path + "errors_plot.png"), "png");
|
||||
|
||||
BLT_INFO("Task '%s' Complete", path.c_str());
|
||||
|
||||
|
|
|
@ -242,7 +242,10 @@ namespace assign3
|
|||
if (running)
|
||||
{
|
||||
if (som->get_current_epoch() < som->get_max_epochs())
|
||||
{
|
||||
som->train_epoch(initial_learn_rate);
|
||||
som->compute_neuron_activations();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
15
src/som.cpp
15
src/som.cpp
|
@ -34,7 +34,8 @@ namespace assign3
|
|||
{
|
||||
for (auto& v : array.get_map())
|
||||
v.randomize(std::random_device{}(), init, normalize, file);
|
||||
compute_errors();
|
||||
topological_errors.push_back(topological_error());
|
||||
quantization_errors.push_back(quantization_error());
|
||||
}
|
||||
|
||||
void som_t::train_epoch(Scalar initial_learn_rate)
|
||||
|
@ -66,7 +67,8 @@ namespace assign3
|
|||
}
|
||||
}
|
||||
current_epoch++;
|
||||
compute_errors();
|
||||
topological_errors.push_back(topological_error());
|
||||
quantization_errors.push_back(quantization_error());
|
||||
}
|
||||
|
||||
blt::size_t som_t::get_closest_neuron(const std::vector<Scalar>& data)
|
||||
|
@ -263,16 +265,9 @@ namespace assign3
|
|||
continue;
|
||||
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