Compare commits

..

No commits in common. "0dd9cade424673717b67c4063c8377002f9a6bc3" and "b9a8d3ffbc11407b66d60369ff17c3a8b572089b" have entirely different histories.

12 changed files with 53 additions and 135 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) 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) include(FetchContent)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
@ -14,6 +14,12 @@ 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/)
@ -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_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) target_link_libraries(COSC-4P80-Assignment-3 PRIVATE BLT_WITH_GRAPHICS matplot)
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.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -94,6 +94,7 @@ 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:

View File

@ -44,8 +44,6 @@ 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);

View File

@ -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")

View File

@ -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))

View File

@ -10,6 +10,7 @@
#include <mutex> #include <mutex>
#include <fstream> #include <fstream>
#include <filesystem> #include <filesystem>
#include <matplot/matplot.h>
using namespace assign3; 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)); 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;
@ -95,7 +101,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<Scalar>> activations{}; std::vector<std::vector<activation>> activations{};
}; };
void action_test(const std::vector<std::string>& argv_vector) 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; 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]() { threads.emplace_back([&task_mutex, &tasks]() {
do do
@ -133,7 +139,7 @@ void action_test(const std::vector<std::string>& argv_vector)
tasks.pop_back(); 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{}; 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);
@ -141,13 +147,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;
std::vector<Scalar> acts; for (const auto& neuron : som->get_array().get_map())
for (const auto& v : som->get_array().get_map()) acts.push_back({neuron.get_x(), neuron.get_y(), neuron.get_activation()});
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;
@ -164,7 +170,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<Scalar> average_activations; std::vector<activation> 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());
@ -178,30 +184,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] += v; average_activations[index].act += v.act;
std::ofstream topological{path + "topological_avg.csv"}; for (auto& v : average_topological_errors)
std::ofstream quantization{path + "quantization_avg.csv"}; v /= static_cast<Scalar>(runs);
std::ofstream activations{path + "activations_avg.csv"}; 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"; auto f = matplot::figure();
quantization << "error\n"; f->tiledlayout(2, 1);
for (auto [i, v] : blt::enumerate(average_topological_errors)) auto axis = f->add_axes();
{ axis->hold(true);
topological << v / static_cast<Scalar>(runs) << '\n'; axis->plot(matplot::linspace(0, static_cast<double>(task.max_epochs)), average_topological_errors)->display_name("Topological Error");
} axis->title("Error");
for (auto [i, v] : blt::enumerate(average_quantization_errors)) axis->xlabel("Epoch");
{ axis->ylabel("Error");
quantization << v / static_cast<Scalar>(runs) << '\n'; axis->grid(true);
} axis->plot(matplot::linspace(0, static_cast<double>(task.max_epochs)), average_quantization_errors)->display_name("Quantization Error");
for (auto [i, v] : blt::enumerate(average_activations)) f->title("Topological and Quantization Errors, " + std::to_string(runs) + " Runs");
{
activations << v / static_cast<Scalar>(runs); f->save((path + "errors_plot.eps"), "postscript");
if (i % task.width == task.width-1) f->save((path + "errors_plot.tex"), "epslatex");
activations << '\n'; f->save((path + "errors_plot.png"), "png");
else
activations << ',';
}
BLT_INFO("Task '%s' Complete", path.c_str()); BLT_INFO("Task '%s' Complete", path.c_str());

View File

@ -242,7 +242,10 @@ 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();
}
} }

View File

@ -34,7 +34,8 @@ 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);
compute_errors(); topological_errors.push_back(topological_error());
quantization_errors.push_back(quantization_error());
} }
void som_t::train_epoch(Scalar initial_learn_rate) void som_t::train_epoch(Scalar initial_learn_rate)
@ -66,7 +67,8 @@ namespace assign3
} }
} }
current_epoch++; 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) blt::size_t som_t::get_closest_neuron(const std::vector<Scalar>& data)
@ -267,12 +269,5 @@ 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());
}
} }