NeuroNetworksBook/Include/realization/neuronproof.mqh

388 lines
32 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:12:34 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| NeuronProof.mqh |
//| Copyright 2021, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//+------------------------------------------------------------------+
//| >4:;NG05< 181;8>B5:8 |
//+------------------------------------------------------------------+
#include "neuronbase.mqh"
#include <Math\Stat\Math.mqh>
//+------------------------------------------------------------------+
//| Class CNeuronProof |
//| 07=0G5=85: ;0AA >@30=870F88 @01>BK ?>42K1>@>G=>3> A;>O |
//+------------------------------------------------------------------+
class CNeuronProof : public CNeuronBase
{
protected:
uint m_iWindow; // 07<5@ >:=0 =0 2E>45 =59@>==>3> A;>O
uint m_iStep; // 07<5@ H030 2E>4=>3> >:=0
uint m_iNeurons; // 07<5@ 2KE>40 >4=>3> D8;LB@0
uint m_iWindowOut; //>;8G5AB2> D8;LB@>2/
ENUM_ACTIVATION m_eActivation; //$C=:F8O 0:B820F88
public:
CNeuronProof(void);
~CNeuronProof(void) {};
//---
virtual bool Init(CLayerDescription *description);
virtual bool FeedForward(CNeuronBase *prevLayer);
virtual bool CalcOutputGradient(CBufferDouble *target) { return false;}
virtual bool CalcHiddenGradient(CNeuronBase *prevLayer);
virtual bool CalcDeltaWeights(CNeuronBase *prevLayer) { return true; }
virtual bool UpdateWeights(int batch_size, double learningRate,
double &Beta[], double &Lambda[])
{ return true; }
//---
virtual CBufferDouble *GetWeights(void) const { return(NULL); }
virtual CBufferDouble *GetDeltaWeights(void) const { return(NULL); }
virtual uint GetNeurons(void) const { return m_iNeurons; }
//--- 5B>4K @01>BK A D09;0<8
virtual bool Save(const int file_handle);
virtual bool Load(const int file_handle);
//--- 5B>4 845=B8D8:0F88 >1J5:B0
virtual int Type(void) const { return(defNeuronProof); }
};
//+------------------------------------------------------------------+
//| >=AB@C:B>@ :;0AA0 |
//+------------------------------------------------------------------+
CNeuronProof::CNeuronProof(void) : m_eActivation(ACT_MAX_POOLING),
m_iWindow(2),
m_iStep(1),
m_iWindowOut(1),
m_iNeurons(0)
{
}
//+------------------------------------------------------------------+
//| 5B>4 8=8F80;870F88 :;0AA0 |
//+------------------------------------------------------------------+
bool CNeuronProof::Init(CLayerDescription *description)
{
//--- ;>: :>=B@>;59
if(!description || description.type != Type() || description.count <= 0)
return false;
//--- !>E@0=O5< :>=AB0=BK
m_iWindow = description.window;
m_iStep = description.step;
m_iWindowOut = description.window_out;
m_iNeurons = description.count;
if(m_iWindow <= 0 || m_iStep <= 0 || m_iWindowOut <= 0 || m_iNeurons <= 0)
return false;
//--- @>25@:0 DC=:F88 ?>B5@L
switch(description.activation)
{
case ACT_AVERAGE_POOLING:
case ACT_MAX_POOLING:
m_eActivation = description.activation;
break;
default:
return false;
break;
}
//--- =8F80;878@C5< 1CD5@ @57C;LB0B>2
if(!m_cOutputs)
if(!(m_cOutputs=new CBufferDouble()))
return false;
if(!m_cOutputs.BufferInit(1,m_iNeurons * m_iWindowOut, 0))
return false;
//--- =8F80;878@C5< 1CD5@ 3@0485=B>2 >H81:8
if(!m_cGradients)
if(!(m_cGradients=new CBufferDouble()))
return false;
if(!m_cGradients.BufferInit(1,m_iNeurons * m_iWindowOut, 0))
return false;
//---
m_eOptimization = None;
//--- #40;O5< =5 8A?>;L7C5<K5 >1J5:BK
if(m_cActivation)
delete m_cActivation;
if(m_cWeights)
delete m_cWeights;
if(m_cDeltaWeights)
delete m_cDeltaWeights;
for(int i = 0; i < 2; i++)
if(m_cMomenum[i])
delete m_cMomenum[i];
//---
return true;
}
//+------------------------------------------------------------------+
//| 5B>4 ?@O<>3> ?@>E>40 |
//+------------------------------------------------------------------+
bool CNeuronProof::FeedForward(CNeuronBase *prevLayer)
{
//--- ;>: :>=B@>;59
if(CheckPointer(prevLayer) == POINTER_INVALID ||
CheckPointer(m_cOutputs) == POINTER_INVALID ||
CheckPointer(prevLayer.GetOutputs()) == POINTER_INVALID)
return false;
CBufferDouble *input_data = prevLayer.GetOutputs();
//--- 0725B2;5=85 0;3>@8B<0 2 7028A8<>AB8 >B CAB@>9AB0 2K?>;=5=88O >?5@0F89
if(CheckPointer(m_cOpenCL) == POINTER_INVALID)
{
uint input_total = input_data.Total();
uint output_total = m_cOutputs.Total();
uint input_neurons = input_total;
if(prevLayer.Type() == defNeuronConv || prevLayer.Type() == defNeuronProof)
{
CNeuronProof *temp = prevLayer;
input_neurons = temp.GetNeurons();
}
double array[];
if(ArrayResize(array, m_iWindow) < 0)
return false;
for(uint f = 0; f < m_iWindowOut; f++)
{
uint shift_inp = f * input_neurons;
uint shift_out = f * m_iNeurons;
if(shift_inp >= input_total)
{
for(uint i = shift_out; i < output_total; i++)
m_cOutputs.Update(i, 0);
break;
}
for(uint o = 0; o < m_iNeurons; o++)
{
uint shift = o * m_iStep;
for(uint i = 0; i < m_iWindow; i++)
array[i] = ((shift_inp + shift + i) >= input_total || (shift + i) >= input_neurons ? 0 :
input_data.At(shift_inp + shift + i));
switch(m_eActivation)
{
case ACT_MAX_POOLING:
m_cOutputs.Update(shift_out + o, array[ArrayMaximum(array)]);
break;
case ACT_AVERAGE_POOLING:
m_cOutputs.Update(shift_out + o, MathMean(array));
break;
default:
return false;
}
}
}
}
else // ;>: @01>BK A OpenCL
{
//--- !>740=85 8 703@C7:0 A>45@68<>5 1CD5@>2 2 :>=B5:AB OpenCL
if(input_data.GetIndex() < 0)
return false;
if(m_cOutputs.GetIndex() < 0)
return false;
//--- 5@540G0 ?0@0<5B@>2 2 :5@=5;
if(!m_cOpenCL.SetArgumentBuffer(def_k_ProofFeedForward, def_prff_inputs, input_data.GetIndex()))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_ProofFeedForward, def_prff_outputs, m_cOutputs.GetIndex()))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofFeedForward, def_prff_inputs_total, input_data.Total()))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofFeedForward, def_prff_window, m_iWindow))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofFeedForward, def_prff_step, m_iStep))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofFeedForward, def_prff_window_out, m_iWindowOut))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofFeedForward, def_prff_activation, (int)m_eActivation))
return false;
//--- >AB0=>2:0 :5@=5;0 2 >G5@54L =0 2K?>;=5=85
uint input_neurons = input_data.Total();
if(prevLayer.Type() == defNeuronConv || prevLayer.Type() == defNeuronProof)
{
CNeuronProof *temp = prevLayer;
input_neurons = temp.GetNeurons();
}
if(!m_cOpenCL.SetArgument(def_k_ProofFeedForward, def_prff_input_neurons, input_neurons))
return false;
uint off_set[] = {0};
uint NDRange[] = {m_iNeurons};
if(!m_cOpenCL.Execute(def_k_ProofFeedForward, 1, off_set, NDRange))
return false;
//--- 03@C7:0 @57C;LB0B>2 @0AGQB0
if(!m_cOutputs.BufferRead())
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| 5B>4 @0A?@545;5=8O 3@0485=B0 >H81:8 G5@57 A:@KBK9 A;>9 |
//+------------------------------------------------------------------+
bool CNeuronProof::CalcHiddenGradient(CNeuronBase *prevLayer)
{
//--- ;>: :>=B@>;59
if(CheckPointer(prevLayer) == POINTER_INVALID ||
CheckPointer(m_cOutputs) == POINTER_INVALID ||
CheckPointer(m_cGradients) == POINTER_INVALID ||
CheckPointer(prevLayer.GetOutputs()) == POINTER_INVALID ||
CheckPointer(prevLayer.GetGradients()) == POINTER_INVALID)
return false;
CBufferDouble *input_data = prevLayer.GetOutputs();
CBufferDouble *input_gradient = prevLayer.GetGradients();
if(!input_gradient.BufferInit(input_data.Total(), 0))
return false;
//--- 0725B2;5=85 0;3>@8B<0 2 7028A8<>AB8 >B CAB@>9AB0 2K?>;=5=88O >?5@0F89
if(CheckPointer(m_cOpenCL) == POINTER_INVALID)
{
uint input_total = input_data.Total();
uint output_total = m_cOutputs.Total();
uint input_neurons = input_total;
if(prevLayer.Type() == defNeuronConv || prevLayer.Type() == defNeuronProof)
{
CNeuronProof *temp = prevLayer;
input_neurons = temp.GetNeurons();
}
for(uint f = 0; f < m_iWindowOut; f++)
{
uint shift_inp = f * input_neurons;
uint shift_out = f * m_iNeurons;
if(shift_inp >= input_total)
break;
for(uint o = 0; o < m_iNeurons; o++)
{
uint shift = o * m_iStep;
double out = m_cOutputs.At(shift_out + o);
double gradient = m_cGradients.At(shift_out + o);
switch(m_eActivation)
{
case ACT_MAX_POOLING:
for(uint i = 0; i < m_iWindow; i++)
{
if((shift_inp + shift + i) >= input_total || (shift + i) >= input_neurons)
break;
if(input_data.At(shift_inp + shift + i) == out)
{
input_gradient.Update(shift_inp + shift + i,
input_gradient.At(shift_inp + shift + i) + gradient);
break;
}
}
break;
case ACT_AVERAGE_POOLING:
gradient /= (double)m_iWindow;
for(uint i = 0; i < m_iWindow; i++)
{
if((shift_inp + shift + i) >= input_total || (shift + i) >= input_neurons)
break;
input_gradient.Update(shift_inp + shift + i,
input_gradient.At(shift_inp + shift + i) + gradient);
}
break;
default:
return false;
}
}
}
}
else // ;>: @01>BK A OpenCL
{
//--- !>740=85 8 703@C7:0 A>45@68<>5 1CD5@>2 2 :>=B5:AB OpenCL
if(input_data.GetIndex() < 0)
return false;
if(m_cOutputs.GetIndex() < 0)
return false;
if(input_gradient.GetIndex() < 0)
return false;
if(m_cGradients.GetIndex() < 0)
return false;
//--- 5@540G0 ?0@0<5B@>2 2 :5@=5;
if(!m_cOpenCL.SetArgumentBuffer(def_k_ProofHiddenGradients, def_prhgr_inputs, input_data.GetIndex()))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_ProofHiddenGradients, def_prhgr_outputs, m_cOutputs.GetIndex()))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_ProofHiddenGradients, def_prhgr_gradients, m_cGradients.GetIndex()))
return false;
if(!m_cOpenCL.SetArgumentBuffer(def_k_ProofHiddenGradients, def_prhgr_gradient_inputs, input_gradient.GetIndex()))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofHiddenGradients, def_prhgr_inputs_total, input_data.Total()))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofHiddenGradients, def_prhgr_window, m_iWindow))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofHiddenGradients, def_prhgr_step, m_iStep))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofHiddenGradients, def_prhgr_window_out, m_iWindowOut))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofHiddenGradients, def_prhgr_activation, (int)m_eActivation))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofHiddenGradients, def_prhgr_neurons, m_iNeurons))
return false;
if(!m_cOpenCL.SetArgument(def_k_ProofHiddenGradients, def_prhgr_outputs_total, m_cOutputs.Total()))
return false;
//--- >AB0=>2:0 :5@=5;0 2 >G5@54L =0 2K?>;=5=5
uint input_neurons = input_data.Total();
if(prevLayer.Type() == defNeuronConv || prevLayer.Type() == defNeuronProof)
{
CNeuronProof *temp = prevLayer;
input_neurons = temp.GetNeurons();
}
uint off_set[] = {0};
uint NDRange[] = {input_neurons};
if(!m_cOpenCL.Execute(def_k_ProofHiddenGradients, 1, off_set, NDRange))
return false;
//--- 03@C7:0 @57C;LB0B>2
if(!input_gradient.BufferRead())
return false;
}
//---
return true;
}
//+------------------------------------------------------------------+
//| 5B>4 A>E@0=5=8O M;5<5=B>2 :0AA0 2 D09; |
//+------------------------------------------------------------------+
bool CNeuronProof::Save(const int file_handle)
{
//--- ;>: :>=B@>;59
if(file_handle == INVALID_HANDLE)
return false;
//--- !>E@0=O5< :>=AB0=BK
if(FileWriteInteger(file_handle, Type()) <= 0)
return false;
if(FileWriteInteger(file_handle, (int)m_iWindow) <= 0)
return false;
if(FileWriteInteger(file_handle, (int)m_iStep) <= 0)
return false;
if(FileWriteInteger(file_handle, (int)m_iWindowOut) <= 0)
return false;
if(FileWriteInteger(file_handle, (int)m_iNeurons) <= 0)
return false;
if(FileWriteInteger(file_handle, (int)m_eActivation) <= 0)
return false;
//---
return true;
}
//+------------------------------------------------------------------+
//| 5B>4 2>AAB0=>2;5=8O @01>BK :;0AA0 87 D09;0 |
//+------------------------------------------------------------------+
bool CNeuronProof::Load(const int file_handle)
{
//--- ;>: :>=B@>;59
if(file_handle == INVALID_HANDLE)
return false;
//--- 03@C605< :>=AB0=BK
m_iWindow = (uint)FileReadInteger(file_handle);
m_iStep = (uint)FileReadInteger(file_handle);
m_iWindowOut = (uint)FileReadInteger(file_handle);
m_iNeurons = (uint)FileReadInteger(file_handle);
m_eActivation = (ENUM_ACTIVATION)FileReadInteger(file_handle);
//--- =8F80;87B8@C5< 8 703@C605< 1CD5@ @57C;LB0B>2
if(CheckPointer(m_cOutputs) == POINTER_INVALID)
{
m_cOutputs = new CBufferDouble();
if(CheckPointer(m_cOutputs) == POINTER_INVALID)
return false;
}
if(!m_cOutputs.BufferInit(m_iNeurons * m_iWindowOut, 0))
return false;
//--- =8F80;878@C5< 8 703@C605< 1CD5@ 3@0485=B>2 >H81:8
if(CheckPointer(m_cGradients) == POINTER_INVALID)
{
m_cGradients = new CBufferDouble();
if(CheckPointer(m_cGradients) == POINTER_INVALID)
return false;
}
if(!m_cGradients.BufferInit(m_iNeurons * m_iWindowOut, 0))
return false;
//---
return true;
}
//+------------------------------------------------------------------+