Better handling of printing results board
This commit is contained in:
		| @@ -1,6 +1,5 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
| namespace fs = std::filesystem; |  | ||||||
| #include "data.hpp" | #include "data.hpp" | ||||||
| #include "toolbox.hpp" | #include "toolbox.hpp" | ||||||
| //#include "config.hpp" | //#include "config.hpp" | ||||||
| @@ -53,62 +52,64 @@ bool unit_test_argsort_2d(const np::Array<T>& a, const np::Array<uint16_t>& indi | |||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T, typename F, typename... Args> | template <typename T, typename F, typename... Args> | ||||||
| T benchmark_function(const char* step_name, const F& fnc, Args &&...args) noexcept { | T benchmark_function(const char* const step_name, const int32_t& column_width, const F& fnc, Args &&...args) noexcept { | ||||||
| #if __DEBUG == false | #if __DEBUG == false | ||||||
| 	printf("%s...\r", step_name); | 	fprintf(stderr, "%s...\r", step_name); | ||||||
| 	fflush(stdout); // manual flush is mandatory, otherwise it will not be shown immediately because the output is buffered | 	fflush(stderr); // manual flush is mandatory, otherwise it will not be shown immediately because the output is buffered | ||||||
| #endif | #endif | ||||||
| 	const std::chrono::system_clock::time_point start = perf_counter_ns(); | 	const std::chrono::system_clock::time_point start = perf_counter_ns(); | ||||||
| 	const T res = fnc(std::forward<Args>(args)...); | 	const T res = fnc(std::forward<Args>(args)...); | ||||||
| 	const long long time_spent = duration_ns(perf_counter_ns() - start); | 	const long long time_spent = duration_ns(perf_counter_ns() - start); | ||||||
| 	printf("| %-49s | %18s | %-29s |\n", step_name, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str()); | 	formatted_row<3>({ column_width, -18, 29 }, { step_name, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() }); | ||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename F, typename... Args> | template <typename F, typename... Args> | ||||||
| void benchmark_function_void(const char* step_name, const F& fnc, Args &&...args) noexcept { | void benchmark_function_void(const char* const step_name, const int32_t& column_width, const F& fnc, Args &&...args) noexcept { | ||||||
| #if __DEBUG == false | #if __DEBUG == false | ||||||
| 	printf("%s...\r", step_name); | 	fprintf(stderr, "%s...\r", step_name); | ||||||
| 	fflush(stdout); // manual flush is mandatory, otherwise it will not be shown immediately because the output is buffered | 	fflush(stderr); // manual flush is mandatory, otherwise it will not be shown immediately because the output is buffered | ||||||
| #endif | #endif | ||||||
| 	const std::chrono::system_clock::time_point start = perf_counter_ns(); | 	const std::chrono::system_clock::time_point start = perf_counter_ns(); | ||||||
| 	fnc(std::forward<Args>(args)...); | 	fnc(std::forward<Args>(args)...); | ||||||
| 	const long long time_spent = duration_ns(perf_counter_ns() - start); | 	const long long time_spent = duration_ns(perf_counter_ns() - start); | ||||||
| 	printf("| %-49s | %18s | %-29s |\n", step_name, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str()); | 	formatted_row<3>({ column_width, -18, 29 }, { step_name, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() }); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T, typename F, typename... Args> | template <typename T, typename F, typename... Args> | ||||||
| np::Array<T> state_saver(const char* step_name, const char* filename, const bool& force_redo, const bool& save_state, const char* out_dir, const F& fnc, Args &&...args) noexcept { | np::Array<T> state_saver(const char* const step_name, const int32_t& column_width, const char* const filename, const bool& force_redo, const bool& save_state, const char* const out_dir, const F& fnc, Args &&...args) noexcept { | ||||||
| 	char filepath[BUFFER_SIZE] = { 0 }; | 	char filepath[BUFFER_SIZE] = { 0 }; | ||||||
| 	sprintf(filepath, "%s/%s.bin", out_dir, filename); | 	snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename); | ||||||
|  |  | ||||||
| 	np::Array<T> bin; | 	np::Array<T> bin; | ||||||
| 	if (!fs::exists(filepath) || force_redo) { | 	if (!std::filesystem::exists(filepath) || force_redo) { | ||||||
| 		bin = std::move(benchmark_function<np::Array<T>>(step_name, fnc, std::forward<Args>(args)...)); | 		//bin = std::move(benchmark_function<np::Array<T>>(step_name, column_width, fnc, std::forward<Args>(args)...)); | ||||||
|  | 		bin = benchmark_function<np::Array<T>>(step_name, column_width, fnc, std::forward<Args>(args)...); | ||||||
| 		if(save_state){ | 		if(save_state){ | ||||||
| #if __DEBUG == false | #if __DEBUG == false | ||||||
| 			printf("Saving results of %s\r", step_name); | 			fprintf(stderr, "Saving results of %s\r", step_name); | ||||||
| 			fflush(stdout); | 			fflush(stderr); | ||||||
| #endif | #endif | ||||||
| 			save<T>(bin, filepath); | 			save<T>(bin, filepath); | ||||||
| #if __DEBUG == false | #if __DEBUG == false | ||||||
| 			printf("%*c\r", 100, ' '); | 			fprintf(stderr, "%*c\r", 100, ' '); // Clear previous clear | ||||||
| 			fflush(stdout); | 			fflush(stderr); | ||||||
| #endif | #endif | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| #if __DEBUG == false | #if __DEBUG == false | ||||||
| 		printf("Loading results of %s\r", step_name); | 		fprintf(stderr, "Loading results of %s\r", step_name); | ||||||
| 		fflush(stdout); | 		fflush(stderr); | ||||||
| #endif | #endif | ||||||
| 		bin = std::move(load<T>(filepath)); | 		//bin = std::move(load<T>(filepath)); | ||||||
| 		printf("| %-49s | %18s | %-29s |\n", step_name, "None", "loaded saved state"); | 		bin = load<T>(filepath); | ||||||
|  | 		formatted_row<3>({ column_width, -18, 29 }, { step_name, "None", "loaded saved state" }); | ||||||
| 	} | 	} | ||||||
| 	return bin; | 	return bin; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T, size_t N, typename F, typename... Args> | template <typename T, size_t N, typename F, typename... Args> | ||||||
| std::array<np::Array<T>, N> state_saver(const char* step_name, const std::vector<const char*>& filenames, const bool& force_redo, const bool& save_state, const char* out_dir, const F& fnc, Args &&...args) noexcept { | std::array<np::Array<T>, N> state_saver(const char* const step_name, const int32_t& column_width, const std::vector<const char*>& filenames, const bool& force_redo, const bool& save_state, const char* const out_dir, const F& fnc, Args &&...args) noexcept { | ||||||
| 	char filepath[BUFFER_SIZE] = { 0 }; | 	char filepath[BUFFER_SIZE] = { 0 }; | ||||||
| 	bool abs = false; | 	bool abs = false; | ||||||
| 	for (const char* filename : filenames){ | 	for (const char* filename : filenames){ | ||||||
| @@ -121,11 +122,12 @@ std::array<np::Array<T>, N> state_saver(const char* step_name, const std::vector | |||||||
|  |  | ||||||
| 	std::array<np::Array<T>, N> bin; | 	std::array<np::Array<T>, N> bin; | ||||||
| 	if (abs || force_redo) { | 	if (abs || force_redo) { | ||||||
| 		bin = std::move(benchmark_function<std::array<np::Array<T>, N>>(step_name, fnc, std::forward<Args>(args)...)); | 		//bin = std::move(benchmark_function<std::array<np::Array<T>, N>>(step_name, column_width, fnc, std::forward<Args>(args)...)); | ||||||
|  | 		bin = benchmark_function<std::array<np::Array<T>, N>>(step_name, column_width, fnc, std::forward<Args>(args)...); | ||||||
| 		if (save_state){ | 		if (save_state){ | ||||||
| #if __DEBUG == false | #if __DEBUG == false | ||||||
| 			printf("Saving results of %s\r", step_name); | 			fprintf(stderr, "Saving results of %s\r", step_name); | ||||||
| 			fflush(stdout); | 			fflush(stderr); | ||||||
| #endif | #endif | ||||||
| 			size_t i = 0; | 			size_t i = 0; | ||||||
| 			for (const char* filename : filenames){ | 			for (const char* filename : filenames){ | ||||||
| @@ -133,21 +135,21 @@ std::array<np::Array<T>, N> state_saver(const char* step_name, const std::vector | |||||||
| 				save<T>(bin[i++], filepath); | 				save<T>(bin[i++], filepath); | ||||||
| 			} | 			} | ||||||
| #if __DEBUG == false | #if __DEBUG == false | ||||||
| 			printf("%*c\r", 100, ' '); | 			fprintf(stderr, "%*c\r", 100, ' '); // Clear previous print | ||||||
| 			fflush(stdout); | 			fflush(stderr); | ||||||
| #endif | #endif | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| #if __DEBUG == false | #if __DEBUG == false | ||||||
| 		printf("Loading results of %s\r", step_name); | 		fprintf(stderr, "Loading results of %s\r", step_name); | ||||||
| 		fflush(stdout); | 		fflush(stderr); | ||||||
| #endif | #endif | ||||||
| 		size_t i = 0; | 		size_t i = 0; | ||||||
| 		for (const char* filename : filenames){ | 		for (const char* filename : filenames){ | ||||||
| 			sprintf(filepath, "%s/%s.bin", out_dir, filename); |  | ||||||
| 			bin[i++] = std::move(load<T>(filepath)); | 			bin[i++] = std::move(load<T>(filepath)); | ||||||
|  | 			snprintf(filepath, BUFFER_SIZE, "%s/%s.bin", out_dir, filename); | ||||||
| 		} | 		} | ||||||
| 		printf("| %-49s | %18s | %-29s |\n", step_name, "None", "loaded saved state"); | 		formatted_row<3>({ column_width, -18, 29 }, { step_name, "None", "loaded saved state" }); | ||||||
| 	} | 	} | ||||||
| 	return bin; | 	return bin; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  | #include <array> | ||||||
|  |  | ||||||
| #define DATA_DIR "../data" | #define DATA_DIR "../data" | ||||||
| #define OUT_DIR "./out" | #define OUT_DIR "./out" | ||||||
| @@ -11,7 +12,7 @@ | |||||||
| #define NB_THREADS_3D_X 16 | #define NB_THREADS_3D_X 16 | ||||||
| #define NB_THREADS_3D_Y 16 | #define NB_THREADS_3D_Y 16 | ||||||
| #define NB_THREADS_3D_Z 4 | #define NB_THREADS_3D_Z 4 | ||||||
| __device__ constexpr const size_t M = 5; //log2(NB_THREADS_2D_Y)); | #define M static_cast<size_t>(log2f(NB_THREADS_2D_Y)) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Save state to avoid recalculation on restart | // Save state to avoid recalculation on restart | ||||||
| @@ -22,17 +23,19 @@ __device__ constexpr const size_t M = 5; //log2(NB_THREADS_2D_Y)); | |||||||
| // Use GPU to greatly accelerate runtime | // Use GPU to greatly accelerate runtime | ||||||
| #define GPU_BOOSTED true | #define GPU_BOOSTED true | ||||||
| // Depending on what you set, the output label will be as follow : | // Depending on what you set, the output label will be as follow : | ||||||
| // | GPU_BOOSTED | LABEL | | // ┌─────────────┬───────┐ | ||||||
| // |-------------|-------| | // │ GPU_BOOSTED │ LABEL │ | ||||||
| // | true        | GPU   | | // ├─────────────┼───────┤ | ||||||
| // | false       | CPU   | | // │ true        │ GPU   │ | ||||||
|  | // │ false       │ CPU   │ | ||||||
|  | // └─────────────┴───────┘ | ||||||
|  |  | ||||||
| // Number of weak classifiers | // Number of weak classifiers | ||||||
| // const size_t TS[] =  { 1 }; | // [[maybe_unused]] constexpr const std::array TS{ 1 }; | ||||||
| // const size_t TS[] =  { 1, 5, 10 }; | // [[maybe_unused]] constexpr const std::array TS{ 1, 5, 10 }; | ||||||
| const size_t TS[] =  { 1, 5, 10, 25, 50 }; | [[maybe_unused]] constexpr const std::array TS{ 1, 5, 10, 25, 50 }; | ||||||
| // const size_t TS[] =  { 1, 5, 10, 25, 50, 100, 200, 300 }; | // [[maybe_unused]] constexpr const std::array TS{ 1, 5, 10, 25, 50, 100, 200, 300 }; | ||||||
| // const size_t TS[] =  { 1, 5, 10, 25, 50, 100, 200, 300, 400, 500, 1000 }; | // [[maybe_unused]] constexpr const std::array TS{ 1, 5, 10, 25, 50, 100, 200, 300, 400, 500, 1000 }; | ||||||
|  |  | ||||||
| // Enable verbose output (for debugging purposes) | // Enable verbose output (for debugging purposes) | ||||||
| #define __DEBUG false | #define __DEBUG false | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
|  |  | ||||||
| #define BUFFER_SIZE 256 | #define BUFFER_SIZE 256 | ||||||
| #define STRING_INT_SIZE 8 // Length of a number in log10 (including '-') | #define STRING_INT_SIZE 8 // Length of a number in log10 (including '-') | ||||||
| #define S(N) std::string(N, '-').c_str() |  | ||||||
|  |  | ||||||
| #ifndef __CUDACC__ | #ifndef __CUDACC__ | ||||||
| #define __host__ | #define __host__ | ||||||
|   | |||||||
							
								
								
									
										152
									
								
								cpp/projet.cpp
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								cpp/projet.cpp
									
									
									
									
									
								
							| @@ -27,10 +27,11 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra | |||||||
| 		for (const char* const folder_name : { "models", "out" }) | 		for (const char* const folder_name : { "models", "out" }) | ||||||
| 			fs::create_directory(folder_name); | 			fs::create_directory(folder_name); | ||||||
|  |  | ||||||
| 	printf("| %-49s | %-18s | %-29s |\n", "Preprocessing", "Time spent (ns)", "Formatted time spent"); | 	const std::chrono::system_clock::time_point preproc_timestamp = perf_counter_ns(); | ||||||
| 	printf("|%s|%s|%s|\n", S(51), S(20), S(31)); | 	const std::array<int32_t, 3> preproc_gaps = { 49, -18, 29 }; | ||||||
|  | 	header({ "Preprocessing", "Time spent (ns)", "Formatted time spent" }, preproc_gaps); | ||||||
|  |  | ||||||
| 	const auto [ X_train, y_train, X_test, y_test ] = state_saver<uint8_t, 4>("Loading sets", {"X_train", "y_train", "X_test", "y_test"}, | 	const auto [ X_train, y_train, X_test, y_test ] = state_saver<uint8_t, 4>("Loading sets", preproc_gaps[0], {"X_train", "y_train", "X_test", "y_test"}, | ||||||
| 			FORCE_REDO, SAVE_STATE, OUT_DIR, load_datasets); | 			FORCE_REDO, SAVE_STATE, OUT_DIR, load_datasets); | ||||||
|  |  | ||||||
| #if __DEBUG | #if __DEBUG | ||||||
| @@ -48,7 +49,7 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra | |||||||
| 	print(y_test, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET }); | 	print(y_test, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET }); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	const np::Array<uint8_t> feats = state_saver<uint8_t>("Building features", "feats", | 	const np::Array<uint8_t> feats = state_saver<uint8_t>("Building features", preproc_gaps[0], "feats", | ||||||
| 			FORCE_REDO, SAVE_STATE, OUT_DIR, build_features, X_train.shape[1], X_train.shape[2]); | 			FORCE_REDO, SAVE_STATE, OUT_DIR, build_features, X_train.shape[1], X_train.shape[2]); | ||||||
|  |  | ||||||
| #if __DEBUG | #if __DEBUG | ||||||
| @@ -57,9 +58,9 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra | |||||||
| 	print_feat(feats, { IDX_INSPECT }); | 	print_feat(feats, { IDX_INSPECT }); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	const np::Array<uint32_t> X_train_ii = state_saver<uint32_t>("Converting training set to integral images (" LABEL ")", "X_train_ii_" LABEL, | 	const np::Array<uint32_t> X_train_ii = state_saver<uint32_t>("Converting training set to integral images (" LABEL ")", preproc_gaps[0], "X_train_ii_" LABEL, | ||||||
| 			FORCE_REDO, SAVE_STATE, OUT_DIR, set_integral_image, X_train); | 			FORCE_REDO, SAVE_STATE, OUT_DIR, set_integral_image, X_train); | ||||||
| 	const np::Array<uint32_t> X_test_ii = state_saver<uint32_t>("Converting testing set to integral images (" LABEL ")", "X_test_ii_" LABEL, | 	const np::Array<uint32_t> X_test_ii = state_saver<uint32_t>("Converting testing set to integral images (" LABEL ")", preproc_gaps[0], "X_test_ii_" LABEL, | ||||||
| 			FORCE_REDO, SAVE_STATE, OUT_DIR, set_integral_image, X_test); | 			FORCE_REDO, SAVE_STATE, OUT_DIR, set_integral_image, X_test); | ||||||
|  |  | ||||||
| #if __DEBUG | #if __DEBUG | ||||||
| @@ -71,9 +72,9 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra | |||||||
| 	print(X_test_ii, { IDX_INSPECT }); | 	print(X_test_ii, { IDX_INSPECT }); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	const np::Array<int32_t> X_train_feat = state_saver<int32_t>("Applying features to training set (" LABEL ")", "X_train_feat_" LABEL, | 	const np::Array<int32_t> X_train_feat = state_saver<int32_t>("Applying features to training set (" LABEL ")", preproc_gaps[0], "X_train_feat_" LABEL, | ||||||
| 			FORCE_REDO, SAVE_STATE, OUT_DIR, apply_features, feats, X_train_ii); | 			FORCE_REDO, SAVE_STATE, OUT_DIR, apply_features, feats, X_train_ii); | ||||||
| 	const np::Array<int32_t> X_test_feat = state_saver<int32_t>("Applying features to testing set (" LABEL ")", "X_test_feat_" LABEL, | 	const np::Array<int32_t> X_test_feat = state_saver<int32_t>("Applying features to testing set (" LABEL ")", preproc_gaps[0], "X_test_feat_" LABEL, | ||||||
| 			FORCE_REDO, SAVE_STATE, OUT_DIR, apply_features, feats, X_test_ii); | 			FORCE_REDO, SAVE_STATE, OUT_DIR, apply_features, feats, X_test_ii); | ||||||
|  |  | ||||||
| #if __DEBUG | #if __DEBUG | ||||||
| @@ -92,7 +93,7 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra | |||||||
| 	// print_feature(indices); | 	// print_feature(indices); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	const np::Array<uint16_t> X_train_feat_argsort = state_saver<uint16_t>("Precalculating training set argsort (" LABEL ")", "X_train_feat_argsort_" LABEL, | 	const np::Array<uint16_t> X_train_feat_argsort = state_saver<uint16_t>("Precalculating training set argsort (" LABEL ")", preproc_gaps[0], "X_train_feat_argsort_" LABEL, | ||||||
| 			FORCE_REDO, SAVE_STATE, OUT_DIR, argsort_2d, X_train_feat); | 			FORCE_REDO, SAVE_STATE, OUT_DIR, argsort_2d, X_train_feat); | ||||||
|  |  | ||||||
| #if __DEBUG | #if __DEBUG | ||||||
| @@ -101,35 +102,38 @@ std::tuple<np::Array<int32_t>, np::Array<uint16_t>, np::Array<uint8_t>, np::Arra | |||||||
| 	print(X_train_feat_argsort, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET }); | 	print(X_train_feat_argsort, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET }); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	const np::Array<uint16_t> X_test_feat_argsort = state_saver<uint16_t>("Precalculating testing set argsort (" LABEL ")", "X_test_feat_argsort_" LABEL, | 	// const np::Array<uint16_t> X_test_feat_argsort = state_saver<uint16_t>("Precalculating testing set argsort (" LABEL ")", preproc_gaps[0], "X_test_feat_argsort_" LABEL, | ||||||
| 			FORCE_REDO, SAVE_STATE, OUT_DIR, argsort_2d, X_test_feat); | 	// 		FORCE_REDO, SAVE_STATE, OUT_DIR, argsort_2d, X_test_feat); | ||||||
|  |  | ||||||
| #if __DEBUG | #if __DEBUG | ||||||
| 	print("X_test_feat_argsort"); | 	// printf("X_test_feat_argsort\n"); | ||||||
| 	print(X_test_feat_argsort.shape); | 	// print(X_test_feat_argsort.shape); | ||||||
| 	print(X_test_feat_argsort, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET }); | 	// print(X_test_feat_argsort, { IDX_INSPECT, IDX_INSPECT + IDX_INSPECT_OFFSET }); | ||||||
| #endif | #endif | ||||||
|  | 	const long long time_spent = duration_ns(perf_counter_ns() - preproc_timestamp); | ||||||
|  | 	formatted_line(preproc_gaps, "├", "┼", "─", "┤"); | ||||||
|  | 	formatted_row(preproc_gaps, { "Preprocessing summary", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() }); | ||||||
|  | 	footer(preproc_gaps); | ||||||
| 	return { X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test }; | 	return { X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test }; | ||||||
| } | } | ||||||
|  |  | ||||||
| void train(const np::Array<int32_t>& X_train_feat, const np::Array<uint16_t>& X_train_feat_argsort, const np::Array<uint8_t>& y_train) { | std::array<std::array<np::Array<float64_t>, 2>, TS.size()> train(const np::Array<int32_t>& X_train_feat, const np::Array<uint16_t>& X_train_feat_argsort, const np::Array<uint8_t>& y_train) noexcept { | ||||||
| 	printf("\n| %-49s | %-18s | %-29s |\n", "Training", "Time spent (ns)", "Formatted time spent"); | 	const std::chrono::system_clock::time_point training_timestamp = perf_counter_ns(); | ||||||
| 	printf("|%s|%s|%s|\n", S(51), S(20), S(31)); | 	const std::array<int32_t, 3> training_gaps = { 26, -18, 29 }; | ||||||
|  | 	header({ "Training", "Time spent (ns)", "Formatted time spent" }, training_gaps); | ||||||
|  |  | ||||||
|  | 	std::array<std::array<np::Array<float64_t>, 2>, TS.size()> models; | ||||||
|  |  | ||||||
|  | 	size_t i = 0; | ||||||
| 	for (const size_t T : TS) { | 	for (const size_t T : TS) { | ||||||
| 		char title[BUFFER_SIZE] = { 0 }; | 		char title[BUFFER_SIZE] = { 0 }; | ||||||
| 		char alphas_title[BUFFER_SIZE] = { 0 }; | 		char alphas_title[BUFFER_SIZE] = { 0 }; | ||||||
| 		char final_classifiers_title[BUFFER_SIZE] = { 0 }; | 		char final_classifiers_title[BUFFER_SIZE] = { 0 }; | ||||||
| 		sprintf(title, "ViolaJones T = %-4lu (%s)", T, LABEL); | 		snprintf(title, BUFFER_SIZE, "ViolaJones T = %-4lu (%s)", T, LABEL); | ||||||
| 		sprintf(alphas_title, "alphas_%lu_%s", T, LABEL); | 		snprintf(alphas_title, BUFFER_SIZE, "alphas_%lu_%s", T, LABEL); | ||||||
| 		sprintf(final_classifiers_title, "final_classifiers_%lu_%s", T, LABEL); | 		snprintf(final_classifiers_title, BUFFER_SIZE, "final_classifiers_%lu_%s", T, LABEL); | ||||||
|  |  | ||||||
| #if __DEBUG | 		const auto [ alphas, final_classifiers ] = state_saver<float64_t, 2>(title, training_gaps[0], { alphas_title, final_classifiers_title }, | ||||||
| 		const auto [ alphas, final_classifiers ] = state_saver<float64_t, 2>(title, { alphas_title, final_classifiers_title }, |  | ||||||
| #else |  | ||||||
| 		state_saver<float64_t, 2>(title, { alphas_title, final_classifiers_title }, |  | ||||||
| #endif |  | ||||||
| 				FORCE_REDO, SAVE_STATE, MODEL_DIR, train_viola_jones, T, X_train_feat, X_train_feat_argsort, y_train); | 				FORCE_REDO, SAVE_STATE, MODEL_DIR, train_viola_jones, T, X_train_feat, X_train_feat_argsort, y_train); | ||||||
| #if __DEBUG | #if __DEBUG | ||||||
| 		print("alphas"); | 		print("alphas"); | ||||||
| @@ -137,31 +141,32 @@ void train(const np::Array<int32_t>& X_train_feat, const np::Array<uint16_t>& X_ | |||||||
| 		print("final_classifiers"); | 		print("final_classifiers"); | ||||||
| 		print(final_classifiers); | 		print(final_classifiers); | ||||||
| #endif | #endif | ||||||
|  | 		models[i++] = { alphas, final_classifiers }; | ||||||
| 	} | 	} | ||||||
|  | 	const long long time_spent = duration_ns(perf_counter_ns() - training_timestamp); | ||||||
|  | 	formatted_line(training_gaps, "├", "┼", "─", "┤"); | ||||||
|  | 	formatted_row(training_gaps, { "Training summary", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() }); | ||||||
|  | 	footer(training_gaps); | ||||||
|  |  | ||||||
|  | 	return models; | ||||||
| } | } | ||||||
|  |  | ||||||
| void testing_and_evaluating(const np::Array<int32_t>& X_train_feat, const np::Array<uint8_t>& y_train, const np::Array<int32_t>& X_test_feat, const np::Array<uint8_t>& y_test) { | void testing_and_evaluating(const std::array<std::array<np::Array<float64_t>, 2>, TS.size()>& models, const np::Array<int32_t>& X_train_feat, const np::Array<uint8_t>& y_train, const np::Array<int32_t>& X_test_feat, const np::Array<uint8_t>& y_test) { | ||||||
| 	printf("\n| %-26s | Time spent (ns) (E) | %-29s | Time spent (ns) (T) | %-29s |\n", "Testing", "Formatted time spent (E)", "Formatted time spent (T)"); | 	const std::array<int32_t, 5> testing_gaps = { 26, -19, 24, -19, 24 }; | ||||||
| 	printf("|%s|%s|%s|%s|%s|\n", S(28), S(21), S(31), S(21), S(31)); | 	header({ "Testing", "Time spent (ns) (E)", "Formatted time spent (E)", "Time spent (ns) (T)", "Formatted time spent (T)" }, testing_gaps); | ||||||
|  | 	std::array<std::array<float64_t, 8>, TS.size()> results; | ||||||
| 	constexpr const size_t NT = sizeof(TS) / sizeof(size_t); |  | ||||||
| 	std::array<std::array<float64_t, 8>, NT> results; |  | ||||||
|  |  | ||||||
| 	size_t i = 0; | 	size_t i = 0; | ||||||
| 	for (const size_t T : TS) { | 	long long total_train_timestamp = 0; | ||||||
|  | 	long long total_test_timestamp = 0; | ||||||
|  | 	for (const auto& [ alphas, final_classifiers ] : models) { | ||||||
| 		char title[BUFFER_SIZE] = { 0 }; | 		char title[BUFFER_SIZE] = { 0 }; | ||||||
| 		char alphas_title[BUFFER_SIZE] = { 0 }; | 		snprintf(title, BUFFER_SIZE, "ViolaJones T = %-4i (%s)", TS[i], LABEL); | ||||||
| 		char final_classifiers_title[BUFFER_SIZE] = { 0 }; |  | ||||||
| 		sprintf(title, "ViolaJones T = %-4lu (%s)", T, LABEL); |  | ||||||
| 		sprintf(alphas_title, MODEL_DIR "/alphas_%lu_%s.bin", T, LABEL); |  | ||||||
| 		sprintf(final_classifiers_title, MODEL_DIR "/final_classifiers_%lu_%s.bin", T, LABEL); |  | ||||||
|  |  | ||||||
| 		const np::Array<float64_t> alphas = load<float64_t>(alphas_title); |  | ||||||
| 		const np::Array<float64_t> final_classifiers = load<float64_t>(final_classifiers_title); |  | ||||||
|  |  | ||||||
| 		std::chrono::system_clock::time_point start = perf_counter_ns(); | 		std::chrono::system_clock::time_point start = perf_counter_ns(); | ||||||
| 		const np::Array<uint8_t> y_pred_train = classify_viola_jones(alphas, final_classifiers, X_train_feat); | 		const np::Array<uint8_t> y_pred_train = classify_viola_jones(alphas, final_classifiers, X_train_feat); | ||||||
| 		const long long t_pred_train = duration_ns(perf_counter_ns() - start); | 		const long long t_pred_train = duration_ns(perf_counter_ns() - start); | ||||||
|  | 		total_train_timestamp += t_pred_train; | ||||||
| 		const float64_t e_acc = accuracy_score(y_train, y_pred_train); | 		const float64_t e_acc = accuracy_score(y_train, y_pred_train); | ||||||
| 		const float64_t e_f1 = f1_score(y_train, y_pred_train); | 		const float64_t e_f1 = f1_score(y_train, y_pred_train); | ||||||
| 		float64_t e_FN, e_FP; | 		float64_t e_FN, e_FP; | ||||||
| @@ -170,48 +175,53 @@ void testing_and_evaluating(const np::Array<int32_t>& X_train_feat, const np::Ar | |||||||
| 		start = perf_counter_ns(); | 		start = perf_counter_ns(); | ||||||
| 		const np::Array<uint8_t> y_pred_test = classify_viola_jones(alphas, final_classifiers, X_test_feat); | 		const np::Array<uint8_t> y_pred_test = classify_viola_jones(alphas, final_classifiers, X_test_feat); | ||||||
| 		const long long t_pred_test = duration_ns(perf_counter_ns() - start); | 		const long long t_pred_test = duration_ns(perf_counter_ns() - start); | ||||||
|  | 		total_test_timestamp += t_pred_test; | ||||||
| 		const float64_t t_acc = accuracy_score(y_test, y_pred_test); | 		const float64_t t_acc = accuracy_score(y_test, y_pred_test); | ||||||
| 		const float64_t t_f1 = f1_score(y_test, y_pred_test); | 		const float64_t t_f1 = f1_score(y_test, y_pred_test); | ||||||
| 		float64_t t_FN, t_FP; | 		float64_t t_FN, t_FP; | ||||||
| 		std::tie(std::ignore, t_FN, t_FP, std::ignore) = confusion_matrix(y_test, y_pred_test); | 		std::tie(std::ignore, t_FN, t_FP, std::ignore) = confusion_matrix(y_test, y_pred_test); | ||||||
| 		results[i++] = { e_acc, e_f1, e_FN, e_FP, t_acc, t_f1, t_FN, t_FP }; | 		results[i++] = { e_acc, e_f1, e_FN, e_FP, t_acc, t_f1, t_FN, t_FP }; | ||||||
|  |  | ||||||
| 		printf("| %-26s | %'19lld | %-29s | %'19lld | %-29s |\n", title, t_pred_train, format_time_ns(t_pred_train).c_str(), t_pred_test, format_time_ns(t_pred_test).c_str()); | 		formatted_row(testing_gaps, { title, thousand_sep(t_pred_train).c_str(), format_time_ns(t_pred_train).c_str(), thousand_sep(t_pred_test).c_str(), format_time_ns(t_pred_test).c_str() }); | ||||||
| 	} | 	} | ||||||
|  | 	formatted_line(testing_gaps, "├", "┼", "─", "┤"); | ||||||
|  | 	formatted_row(testing_gaps, { "Testing summary", thousand_sep(total_train_timestamp).c_str(), format_time_ns(total_train_timestamp).c_str(), thousand_sep(total_test_timestamp).c_str(), format_time_ns(total_test_timestamp).c_str() }); | ||||||
|  | 	footer(testing_gaps); | ||||||
|  |  | ||||||
| 	printf("\n| %-19s | ACC (E) | F1 (E) | FN (E) | FP (E) | ACC (T) | F1 (T) | FN (T) | FP (T) |\n", "Evaluating"); | 	const std::array<int32_t, 9> evaluating_gaps = { 19, -7, -6, -6, -6, -7, -6, -6, -6 }; | ||||||
| 	printf("|%s|%s|%s|%s|%s|%s|%s|%s|%s|\n", S(21), S(9), S(8), S(8), S(8), S(9), S(8), S(8), S(8)); | 	header({ "Evaluating", "ACC (E)", "F1 (E)", "FN (E)", "FP (E)", "ACC (T)", "F1 (T)", "FN (T)", "FP (T)"}, evaluating_gaps); | ||||||
|  |  | ||||||
| 	i = 0; | 	i = 0; | ||||||
| 	for (const size_t T : TS) { | 	for (const size_t T : TS) { | ||||||
| 		char title[BUFFER_SIZE] = { 0 }; | 		char title[BUFFER_SIZE] = { 0 }; | ||||||
| 		sprintf(title, "ViolaJones T = %-4lu", T); | 		snprintf(title, BUFFER_SIZE, "ViolaJones T = %-4lu", T); | ||||||
| 		const auto [e_acc, e_f1, e_FN, e_FP, t_acc, t_f1, t_FN, t_FP] = results[i++]; | 		const auto [e_acc, e_f1, e_FN, e_FP, t_acc, t_f1, t_FN, t_FP] = results[i++]; | ||||||
| 		printf("| %-19s | %'6.2f%% | %'6.2f | %'6.0f | %'6.0f | %6.2f%% | %'6.2f | %'6.0f | %'6.0f |\n", title, e_acc * 100, e_f1, e_FN, e_FP, t_acc * 100, t_f1, t_FN, t_FP); | 		printf("│ %-19s │ %'6.2f%% │ %'6.2f │ %'6.0f │ %'6.0f │ %6.2f%% │ %'6.2f │ %'6.0f │ %'6.0f │\n", title, e_acc * 100, e_f1, e_FN, e_FP, t_acc * 100, t_f1, t_FN, t_FP); | ||||||
| 	} | 	} | ||||||
|  | 	footer(evaluating_gaps); | ||||||
| } | } | ||||||
|  |  | ||||||
| void unit_test(void) { | void unit_test(void) { | ||||||
| 	printf("\n| %-37s | %-10s | %-18s | %-29s |\n", "Unit testing", "Test state", "Time spent (ns)", "Formatted time spent"); | 	const std::chrono::system_clock::time_point unit_timestamp = perf_counter_ns(); | ||||||
| 	printf("|%s|%s|%s|%s|\n", S(39), S(12), S(20), S(31)); | 	const std::array<int32_t, 4> unit_gaps = { 37, -10, -18, 29}; | ||||||
|  | 	header({ "Unit testing", "Test state", "Time spent (ns)", "Formatted time spent" }, unit_gaps); | ||||||
|  |  | ||||||
| 	char title[BUFFER_SIZE] = { 0 }; | 	char title[BUFFER_SIZE] = { 0 }; | ||||||
| 	char tmp_title[BUFFER_SIZE / 2] = { 0 }; | 	char tmp_title[BUFFER_SIZE / 2] = { 0 }; | ||||||
| 	char file_cpu[BUFFER_SIZE] = { 0 }; | 	char file_cpu[BUFFER_SIZE] = { 0 }; | ||||||
| 	char file_gpu[BUFFER_SIZE] = { 0 }; | 	char file_gpu[BUFFER_SIZE] = { 0 }; | ||||||
| 	const std::chrono::system_clock::time_point fnc_s = perf_counter_ns(); |  | ||||||
| 	uint64_t n_total = 0, n_success = 0; | 	uint64_t n_total = 0, n_success = 0; | ||||||
|  |  | ||||||
| 	auto test_fnc = [&n_total, &n_success](const char* title, const auto& fnc) { | 	const auto test_fnc = [&unit_gaps, &n_total, &n_success](const char* const title, const auto& fnc) noexcept { | ||||||
| 		++n_total; | 		++n_total; | ||||||
| 		const std::chrono::system_clock::time_point start = perf_counter_ns(); | 		const std::chrono::system_clock::time_point start = perf_counter_ns(); | ||||||
| 		const bool state = fnc(); | 		const bool state = fnc(); | ||||||
| 		const long long time_spent = duration_ns(perf_counter_ns() - start); | 		const long long time_spent = duration_ns(perf_counter_ns() - start); | ||||||
| 		if(state){ | 		if(state){ | ||||||
| 			printf("| %-37s | %10s | %18s | %-29s |\n", title, "Passed", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str()); | 			formatted_row(unit_gaps, { title, "Passed", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() }); | ||||||
| 			++n_success; | 			++n_success; | ||||||
| 		} else | 		} else | ||||||
| 			printf("| %-37s | %10s | %18s | %-29s |\n", title, "Failed", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str()); | 			formatted_row(unit_gaps, { title, "Failed", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() }); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	for (const char* label : { "train", "test" }) { | 	for (const char* label : { "train", "test" }) { | ||||||
| @@ -275,32 +285,38 @@ void unit_test(void) { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 	const long long time_spent = duration_ns(perf_counter_ns() - fnc_s); | 	const long long time_spent = duration_ns(perf_counter_ns() - unit_timestamp); | ||||||
| 	sprintf(title, "%ld/%ld", n_success, n_total); | 	snprintf(title, BUFFER_SIZE, "%ld/%ld", n_success, n_total); | ||||||
|  |  | ||||||
| 	printf("|%s|%s|%s|%s|\n", S(39), S(12), S(20), S(31)); | 	formatted_line(unit_gaps, "├", "┼", "─", "┤"); | ||||||
| 	printf("| %-37s | %10s | %18s | %-29s |\n", "Unit testing summary", title, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str()); | 	formatted_row(unit_gaps, { "Unit testing summary", title, thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() }); | ||||||
|  | 	footer(unit_gaps); | ||||||
| } | } | ||||||
|  |  | ||||||
| int main(){ | int main(){ | ||||||
| 	setlocale(LC_NUMERIC, ""); // Allow proper number display | 	setlocale(LC_NUMERIC, ""); // Allow proper number display | ||||||
|  |  | ||||||
| 	printf("| %-49s | %-18s | %-29s |\n", "Unit testing", "Time spent (ns)", "Formatted time spent"); | 	const std::chrono::system_clock::time_point unit_timestamp = perf_counter_ns(); | ||||||
| 	printf("|%s|%s|%s|\n", S(51), S(20), S(31)); | 	const std::array<int32_t, 3> unit_gaps = { 27, -18, 29 }; | ||||||
|  | 	header({ "Unit testing", "Time spent (ns)", "Formatted time spent" }, unit_gaps); | ||||||
| #if GPU_BOOSTED | #if GPU_BOOSTED | ||||||
| 	benchmark_function_void("Testing GPU capabilities 1D", test_working, 3 + (1<<29)); | 	benchmark_function_void("Testing GPU capabilities 1D", unit_gaps[0], test_working, 50000); | ||||||
| 	benchmark_function_void("Testing GPU capabilities 2D", test_working_2d, 3 + (1<<15), 2 + (1<<14)); | 	benchmark_function_void("Testing GPU capabilities 2D", unit_gaps[0], test_working_2d, 200, 500); | ||||||
| 	benchmark_function_void("Testing GPU capabilities 3D", test_working_3d, 9 + (1<<10), 5 + (1<<10), 7 + (1<<9)); | 	benchmark_function_void("Testing GPU capabilities 3D", unit_gaps[0], test_working_3d, 30, 40, 500); | ||||||
| #endif | #endif | ||||||
| 	benchmark_function_void("Testing format_time", format_time_test); | 	benchmark_function_void("Testing format_time", unit_gaps[0], format_time_test); | ||||||
| 	benchmark_function_void("Testing format_time_ns", format_time_ns_test); | 	benchmark_function_void("Testing format_time_ns", unit_gaps[0], format_time_ns_test); | ||||||
| 	benchmark_function_void("Testing format_byte_size", format_byte_size_test); | 	benchmark_function_void("Testing format_byte_size", unit_gaps[0], format_byte_size_test); | ||||||
| 	benchmark_function_void("Testing thousand_sep", thousand_sep_test); | 	benchmark_function_void("Testing thousand_sep", unit_gaps[0], thousand_sep_test); | ||||||
| 	printf("\n"); | 	const long long time_spent = duration_ns(perf_counter_ns() - unit_timestamp); | ||||||
|  | 	formatted_line(unit_gaps, "├", "┼", "─", "┤"); | ||||||
|  | 	formatted_row(unit_gaps, { "Unit testing summary", thousand_sep(time_spent).c_str(), format_time_ns(time_spent).c_str() }); | ||||||
|  | 	footer(unit_gaps); | ||||||
|  |  | ||||||
| 	const auto [ X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test ] = preprocessing(); | 	const auto [ X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test ] = preprocessing(); | ||||||
| 	train(X_train_feat, X_train_feat_argsort, y_train); | 	const std::array<std::array<np::Array<float64_t>, 2>, TS.size()> models = train(X_train_feat, X_train_feat_argsort, y_train); | ||||||
| 	testing_and_evaluating(X_train_feat, y_train, X_test_feat, y_test); | 	testing_and_evaluating(models, X_train_feat, y_train, X_test_feat, y_test); | ||||||
| 	unit_test(); | 	unit_test(); | ||||||
|  |  | ||||||
| 	return EXIT_SUCCESS; | 	return EXIT_SUCCESS; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,7 +1,41 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include <array> | #include <array> | ||||||
| #include <chrono> |  | ||||||
| #include <string> | #include <string> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | template<size_t N> | ||||||
|  | constexpr void formatted_row(const std::array<int32_t, N>& gaps, const std::array<const char* const, N>& titles, | ||||||
|  | 					const char* const separator = "│") noexcept { | ||||||
|  | 	for(size_t i = 0; i < N; ++i) | ||||||
|  | 		printf("%s %*s ", separator, -gaps[i], titles[i]); | ||||||
|  | 	printf("%s\n", separator); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<size_t N> | ||||||
|  | constexpr void formatted_line(const std::array<int32_t, N>& gaps, const char* const right, const char* const middle, | ||||||
|  | 			const char* const separator, const char* const left) noexcept { | ||||||
|  | 	printf("%s", right); | ||||||
|  | 	for(size_t i = 0; i < N; ++i){ | ||||||
|  | 		for(int32_t j = std::abs(gaps[i]) + 2; j > 0; --j) | ||||||
|  | 			printf("%s", separator); | ||||||
|  | 		if(i != N - 1) | ||||||
|  | 			printf("%s", middle); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printf("%s\n", left); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<size_t N> | ||||||
|  | constexpr void header(const std::array<const char* const, N>& titles, const std::array<int32_t, N>& gaps) noexcept { | ||||||
|  | 	formatted_line(gaps, "┌", "┬", "─", "┐"); | ||||||
|  | 	formatted_row(gaps, titles); | ||||||
|  | 	formatted_line(gaps, "├", "┼", "─", "┤"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<size_t N> | ||||||
|  | constexpr inline void footer(const std::array<int32_t, N>& gaps) noexcept { | ||||||
|  | 	formatted_line(gaps, "└", "┴", "─", "┘"); | ||||||
|  | } | ||||||
|  |  | ||||||
| #define duration_ns(a) std::chrono::duration_cast<std::chrono::nanoseconds>(a).count() | #define duration_ns(a) std::chrono::duration_cast<std::chrono::nanoseconds>(a).count() | ||||||
| #define perf_counter_ns() std::chrono::high_resolution_clock::now() | #define perf_counter_ns() std::chrono::high_resolution_clock::now() | ||||||
|   | |||||||
| @@ -1,44 +1,47 @@ | |||||||
|  | from typing import Final | ||||||
| import numpy as np | import numpy as np | ||||||
|  |  | ||||||
| DATA_DIR = "../data" | DATA_DIR: Final = '../data' | ||||||
| OUT_DIR = "./out" | OUT_DIR: Final = './out' | ||||||
| MODEL_DIR = "./models" | MODEL_DIR: Final = './models' | ||||||
|  |  | ||||||
| NB_THREADS = 1024 | NB_THREADS: Final = 1024 | ||||||
| NB_THREADS_2D = (32, 32) | NB_THREADS_2D: Final = (32, 32) | ||||||
| NB_THREADS_3D = (16, 16, 4) | NB_THREADS_3D: Final = (16, 16, 4) | ||||||
| M = int(np.log2(NB_THREADS_2D[1])) | M: Final = int(np.log2(NB_THREADS_2D[1])) | ||||||
|  |  | ||||||
| # Save state to avoid recalculation on restart | # Save state to avoid recalculation on restart | ||||||
| SAVE_STATE = True | SAVE_STATE: Final = True | ||||||
| # Redo the state even if it's already saved | # Redo the state even if it's already saved | ||||||
| FORCE_REDO = False | FORCE_REDO: Final = False | ||||||
| # Use NJIT to greatly accelerate runtime | # Use NJIT to greatly accelerate runtime | ||||||
| COMPILE_WITH_C = True | COMPILE_WITH_C: Final = True | ||||||
| # Use GPU to greatly accelerate runtime (as priority over NJIT) | # Use GPU to greatly accelerate runtime (as priority over NJIT) | ||||||
| GPU_BOOSTED = True | GPU_BOOSTED: Final = True | ||||||
| # Depending on what you set, the output label will be as follow : | # Depending on what you set, the output label will be as follow : | ||||||
| # | COMPILE_WITH_C | GPU_BOOSTED | LABEL | | # ┌────────────────┬─────────────┬───────┐ | ||||||
| # |----------------|-------------|-------| | # │ COMPILE_WITH_C │ GPU_BOOSTED │ LABEL │ | ||||||
| # | True           | True        | GPU   | | # ├────────────────┼─────────────┼───────┤ | ||||||
| # | True           | False       | CPU   | | # │ True           │ True        │ GPU   │ | ||||||
| # | False          | True        | PGPU  | | # │ True           │ False       │ CPU   │ | ||||||
| # | False          | False       | PY    | | # │ False          │ True        │ PGPU  │ | ||||||
|  | # │ False          │ False       │ PY    │ | ||||||
|  | # └────────────────┴─────────────┴───────┘ | ||||||
|  |  | ||||||
| # Number of weak classifiers | # Number of weak classifiers | ||||||
| # TS = [1] | # TS: Final = [1] | ||||||
| # TS = [1, 5, 10] | # TS: Final = [1, 5, 10] | ||||||
| TS = [1, 5, 10, 25, 50] | TS: Final = [1, 5, 10, 25, 50] | ||||||
| # TS = [1, 5, 10, 25, 50, 100, 200] | # TS: Final = [1, 5, 10, 25, 50, 100, 200] | ||||||
| # TS = [1, 5, 10, 25, 50, 100, 200, 300] | # TS: Final = [1, 5, 10, 25, 50, 100, 200, 300] | ||||||
| # TS = [1, 5, 10, 25, 50, 100, 200, 300, 400, 500, 1000] | # TS: Final = [1, 5, 10, 25, 50, 100, 200, 300, 400, 500, 1000] | ||||||
|  |  | ||||||
| # Enable verbose output (for debugging purposes) | # Enable verbose output (for debugging purposes) | ||||||
| __DEBUG = False | __DEBUG: Final = False | ||||||
| # Debugging options | # Debugging options | ||||||
| if __DEBUG: | if __DEBUG: | ||||||
| 	IDX_INSPECT = 4548 | 	IDX_INSPECT: Final = 4548 | ||||||
| 	IDX_INSPECT_OFFSET = 100 | 	IDX_INSPECT_OFFSET: Final = 100 | ||||||
| 	np.seterr(all = 'raise') | 	np.seterr(all = 'raise') | ||||||
| 	# Debug option (image width * log_10(length) + extra characters) | 	# Debug option (image width * log_10(length) + extra characters) | ||||||
| 	np.set_printoptions(linewidth = 19 * 6 + 3) | 	np.set_printoptions(linewidth = 19 * 6 + 3) | ||||||
|   | |||||||
							
								
								
									
										110
									
								
								python/projet.py
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								python/projet.py
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ | |||||||
| from ViolaJones import train_viola_jones, classify_viola_jones | from ViolaJones import train_viola_jones, classify_viola_jones | ||||||
| from toolbox import state_saver, picke_multi_loader, format_time_ns, benchmark_function, unit_test_argsort_2d | from toolbox import state_saver, picke_multi_loader, format_time_ns, benchmark_function, unit_test_argsort_2d | ||||||
| from toolbox_unit_test import format_time_ns_test | from toolbox_unit_test import format_time_ns_test | ||||||
|  | from toolbox import header, footer, formatted_row, formatted_line | ||||||
| from sklearn.metrics import accuracy_score, f1_score, confusion_matrix | from sklearn.metrics import accuracy_score, f1_score, confusion_matrix | ||||||
| from sklearn.feature_selection import SelectPercentile, f_classif | from sklearn.feature_selection import SelectPercentile, f_classif | ||||||
| from common import load_datasets, unit_test | from common import load_datasets, unit_test | ||||||
| @@ -38,9 +39,11 @@ def preprocessing() -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: | |||||||
| 		for folder_name in ["models", "out"]: | 		for folder_name in ["models", "out"]: | ||||||
| 			makedirs(folder_name, exist_ok = True) | 			makedirs(folder_name, exist_ok = True) | ||||||
|  |  | ||||||
| 	print(f"| {'Preprocessing':<49} | {'Time spent (ns)':<18} | {'Formatted time spent':<29} |\n|{'-'*51}|{'-'*20}|{'-'*31}|") | 	preproc_timestamp = perf_counter_ns() | ||||||
|  | 	preproc_gaps = [49, -18, 29] | ||||||
|  | 	header(['Preprocessing', 'Time spent (ns)', 'Formatted time spent'], preproc_gaps) | ||||||
|  |  | ||||||
| 	X_train, y_train, X_test, y_test = state_saver("Loading sets", ["X_train", "y_train", "X_test", "y_test"], | 	X_train, y_train, X_test, y_test = state_saver('Loading sets', preproc_gaps[0], ['X_train', 'y_train', 'X_test', 'y_test'], | ||||||
| 	 											   load_datasets, FORCE_REDO, SAVE_STATE) | 	 											   load_datasets, FORCE_REDO, SAVE_STATE) | ||||||
|  |  | ||||||
| 	if __DEBUG: | 	if __DEBUG: | ||||||
| @@ -57,16 +60,17 @@ def preprocessing() -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: | |||||||
| 		print(y_test.shape) | 		print(y_test.shape) | ||||||
| 		print(y_test[IDX_INSPECT: IDX_INSPECT + IDX_INSPECT_OFFSET]) | 		print(y_test[IDX_INSPECT: IDX_INSPECT + IDX_INSPECT_OFFSET]) | ||||||
|  |  | ||||||
| 	feats = state_saver("Building features", "feats", lambda: build_features(X_train.shape[1], X_train.shape[2]), FORCE_REDO, SAVE_STATE) | 	feats = state_saver('Building features', preproc_gaps[0], 'feats', lambda: build_features(X_train.shape[1], X_train.shape[2]), | ||||||
|  | 						FORCE_REDO, SAVE_STATE) | ||||||
|  |  | ||||||
| 	if __DEBUG: | 	if __DEBUG: | ||||||
| 		print("feats") | 		print("feats") | ||||||
| 		print(feats.shape) | 		print(feats.shape) | ||||||
| 		print(feats[IDX_INSPECT].ravel()) | 		print(feats[IDX_INSPECT].ravel()) | ||||||
|  |  | ||||||
| 	X_train_ii = state_saver(f"Converting training set to integral images ({label})", f"X_train_ii_{label}", | 	X_train_ii = state_saver(f'Converting training set to integral images ({label})', preproc_gaps[0], f'X_train_ii_{label}', | ||||||
| 							lambda: set_integral_image(X_train), FORCE_REDO, SAVE_STATE) | 							lambda: set_integral_image(X_train), FORCE_REDO, SAVE_STATE) | ||||||
| 	X_test_ii = state_saver(f"Converting testing set to integral images ({label})", f"X_test_ii_{label}", | 	X_test_ii = state_saver(f'Converting testing set to integral images ({label})', preproc_gaps[0], f'X_test_ii_{label}', | ||||||
| 							lambda: set_integral_image(X_test), FORCE_REDO, SAVE_STATE) | 							lambda: set_integral_image(X_test), FORCE_REDO, SAVE_STATE) | ||||||
|  |  | ||||||
| 	if __DEBUG: | 	if __DEBUG: | ||||||
| @@ -77,9 +81,9 @@ def preprocessing() -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: | |||||||
| 		print(X_test_ii.shape) | 		print(X_test_ii.shape) | ||||||
| 		print(X_test_ii[IDX_INSPECT]) | 		print(X_test_ii[IDX_INSPECT]) | ||||||
|  |  | ||||||
| 	X_train_feat = state_saver(f"Applying features to training set ({label})", f"X_train_feat_{label}", | 	X_train_feat = state_saver(f'Applying features to training set ({label})', preproc_gaps[0], f'X_train_feat_{label}', | ||||||
| 							lambda: apply_features(feats, X_train_ii), FORCE_REDO, SAVE_STATE) | 							lambda: apply_features(feats, X_train_ii), FORCE_REDO, SAVE_STATE) | ||||||
| 	X_test_feat = state_saver(f"Applying features to testing set ({label})", f"X_test_feat_{label}", | 	X_test_feat = state_saver(f'Applying features to testing set ({label})', preproc_gaps[0], f'X_test_feat_{label}', | ||||||
| 							lambda: apply_features(feats, X_test_ii), FORCE_REDO, SAVE_STATE) | 							lambda: apply_features(feats, X_test_ii), FORCE_REDO, SAVE_STATE) | ||||||
| 	del X_train_ii, X_test_ii, feats | 	del X_train_ii, X_test_ii, feats | ||||||
|  |  | ||||||
| @@ -106,14 +110,14 @@ def preprocessing() -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: | |||||||
|  |  | ||||||
| 	# X_train_feat, X_test_feat = X_train_feat[indices], X_test_feat[indices] | 	# X_train_feat, X_test_feat = X_train_feat[indices], X_test_feat[indices] | ||||||
|  |  | ||||||
| 	X_train_feat_argsort = state_saver(f"Precalculating training set argsort ({label})", f"X_train_feat_argsort_{label}", | 	X_train_feat_argsort = state_saver(f'Precalculating training set argsort ({label})', preproc_gaps[0], f'X_train_feat_argsort_{label}', | ||||||
| 									lambda: argsort(X_train_feat), FORCE_REDO, SAVE_STATE) | 									lambda: argsort(X_train_feat), FORCE_REDO, SAVE_STATE) | ||||||
|  |  | ||||||
| 	if __DEBUG: | 	if __DEBUG: | ||||||
| 		print("X_train_feat_argsort") | 		print("X_train_feat_argsort") | ||||||
| 		print(X_train_feat_argsort.shape) | 		print(X_train_feat_argsort.shape) | ||||||
| 		print(X_train_feat_argsort[IDX_INSPECT, : IDX_INSPECT_OFFSET]) | 		print(X_train_feat_argsort[IDX_INSPECT, : IDX_INSPECT_OFFSET]) | ||||||
| 		benchmark_function("Arg unit test", lambda: unit_test_argsort_2d(X_train_feat, X_train_feat_argsort)) | 		benchmark_function('Arg unit test', preproc_gaps[0], lambda: unit_test_argsort_2d(X_train_feat, X_train_feat_argsort)) | ||||||
|  |  | ||||||
| 	X_test_feat_argsort = state_saver(f"Precalculating testing set argsort ({label})", f"X_test_feat_argsort_{label}", | 	X_test_feat_argsort = state_saver(f"Precalculating testing set argsort ({label})", f"X_test_feat_argsort_{label}", | ||||||
| 									lambda: argsort(X_test_feat), FORCE_REDO, SAVE_STATE) | 									lambda: argsort(X_test_feat), FORCE_REDO, SAVE_STATE) | ||||||
| @@ -123,48 +127,70 @@ def preprocessing() -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: | |||||||
| 		print(X_test_feat_argsort.shape) | 		print(X_test_feat_argsort.shape) | ||||||
| 		print(X_test_feat_argsort[IDX_INSPECT, : IDX_INSPECT_OFFSET]) | 		print(X_test_feat_argsort[IDX_INSPECT, : IDX_INSPECT_OFFSET]) | ||||||
| 		benchmark_function("Arg unit test", lambda: unit_test_argsort_2d(X_test_feat, X_test_feat_argsort)) | 		benchmark_function("Arg unit test", lambda: unit_test_argsort_2d(X_test_feat, X_test_feat_argsort)) | ||||||
|  | 	time_spent = perf_counter_ns() - preproc_timestamp | ||||||
|  | 	formatted_line(preproc_gaps, '├', '┼', '─', '┤') | ||||||
|  | 	formatted_row(preproc_gaps, ['Preprocessing summary', f'{time_spent:,}', format_time_ns(time_spent)]) | ||||||
|  | 	footer(preproc_gaps) | ||||||
|  |  | ||||||
| 	return X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test | 	return X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test | ||||||
|  |  | ||||||
| def train(X_train_feat: np.ndarray, X_train_feat_argsort: np.ndarray, y_train: np.ndarray) -> None: | def train(X_train_feat: np.ndarray, X_train_feat_argsort: np.ndarray, y_train: np.ndarray) -> List[np.ndarray]: | ||||||
| 	"""Train the weak classifiers. | 	"""Train the weak classifiers. | ||||||
|  |  | ||||||
| 	Args: | 	Args: | ||||||
| 		X_train (np.ndarray): Training images. | 		X_train (np.ndarray): Training images. | ||||||
| 		X_test (np.ndarray): Testing Images. | 		X_train_feat_argsort (np.ndarray): Sorted indexes of the training images features. | ||||||
| 		y_train (np.ndarray): Training labels. | 		y_train (np.ndarray): Training labels. | ||||||
|  |  | ||||||
|  | 	Returns: List of trained models | ||||||
| 	""" | 	""" | ||||||
| 	print(f"\n| {'Training':<49} | {'Time spent (ns)':<18} | {'Formatted time spent':<29} |\n|{'-'*51}|{'-'*20}|{'-'*31}|") |  | ||||||
|  | 	training_timestamp = perf_counter_ns() | ||||||
|  | 	training_gaps = [26, -18, 29] | ||||||
|  | 	header(['Training', 'Time spent (ns)', 'Formatted time spent'], training_gaps) | ||||||
|  | 	models = [] | ||||||
|  |  | ||||||
| 	for T in TS: | 	for T in TS: | ||||||
| 		alphas, final_classifiers = state_saver(f"ViolaJones T = {T:<3} ({label})", [f"alphas_{T}_{label}", f"final_classifiers_{T}_{label}"], | 		alphas, final_classifiers = state_saver(f'ViolaJones T = {T:<4} ({label})', training_gaps[0], | ||||||
| 					lambda: train_viola_jones(T, X_train_feat, X_train_feat_argsort, y_train), FORCE_REDO, SAVE_STATE, MODEL_DIR) | 			[f'alphas_{T}_{label}', f'final_classifiers_{T}_{label}'], | ||||||
|  | 			lambda: train_viola_jones(T, X_train_feat, X_train_feat_argsort, y_train), FORCE_REDO, SAVE_STATE, MODEL_DIR) | ||||||
|  | 		models.append([alphas, final_classifiers]) | ||||||
|  |  | ||||||
| 		if __DEBUG: | 		if __DEBUG: | ||||||
| 			print("alphas") | 			print("alphas") | ||||||
| 			print(alphas) | 			print(alphas) | ||||||
| 			print("final_classifiers") | 			print("final_classifiers") | ||||||
| 			print(final_classifiers) | 			print(final_classifiers) | ||||||
|  |  | ||||||
| def testing_and_evaluating(X_train_feat: np.ndarray, y_train: np.ndarray, X_test_feat: np.ndarray, y_test: np.ndarray) -> None: | 	time_spent = perf_counter_ns() - training_timestamp | ||||||
|  | 	formatted_line(training_gaps, '├', '┼', '─', '┤') | ||||||
|  | 	formatted_row(training_gaps, ['Training summary', f'{time_spent:,}', format_time_ns(time_spent)]) | ||||||
|  | 	footer(training_gaps) | ||||||
|  |  | ||||||
|  | 	return models | ||||||
|  |  | ||||||
|  | def testing_and_evaluating(models: List[np.ndarray], X_train_feat: np.ndarray, y_train: np.ndarray, X_test_feat: np.ndarray, y_test: np.ndarray) -> None: | ||||||
| 	"""Benchmark the trained classifiers on the training and testing sets. | 	"""Benchmark the trained classifiers on the training and testing sets. | ||||||
|  |  | ||||||
| 	Args: | 	Args: | ||||||
|  | 	    models (List[np.ndarray]): List of trained models. | ||||||
| 		X_train_feat (np.ndarray): Training features. | 		X_train_feat (np.ndarray): Training features. | ||||||
| 		y_train (np.ndarray): Training labels. | 		y_train (np.ndarray): Training labels. | ||||||
| 		X_test_feat (np.ndarray): Testing features. | 		X_test_feat (np.ndarray): Testing features. | ||||||
| 		y_test (np.ndarray): Testing labels. | 		y_test (np.ndarray): Testing labels. | ||||||
| 	""" | 	""" | ||||||
| 	print(f"\n| {'Testing':<26} | Time spent (ns) (E) | {'Formatted time spent (E)':<29}", end = " | ") |  | ||||||
| 	print(f"Time spent (ns) (T) | {'Formatted time spent (T)':<29} |") |  | ||||||
| 	print(f"|{'-'*28}|{'-'*21}|{'-'*31}|{'-'*21}|{'-'*31}|") |  | ||||||
|  |  | ||||||
| 	perfs = [] | 	testing_gaps = [26, -19, 24, -19, 24] | ||||||
| 	for T in TS: | 	header(['Testing', 'Time spent (ns) (E)', 'Formatted time spent (E)', 'Time spent (ns) (T)', 'Formatted time spent (T)'], testing_gaps) | ||||||
| 		(alphas, final_classifiers) = picke_multi_loader([f"alphas_{T}_{label}", f"final_classifiers_{T}_{label}"]) |  | ||||||
|  |  | ||||||
|  | 	performances = [] | ||||||
|  | 	total_train_timestamp = 0 | ||||||
|  | 	total_test_timestamp = 0 | ||||||
|  | 	for T, (alphas, final_classifiers) in zip(TS, models): | ||||||
| 		s = perf_counter_ns() | 		s = perf_counter_ns() | ||||||
| 		y_pred_train = classify_viola_jones(alphas, final_classifiers, X_train_feat) | 		y_pred_train = classify_viola_jones(alphas, final_classifiers, X_train_feat) | ||||||
| 		t_pred_train = perf_counter_ns() - s | 		t_pred_train = perf_counter_ns() - s | ||||||
|  | 		total_train_timestamp += t_pred_train | ||||||
| 		e_acc = accuracy_score(y_train, y_pred_train) | 		e_acc = accuracy_score(y_train, y_pred_train) | ||||||
| 		e_f1 = f1_score(y_train, y_pred_train) | 		e_f1 = f1_score(y_train, y_pred_train) | ||||||
| 		(_, e_FP), (e_FN, _) = confusion_matrix(y_train, y_pred_train) | 		(_, e_FP), (e_FN, _) = confusion_matrix(y_train, y_pred_train) | ||||||
| @@ -172,36 +198,48 @@ def testing_and_evaluating(X_train_feat: np.ndarray, y_train: np.ndarray, X_test | |||||||
| 		s = perf_counter_ns() | 		s = perf_counter_ns() | ||||||
| 		y_pred_test = classify_viola_jones(alphas, final_classifiers, X_test_feat) | 		y_pred_test = classify_viola_jones(alphas, final_classifiers, X_test_feat) | ||||||
| 		t_pred_test = perf_counter_ns() - s | 		t_pred_test = perf_counter_ns() - s | ||||||
|  | 		total_test_timestamp += t_pred_test | ||||||
| 		t_acc = accuracy_score(y_test, y_pred_test) | 		t_acc = accuracy_score(y_test, y_pred_test) | ||||||
| 		t_f1 = f1_score(y_test, y_pred_test) | 		t_f1 = f1_score(y_test, y_pred_test) | ||||||
| 		(_, t_FP), (t_FN, _) = confusion_matrix(y_test, y_pred_test) | 		(_, t_FP), (t_FN, _) = confusion_matrix(y_test, y_pred_test) | ||||||
| 		perfs.append((e_acc, e_f1, e_FN, e_FP, t_acc, t_f1, t_FN, t_FP)) | 		performances.append((e_acc, e_f1, e_FN, e_FP, t_acc, t_f1, t_FN, t_FP)) | ||||||
|  |  | ||||||
| 		print(f"| {'ViolaJones T = ' + str(T):<19} {'(' + label + ')':<6}", end = " | ") | 		formatted_row(testing_gaps, [f"{'ViolaJones T = ' + str(T):<19} {'(' + label + ')':<6}", f'{t_pred_train:,}', | ||||||
| 		print(f"{t_pred_train:>19,} | {format_time_ns(t_pred_train):<29}", end = " | ") | 									format_time_ns(t_pred_train), f'{t_pred_test:,}', format_time_ns(t_pred_test)]) | ||||||
| 		print(f"{t_pred_test:>19,} | {format_time_ns(t_pred_test):<29} |") |  | ||||||
|  |  | ||||||
| 	print(f"\n| {'Evaluating':<19} | ACC (E) | F1 (E) | FN (E) | FP (E) | ACC (T) | F1 (T) | FN (T) | FP (T) | ") | 	formatted_line(testing_gaps, '├', '┼', '─', '┤') | ||||||
| 	print(f"|{'-'*21}|{'-'*9}|{'-'*8}|{'-'*8}|{'-'*8}|{'-'*9}|{'-'*8}|{'-'*8}|{'-'*8}|") | 	formatted_row(testing_gaps, ['Testing summary', f'{total_train_timestamp:,}', format_time_ns(total_train_timestamp), f'{total_test_timestamp:,}', | ||||||
|  | 					format_time_ns(total_test_timestamp)]) | ||||||
|  | 	footer(testing_gaps) | ||||||
|  |  | ||||||
| 	for T, (e_acc, e_f1, e_FN, e_FP, t_acc, t_f1, t_FN, t_FP) in zip(TS, perfs): | 	evaluating_gaps = [19, 7, 6, 6, 6, 7, 6, 6, 6] | ||||||
| 		print(f"| {'ViolaJones T = ' + str(T):<19} | {e_acc:>7.2%} | {e_f1:>6.2f} | {e_FN:>6,} | {e_FP:>6,}", end = " | ") | 	header(['Evaluating', 'ACC (E)', 'F1 (E)', 'FN (E)', 'FP (E)', 'ACC (T)', 'F1 (T)', 'FN (T)', 'FP (T)'], evaluating_gaps) | ||||||
| 		print(f"{t_acc:>7.2%} | {t_f1:>6.2f} | {t_FN:>6,} | {t_FP:>6,} |") |  | ||||||
|  | 	for T, (e_acc, e_f1, e_FN, e_FP, t_acc, t_f1, t_FN, t_FP) in zip(TS, performances): | ||||||
|  | 		print(f'│ ViolaJones T = {T:<4} │ {e_acc:>7.2%} │ {e_f1:>6.2f} │ {e_FN:>6,} │ {e_FP:>6,}', end = ' │ ') | ||||||
|  | 		print(f'{t_acc:>7.2%} │ {t_f1:>6.2f} │ {t_FN:>6,} │ {t_FP:>6,} │') | ||||||
|  |  | ||||||
|  | 	footer(evaluating_gaps) | ||||||
|  |  | ||||||
| def main() -> None: | def main() -> None: | ||||||
| 	print(f"| {'Unit testing':<49} | {'Time spent (ns)':<18} | {'Formatted time spent':<29} |") | 	unit_timestamp = perf_counter_ns() | ||||||
| 	print(f"|{'-'*51}|{'-'*20}|{'-'*31}|") | 	unit_gaps = [27, -18, 29] | ||||||
| 	benchmark_function("Testing format_time_ns", format_time_ns_test) | 	header(['Unit testing', 'Time spent (ns)', 'Formatted time spent'], unit_gaps) | ||||||
| 	print() | 	benchmark_function('testing format_time', unit_gaps[0], format_time_test) | ||||||
|  | 	benchmark_function('testing format_time_ns', unit_gaps[0], format_time_ns_test) | ||||||
|  | 	time_spent = perf_counter_ns() - unit_timestamp | ||||||
|  | 	formatted_line(unit_gaps, '├', '┼', '─', '┤') | ||||||
|  | 	formatted_row(unit_gaps, ['Unit testing summary', f'{time_spent:,}', format_time_ns(time_spent)]) | ||||||
|  | 	footer(unit_gaps) | ||||||
|  |  | ||||||
| 	X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test = preprocessing() | 	X_train_feat, X_train_feat_argsort, y_train, X_test_feat, y_test = preprocessing() | ||||||
| 	train(X_train_feat, X_train_feat_argsort, y_train) | 	models = train(X_train_feat, X_train_feat_argsort, y_train) | ||||||
|  |  | ||||||
| 	# X_train_feat, X_test_feat = picke_multi_loader([f"X_train_feat_{label}", f"X_test_feat_{label}"], OUT_DIR) | 	# X_train_feat, X_test_feat = picke_multi_loader([f"X_train_feat_{label}", f"X_test_feat_{label}"], OUT_DIR) | ||||||
| 	# indices = picke_multi_loader(["indices"], OUT_DIR)[0] | 	# indices = picke_multi_loader(["indices"], OUT_DIR)[0] | ||||||
| 	# X_train_feat, X_test_feat = X_train_feat[indices], X_test_feat[indices] | 	# X_train_feat, X_test_feat = X_train_feat[indices], X_test_feat[indices] | ||||||
|  |  | ||||||
| 	testing_and_evaluating(X_train_feat, y_train, X_test_feat, y_test) | 	testing_and_evaluating(models, X_train_feat, y_train, X_test_feat, y_test) | ||||||
| 	unit_test(TS) | 	unit_test(TS) | ||||||
|  |  | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|   | |||||||
| @@ -2,12 +2,35 @@ from typing import Any, Callable, List, Union, Final | |||||||
| from time import perf_counter_ns | from time import perf_counter_ns | ||||||
| from numba import njit | from numba import njit | ||||||
| import numpy as np | import numpy as np | ||||||
|  | from sys import stderr | ||||||
| import pickle | import pickle | ||||||
| import os | import os | ||||||
| from config import MODEL_DIR, OUT_DIR | from config import MODEL_DIR, OUT_DIR | ||||||
| from decorators import njit | from decorators import njit | ||||||
|  |  | ||||||
| time_formats: Final = ["ns", "µs", "ms", "s", "m", "h", "j", "w", "M", "y", "c"] | time_formats: Final = ["ns", "µs", "ms", "s", "m", "h", "j", "w", "M", "y", "c"] | ||||||
|  | def formatted_row(gaps: list[int], titles: list[str], separator: str = '│') -> None: | ||||||
|  | 	for gap, title in zip(gaps, titles): | ||||||
|  | 		print(f"{separator} {title:{'>' if gap < 0 else '<'}{abs(gap)}} ", end = '') | ||||||
|  | 	print(separator) | ||||||
|  |  | ||||||
|  | def formatted_line(gaps: list[int], right: str, middle: str, separator: str, left: str) -> None: | ||||||
|  | 	print(right, end = '') | ||||||
|  | 	last_gap = len(gaps) - 1 | ||||||
|  | 	for i, gap in enumerate(gaps): | ||||||
|  | 		print(f'{separator * (abs(gap) + 2)}', end = '') | ||||||
|  | 		if i != last_gap: | ||||||
|  | 			print(middle, end = '') | ||||||
|  | 	print(left) | ||||||
|  |  | ||||||
|  | def header(titles: list[str], gaps: list[int]) -> None: | ||||||
|  | 	formatted_line(gaps, '┌', '┬', '─', '┐') | ||||||
|  | 	formatted_row(gaps, titles) | ||||||
|  | 	formatted_line(gaps, '├', '┼', '─', '┤') | ||||||
|  |  | ||||||
|  | def footer(gaps: list[int]) -> None: | ||||||
|  | 	formatted_line(gaps, '└', '┴', '─', '┘') | ||||||
|  |  | ||||||
| time_numbers: Final = np.array([1, 1e3, 1e6, 1e9, 6e10, 36e11, 864e11, 6048e11, 26784e11, 31536e12, 31536e14], dtype = np.uint64) | time_numbers: Final = np.array([1, 1e3, 1e6, 1e9, 6e10, 36e11, 864e11, 6048e11, 26784e11, 31536e12, 31536e14], dtype = np.uint64) | ||||||
| @njit('str(uint64)') | @njit('str(uint64)') | ||||||
| def format_time_ns(time: int) -> str: | def format_time_ns(time: int) -> str: | ||||||
| @@ -53,7 +76,7 @@ def picke_multi_loader(filenames: List[str], save_dir: str = MODEL_DIR) -> List[ | |||||||
| 			b.append(None) | 			b.append(None) | ||||||
| 	return b | 	return b | ||||||
|  |  | ||||||
| def benchmark_function(step_name: str, fnc: Callable) -> Any: | def benchmark_function(step_name: str, column_width: int, fnc: Callable) -> Any: | ||||||
| 	"""Benchmark a function and display the result of stdout. | 	"""Benchmark a function and display the result of stdout. | ||||||
|  |  | ||||||
| 	Args: | 	Args: | ||||||
| @@ -63,14 +86,15 @@ def benchmark_function(step_name: str, fnc: Callable) -> Any: | |||||||
| 	Returns: | 	Returns: | ||||||
| 		Any: Result of the function. | 		Any: Result of the function. | ||||||
| 	""" | 	""" | ||||||
| 	print(f"{step_name}...", end = "\r") | 	print(f'{step_name}...', file = stderr, end = '\r') | ||||||
| 	s = perf_counter_ns() | 	s = perf_counter_ns() | ||||||
| 	b = fnc() | 	b = fnc() | ||||||
| 	e = perf_counter_ns() - s | 	e = perf_counter_ns() - s | ||||||
| 	print(f"| {step_name:<49} | {e:>18,} | {format_time_ns(e):<29} |") | 	print(f'│ {step_name:<{column_width}} │ {e:>18,} │ {format_time_ns(e):<29} │') | ||||||
| 	return b | 	return b | ||||||
|  |  | ||||||
| def state_saver(step_name: str, filename: Union[str, List[str]], fnc, force_redo: bool = False, save_state: bool = True, save_dir: str = OUT_DIR) -> Any: | def state_saver(step_name: str, column_width: int, filename: Union[str, List[str]], fnc, force_redo: bool = False, | ||||||
|  | 				save_state: bool = True, save_dir: str = OUT_DIR) -> Any: | ||||||
| 	"""Either execute a function then saves the result or load the already existing result. | 	"""Either execute a function then saves the result or load the already existing result. | ||||||
|  |  | ||||||
| 	Args: | 	Args: | ||||||
| @@ -85,18 +109,18 @@ def state_saver(step_name: str, filename: Union[str, List[str]], fnc, force_redo | |||||||
| 	""" | 	""" | ||||||
| 	if isinstance(filename, str): | 	if isinstance(filename, str): | ||||||
| 		if not os.path.exists(f"{save_dir}/{filename}.pkl") or force_redo: | 		if not os.path.exists(f"{save_dir}/{filename}.pkl") or force_redo: | ||||||
| 			b = benchmark_function(step_name, fnc) | 			b = benchmark_function(step_name, column_width, fnc) | ||||||
| 			if save_state: | 			if save_state: | ||||||
| 				print(f"Saving results of {step_name}", end = '\r') |  | ||||||
| 				with open(f"{save_dir}/{filename}.pkl", 'wb') as f: | 				with open(f"{save_dir}/{filename}.pkl", 'wb') as f: | ||||||
|  | 				print(f'Saving results of {step_name}', file = stderr, end = '\r') | ||||||
| 					pickle.dump(b, f) | 					pickle.dump(b, f) | ||||||
| 				print(' ' * 100, end = '\r') | 				print(' ' * 100, file = stderr, end = '\r') | ||||||
| 			return b | 			return b | ||||||
| 		else: | 		else: | ||||||
| 			print(f"Loading results of {step_name}", end = '\r') |  | ||||||
| 			with open(f"{save_dir}/{filename}.pkl", "rb") as f: | 			with open(f"{save_dir}/{filename}.pkl", "rb") as f: | ||||||
|  | 			print(f'Loading results of {step_name}', file = stderr, end = '\r') | ||||||
| 				res = pickle.load(f) | 				res = pickle.load(f) | ||||||
| 			print(f"| {step_name:<49} | {'None':>18} | {'loaded saved state':<29} |") | 			print(f"│ {step_name:<{column_width}} │ {'None':>18} │ {'loaded saved state':<29} │") | ||||||
| 			return res | 			return res | ||||||
| 	elif isinstance(filename, list): | 	elif isinstance(filename, list): | ||||||
| 		abs = False | 		abs = False | ||||||
| @@ -105,22 +129,22 @@ def state_saver(step_name: str, filename: Union[str, List[str]], fnc, force_redo | |||||||
| 				abs = True | 				abs = True | ||||||
| 				break | 				break | ||||||
| 		if abs or force_redo: | 		if abs or force_redo: | ||||||
| 			b = benchmark_function(step_name, fnc) | 			b = benchmark_function(step_name, column_width, fnc) | ||||||
| 			if save_state: | 			if save_state: | ||||||
| 				print(f"Saving results of {step_name}", end = '\r') | 				print(f'Saving results of {step_name}', file = stderr, end = '\r') | ||||||
| 				for bi, fnI in zip(b, filename): | 				for bi, fnI in zip(b, filename): | ||||||
| 					with open(f"{save_dir}/{fnI}.pkl", 'wb') as f: | 					with open(f"{save_dir}/{fnI}.pkl", 'wb') as f: | ||||||
| 						pickle.dump(bi, f) | 						pickle.dump(bi, f) | ||||||
| 				print(' ' * 100, end = '\r') | 				print(' ' * 100, file = stderr, end = '\r') | ||||||
| 			return b | 			return b | ||||||
|  |  | ||||||
| 		print(f"| {step_name:<49} | {'None':>18} | {'loaded saved state':<29} |") | 		print(f"│ {step_name:<{column_width}} │ {'None':>18} │ {'loaded saved state':<29} │") | ||||||
| 		b = [] | 		b = [] | ||||||
| 		print(f"Loading results of {step_name}", end = '\r') | 		print(f'Loading results of {step_name}', file = stderr, end = '\r') | ||||||
| 		for fn in filename: | 		for fn in filename: | ||||||
| 			with open(f"{save_dir}/{fn}.pkl", "rb") as f: | 			with open(f"{save_dir}/{fn}.pkl", "rb") as f: | ||||||
| 				b.append(pickle.load(f)) | 				b.append(pickle.load(f)) | ||||||
| 		print(' ' * 100, end = '\r') | 		print(' ' * 100, file = stderr, end = '\r') | ||||||
| 		return b | 		return b | ||||||
| 	else: | 	else: | ||||||
| 		assert False, f"Incompatible filename type = {type(filename)}" | 		assert False, f"Incompatible filename type = {type(filename)}" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user