Машинное обучение в трейдинге: теория, модели, практика и алготорговля - страница 3256

 
mytarmailS #:

 MathAbs() мне кажеться лишним

Можно и по отдельности знаки проверять. Не суть.

 
fxsaber #:

400 миллионов double-чисел весят 3 гига.

ну понятно, памяти не хватает на всю эту радость

 
Forester #:
в statistics.mqh

функции
PearsonCorrM - Корреляция всех строк ко всем - самая быстрая.

Где-то ошибся, но не вижу.
#include <Math\Alglib\statistics.mqh> 

void OnStart()
{
  const matrix<double> matrix1 = {{1, 2, 3}, {1, 2, 3}, {1, 2, 3}};
  
  const CMatrixDouble Matrix1(matrix1);
  CMatrixDouble Matrix2;
    
  if (CBaseStat::PearsonCorrM(Matrix1, 3, 3, Matrix2))  
    Print(Matrix2.ToMatrix());
}
 
fxsaber #:
Где-то ошибся, но не вижу.

А вот с такой строкой работает

  const matrix<double> matrix1 = {{2, 2, 3}, {3, 2, 3}, {1, 2, 1}};

[[1,0,0.8660254037844387]
[0,0,0]
[0.8660254037844387,0,1]]

Видимо если в столбце все данные одинаковые то расчет пропускается.
Вот во 2-м столбце оставил все по 2 и 2-я строка матрицы осталась нулевой. Хотя наверное правильно бы диагональ заполнять 1-цами.

ПС. Вначале подумал, что баг с Alglib-ом.

В старом коде значения элементам устанавливались через
m[row].Set(col, val);
А сейчас
m.Set(row,col, val);

Жаль что нет обратной совместимости. Ну мне это не важно. Сейчас не через Alglib работаю. Если у кого-то старые коды перестанут работать - то нужно будет исправлять.
Самое печальное, что старая версия

m[row].Set(col, val);

не пишет сообщений об ошибке, а просто ничего не делает. Люди просто не заменят и не узнают, что надо менять код. Будет что-то считать, но с неизмененными матрицами.

 
Forester #:

Видимо если в столбце все данные одинаковые то расчет пропускается.

Пирсон не между рядами вычисляет, а между столбцами?

ЗЫ Похоже, что так.
const matrix<double> matrix1 = {{1, 1, 1}, {2, 2, 2}, {3, 3, 3}};
Выдает единичную матрицу.
 
fxsaber #:

Пирсон не между рядами вычисляет, а между столбцами?

ЗЫ Похоже, что так. Выдает единичную матрицу.
Транспонировать можно.
 

Alglib хорошая библиотека, есть все для МО. Нейросети там овер медленные, в ранних версиях так было.

 
Forester #:
в statistics.mqh

PearsonCorrM - Корреляция всех строк ко всем - самая быстрая.

На ее основе сделал расчет корреляционной матрицы.

#include <Math\Alglib\statistics.mqh> // https://www.mql5.com/ru/code/11077

const matrix<double> CorrMatrix( const matrix<double> &Matrix )
{
  matrix<double> Res = {};
  
  const CMatrixDouble MatrixIn(Matrix);
  CMatrixDouble MatrixOut;  

  if (CBaseStat::PearsonCorrM(MatrixIn, MatrixIn.Rows(), MatrixIn.Cols(), MatrixOut)) // https://www.mql5.com/ru/code/11077
    Res = MatrixOut.ToMatrix();
  
  return(Res);
}


Замерил производительность.

#property script_show_inputs

input int inRows = 100; // Длина строки
input int inCols = 15000; // Количество строк

void FillArray( double &Array[], const int Amount )
{
  for (uint i = ArrayResize(Array, Amount); (bool)i--;)
    Array[i] = MathRand();
}

bool IsEqual( matrix<double> &Matrix1, const matrix<double> &Matrix2 )
{
//  return(MathAbs((Matrix1 - Matrix2).Mean()) < 1e-15); // Дорого по памяти.
  
  Matrix1 -= Matrix2;  
  
  const bool Res = (MathAbs(Matrix1.Mean()) < 1e-15);
  
  Matrix1 += Matrix2;
  
  return(Res);
}

#define TOSTRING(A) #A + " = " + (string)(A) + " "

