diff --git a/.idea/editor.xml b/.idea/editor.xml
index 5fff85e..b0d69ef 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -240,5 +240,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0d49a2b..227a303 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
-project(COSC-4P80-Assignment-3 VERSION 0.0.25)
+project(COSC-4P80-Assignment-3 VERSION 0.0.26)
include(FetchContent)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
diff --git a/__pycache__/plot_heatmap.cpython-311.pyc b/__pycache__/plot_heatmap.cpython-311.pyc
new file mode 100644
index 0000000..900d7fc
Binary files /dev/null and b/__pycache__/plot_heatmap.cpython-311.pyc differ
diff --git a/include/assign3/fwdecl.h b/include/assign3/fwdecl.h
index ee1e48f..f5b8e06 100644
--- a/include/assign3/fwdecl.h
+++ b/include/assign3/fwdecl.h
@@ -64,9 +64,9 @@ namespace assign3
};
inline std::array init_names{
- "Completely Random",
- "Random Data Based",
- "Sample Based"
+ "Random Unit",
+ "Random Bounded",
+ "Random Sample"
};
inline std::array init_helps{
diff --git a/plot_heatmap.py b/plot_heatmap.py
index 127d45c..7d53964 100644
--- a/plot_heatmap.py
+++ b/plot_heatmap.py
@@ -1,8 +1,6 @@
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]
@@ -25,8 +23,8 @@ 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.suptitle(subtitle)
+plt.suptitle('Heatmap of Motor Data (Bins: {})'.format(size))
+plt.title(subtitle)
plt.gca().invert_yaxis()
diff --git a/plot_line_graph.py b/plot_line_graph.py
index a628c32..dc3aaee 100644
--- a/plot_line_graph.py
+++ b/plot_line_graph.py
@@ -2,17 +2,28 @@ import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import sys
-
-from plot_heatmap import subtitle
+import os
file1 = sys.argv[1]
file2 = sys.argv[2]
bins = sys.argv[3]
split = sys.argv[4]
if len(sys.argv) > 4:
- subtitle = sys.argv[5]
+ subtitle1 = sys.argv[5]
+ subtitle2 = sys.argv[6]
else:
- subtitle = ""
+ subtitle1 = ""
+ subtitle2 = ""
+
+print(file1)
+print(file2)
+dir_path = os.path.dirname(os.path.realpath(__file__))
+cwd = os.getcwd()
+print(dir_path)
+print(cwd)
+
+with open(file1, "r+") as f:
+ print(f.name)
df1 = pd.read_csv(file1)
df2 = pd.read_csv(file2)
@@ -41,7 +52,7 @@ if split.lower() == "false":
ax2.set_ylim(y_min, y_max)
ax1.set_title('Topological and Quantization Error (Bins: {})'.format(bins))
- fig.suptitle(subtitle)
+ fig.suptitle(subtitle1)
plt.savefig("errors{}.png".format(bins))
else:
@@ -51,8 +62,8 @@ else:
plt.tick_params(axis='y', labelcolor='b')
plt.ylim(0, 1)
- plt.title("Topological Error (Bins: {})".format(bins))
- plt.suptitle(subtitle)
+ plt.suptitle("Topological Error (Bins: {})".format(bins))
+ plt.title(subtitle1)
plt.savefig("errors-topological{}.png".format(bins))
@@ -62,8 +73,8 @@ else:
plt.tick_params(axis='y', labelcolor='b')
plt.ylim(y_min, y_max)
- plt.title("Quantization Error (Bins: {})".format(bins))
- plt.suptitle(subtitle)
+ plt.suptitle("Quantization Error (Bins: {})".format(bins))
+ plt.title(subtitle2)
plt.savefig("errors-quantization{}.png".format(bins))
diff --git a/src/main.cpp b/src/main.cpp
index cc503a3..cf63636 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -12,28 +12,26 @@
#include
#include
-void plot_heatmap(const std::string& path, const std::string& activations_csv, blt::size_t bin_size, const std::string& subtitle)
+void plot_heatmap(const std::string& activations_csv, const blt::size_t bin_size, const std::string& subtitle)
{
#ifdef __linux__
- auto pwd = std::filesystem::current_path();
- if (!blt::string::ends_with(pwd.string(), '/'))
- pwd += '/';
- std::string command = "cd '" + path + "' && python3 " + pwd.string() + "plot_heatmap.py '" + activations_csv + "' " + std::to_string(bin_size) + " '" +
- subtitle + "'";
- std::system(("sh -c \"" + command + "\"").c_str());
+ const auto path = std::filesystem::current_path().string();
+ const std::string command = "cd '" + path + "' && python3 ../plot_heatmap.py '" + activations_csv + "' '" + std::to_string(bin_size) + "' '" +
+ subtitle + "'";
+ BLT_TRACE(command);
+ std::system(command.c_str());
#endif
}
-void plot_line_graph(const std::string& path, const std::string& topological_csv, const std::string& quantization_csv, blt::size_t bin_size,
- const std::string& subtitle)
+void plot_line_graph(const std::string& topological_csv, const std::string& quantization_csv, blt::size_t bin_size,
+ const std::string& subtitle, const std::string& subtitle2)
{
#ifdef __linux__
- auto pwd = std::filesystem::current_path();
- if (!blt::string::ends_with(pwd.string(), '/'))
- pwd += '/';
- std::string command = "cd '" + path + "' && python3 " + pwd.string() + "plot_line_graph.py '" + topological_csv + "' '" + quantization_csv + "' " +
- std::to_string(bin_size) + " false '" + subtitle + "'";
- std::system(("sh -c \"" + command + "\"").c_str());
+ const auto path = std::filesystem::current_path().string();
+ const std::string command = "cd '" + path + "' && python3 ../plot_line_graph.py \"" + topological_csv + "\" \"" + quantization_csv + "\" " +
+ std::to_string(bin_size) + " true \"" + subtitle + "\" \"" + subtitle2 + "\"";
+ BLT_TRACE(command);
+ std::system(command.c_str());
#endif
}
@@ -49,11 +47,11 @@ void init(const blt::gfx::window_data&)
{
using namespace blt::gfx;
BLT_INFO("Hello World!");
-
+
global_matrices.create_internals();
resources.load_resources();
renderer.create();
-
+
ImPlot::CreateContext();
}
@@ -61,11 +59,11 @@ void update(const blt::gfx::window_data& window_data)
{
using namespace blt::gfx;
global_matrices.update_perspectives(window_data.width, window_data.height, 90, 0.1, 2000);
-
+
camera.update();
camera.update_view(global_matrices);
global_matrices.update();
-
+
renderer.render();
}
@@ -91,15 +89,15 @@ void action_start_graphics(const std::vector& argv_vector)
{
blt::arg_parse parser{};
parser.setHelpExtras("graphics");
-
+
parser.addArgument(blt::arg_builder{"--file", "-f"}
- .setDefault("../data")
- .setHelp("Path to data files").build());
-
+ .setDefault("../data")
+ .setHelp("Path to data files").build());
+
auto args = parser.parse_args(argv_vector);
-
+
load_data_files(args.get("file"));
-
+
blt::gfx::init(blt::gfx::window_data{"My Sexy Window", init, update, destroy}.setSyncInterval(1).setMaximized(true));
}
@@ -111,13 +109,14 @@ struct task_t // NOLINT
shape_t shape;
init_t init;
Scalar initial_learn_rate;
-
+
task_t() = default; // NOLINT
-
+
task_t(data_file_t* file, blt::u32 width, blt::u32 height, size_t maxEpochs, shape_t shape, init_t init, Scalar initial_learn_rate):
- file(file), width(width), height(height), max_epochs(maxEpochs), shape(shape), init(init), initial_learn_rate(initial_learn_rate)
- {}
-
+ file(file), width(width), height(height), max_epochs(maxEpochs), shape(shape), init(init), initial_learn_rate(initial_learn_rate)
+ {
+ }
+
gaussian_function_t topology_func{};
std::vector> topological_errors{};
std::vector> quantization_errors{};
@@ -128,26 +127,27 @@ void action_test(const std::vector& argv_vector)
{
blt::arg_parse parser{};
parser.setHelpExtras("test");
-
+
parser.addArgument(blt::arg_builder{"--file", "-f"}
- .setDefault("../data")
- .setHelp("Path to data files").build());
-
+ .setDefault("../data")
+ .setHelp("Path to data files").build());
+
auto args = parser.parse_args(argv_vector);
-
+
load_data_files(args.get("file"));
-
+
std::vector tasks;
std::vector threads;
std::mutex task_mutex;
-
+
tasks.emplace_back(&data.files[1], 5, 5, 1000, shape_t::GRID, init_t::RANDOM_DATA, 0.1);
-
+
static blt::size_t runs = 30;
-
+
for (blt::size_t _ = 0; _ < std::thread::hardware_concurrency(); _++)
{
- threads.emplace_back([&task_mutex, &tasks]() {
+ threads.emplace_back([&task_mutex, &tasks]()
+ {
do
{
task_t task;
@@ -158,26 +158,26 @@ void action_test(const std::vector& argv_vector)
task = std::move(tasks.back());
tasks.pop_back();
}
-
+
for (blt::size_t run = 0; run < runs; run++)
{
gaussian_function_t func{};
auto dist = distance_function_t::from_shape(task.shape, task.width, task.height);
- std::unique_ptr som = std::make_unique(*task.file, task.width, task.height, task.max_epochs, dist.get(),
- &task.topology_func, task.shape, task.init, false);
+ auto som = std::make_unique(*task.file, task.width, task.height, task.max_epochs, dist.get(),
+ &task.topology_func, task.shape, task.init, false);
while (som->get_current_epoch() < som->get_max_epochs())
som->train_epoch(task.initial_learn_rate);
-
+
task.topological_errors.push_back(som->get_topological_errors());
task.quantization_errors.push_back(som->get_quantization_errors());
-
+
std::vector acts;
for (const auto& v : som->get_array().get_map())
acts.push_back(v.get_activation());
task.activations.emplace_back(std::move(acts));
}
std::stringstream paths;
- paths << "./bins-" << task.file->data_points.begin()->bins.size() << "/";
+ paths << "bins-" << task.file->data_points.begin()->bins.size() << "/";
paths << task.width << "x" << task.height << '-' << task.max_epochs << '/';
std::string shape_name = shape_names[static_cast(task.shape)];
blt::string::replaceAll(shape_name, " ", "-");
@@ -187,15 +187,15 @@ void action_test(const std::vector& argv_vector)
paths << init_name << '-' << task.initial_learn_rate << '/';
auto path = paths.str();
std::filesystem::create_directories(path);
-
+
std::vector average_topological_errors;
std::vector average_quantization_errors;
std::vector average_activations;
-
+
average_topological_errors.resize(task.topological_errors.begin()->size());
average_quantization_errors.resize(task.quantization_errors.begin()->size());
average_activations.resize(task.activations.begin()->size());
-
+
for (const auto& vec : task.topological_errors)
for (auto [index, v] : blt::enumerate(vec))
average_topological_errors[index] += v;
@@ -205,11 +205,18 @@ void action_test(const std::vector& argv_vector)
for (const auto& vec : task.activations)
for (auto [index, v] : blt::enumerate(vec))
average_activations[index] += v;
-
+
+ auto min_quant = *std::min_element(average_quantization_errors.begin(), average_quantization_errors.end()) / static_cast(runs);
+ auto max_quant = *std::max_element(average_quantization_errors.begin(), average_quantization_errors.end()) / static_cast(runs);
+
+ auto min_topo = *std::min_element(average_topological_errors.begin(), average_topological_errors.end()) / static_cast(runs);
+ auto max_topo = *std::max_element(average_topological_errors.begin(), average_topological_errors.end()) / static_cast(runs);
+
std::ofstream topological{path + "topological_avg.csv"};
std::ofstream quantization{path + "quantization_avg.csv"};
- std::ofstream activations{path + "activations_avg.csv"};
-
+ std::ofstream activations_avg{path + "activations_avg.csv"};
+ std::ofstream activations{path + "activations.csv"};
+
topological << "error\n";
quantization << "error\n";
for (auto [i, v] : blt::enumerate(average_topological_errors))
@@ -221,6 +228,15 @@ void action_test(const std::vector& argv_vector)
quantization << v / static_cast(runs) << '\n';
}
for (auto [i, v] : blt::enumerate(average_activations))
+ {
+ activations_avg << v / static_cast(runs);
+ if (i % task.width == task.width - 1)
+ activations_avg << '\n';
+ else
+ activations_avg << ',';
+ }
+
+ for (auto [i, v] : blt::enumerate(task.activations.front()))
{
activations << v / static_cast(runs);
if (i % task.width == task.width - 1)
@@ -228,13 +244,24 @@ void action_test(const std::vector& argv_vector)
else
activations << ',';
}
-
+
+ plot_heatmap(path + "activations.csv", task.file->data_points.front().bins.size(),
+ std::to_string(task.width) + "x" + std::to_string(task.height) + " " += shape_name + ", " += init_name + ", " +
+ std::to_string(task.max_epochs) + " Epochs");
+
+ plot_line_graph(path + "topological_avg.csv", path + "quantization_avg.csv", task.file->data_points.front().bins.size(),
+ std::to_string(task.width) + "x" + std::to_string(task.height) + " " += shape_name + ", " += init_name + ", Min: " +
+ std::to_string(min_topo) + ", Max: " + std::to_string(max_topo) + ", " + std::to_string(task.max_epochs) + " Epochs",
+ std::to_string(task.width) + "x" + std::to_string(task.height) + " " += shape_name + ", " += init_name + ", Min: " +
+ std::to_string(min_quant) + ", Max: " + std::to_string(max_quant) + ", " + std::to_string(task.max_epochs) +
+ " Epochs");
+
BLT_INFO("Task '%s' Complete", path.c_str());
-
- } while (true);
+ }
+ while (true);
});
}
-
+
while (!threads.empty())
{
if (threads.back().joinable())
@@ -249,7 +276,7 @@ void action_convert(const std::vector& argv_vector)
{
blt::arg_parse parser{};
parser.setHelpExtras("convert");
-
+
auto args = parser.parse_args(argv_vector);
}
@@ -258,28 +285,28 @@ int main(int argc, const char** argv)
std::vector argv_vector;
for (int i = 0; i < argc; i++)
argv_vector.emplace_back(argv[i]);
-
+
blt::arg_parse parser{};
-
+
parser.addArgument(blt::arg_builder{"action"}
- .setAction(blt::arg_action_t::SUBCOMMAND)
- .setHelp("Action to run. Can be: [graphics, test, convert]").build());
-
+ .setAction(blt::arg_action_t::SUBCOMMAND)
+ .setHelp("Action to run. Can be: [graphics, test, convert]").build());
+
auto args = parser.parse_args(argv_vector);
-
+
if (!args.contains("action"))
{
BLT_ERROR("Please provide an action");
return 0;
}
-// argv_vector.erase(argv_vector.begin() + 1);
+ // argv_vector.erase(argv_vector.begin() + 1);
#ifdef __EMSCRIPTEN__
action_start_graphics(argv_vector);
return 0;
#endif
-
+
auto action = blt::string::toLowerCase(args.get("action"));
if (action == "graphics")
action_start_graphics(argv_vector);
@@ -287,5 +314,4 @@ int main(int argc, const char** argv)
action_test(argv_vector);
else if (action == "convert")
action_convert(argv_vector);
-
}