//+------------------------------------------------------------------+ //| ScalerBaseCL.mqh | //| Copyright 2025, Leo. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Leo." #property link "https://www.mql5.com" #property strict #ifndef SCALERBYLEO_SCALER_BASE_CL_MQH #define SCALERBYLEO_SCALER_BASE_CL_MQH //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ #ifdef SCALER_BASE_CL_DEBUG #include "..\\..\\CLByLeo\\CL.mqh" #else #include "..\\..\\CLByLeo\\CLFast.mqh" #endif //+------------------------------------------------------------------+ //| Defines | //+------------------------------------------------------------------+ #resource "Kernels\\ScalerUint.cl" as const string cl_scaler_program_uint #resource "Kernels\\ScalerUlong.cl" as const string cl_scaler_program_ulong //--- Generales #define SCALER_BASE_CL_MIN_VAL 1e-9 //--- Principal - Global #define cl_scaler_kernels_total 16 #define cl_scaler_buffers_total 8 //--- Kernels globales (compartidos) #define kernel_matrix_extraer 0 #define kernel_matrix_reconstruir 1 #define kernel_vector_extraer 2 #define kernel_vector_reconstruir 3 //--- Argumentos recons/extraer matrix #define kernel_matrix_extraer_recons_arg_buff_data 0 #define kernel_matrix_extraer_recons_arg_buff_res 1 #define kernel_matrix_extraer_recons_arg_rows_data 2 #define kernel_matrix_extraer_recons_arg_cols_data 3 #define kernel_matrix_extraer_recons_arg_rows_res 4 #define kernel_matrix_extraer_recons_arg_cols_res 5 #define kernel_matrix_extraer_recons_arg_extraer_cols 6 #define kernel_matrix_extraer_recons_arg_start_col 7 //--- Kernel global [2] - Kernel[3] Vectores argumentos #define kernel_vector_extraer_recons_arg_buff_data 0 #define kernel_vector_extraer_recons_arg_buff_res 1 #define kernel_vector_extraer_recons_arg_start_col 2 #define kernel_vector_extraer_recons_arg_count_col 3 //--- Buffers globales // argumentos/buffer - no solo de esta funcion GLOBALES #define global_buffer_data_1 0 //mean/min/iqrs - buffer #define global_buffer_data_2 1 // std/max/medians - buffer #define global_matrix_to_escale 2 //Matriz a escalar (transform, fit_tranform, inverse_tranform) - buffer #define global_vector_to_escale 3 //Vector a escalar (fit_tranform, inverse_tranform) - buffer // Para extracion de matrizes si es necesario #define global_extraer_recos_mtx_matrix_data 4 #define global_extraer_recos_mtx_matrix_res 5 // Para extracion de vecores si es necesario #define global_extraer_recos_vec_vector_data 6 #define global_extraer_recos_vec_vector_res 7 //--- Indice general para el vector data // Indice general del vector /TRANSFORM - FITTRANSFORM #define kernel_arg_index_all_vector_to_escale 2 //En caso que se escale un vector - indice de argunmento //--- Kernels StandardizationScaler (4-9) #define kernel_standardization_fit_init 4 #define kernel_standardization_transform_matrix 5 #define kernel_standardization_transform_vector 6 #define kernel_standardization_inverse_matrix 7 #define kernel_standardization_inverse_vector 8 #define kernel_standardization_fit_transform_vector 9 //--- Argumentos StandardizationScaler #define kernel_standardization_arg_cols 3 #define kernel_standardization_arg_rows 4 //--- Kernels MaxMinScaler (10-15) #define kernel_maxmin_fit_init 10 #define kernel_maxmin_transform_matrix 11 #define kernel_maxmin_transform_vector 12 #define kernel_maxmin_inverse_matrix 13 #define kernel_maxmin_inverse_vector 14 #define kernel_maxmin_fit_transform_vector 15 //--- Argumentos MaxMinScaler #define kernel_maxmin_arg_cols 3 #define kernel_maxmin_arg_rows 4 //--- Argumentos fit_transform_vector (ambos scalers) #define kernel_fit_transform_vector_arg_data1 0 #define kernel_fit_transform_vector_arg_data2 1 //--- #define SCALER_BASE_CL_FINAL_LINE -1 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template //T es uint o ulong class ScalerBaseCL : public CLoggerBase { private: //--- static void CleanBufferVector(); static void CleanBufferMatrix(); protected: static COpenCL cl; static uint8_t type_suported; static bool open_cl_is_create; static bool kernels_base_created; string file_name_out; string prefix_file; bool loaded_scaler; bool use_custom; //Bandera para saber si se usa custom (true) o excluyed (false) T start_col; T count_cols; T excluyed_cols; virtual bool Save() = 0; virtual bool Load(string prefix_name) = 0; //--- Chekear el tamaño bool CheckSizeCustom(const matrix &mtx) const; bool CheckSizeExcluded(const matrix &mtx) const; bool CheckSizeCustom(const vector &v) const; bool CheckSizeExcluded(const vector &v) const; //--- void CleanBuffersOnlyData(); void CleanExtraData(); public: ScalerBaseCL(); static inline COpenCL* GetCLPointer() { return GetPointer(cl); } //--- Seteo de rangos void SetRangeEscaler(T start_col_, T count_col_); //Custom void SetRangeEscaler(T excluyed_cols_ = 1); //Mas simple, el usuario decide cuantas columnas empezando por atras se excluyen //--- Metodos para guardar o cargar inline bool save(string prefix_name); inline bool load(string prefix_name); //--- Tranformar \ Inverse Transform \ Fit Transform //- Fit // Transorfmra un archivo bool fit_transform_file(const string &file_name, ushort sep, int extra_file_flags, bool save_data, uint file_code_page = CP_ACP, int start_line = 1); // Transforma un archivo y devuelve la matriz matrix fit_transform_by_file(const string& file_name, ushort sep, int file_flags, bool save_data, uint file_code_page = CP_ACP, int start_line = 1, int end_line = SCALER_BASE_CL_FINAL_LINE); // Transforma un string matrix fit_transform_by_src(const string& src, ushort sep, bool save_data, int str_start_line = 1, int str_end_line = SCALER_BASE_CL_FINAL_LINE); // Transforma string // Matrix real virtual matrix fit_transform(matrix &X, bool save_data) = 0; // Vector virtual vector fit_transform(vector &X) = 0; //Para vectores no se guarda data //- Normal virtual matrix transform(matrix &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) = 0; virtual vector transform(vector &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) = 0; virtual matrix inverse_transform(matrix &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) = 0; virtual vector inverse_transform(vector &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) = 0; //--- Extracion matrix ExtractMatrixToScale(matrix &X) const; vector ExtractVectorToScale(vector &X) const; //--- Reconstruccion matrix ReconstructMatrix(matrix &X_original, matrix &X_scaled) const; vector ReconstructVector(vector &X_original, vector &X_scaled) const; //--- Archivos virtual inline string GetOutputFile() const final { return this.file_name_out; } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template static COpenCL ScalerBaseCL::cl; template static bool ScalerBaseCL::open_cl_is_create = false; template static bool ScalerBaseCL::kernels_base_created = false; template static uint8_t ScalerBaseCL::type_suported = 0; #define SCALER_BASE_CL_FLAG_UINT 1 #define SCALER_BASE_CL_FLAG_ULONG 2 //+------------------------------------------------------------------+ string ScalerBaseCL_FlagToStr(uint8_t f) { //--- if(f == 0) { return "Indefinido"; } //--- string str = ""; //--- if((f & SCALER_BASE_CL_FLAG_UINT) != 0) str = "(uint"; //--- if((f & SCALER_BASE_CL_FLAG_ULONG) != 0) str += (str == "") ? "(ulong)" : (" Y ulong)"); else str += ")"; //--- return str; } //+------------------------------------------------------------------+ uint8_t ScalerBaseCL_StrToFlag(const string& in) { //--- uint8_t f = 0; //--- if(in == "uint") f |= SCALER_BASE_CL_FLAG_UINT; //--- if(in == "ulong") f |= SCALER_BASE_CL_FLAG_ULONG; //--- return f; } //+------------------------------------------------------------------+ template ScalerBaseCL::ScalerBaseCL() : start_col(0), count_cols(0), use_custom(false), excluyed_cols(1), file_name_out(NULL), loaded_scaler(false) { //--- const string curr_type_s = typename(T); uint8_t curr_type = ScalerBaseCL_StrToFlag(curr_type_s); //--- if(!open_cl_is_create) { //--- Creamos el contexto const int divice = CL_USE_ANY; cl.ContextCreate(divice); type_suported = cl.SupportInt64() ? (3) : (1); // Si soporta INT64 soporta tambien int32 | solo soporta int32 //--- Verificamos que la clase se haya instanciado con el tipo soportado if((type_suported & curr_type) == 0) { LogError(StringFormat("El device solo soporta %s, clase creada con %s", ScalerBaseCL_FlagToStr(type_suported), curr_type_s), FUNCION_ACTUAL); Remover(); return; } cl.ProgramCreate((curr_type == 3 ? cl_scaler_program_ulong : cl_scaler_program_uint)); //--- if(!cl.SupportDouble()) { LogFatalError("Es necesario que el divice soporte double para calculos precisos", FUNCION_ACTUAL); Remover(); return; } //--- cl.SetKernelsCount(cl_scaler_kernels_total); cl.SetBuffersCount(cl_scaler_buffers_total); //--- Creamos los kerneles base (solo una vez) if(!kernels_base_created) { if(!cl.KernelCreate(kernel_matrix_extraer, "ExtractMatrixToScaler")) { Remover(); return; } if(!cl.KernelCreate(kernel_vector_extraer, "ExtractVectorToScale")) { Remover(); return; } if(!cl.KernelCreate(kernel_vector_reconstruir, "ReconstructVector")) { Remover(); return; } if(!cl.KernelCreate(kernel_matrix_reconstruir, "ReconstructMatrix")) { Remover(); return; } kernels_base_created = true; } //--- open_cl_is_create = true; } else { // Unicamente verirficamos si el tipo con el que se creo la clase es valido if((type_suported & curr_type) == 0) { LogError(StringFormat("El device solo soporta %s, clase creada con %s", ScalerBaseCL_FlagToStr(type_suported), curr_type_s), FUNCION_ACTUAL); Remover(); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template bool ScalerBaseCL::CheckSizeCustom(const matrix &mtx) const { if(start_col >= mtx.Cols()) { LogError(StringFormat("Columna de inicio %I64u >= total columnas %I64u", start_col, mtx.Cols()), FUNCION_ACTUAL); return false; } if(start_col + count_cols > mtx.Cols()) { LogError(StringFormat("Rango [%I64u:%I64u] excede columnas disponibles %I64u", start_col, start_col + count_cols - 1, mtx.Cols()), FUNCION_ACTUAL); return false; } return true; } //+------------------------------------------------------------------+ template bool ScalerBaseCL::CheckSizeExcluded(const matrix &mtx) const { if(mtx.Cols() < excluyed_cols) { LogError(StringFormat("Columnas a excluir %I64u >= total columnas %I64u", excluyed_cols, mtx.Cols()), FUNCION_ACTUAL); return false; } return true; } //+------------------------------------------------------------------+ template bool ScalerBaseCL::CheckSizeCustom(const vector &v) const { if(start_col >= v.Size()) { LogError(StringFormat("Columna de inicio %I64u >= tamaño total del vector%I64u", start_col, v.Size()), FUNCION_ACTUAL); return false; } if(start_col + count_cols > v.Size()) { LogError(StringFormat("Rango [%I64u:%I64u] excede el tamaño del vector %I64u", start_col, start_col + count_cols - 1, v.Size()), FUNCION_ACTUAL); return false; } return true; } //+------------------------------------------------------------------+ template bool ScalerBaseCL::CheckSizeExcluded(const vector &v) const { if(v.Size() < excluyed_cols) { LogError(StringFormat("Columnas a excluir %I64u >= tamaño del vector: %I64u", excluyed_cols, v.Size()), FUNCION_ACTUAL); return false; } return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template void ScalerBaseCL::CleanBufferMatrix(void) { cl.BufferFree(global_extraer_recos_mtx_matrix_data); cl.BufferFree(global_extraer_recos_mtx_matrix_res); } //+------------------------------------------------------------------+ template void ScalerBaseCL::CleanBufferVector(void) { cl.BufferFree(global_extraer_recos_vec_vector_data); cl.BufferFree(global_extraer_recos_vec_vector_res); } //+------------------------------------------------------------------+ template void ScalerBaseCL::SetRangeEscaler(T start_col_, T count_col_) { this.use_custom = true; this.count_cols = count_col_; this.start_col = start_col_; LogInfo(StringFormat("Configurado escalado CUSTOM: columnas %I64u a %I64u (%I64u columnas)", start_col_, start_col_ + count_col_ - 1, count_col_), FUNCION_ACTUAL); } //+------------------------------------------------------------------+ template void ScalerBaseCL::SetRangeEscaler(T excluyed_cols_ = 1) { this.excluyed_cols = excluyed_cols_; this.use_custom = false; LogInfo(StringFormat("Configurado escalado EXCLUDED: excluir últimas %I64u columnas", excluyed_cols_), FUNCION_ACTUAL); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template matrix ScalerBaseCL::ExtractMatrixToScale(matrix &X) const { /* Recordemos que previamenet se compmprueba el tamaño asi que no hace falta hacerlo */ if(use_custom) { if(X.Cols() == count_cols) //Se extrae todo, asi que no hacemo snada return X; matrix result(X.Rows(), count_cols); cl.BufferFromMatrix(global_extraer_recos_mtx_matrix_data, X, CL_MEM_READ_ONLY); //no lo modifica solo lectura cl.BufferFromMatrix(global_extraer_recos_mtx_matrix_res, result, CL_MEM_WRITE_ONLY); cl.SetArgumentBuffer(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_buff_data, global_extraer_recos_mtx_matrix_data); cl.SetArgumentBuffer(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_buff_res, global_extraer_recos_mtx_matrix_res); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_rows_data, (T)X.Rows()); //cast a t dado que cl es stricto cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_cols_data, (T)X.Cols()); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_rows_res, (T)result.Rows()); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_cols_res, (T)result.Cols()); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_extraer_cols, count_cols); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_start_col, start_col); uint work_off[2] = {0, 0}; uint work_size[2] = {(uint)result.Rows(), (uint)result.Cols()}; cl.Execute(kernel_matrix_extraer, 2, work_off, work_size); /* CPU for(ulong row = 0; row < X.Rows(); row++) for(ulong col = 0; col < count_cols; col++) result[row][col] = X[row][start_col + col]; */ cl.BufferToMatrix(global_extraer_recos_mtx_matrix_res, result, result.Rows(), result.Cols()); //--- CleanBufferMatrix(); return result; } else { if(excluyed_cols == 0) //No hay columnas a exlcuir escalar todo return X; T cols_to_scale = T(X.Cols() - excluyed_cols); matrix result(X.Rows(), cols_to_scale); //Tinee que tener el mismo tamaño cl.BufferFromMatrix(global_extraer_recos_mtx_matrix_data, X, CL_MEM_READ_ONLY); cl.BufferFromMatrix(global_extraer_recos_mtx_matrix_res, result, CL_MEM_WRITE_ONLY); cl.SetArgumentBuffer(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_buff_data, global_extraer_recos_mtx_matrix_data); cl.SetArgumentBuffer(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_buff_res, global_extraer_recos_mtx_matrix_res); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_rows_data, (T)X.Rows()); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_cols_data, (T)X.Cols()); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_rows_res, (T)result.Rows()); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_cols_res, (T)result.Cols()); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_extraer_cols, cols_to_scale); cl.SetArgument(kernel_matrix_extraer, kernel_matrix_extraer_recons_arg_start_col, (T)0); uint work_off[2] = {0, 0}; uint work_size[2] = {(uint)result.Rows(), (uint)result.Cols()}; cl.Execute(kernel_matrix_extraer, 2, work_off, work_size); /* for(ulong row = 0; row < X.Rows(); row++) for(ulong col = 0; col < cols_to_scale; col++) result[row][col] = X[row][col]; */ cl.BufferToMatrix(global_extraer_recos_mtx_matrix_res, result, result.Rows(), result.Cols()); //queremos modfiicar result //--- CleanBufferMatrix(); return result; } } //+------------------------------------------------------------------+ template matrix ScalerBaseCL::ReconstructMatrix(matrix &X_original, matrix &X_scaled) const //X_Scaled solo lectura.. { if(X_original.Rows() == X_scaled.Rows() && X_original.Cols() == X_scaled.Cols()) return X_scaled; matrix result = X_original; // Copia completa if(use_custom) { cl.BufferFromMatrix(global_extraer_recos_mtx_matrix_data, X_scaled, CL_MEM_READ_ONLY); cl.BufferFromMatrix(global_extraer_recos_mtx_matrix_res, result, CL_MEM_READ_WRITE); cl.SetArgumentBuffer(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_buff_data, global_extraer_recos_mtx_matrix_data); cl.SetArgumentBuffer(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_buff_res, global_extraer_recos_mtx_matrix_res); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_rows_data, (T)X_scaled.Rows()); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_cols_data, (T)X_scaled.Cols()); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_rows_res, (T)result.Rows()); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_cols_res, (T)result.Cols()); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_extraer_cols, count_cols); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_start_col, start_col); uint work_off[2] = {0, 0}; uint work_size[2] = {(uint)X_scaled.Rows(), (uint)X_scaled.Cols()}; cl.Execute(kernel_matrix_reconstruir, 2, work_off, work_size); cl.BufferToMatrix(global_extraer_recos_mtx_matrix_res, result, result.Rows(), result.Cols()); /* for(ulong row = 0; row < X_original.Rows(); row++) for(ulong col = 0; col < count_cols; col++) result[row][start_col + col] = X_scaled[row][col];*/ //--- CleanBufferMatrix(); } else { cl.BufferFromMatrix(global_extraer_recos_mtx_matrix_data, X_scaled, CL_MEM_READ_ONLY); cl.BufferFromMatrix(global_extraer_recos_mtx_matrix_res, result, CL_MEM_READ_WRITE); cl.SetArgumentBuffer(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_buff_data, global_extraer_recos_mtx_matrix_data); cl.SetArgumentBuffer(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_buff_res, global_extraer_recos_mtx_matrix_res); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_rows_data, (T)X_scaled.Rows()); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_cols_data, (T)X_scaled.Cols()); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_rows_res, (T)result.Rows()); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_cols_res, (T)result.Cols()); cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_extraer_cols, (T)X_scaled.Cols()); //aqui del original... cl.SetArgument(kernel_matrix_reconstruir, kernel_matrix_extraer_recons_arg_start_col, (T)0); uint work_off[2] = {0, 0}; uint work_size[2] = {(uint)X_scaled.Rows(), (uint)X_scaled.Cols()}; cl.Execute(kernel_matrix_reconstruir, 2, work_off, work_size); cl.BufferToMatrix(global_extraer_recos_mtx_matrix_res, result, result.Rows(), result.Cols()); /* for(ulong row = 0; row < X_original.Rows(); row++) for(ulong col = 0; col < X_scaled.Cols(); col++) result[row][col] = X_scaled[row][col];*/ //--- CleanBufferMatrix(); } return result; } //+------------------------------------------------------------------+ template vector ScalerBaseCL::ExtractVectorToScale(vector &X) const { if(use_custom) { if(X.Size() == count_cols) return X; vector result(count_cols); cl.BufferFromVector(global_extraer_recos_vec_vector_data, X, CL_MEM_READ_ONLY); //No se modifica X solo lectura cl.BufferFromVector(global_extraer_recos_vec_vector_res, result, CL_MEM_WRITE_ONLY); cl.SetArgumentBuffer(kernel_vector_extraer, kernel_vector_extraer_recons_arg_buff_data, global_extraer_recos_vec_vector_data); cl.SetArgumentBuffer(kernel_vector_extraer, kernel_vector_extraer_recons_arg_buff_res, global_extraer_recos_vec_vector_res); cl.SetArgument(kernel_vector_extraer, kernel_vector_extraer_recons_arg_start_col, start_col); cl.SetArgument(kernel_vector_extraer, kernel_vector_extraer_recons_arg_count_col, count_cols); // Extraer rango específico /* result.Resize(count_cols); for(ulong i = 0; i < count_cols; i++) result[i] = X[start_col + i];*/ uint work_off[1] = {0}; uint work_size[1] = {(uint)result.Size()}; cl.Execute(kernel_vector_extraer, 1, work_off, work_size); cl.BufferToVector(global_extraer_recos_vec_vector_res, result, result.Size()); //--- CleanBufferVector(); return result; } else { if(excluyed_cols == 0) return X; T size_to_scale = T(X.Size() - excluyed_cols); vector result(size_to_scale); cl.BufferFromVector(global_extraer_recos_vec_vector_data, X, CL_MEM_READ_ONLY); //No se modifica X solo lectura cl.BufferFromVector(global_extraer_recos_vec_vector_res, result, CL_MEM_WRITE_ONLY); cl.SetArgumentBuffer(kernel_vector_extraer, kernel_vector_extraer_recons_arg_buff_data, global_extraer_recos_vec_vector_data); cl.SetArgumentBuffer(kernel_vector_extraer, kernel_vector_extraer_recons_arg_buff_res, global_extraer_recos_vec_vector_res); cl.SetArgument(kernel_vector_extraer, kernel_vector_extraer_recons_arg_start_col, (T)0); cl.SetArgument(kernel_vector_extraer, kernel_vector_extraer_recons_arg_count_col, (T)size_to_scale); // Extraer todas excepto las últimas N uint work_off[1] = {0}; uint work_size[1] = {(uint)result.Size()}; cl.Execute(kernel_vector_extraer, 1, work_off, work_size); cl.BufferToVector(global_extraer_recos_vec_vector_res, result, result.Size()); //--- CleanBufferVector(); return result; } } //+------------------------------------------------------------------+ template vector ScalerBaseCL::ReconstructVector(vector &X_original, vector &X_scaled) const { if(X_original.Size() == X_scaled.Size()) return X_scaled; vector result = X_original; if(use_custom) { // Reemplazar rango específico cl.BufferFromVector(global_extraer_recos_vec_vector_data, X_scaled, CL_MEM_READ_ONLY); cl.BufferFromVector(global_extraer_recos_vec_vector_res, result, CL_MEM_READ_WRITE); cl.SetArgumentBuffer(kernel_vector_reconstruir, kernel_vector_extraer_recons_arg_buff_data, global_extraer_recos_vec_vector_data); cl.SetArgumentBuffer(kernel_vector_reconstruir, kernel_vector_extraer_recons_arg_buff_res, global_extraer_recos_vec_vector_res); cl.SetArgument(kernel_vector_reconstruir, kernel_vector_extraer_recons_arg_start_col, start_col); cl.SetArgument(kernel_vector_reconstruir, kernel_vector_extraer_recons_arg_count_col, count_cols); uint work_off[1] = {0}; uint work_size[1] = {(uint) X_scaled.Size()}; cl.Execute(kernel_vector_reconstruir, 1, work_off, work_size); cl.BufferToVector(global_extraer_recos_vec_vector_res, result, result.Size()); //escribimos en el result vector final /* for(ulong i = 0; i < count_cols; i++) result[start_col + i] = X_scaled[i]; */ //--- CleanBufferVector(); } else { // Reemplazar todas excepto las últimas N cl.BufferFromVector(global_extraer_recos_vec_vector_data, X_scaled, CL_MEM_READ_ONLY); cl.BufferFromVector(global_extraer_recos_vec_vector_res, result, CL_MEM_READ_WRITE); cl.SetArgumentBuffer(kernel_vector_reconstruir, kernel_vector_extraer_recons_arg_buff_data, global_extraer_recos_vec_vector_data); cl.SetArgumentBuffer(kernel_vector_reconstruir, kernel_vector_extraer_recons_arg_buff_res, global_extraer_recos_vec_vector_res); cl.SetArgument(kernel_vector_reconstruir, kernel_vector_extraer_recons_arg_start_col, (T)0); cl.SetArgument(kernel_vector_reconstruir, kernel_vector_extraer_recons_arg_count_col, (T)X_scaled.Size()); //aqui del original... no del "no_const" uint work_off[1] = {0}; uint work_size[1] = {(uint) X_scaled.Size()}; cl.Execute(kernel_vector_reconstruir, 1, work_off, work_size); cl.BufferToVector(global_extraer_recos_vec_vector_res, result, result.Size()); //escribimos en el result vector final /* for(ulong i = 0; i < X_scaled.Size(); i++) result[i] = X_scaled[i];*/ //--- CleanBufferVector(); } return result; } //+------------------------------------------------------------------+ template inline bool ScalerBaseCL::load(string prefix_name) { loaded_scaler = true; return this.Load(prefix_name); } //+------------------------------------------------------------------+ template inline bool ScalerBaseCL::save(string prefix_name) { this.file_name_out = prefix_name + this.prefix_file; return this.Save(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template void ScalerBaseCL::CleanBuffersOnlyData(void) { cl.BufferFree(global_matrix_to_escale); cl.BufferFree(global_vector_to_escale); } //+------------------------------------------------------------------+ template void ScalerBaseCL::CleanExtraData(void) { cl.BufferFree(global_buffer_data_1); cl.BufferFree(global_buffer_data_2); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ /* Notas: - file_flags: puede tener los valores de FILE_ANSI, FILE_COMON, etc.. las banderas (FILE_READ) ya bienen por derfecto */ //+------------------------------------------------------------------+ template matrix ScalerBaseCL::fit_transform_by_file(const string& file_name, ushort sep, int file_flags, bool save_data, uint file_code_page = CP_ACP, int start_line = 1, int end_line = SCALER_BASE_CL_FINAL_LINE) { //--- ResetLastError(); //--- matrix m = {}; const int file_handle = FileOpen(file_name, (file_flags | FILE_READ | FILE_TXT), '\n', file_code_page); if(file_handle == INVALID_HANDLE) { LogCriticalError(StringFormat("Error al abrir el archivo = %s, ultimo erorr = %d", file_name, GetLastError()), FUNCION_ACTUAL); return m; } //--- int curr_line = 0; string arr[]; int dt = 0; int curr_row = 0; string line = ""; //--- Se lee hasta el final if(end_line == SCALER_BASE_CL_FINAL_LINE) { //--- while(!FileIsEnding(file_handle)) { //--- line = FileReadString(file_handle); //--- if(curr_line >= start_line) { //--- if((dt = StringSplit(line, sep, arr)) < 1) { LogError(StringFormat("Linea mal formada = %d:\n%s", curr_line, line), FUNCION_ACTUAL); FileClose(file_handle); return m; } //--- m.Resize(curr_row + 1, dt); for(int i = 0; i < dt; i++) { m[curr_row][i] = double(arr[i]); } //--- curr_row++; } //--- curr_line++; } } else { //--- while(!FileIsEnding(file_handle)) { //--- line = FileReadString(file_handle); //--- if(curr_line >= start_line) { //--- if((dt = StringSplit(line, sep, arr)) < 1) { LogError(StringFormat("Linea mal formada = %d:\n%s", curr_line, line), FUNCION_ACTUAL); FileClose(file_handle); return m; } //--- m.Resize(curr_row + 1, dt); for(int i = 0; i < dt; i++) { m[curr_row][i] = double(arr[i]); } //--- curr_row++; } //--- curr_line++; if(curr_line > end_line) break; } } //--- FileClose(file_handle); //--- return fit_transform(m, save_data); } //+------------------------------------------------------------------+ template bool ScalerBaseCL::fit_transform_file(const string &file_name, ushort sep, int extra_file_flags, bool save_data, uint file_code_page = CP_ACP, int start_line = 1) { //--- ResetLastError(); //--- matrix m = {}; int file_handle = FileOpen(file_name, (extra_file_flags | FILE_TXT | FILE_READ), '\n', file_code_page); if(file_handle == INVALID_HANDLE) { LogCriticalError(StringFormat("Error al abrir el archivo = %s, ultimo erorr = %d", file_name, GetLastError()), FUNCION_ACTUAL); return false; } //--- int curr_line = 0; string arr[]; int dt = 0; int curr_row = 0; string line = ""; string extra[]; ArrayResize(extra, 0); //--- Se lee hasta el final while(!FileIsEnding(file_handle)) { //--- line = FileReadString(file_handle); //PrintFormat("'%s'", line); //--- if(curr_line >= start_line) { //--- if((dt = StringSplit(line, sep, arr)) < 1) { LogError(StringFormat("Linea mal formada = %d:\n%s", curr_line, line), FUNCION_ACTUAL); FileClose(file_handle); return false; } //--- m.Resize(curr_row + 1, dt); for(int i = 0; i < dt; i++) { m[curr_row][i] = double(arr[i]); } //--- curr_row++; } else { extra[ArrayResize(extra, ArraySize(extra) + 1) - 1] = line; } //--- curr_line++; } //--- Transformamos y cerramos m = fit_transform(m, save_data); FileClose(file_handle); //--- Reescribir // Abrimos pero en escritura file_handle = FileOpen(file_name, (extra_file_flags | FILE_TXT | FILE_WRITE), 0, file_code_page); if(file_handle == INVALID_HANDLE) { LogCriticalError(StringFormat("Error al abrir el archivo = %s, ultimo erorr = %d", file_name, GetLastError()), FUNCION_ACTUAL); return false; } // Init line for(int i = 0; i < ArraySize(extra); i++) FileWrite(file_handle, extra[i]); // Matrix const ulong rows = m.Rows(); const ulong cols = m.Cols(); for(ulong row = 0; row < rows; row++) { //--- line = ""; for(ulong col = 0; col < cols; col++) { line += string(m[row][col]) + ", "; } StringSetLength(line, StringLen(line) - 2); //--- FileWrite(file_handle, line); } //--- Ceramos el archivo FileClose(file_handle); //--- return true; } //+------------------------------------------------------------------+ template matrix ScalerBaseCL::fit_transform_by_src(const string& src, ushort sep, bool save_data, int str_start_line = 1, int str_end_line = SCALER_BASE_CL_FINAL_LINE) { //--- matrix m = {}; //--- int curr_line = 0; string arr[]; int dt = 0; int curr_row = 0; string general_arr[]; string line = ""; //--- const int total_row = StringSplit(src, '\n', general_arr); if(total_row <= str_start_line) { LogError(StringFormat("Numero de filas del string %d es invalida", total_row), FUNCION_ACTUAL); return m; } //--- Se lee hasta el final if(str_end_line == SCALER_BASE_CL_FINAL_LINE) { //--- for(int r = 0; r < total_row; r++) { //--- line = general_arr[r]; //--- if(curr_line >= str_start_line) { //--- if((dt = StringSplit(line, sep, arr)) < 1) { LogError(StringFormat("Linea mal formada = %d:\n%s", curr_line, line), FUNCION_ACTUAL); return m; } //--- m.Resize(curr_row + 1, dt); for(int i = 0; i < dt; i++) { m[curr_row][i] = double(arr[i]); } //--- curr_row++; } //--- curr_line++; } } else { //--- for(int r = 0; r < total_row; r++) { //--- line = general_arr[r]; //--- if(curr_line >= str_start_line) { //--- if((dt = StringSplit(line, sep, arr)) < 1) { LogError(StringFormat("Linea mal formada = %d:\n%s", curr_line, line), FUNCION_ACTUAL); return m; } //--- m.Resize(curr_row + 1, dt); for(int i = 0; i < dt; i++) { m[curr_row][i] = double(arr[i]); } //--- curr_row++; } //--- curr_line++; if(curr_line > str_end_line) break; } } //--- return fit_transform(m, save_data); } //+------------------------------------------------------------------+ //| Standardization Scaler | //+------------------------------------------------------------------+ template class StandardizationScalerCL : public ScalerBaseCL { private: static bool kernels_created; protected: vector mean, std; bool Save() override; bool Load(string prefix_name) override; public: StandardizationScalerCL(); vector fit_transform(vector &X) override; matrix fit_transform(matrix &X, bool save_data) override; matrix transform(matrix &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) override; vector transform(vector &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) override; matrix inverse_transform(matrix &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) override; vector inverse_transform(vector &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) override; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template static bool StandardizationScalerCL::kernels_created = false; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template StandardizationScalerCL::StandardizationScalerCL() { this.prefix_file = "_mean_std.csv"; //--- Seteamos los kernels (solo una vez) if(!kernels_created) { if(!cl.KernelCreate(kernel_standardization_fit_init, "fit_standard_scaler_init")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_standardization_transform_matrix, "standard_scaler_tranform_matrix")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_standardization_transform_vector, "standard_scaler_tranform_vector")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_standardization_inverse_matrix, "standard_scaler_inverse_tranform_matrix")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_standardization_inverse_vector, "standard_scaler_inverse_tranform_vector")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_standardization_fit_transform_vector, "standar_scaler_fit_transform_vector")) { Remover(); return; } kernels_created = true; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template bool StandardizationScalerCL::Save() { FileDelete(this.file_name_out); ResetLastError(); //--- int handle = FileOpen(this.file_name_out, FILE_WRITE | FILE_CSV | FILE_COMMON); if(handle == INVALID_HANDLE) { LogFatalError(StringFormat("Invalid handle Err= %d >> Filename= %s", GetLastError(), this.file_name_out), FUNCION_ACTUAL); return false; } //--- FileWrite(handle, vector_to_string(this.mean)); FileWrite(handle, vector_to_string(this.std)); FileWrite(handle, count_cols); FileWrite(handle, start_col); FileWrite(handle, excluyed_cols); FileWrite(handle, (int)use_custom); //--- FileClose(handle); return true; } //+------------------------------------------------------------------+ template bool StandardizationScalerCL::Load(string prefix_name) { this.file_name_out = prefix_name + this.prefix_file; //--- ResetLastError(); int handle = FileOpen(file_name_out, FILE_READ | FILE_CSV | FILE_COMMON, "\n"); if(handle == INVALID_HANDLE) { LogFatalError(StringFormat("Invalid handle Err= %d >> Filename= %s", GetLastError(), this.file_name_out), FUNCION_ACTUAL); return false; } //--- this.mean = string_to_vector(FileReadString(handle)); this.std = string_to_vector(FileReadString(handle)); this.count_cols = (T)StringToInteger(FileReadString(handle)); this.start_col = (T)StringToInteger(FileReadString(handle)); this.excluyed_cols = (T)StringToInteger(FileReadString(handle)); this.use_custom = (bool)StringToInteger(FileReadString(handle)); //--- FileClose(handle); return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template vector StandardizationScalerCL::fit_transform(vector &X) { if(loaded_scaler) { LogWarning("Este es un escalador cargado >> no es necesario ajustarlo a los nuevos datos, llame a otra instancia de una clase", FUNCION_ACTUAL); return transform(X); } //--- if(use_custom) { if(!CheckSizeCustom(X)) return X; } else { if(!CheckSizeExcluded(X)) return X; } //--- vector X_to_scaled = ExtractVectorToScale(X); const ulong X_to_scaled_size = X_to_scaled.Size(); //--- double mean_val = X_to_scaled.Mean(); double std_val = X_to_scaled.Std(); if(std_val < SCALER_BASE_CL_MIN_VAL) std_val = 1.0; //--- cl.BufferFromVector(global_vector_to_escale, X_to_scaled, CL_MEM_READ_WRITE); cl.SetArgument(kernel_standardization_fit_transform_vector, kernel_fit_transform_vector_arg_data1, mean_val); cl.SetArgument(kernel_standardization_fit_transform_vector, kernel_fit_transform_vector_arg_data2, std_val); cl.SetArgumentBuffer(kernel_standardization_fit_transform_vector, kernel_arg_index_all_vector_to_escale, global_vector_to_escale); //--- uint work_size[1] = { (uint)X_to_scaled_size }; uint offset[1] = {0}; if(!cl.Execute(kernel_standardization_fit_transform_vector, 1, offset, work_size)) return X; //--- cl.BufferToVector(global_vector_to_escale, X_to_scaled, X_to_scaled_size); return ReconstructVector(X, X_to_scaled); } //+------------------------------------------------------------------+ template matrix StandardizationScalerCL::fit_transform(matrix &X, bool save_data) { if(loaded_scaler) { LogWarning("Este es un escalador cargado >> no es necesario ajustarlo a los nuevos datos, llame a otra instancia de una clase", FUNCION_ACTUAL); return transform(X); } LogInfo(StringFormat("Numero de columnas de entrada: %I64u", X.Cols()), FUNCION_ACTUAL); //--- if(use_custom) { if(!CheckSizeCustom(X)) return X; } else { if(!CheckSizeExcluded(X)) return X; } //--- matrix X_to_scale = ExtractMatrixToScale(X); const ulong X_to_scale_cols = X_to_scale.Cols(); const ulong X_to_scale_rows = X_to_scale.Rows(); LogInfo(StringFormat("Columnas a escalar: %I64u", X_to_scale_cols), FUNCION_ACTUAL); //--- vector mean_cts(X_to_scale_cols); vector std_cts(X_to_scale_cols); //--- cl.BufferFromVector(global_buffer_data_1, mean_cts, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_2, std_cts, CL_MEM_READ_WRITE); cl.BufferFromMatrix(global_matrix_to_escale, X_to_scale, CL_MEM_READ_WRITE); //--- Argumentos 1 cl.SetArgumentBuffer(kernel_standardization_fit_init, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_standardization_fit_init, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_standardization_fit_init, global_matrix_to_escale, global_matrix_to_escale); cl.SetArgument(kernel_standardization_fit_init, kernel_standardization_arg_cols, (T)X_to_scale_cols); cl.SetArgument(kernel_standardization_fit_init, kernel_standardization_arg_rows, (T)X_to_scale_rows); // Read cl.BufferToVector(global_buffer_data_1, mean_cts, X_to_scale_cols); cl.BufferToVector(global_buffer_data_2, std_cts, X_to_scale_cols); //--- const static uint work_off_set[1] = {0}; uint work_size[1] = { (uint)X_to_scale_cols }; cl.Execute(kernel_standardization_fit_init, 1, work_off_set, work_size); //--- Argumentos 2 cl.SetArgumentBuffer(kernel_standardization_transform_matrix, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_standardization_transform_matrix, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_standardization_transform_matrix, global_matrix_to_escale, global_matrix_to_escale); cl.SetArgument(kernel_standardization_transform_matrix, kernel_standardization_arg_cols, (T)X_to_scale_cols); // Read const static uint work_off_tranforst[2] = {0, 0}; uint work_size_tranfors[2] = { (uint)X_to_scale_rows, (uint)X_to_scale_cols }; cl.Execute(kernel_standardization_transform_matrix, 2, work_off_tranforst, work_size_tranfors); //--- cl.BufferToMatrix(global_matrix_to_escale, X_to_scale, X_to_scale_rows, X_to_scale_cols); //--- if(save_data) { this.mean = mean_cts; this.std = std_cts; } //--- Limpiar los buffers CleanBuffersOnlyData(); CleanExtraData(); //--- Aqui siempre se reconstruye return ReconstructMatrix(X, X_to_scale); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template matrix StandardizationScalerCL::transform(matrix &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) { if(!loaded_scaler) { LogError("Primero llame a fit_transform o load() antes de transform", FUNCION_ACTUAL); return X; } //--- if(use_custom) { if(!CheckSizeCustom(X)) return X; } else { if(!CheckSizeExcluded(X)) return X; } //--- matrix X_to_scale = solo_escalar_lo_previsto ? ExtractMatrixToScale(X) : X; const ulong X_to_scale_cols = X_to_scale.Cols(); const ulong X_to_scale_rows = X_to_scale.Rows(); //--- if(X_to_scale_cols != this.mean.Size()) { LogError(StringFormat("Columnas a escalar %I64u != columnas entrenadas %u", X_to_scale_cols, this.mean.Size()), FUNCION_ACTUAL); return X; } //--- cl.BufferFromMatrix(global_matrix_to_escale, X_to_scale, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_1, mean, CL_MEM_READ_ONLY); cl.BufferFromVector(global_buffer_data_2, std, CL_MEM_READ_ONLY); //--- Argumentos cl.SetArgumentBuffer(kernel_standardization_transform_matrix, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_standardization_transform_matrix, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_standardization_transform_matrix, global_matrix_to_escale, global_matrix_to_escale); cl.SetArgument(kernel_standardization_transform_matrix, kernel_standardization_arg_cols, (T)X_to_scale_cols); //--- const static uint work_off_set[2] = {0, 0}; uint work_size_tranfors[2] = { (uint)X_to_scale_rows, (uint)X_to_scale_cols }; cl.Execute(kernel_standardization_transform_matrix, 2, work_off_set, work_size_tranfors); //--- cl.BufferToMatrix(global_matrix_to_escale, X_to_scale, X_to_scale_rows, X_to_scale_cols); //--- Limpiar los buffers CleanBuffersOnlyData(); //--- return (reconstruir) ? ReconstructMatrix(X, X_to_scale) : X_to_scale; } //+------------------------------------------------------------------+ template vector StandardizationScalerCL::transform(vector &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) { if(!loaded_scaler) { LogError("Primero llame a fit_transform o load() antes de transform", FUNCION_ACTUAL); return X; } //--- vector X_to_scale = solo_escalar_lo_previsto ? ExtractVectorToScale(X) : X; const ulong X_to_scale_size = X_to_scale.Size(); if(X_to_scale_size != this.mean.Size()) { LogError(StringFormat("Elementos a escalar %I64u != elementos entrenados %u", X_to_scale_size, this.mean.Size()), FUNCION_ACTUAL); return X; } //--- cl.BufferFromVector(global_vector_to_escale, X_to_scale, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_1, mean, CL_MEM_READ_ONLY); cl.BufferFromVector(global_buffer_data_2, std, CL_MEM_READ_ONLY); //--- Argumentos cl.SetArgumentBuffer(kernel_standardization_transform_vector, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_standardization_transform_vector, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_standardization_transform_vector, kernel_arg_index_all_vector_to_escale, global_vector_to_escale); //--- const static uint work_off_set[1] = {0}; uint work_size_tranfors[1] = { (uint)X_to_scale_size}; cl.Execute(kernel_standardization_transform_vector, 1, work_off_set, work_size_tranfors); //--- cl.BufferToVector(global_vector_to_escale, X_to_scale, X_to_scale_size); //--- Limpiar los buffers CleanBuffersOnlyData(); //--- return (reconstruir) ? ReconstructVector(X, X_to_scale) : X_to_scale; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template matrix StandardizationScalerCL::inverse_transform(matrix &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) { if(!loaded_scaler) { LogError("Escalador no entrenado. Llame primero a fit_transform", FUNCION_ACTUAL); return X_scaled; } //--- matrix X_to_unscale = (solo_escalar_lo_previsto) ? ExtractMatrixToScale(X_scaled) : X_scaled; const ulong X_to_unscale_cols = X_to_unscale.Cols(); const ulong X_to_unscale_rows = X_to_unscale.Rows(); //--- if(X_to_unscale_cols != this.mean.Size()) { LogError(StringFormat("Columnas escaladas %I64u != columnas entrenadas %u", X_to_unscale_cols, this.mean.Size()), FUNCION_ACTUAL); return X_scaled; } //--- cl.BufferFromMatrix(global_matrix_to_escale, X_to_unscale, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_1, mean, CL_MEM_READ_ONLY); cl.BufferFromVector(global_buffer_data_2, std, CL_MEM_READ_ONLY); //--- Argumentos cl.SetArgumentBuffer(kernel_standardization_inverse_matrix, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_standardization_inverse_matrix, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_standardization_inverse_matrix, global_matrix_to_escale, global_matrix_to_escale); cl.SetArgument(kernel_standardization_inverse_matrix, kernel_standardization_arg_cols, (T)X_to_unscale_cols); //--- const static uint work_off_set[2] = {0, 0}; uint work_size_tranfors[2] = { (uint)X_to_unscale_rows, (uint)X_to_unscale_cols }; cl.Execute(kernel_standardization_inverse_matrix, 2, work_off_set, work_size_tranfors); //--- cl.BufferToMatrix(global_matrix_to_escale, X_to_unscale, X_to_unscale_rows, X_to_unscale_cols); //--- Limpiar los buffers CleanBuffersOnlyData(); //--- return (reconstruir) ? ReconstructMatrix(X_scaled, X_to_unscale) : X_to_unscale; } //+------------------------------------------------------------------+ template vector StandardizationScalerCL::inverse_transform(vector &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) { if(!loaded_scaler) { LogError("Escalador no entrenado. Llame primero a fit_transform", FUNCION_ACTUAL); return X_scaled; } //--- vector X_to_unscale = (solo_escalar_lo_previsto) ? ExtractVectorToScale(X_scaled) : X_scaled; const ulong X_to_unscale_size = X_to_unscale.Size(); //--- if(X_to_unscale_size != this.mean.Size()) { LogError(StringFormat("Elementos escalados %I64u != elementos entrenados %u", X_to_unscale_size, this.mean.Size()), FUNCION_ACTUAL); return X_scaled; } //--- cl.BufferFromVector(global_vector_to_escale, X_to_unscale, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_1, mean, CL_MEM_READ_ONLY); cl.BufferFromVector(global_buffer_data_2, std, CL_MEM_READ_ONLY); //--- Argumentos cl.SetArgumentBuffer(kernel_standardization_inverse_vector, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_standardization_inverse_vector, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_standardization_inverse_vector, kernel_arg_index_all_vector_to_escale, global_vector_to_escale); //--- const static uint work_off_set[1] = {0}; uint work_size_tranfors[1] = { (uint)X_to_unscale_size}; cl.Execute(kernel_standardization_inverse_vector, 1, work_off_set, work_size_tranfors); //--- cl.BufferToVector(global_vector_to_escale, X_to_unscale, X_to_unscale_size); //--- Limpiar los buffers CleanBuffersOnlyData(); //--- return (reconstruir) ? ReconstructVector(X_scaled, X_to_unscale) : X_to_unscale; } //+------------------------------------------------------------------+ //| MaxMin Scaler | //+------------------------------------------------------------------+ template class MaxMinScalerCL : public ScalerBaseCL { private: static bool kernels_created; protected: vector min_vals, max_vals; bool Save() override; bool Load(string prefix_name) override; public: MaxMinScalerCL(); vector fit_transform(vector &X) override; matrix fit_transform(matrix &X, bool save_data) override; matrix transform(matrix &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) override; vector transform(vector &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) override; matrix inverse_transform(matrix &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) override; vector inverse_transform(vector &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) override; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template static bool MaxMinScalerCL::kernels_created = false; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template MaxMinScalerCL::MaxMinScalerCL(void) { this.prefix_file = "_min_max.csv"; //--- Seteamos los kernels (solo una vez) if(!kernels_created) { if(!cl.KernelCreate(kernel_maxmin_fit_init, "fit_scaler_max_min_init")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_maxmin_transform_matrix, "max_min_scaler_tranform_matrix")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_maxmin_transform_vector, "max_min_scaler_tranform_vector")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_maxmin_inverse_matrix, "min_max_inverse_tranform_matrix")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_maxmin_inverse_vector, "max_min_scaler_inverse_tranform_vector")) { Remover(); return; } //--- if(!cl.KernelCreate(kernel_maxmin_fit_transform_vector, "max_min_scaler_fit_transform_vector")) { Remover(); return; } kernels_created = true; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template bool MaxMinScalerCL::Save() { FileDelete(this.file_name_out); ResetLastError(); //--- int handle = FileOpen(this.file_name_out, FILE_WRITE | FILE_CSV | FILE_COMMON); if(handle == INVALID_HANDLE) { LogFatalError(StringFormat("Invalid handle Err= %d >> Filename= %s", GetLastError(), this.file_name_out), FUNCION_ACTUAL); return false; } //--- FileWrite(handle, vector_to_string(this.min_vals)); FileWrite(handle, vector_to_string(this.max_vals)); FileWrite(handle, count_cols); FileWrite(handle, start_col); FileWrite(handle, excluyed_cols); FileWrite(handle, (int)use_custom); //--- FileClose(handle); return true; } //+------------------------------------------------------------------+ template bool MaxMinScalerCL::Load(string prefix_name) { this.file_name_out = prefix_name + this.prefix_file; //--- ResetLastError(); int handle = FileOpen(file_name_out, FILE_READ | FILE_CSV | FILE_COMMON, "\n"); if(handle == INVALID_HANDLE) { LogFatalError(StringFormat("Invalid handle Err= %d >> Filename= %s", GetLastError(), this.file_name_out), FUNCION_ACTUAL); return false; } //--- this.min_vals = string_to_vector(FileReadString(handle)); this.max_vals = string_to_vector(FileReadString(handle)); this.count_cols = (T)StringToInteger(FileReadString(handle)); this.start_col = (T)StringToInteger(FileReadString(handle)); this.excluyed_cols = (T)StringToInteger(FileReadString(handle)); this.use_custom = (bool)StringToInteger(FileReadString(handle)); //--- FileClose(handle); return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template vector MaxMinScalerCL::fit_transform(vector &X) { if(loaded_scaler) { LogWarning("Este es un escalador cargado >> no es necesario ajustarlo a los nuevos datos, llame a otra instancia de una clase", FUNCION_ACTUAL); return transform(X); } //--- if(use_custom) { if(!CheckSizeCustom(X)) return X; } else { if(!CheckSizeExcluded(X)) return X; } //--- vector X_to_scaled = ExtractVectorToScale(X); const ulong X_to_scaled_size = X_to_scaled.Size(); //--- double min = X_to_scaled.Min(); double max = X_to_scaled.Max(); if((max - min) < SCALER_BASE_CL_MIN_VAL) max = min + 1.0; //--- cl.BufferFromVector(global_vector_to_escale, X_to_scaled, CL_MEM_READ_WRITE); cl.SetArgument(kernel_maxmin_fit_transform_vector, kernel_fit_transform_vector_arg_data1, min); cl.SetArgument(kernel_maxmin_fit_transform_vector, kernel_fit_transform_vector_arg_data2, max); cl.SetArgumentBuffer(kernel_maxmin_fit_transform_vector, kernel_arg_index_all_vector_to_escale, global_vector_to_escale); //--- uint work_size[1] = { (uint)X_to_scaled_size }; uint offset[1] = {0}; if(!cl.Execute(kernel_maxmin_fit_transform_vector, 1, offset, work_size)) return X; //--- cl.BufferToVector(global_vector_to_escale, X_to_scaled, X_to_scaled_size); return ReconstructVector(X, X_to_scaled); } //+------------------------------------------------------------------+ template matrix MaxMinScalerCL::fit_transform(matrix &X, bool save_data) { if(loaded_scaler) { LogWarning("Este es un escalador cargado >> no es necesario ajustarlo a los nuevos datos, llame a otra instancia de una clase", FUNCION_ACTUAL); return transform(X); } LogInfo(StringFormat("Numero de columnas de entrada: %I64u", X.Cols()), FUNCION_ACTUAL); //--- if(use_custom) { if(!CheckSizeCustom(X)) return X; } else { if(!CheckSizeExcluded(X)) return X; } //--- matrix X_to_scale = ExtractMatrixToScale(X); const ulong X_to_scale_cols = X_to_scale.Cols(); const ulong X_to_scale_rows = X_to_scale.Rows(); LogInfo(StringFormat("Columnas a escalar: %I64u", X_to_scale_cols), FUNCION_ACTUAL); //--- vector min_cts(X_to_scale_cols); vector max_cts(X_to_scale_cols); //--- Buffers cl.BufferFromVector(global_buffer_data_1, min_cts, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_2, max_cts, CL_MEM_READ_WRITE); cl.BufferFromMatrix(global_matrix_to_escale, X_to_scale, CL_MEM_READ_WRITE); //--- Argumentos 1 cl.SetArgumentBuffer(kernel_maxmin_fit_init, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_maxmin_fit_init, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_maxmin_fit_init, global_matrix_to_escale, global_matrix_to_escale); cl.SetArgument(kernel_maxmin_fit_init, kernel_maxmin_arg_cols, (T)X_to_scale_cols); cl.SetArgument(kernel_maxmin_fit_init, kernel_maxmin_arg_rows, (T)X_to_scale_rows); //--- const static uint work_off_set[1] = {0}; uint work_size[1] = { (uint)X_to_scale_cols }; cl.Execute(kernel_maxmin_fit_init, 1, work_off_set, work_size); // Read vector cl.BufferToVector(global_buffer_data_1, min_cts, X_to_scale_cols); cl.BufferToVector(global_buffer_data_2, max_cts, X_to_scale_cols); //--- Argumentos 2 cl.SetArgumentBuffer(kernel_maxmin_transform_matrix, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_maxmin_transform_matrix, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_maxmin_transform_matrix, global_matrix_to_escale, global_matrix_to_escale); cl.SetArgument(kernel_maxmin_transform_matrix, kernel_maxmin_arg_cols, (T)X_to_scale_cols); // Read matrix const static uint work_off_tranforst[2] = {0, 0}; uint work_size_tranfors[2] = { (uint)X_to_scale_rows, (uint)X_to_scale_cols }; cl.Execute(kernel_maxmin_transform_matrix, 2, work_off_tranforst, work_size_tranfors); //--- cl.BufferToMatrix(global_matrix_to_escale, X_to_scale, X_to_scale_rows, X_to_scale_cols); //--- if(save_data) { this.min_vals = min_cts; this.max_vals = max_cts; } //--- Limpiar los buffers CleanBuffersOnlyData(); CleanExtraData(); //--- Aqui siempre se reconstruye return ReconstructMatrix(X, X_to_scale); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template matrix MaxMinScalerCL::transform(matrix &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) { if(!loaded_scaler) { LogError("Primero llame a fit_transform o load() antes de transform", FUNCION_ACTUAL); return X; } //--- if(use_custom) { if(!CheckSizeCustom(X)) return X; } else { if(!CheckSizeExcluded(X)) return X; } //--- matrix X_to_scale = solo_escalar_lo_previsto ? ExtractMatrixToScale(X) : X; const ulong X_to_scale_cols = X_to_scale.Cols(); const ulong X_to_scale_rows = X_to_scale.Rows(); //--- if(X_to_scale_cols != this.min_vals.Size()) { LogError(StringFormat("Columnas a escalar %I64u != columnas entrenadas %u", X_to_scale_cols, this.min_vals.Size()), FUNCION_ACTUAL); return X; } //--- cl.BufferFromMatrix(global_matrix_to_escale, X_to_scale, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_1, min_vals, CL_MEM_READ_ONLY); cl.BufferFromVector(global_buffer_data_2, max_vals, CL_MEM_READ_ONLY); //--- Argumentos cl.SetArgumentBuffer(kernel_maxmin_transform_matrix, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_maxmin_transform_matrix, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_maxmin_transform_matrix, global_matrix_to_escale, global_matrix_to_escale); cl.SetArgument(kernel_maxmin_transform_matrix, kernel_maxmin_arg_cols, (T)X_to_scale_cols); //--- const static uint work_off_set[2] = {0, 0}; uint work_size_tranfors[2] = { (uint)X_to_scale_rows, (uint)X_to_scale_cols }; cl.Execute(kernel_maxmin_transform_matrix, 2, work_off_set, work_size_tranfors); //--- cl.BufferToMatrix(global_matrix_to_escale, X_to_scale, X_to_scale_rows, X_to_scale_cols); //--- Limpiar los buffers CleanBuffersOnlyData(); //--- return (reconstruir) ? ReconstructMatrix(X, X_to_scale) : X_to_scale; } //+------------------------------------------------------------------+ template vector MaxMinScalerCL::transform(vector &X, bool solo_escalar_lo_previsto = false, bool reconstruir = false) { if(!loaded_scaler) { LogError("Primero llame a fit_transform o load() antes de transform", FUNCION_ACTUAL); return X; } //--- vector X_to_scale = solo_escalar_lo_previsto ? ExtractVectorToScale(X) : X; const ulong X_to_scale_size = X_to_scale.Size(); if(X_to_scale_size != this.min_vals.Size()) { LogError(StringFormat("Elementos a escalar %I64u != elementos entrenados %u", X_to_scale_size, this.min_vals.Size()), FUNCION_ACTUAL); return X; } //--- cl.BufferFromVector(global_vector_to_escale, X_to_scale, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_1, min_vals, CL_MEM_READ_ONLY); cl.BufferFromVector(global_buffer_data_2, max_vals, CL_MEM_READ_ONLY); //--- Argumentos cl.SetArgumentBuffer(kernel_maxmin_transform_vector, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_maxmin_transform_vector, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_maxmin_transform_vector, kernel_arg_index_all_vector_to_escale, global_vector_to_escale); //--- const static uint work_off_set[1] = {0}; uint work_size_tranfors[1] = { (uint)X_to_scale_size}; cl.Execute(kernel_maxmin_transform_vector, 1, work_off_set, work_size_tranfors); //--- cl.BufferToVector(global_vector_to_escale, X_to_scale, X_to_scale_size); //--- Limpiar los buffers CleanBuffersOnlyData(); //--- return (reconstruir) ? ReconstructVector(X, X_to_scale) : X_to_scale; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template matrix MaxMinScalerCL::inverse_transform(matrix &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) { if(!loaded_scaler) { LogError("Escalador no entrenado. Llame primero a fit_transform", FUNCION_ACTUAL); return X_scaled; } //--- matrix X_to_unscale = (solo_escalar_lo_previsto) ? ExtractMatrixToScale(X_scaled) : X_scaled; const ulong X_to_unscale_cols = X_to_unscale.Cols(); const ulong X_to_unscale_rows = X_to_unscale.Rows(); //--- if(X_to_unscale_cols != this.min_vals.Size()) { LogError(StringFormat("Columnas escaladas %I64u != columnas entrenadas %u", X_to_unscale_cols, this.min_vals.Size()), FUNCION_ACTUAL); return X_scaled; } //--- cl.BufferFromMatrix(global_matrix_to_escale, X_to_unscale, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_1, min_vals, CL_MEM_READ_ONLY); cl.BufferFromVector(global_buffer_data_2, max_vals, CL_MEM_READ_ONLY); //--- Argumentos cl.SetArgumentBuffer(kernel_maxmin_inverse_matrix, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_maxmin_inverse_matrix, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_maxmin_inverse_matrix, global_matrix_to_escale, global_matrix_to_escale); cl.SetArgument(kernel_maxmin_inverse_matrix, kernel_maxmin_arg_cols, (T)X_to_unscale_cols); //--- const static uint work_off_set[2] = {0, 0}; uint work_size_tranfors[2] = { (uint)X_to_unscale_rows, (uint)X_to_unscale_cols }; cl.Execute(kernel_maxmin_inverse_matrix, 2, work_off_set, work_size_tranfors); //--- cl.BufferToMatrix(global_matrix_to_escale, X_to_unscale, X_to_unscale_rows, X_to_unscale_cols); //--- Limpiar los buffers CleanBuffersOnlyData(); //--- return (reconstruir) ? ReconstructMatrix(X_scaled, X_to_unscale) : X_to_unscale; } //+------------------------------------------------------------------+ template vector MaxMinScalerCL::inverse_transform(vector &X_scaled, bool solo_escalar_lo_previsto = false, bool reconstruir = false) { if(!loaded_scaler) { LogError("Escalador no entrenado. Llame primero a fit_transform", FUNCION_ACTUAL); return X_scaled; } //--- vector X_to_unscale = (solo_escalar_lo_previsto) ? ExtractVectorToScale(X_scaled) : X_scaled; const ulong X_to_unscale_size = X_to_unscale.Size(); //--- if(X_to_unscale_size != this.min_vals.Size()) { LogError(StringFormat("Elementos escalados %I64u != elementos entrenados %u", X_to_unscale_size, this.min_vals.Size()), FUNCION_ACTUAL); return X_scaled; } //--- cl.BufferFromVector(global_vector_to_escale, X_to_unscale, CL_MEM_READ_WRITE); cl.BufferFromVector(global_buffer_data_1, min_vals, CL_MEM_READ_ONLY); cl.BufferFromVector(global_buffer_data_2, max_vals, CL_MEM_READ_ONLY); //--- Argumentos cl.SetArgumentBuffer(kernel_maxmin_inverse_vector, global_buffer_data_1, global_buffer_data_1); cl.SetArgumentBuffer(kernel_maxmin_inverse_vector, global_buffer_data_2, global_buffer_data_2); cl.SetArgumentBuffer(kernel_maxmin_inverse_vector, kernel_arg_index_all_vector_to_escale, global_vector_to_escale); //--- const static uint work_off_set[1] = {0}; uint work_size_tranfors[1] = { (uint)X_to_unscale_size}; cl.Execute(kernel_maxmin_inverse_vector, 1, work_off_set, work_size_tranfors); //--- cl.BufferToVector(global_vector_to_escale, X_to_unscale, X_to_unscale_size); //--- Limpiar los buffers CleanBuffersOnlyData(); //--- return (reconstruir) ? ReconstructVector(X_scaled, X_to_unscale) : X_to_unscale; } //+------------------------------------------------------------------+ #endif // SCALERBYLEO_SCALER_BASE_CL_MQH //+------------------------------------------------------------------+