#define BENCH(A)                                                              \
  StartMemory = MQLInfoInteger(MQL_MEMORY_USED);                              \
  StartTime = GetMicrosecondCount();                                          \
  A;                                                                          \
  Print(#A + " - " + (string)(GetMicrosecondCount() - StartTime) + " mcs, " + \
       (string)(MQLInfoInteger(MQL_MEMORY_USED) - StartMemory) + " MB"); 

void PrintCPU()
{
#ifdef _RELEASE
  Print("EX5: " + (string)__MQLBUILD__ + " " + __CPU_ARCHITECTURE__ + " Release.");
#else // #ifdef _RELEASE
  Print("EX5: " + (string)__MQLBUILD__ + " " + __CPU_ARCHITECTURE__ + " Debug.");
#endif // #ifdef _RELEASE #else
  Print(TOSTRING(TerminalInfoString(TERMINAL_CPU_NAME)));
  Print(TOSTRING(TerminalInfoInteger(TERMINAL_CPU_CORES)));
  Print(TOSTRING(TerminalInfoString(TERMINAL_CPU_ARCHITECTURE)));
}

void OnStart()
{  
  PrintCPU();
  
  double Array[];
  FillArray(Array, inRows * inCols);
  
  matrix<double> Matrix;  
  Matrix.Assign(Array);
  Matrix.Init(inCols, inRows);
  Matrix = Matrix.Transpose();
  
  ulong StartTime, StartMemory;
  
  Print(TOSTRING(inRows) + TOSTRING(inCols));

  BENCH(matrix<double> Matrix1 = CorrMatrix(Matrix)) // https://www.mql5.com/ru/code/11077
  BENCH(matrix<double> Matrix2 = Matrix.CorrCoef(false)); // https://www.mql5.com/ru/docs/basis/types/matrix_vector
//  BENCH(matrix<double> Matrix3 = CorrMatrix(Array, inRows)); // https://www.mql5.com/ru/code/17982 

  Print(TOSTRING(IsEqual(Matrix1, Matrix2)));
//  Print(TOSTRING(IsEqual(Matrix3, Matrix2)));  
}


Результат.

EX5: 3981 AVX Release.
TerminalInfoString(TERMINAL_CPU_NAME) = Intel Core i7-2700K  @ 3.50GHz 
TerminalInfoInteger(TERMINAL_CPU_CORES) = 8 
TerminalInfoString(TERMINAL_CPU_ARCHITECTURE) = AVX 
inRows = 100 inCols = 15000 
matrix<double> Matrix1 = CorrMatrix(Matrix) - 14732702 mcs, 1717 MB
matrix<double> Matrix2 = Matrix.CorrCoef(false) - 40318390 mcs, 1717 MB
IsEqual(Matrix1, Matrix2) = true 


Хорошо видно, что Alglib считает матрицу быстрее, чем штатный матричный метод.

Однако, для поиска паттернов считать корреляционную матрицу - безумие по потреблению RAM.


Питон за какое время считает такую же по размерам исходную матрицу, как в примере выше?

 
fxsaber #:

Однако, для поиска паттернов считать корреляционную матрицу - безумие по потреблению RAM.

У меня встроенный побыстрее сработал: на i7-6700

inRows = 100 inCols = 15000 
matrix<double> Matrix1 = CorrMatrix(Matrix) - 14648864 mcs, 1717 MB
matrix<double> Matrix2 = Matrix.CorrCoef(false) - 29589590 mcs, 1717 MB
IsEqual(Matrix1, Matrix2) = true 

Странно что штатный медленнее, могли бы просто скопировать. Вряд ли в Alglibe какой то уникальный ускоренный алгоритм под лицензией.

Другие 2 варианта из Alglib не пробовали?
Если считать в циклах каждая строка к каждой строке или каждая строка ко всем строкам, то память будет экономнее расходоваться (2 строки или 1 строка +матрица). Но это будет дольше, точно не помню, но думаю, что и медленнее встроенной ф-ии.

 
fxsaber #:

Однако, для поиска паттернов считать корреляционную матрицу - безумие по потреблению RAM.

С памятью все хуже.
Перед запуском



А во время работы Алглибовского PearsonCorrM память все время растет: и 5 гг видел, на скрин 4,6 попало


и во время работы штатного Matrix.CorrCoef

Видимо штатный оптиизирован для мин. использования памяти, а алглибовский оптимизирован на скорость.

Причина обращения: