ScalerByLeo/Src/ScalerBaseCL.mqh
Nique_372 0cc42ae7f5
2026-01-01 21:54:18 -05:00

2041 lines
140 KiB
MQL5

//+------------------------------------------------------------------+
//| 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 <typename T> //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 <typename T>
static COpenCL ScalerBaseCL::cl;
template <typename T>
static bool ScalerBaseCL::open_cl_is_create = false;
template <typename T>
static bool ScalerBaseCL::kernels_base_created = false;
template <typename t>
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 <typename T> 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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
void ScalerBaseCL::CleanBufferMatrix(void)
{
cl.BufferFree(global_extraer_recos_mtx_matrix_data);
cl.BufferFree(global_extraer_recos_mtx_matrix_res);
}
//+------------------------------------------------------------------+
template <typename T>
void ScalerBaseCL::CleanBufferVector(void)
{
cl.BufferFree(global_extraer_recos_vec_vector_data);
cl.BufferFree(global_extraer_recos_vec_vector_res);
}
//+------------------------------------------------------------------+
template <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
inline bool ScalerBaseCL::load(string prefix_name)
{
loaded_scaler = true;
return this.Load(prefix_name);
}
//+------------------------------------------------------------------+
template <typename T>
inline bool ScalerBaseCL::save(string prefix_name)
{
this.file_name_out = prefix_name + this.prefix_file;
return this.Save();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename T>
void ScalerBaseCL::CleanBuffersOnlyData(void)
{
cl.BufferFree(global_matrix_to_escale);
cl.BufferFree(global_vector_to_escale);
}
//+------------------------------------------------------------------+
template <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
class StandardizationScalerCL : public ScalerBaseCL<T>
{
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 <typename T>
static bool StandardizationScalerCL::kernels_created = false;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename T> 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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
class MaxMinScalerCL : public ScalerBaseCL<T>
{
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 <typename T>
static bool MaxMinScalerCL::kernels_created = false;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
template <typename T> 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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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 <typename T>
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
//+------------------------------------------------------------------+