287 lines
No EOL
20 KiB
MQL5
287 lines
No EOL
20 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Convolution_test.mq5 |
|
|
//| Copyright 2021, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2021, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
#property script_show_inputs
|
|
//+------------------------------------------------------------------+
|
|
//| Внешние параметры для работы скрипта |
|
|
//+------------------------------------------------------------------+
|
|
input string StudyFileName = "study_data.csv"; // Имя файла с обучающей выборкой
|
|
input string OutputFileName = "loss_study_conv.csv";// Имя файла для записи динамики ошибки
|
|
input int BarsToLine = 40; // Количество исторических баров в одном паттерне
|
|
input int NeuronsToBar = 4; // Количество нейронов входного слоя на 1 бар
|
|
input bool UseOpenCL = false; // Использовать OpenCL
|
|
input int BatchSize = 10000; // Размер пакета для обновления матрицы весов
|
|
input double LearningRate = 0.00001; // Коэффициент обучения
|
|
input int HiddenLayers = 1; // Количество скрытых слоёв
|
|
input int HiddenLayer = 40; // Количество нейронов в одном скрытом слое
|
|
input int Epochs = 10000; // Количество эпох обучения
|
|
//+------------------------------------------------------------------+
|
|
//| Подключаем библиотеку нейронной сети |
|
|
//+------------------------------------------------------------------+
|
|
#include <NeuroNetworksBook\realization\neuronnet.mqh>
|
|
CNet *net;
|
|
//+------------------------------------------------------------------+
|
|
//| Начало программы скрипта |
|
|
//+------------------------------------------------------------------+
|
|
void OnStart()
|
|
{
|
|
//---
|
|
CArrayObj *layers = new CArrayObj();
|
|
if(CheckPointer(layers) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create CArrayObj: %d", GetLastError());
|
|
return;
|
|
}
|
|
//--- Слой исходных данных
|
|
CLayerDescription *descr = new CLayerDescription();
|
|
if(CheckPointer(descr) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create CLayerDescription: %d", GetLastError());
|
|
return;
|
|
}
|
|
descr.type = defNeuronBase;
|
|
descr.count = NeuronsToBar * BarsToLine;
|
|
descr.window = 0;
|
|
descr.activation = ACT_None;
|
|
descr.optimization = None;
|
|
if(!layers.Add(descr))
|
|
{
|
|
PrintFormat("Error of add layer: %d", GetLastError());
|
|
return;
|
|
}
|
|
//--- Свёрточный слой
|
|
descr = new CLayerDescription();
|
|
if(CheckPointer(descr) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create CLayerDescription: %d", GetLastError());
|
|
delete layers;
|
|
return;
|
|
}
|
|
descr.type = defNeuronConv;
|
|
descr.count = BarsToLine;
|
|
descr.window = NeuronsToBar;
|
|
descr.window_out = 8;
|
|
descr.step = NeuronsToBar;
|
|
descr.activation = ACT_SWISH;
|
|
descr.optimization = Adam;
|
|
descr.activation_params[0] = 1;
|
|
if(!layers.Add(descr))
|
|
{
|
|
PrintFormat("Error of add layer: %d", GetLastError());
|
|
delete layers;
|
|
delete descr;
|
|
return;
|
|
}
|
|
//--- Подвыборочный слой
|
|
descr = new CLayerDescription();
|
|
if(CheckPointer(descr) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create CLayerDescription: %d", GetLastError());
|
|
delete layers;
|
|
return;
|
|
}
|
|
descr.type = defNeuronProof;
|
|
int prev_count = descr.count = BarsToLine - 1;
|
|
descr.window = 2;
|
|
descr.window_out = 8;
|
|
descr.step = 1;
|
|
descr.activation = ACT_MAX_POOLING;
|
|
descr.optimization = None;
|
|
descr.activation_params[0] = 0;
|
|
if(!layers.Add(descr))
|
|
{
|
|
PrintFormat("Error of add layer: %d", GetLastError());
|
|
delete layers;
|
|
delete descr;
|
|
return;
|
|
}
|
|
//--- Скрытые слоя
|
|
for(int i = 0; i < HiddenLayers; i++)
|
|
{
|
|
descr = new CLayerDescription();
|
|
if(CheckPointer(descr) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create CLayerDescription: %d", GetLastError());
|
|
return;
|
|
}
|
|
descr.type = defNeuronBase;
|
|
descr.count = HiddenLayer;
|
|
descr.activation = ACT_SWISH;
|
|
descr.optimization = Adam;
|
|
descr.activation_params[0] = 1;
|
|
if(!layers.Add(descr))
|
|
{
|
|
PrintFormat("Error of add layer: %d", GetLastError());
|
|
return;
|
|
}
|
|
}
|
|
//--- Слой результатов
|
|
descr = new CLayerDescription();
|
|
if(CheckPointer(descr) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create CLayerDescription: %d", GetLastError());
|
|
return;
|
|
}
|
|
descr.type = defNeuronBase;
|
|
descr.count = 2;
|
|
descr.activation = ACT_LINE;
|
|
descr.optimization = Adam;
|
|
descr.activation_params[0] = 1;
|
|
if(!layers.Add(descr))
|
|
{
|
|
PrintFormat("Error of add layer: %d", GetLastError());
|
|
return;
|
|
}
|
|
//--- Инициализация модели нейронной сети
|
|
net = new CNet();
|
|
if(CheckPointer(net) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create Net: %d", GetLastError());
|
|
return;
|
|
}
|
|
//---
|
|
if(!net.Create(layers, LearningRate, 0.9, 0.999, ENUM_LOSS_MSE, 0, 0))
|
|
{
|
|
PrintFormat("Error of init Net: %d", GetLastError());
|
|
return;
|
|
}
|
|
delete layers;
|
|
net.UseOpenCL(UseOpenCL);
|
|
net.LossSmoothFactor(BatchSize);
|
|
//--- Блок загрузки обучающей выборки
|
|
CArrayObj *data = new CArrayObj();
|
|
if(CheckPointer(data) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create Historical data array: %d", GetLastError());
|
|
return;
|
|
}
|
|
//---
|
|
CArrayObj *result = new CArrayObj();
|
|
if(CheckPointer(result) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create Target data array: %d", GetLastError());
|
|
return;
|
|
}
|
|
CBufferDouble *pattern;
|
|
//---
|
|
CBufferDouble *target;
|
|
//--- Открываем файл с обучающей выборкой
|
|
int handle = FileOpen(StudyFileName, FILE_READ | FILE_CSV | FILE_ANSI | FILE_SHARE_READ, ",", CP_UTF8);
|
|
if(handle == INVALID_HANDLE)
|
|
{
|
|
PrintFormat("Error of open study data file: %d", GetLastError());
|
|
return;
|
|
}
|
|
//--- Создаём цикл загрузки обучающей выборки
|
|
while(!FileIsEnding(handle) && !IsStopped())
|
|
{
|
|
pattern = new CBufferDouble();
|
|
if(CheckPointer(pattern) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create Pattern data array: %d", GetLastError());
|
|
return;
|
|
}
|
|
target = new CBufferDouble();
|
|
if(CheckPointer(target) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create Pattern Target array: %d", GetLastError());
|
|
return;
|
|
}
|
|
for(int i = 0; i < NeuronsToBar * BarsToLine; i++)
|
|
{
|
|
if(!pattern.Add(FileReadNumber(handle)))
|
|
{
|
|
PrintFormat("Error of read study data from file: %d", GetLastError());
|
|
return;
|
|
}
|
|
}
|
|
for(int i = 0; i < 2; i++)
|
|
if(!target.Add(FileReadNumber(handle)))
|
|
{
|
|
PrintFormat("Error of read study data from file: %d", GetLastError());
|
|
return;
|
|
}
|
|
if(!data.Add(pattern))
|
|
{
|
|
PrintFormat("Error of add study data to array: %d", GetLastError());
|
|
return;
|
|
}
|
|
if(!result.Add(target))
|
|
{
|
|
PrintFormat("Error of add study data to array: %d", GetLastError());
|
|
return;
|
|
}
|
|
int total = data.Total();
|
|
Comment(StringFormat("Read %d patterns", total));
|
|
}
|
|
FileClose(handle);
|
|
//--- Блок обучения нейронной сети
|
|
int patterns = data.Total();
|
|
CArrayDouble *loss = new CArrayDouble();
|
|
if(CheckPointer(loss) == POINTER_INVALID)
|
|
{
|
|
PrintFormat("Error of create loss array: %d", GetLastError());
|
|
return;
|
|
}
|
|
for(int epoch = 0; epoch < Epochs && !IsStopped(); epoch++)
|
|
{
|
|
for(int i = 0; i < BatchSize && !IsStopped(); i++)
|
|
{
|
|
int k = (int)((double)(MathRand() * MathRand()) / MathPow(32767.0, 2) * patterns);
|
|
pattern=data.At(k);
|
|
target=result.At(k);
|
|
if(CheckPointer(pattern)==POINTER_INVALID || CheckPointer(target)==POINTER_INVALID)
|
|
{
|
|
i--;
|
|
continue;
|
|
}
|
|
if(!net.FeedForward(pattern))
|
|
{
|
|
PrintFormat("Error in FeedForward: %d", GetLastError());
|
|
return;
|
|
}
|
|
if(!net.Backpropagation(target))
|
|
{
|
|
PrintFormat("Error in Backpropagation: %d", GetLastError());
|
|
return;
|
|
}
|
|
}
|
|
net.UpdateWeights(BatchSize);
|
|
if(!loss.Add(net.GetRecentAverageLoss()))
|
|
{
|
|
PrintFormat("Error of add loss to array: %d", GetLastError());
|
|
return;
|
|
}
|
|
string s;
|
|
Comment(s = StringFormat("Studied %d epoch, error %.5f", epoch, net.GetRecentAverageLoss()));
|
|
}
|
|
//--- Сохраняем результаты обучения модели
|
|
handle = FileOpen(OutputFileName, FILE_WRITE | FILE_CSV | FILE_ANSI, ",", CP_UTF8);
|
|
if(handle == INVALID_HANDLE)
|
|
{
|
|
PrintFormat("Error of open loss file: %d", GetLastError());
|
|
return;
|
|
}
|
|
for(int i = 0; i < loss.Total(); i++)
|
|
{
|
|
FileWrite(handle, loss.At(i));
|
|
}
|
|
FileClose(handle);
|
|
PrintFormat("The dynamics of the error change is saved to a file %s\\%s",
|
|
TerminalInfoString(TERMINAL_DATA_PATH), OutputFileName);
|
|
net.Save("Study.net");
|
|
//--- Очищаем память
|
|
delete net;
|
|
delete loss;
|
|
delete data;
|
|
delete result;
|
|
delete pattern;
|
|
delete target;
|
|
Comment("");
|
|
}
|
|
//+------------------------------------------------------------------+ |