Watch
1
0
Fork
You've already forked NeuroBook
0
forked from rosh/NeuroBook
NeuroBook/Include/realization/neuronproof.mqh

364 lines
30 KiB
MQL5

2025-05-30 16:12:30 +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"
//+------------------------------------------------------------------+
//| Connect libraries |
//+------------------------------------------------------------------+
#include "neuronbase.mqh"
#include <Math\Stat\Math.mqh>
//+------------------------------------------------------------------+
//| Class CNeuronProof |
//| Purpose: Class organizing the pooling layer |
//+------------------------------------------------------------------+
class CNeuronProof : public CNeuronBase
{
protected:
uint m_iWindow; //Window size at the input of the neural layer
uint m_iStep; //Input window step size
uint m_iNeurons; //Output size of one filter
uint m_iWindowOut; //Number of filters
ENUM_PROOF m_eActivation; //Activation function
public:
CNeuronProof(void);
~CNeuronProof(void) {};
//---
virtual bool Init(const CLayerDescription *desc) override;
virtual bool FeedForward(CNeuronBase *prevLayer) override;
virtual bool CalcOutputGradient(CBufferType *target, ENUM_LOSS_FUNCTION loss) override { return false;}
virtual bool CalcHiddenGradient(CNeuronBase *prevLayer) override;
virtual bool CalcDeltaWeights(CNeuronBase *prevLayer, bool read) override { return true; }
virtual bool UpdateWeights(int batch_size, TYPE learningRate, VECTOR &Beta, VECTOR &Lambda) override
{ return true; }
//---
virtual CBufferType *GetWeights(void) override const { return(NULL); }
virtual CBufferType *GetDeltaWeights(void) override const { return(NULL); }
virtual uint GetNeurons(void) const { return m_iNeurons; }
//--- File handling methods
virtual bool Save(const int file_handle) override;
virtual bool Load(const int file_handle) override;
//--- Object identification method
virtual int Type(void) override const { return(defNeuronProof); }
};
//+------------------------------------------------------------------+
//| Class constructor |
//+------------------------------------------------------------------+
CNeuronProof::CNeuronProof(void) : m_eActivation(AF_MAX_POOLING),
m_iWindow(2),
m_iStep(1),
m_iWindowOut(1),
m_iNeurons(0)
{
}
//+------------------------------------------------------------------+
//| Class initialization method |
//+------------------------------------------------------------------+
bool CNeuronProof::Init(const CLayerDescription *description)
{
//--- Control block
if(!description || description.type != Type() ||
description.count <= 0)
return false;
//--- Save constants
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;
//--- Check activation function
switch((ENUM_PROOF)description.activation)
{
case AF_AVERAGE_POOLING:
case AF_MAX_POOLING:
m_eActivation = (ENUM_PROOF)description.activation;
break;
default:
return false;
break;
}
//--- Initialize results buffer
if(!m_cOutputs)
if(!(m_cOutputs = new CBufferType()))
return false;
if(!m_cOutputs.BufferInit(m_iWindowOut, m_iNeurons, 0))
return false;
//--- Initialize the error gradient buffer
if(!m_cGradients)
if(!(m_cGradients = new CBufferType()))
return false;
if(!m_cGradients.BufferInit(m_iWindowOut, m_iNeurons, 0))
return false;
//---
m_eOptimization = None;
//--- Delete unused objects
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;
}
//+------------------------------------------------------------------+
//| Feed-forward method |
//+------------------------------------------------------------------+
bool CNeuronProof::FeedForward(CNeuronBase *prevLayer)
{
//--- Control block
if(!prevLayer || !m_cOutputs ||
!prevLayer.GetOutputs())
return false;
CBufferType *input_data = prevLayer.GetOutputs();
//--- Branching of the algorithm depending on the device used for operations
if(!m_cOpenCL)
{
MATRIX inputs = input_data.m_mMatrix;
if(inputs.Rows() != m_iWindowOut)
{
ulong cols = (input_data.Total() + m_iWindowOut - 1) / m_iWindowOut;
if(!inputs.Reshape(m_iWindowOut, cols))
return false;
}
//--- Create a local matrix to collect data from one filter
MATRIX array = MATRIX::Zeros(m_iNeurons, m_iWindow);
m_cOutputs.m_mMatrix.Fill(0);
//--- Filter iteration loop
for(uint f = 0; f < m_iWindowOut; f++)
{
//--- Loop through the elements of the results buffer
for(uint o = 0; o < m_iNeurons; o++)
{
uint shift = o * m_iStep;
for(uint i = 0; i < m_iWindow; i++)
array[o, i] = ((shift + i) >= inputs.Cols() ? 0 :
inputs[f, shift + i]);
}
//--- Save the current result in accordance with the activation function
switch(m_eActivation)
{
case AF_MAX_POOLING:
if(!m_cOutputs.Row(array.Max(1), f))
return false;;
break;
case AF_AVERAGE_POOLING:
if(!m_cOutputs.Row(array.Mean(1), f))
return false;
break;
default:
return false;
}
}
}
else // OpenCL operations block
{
//--- check the presence of buffers in the OpenCL context
if(input_data.GetIndex() < 0)
return false;
if(m_cOutputs.GetIndex() < 0)
return false;
//--- Pass parameters to the kernel
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_activation, (int)m_eActivation))
return false;
ulong input_neurons = (input_data.Total() + m_iWindowOut - 1) / m_iWindowOut;
if(!m_cOpenCL.SetArgument(def_k_ProofFeedForward, def_prff_input_neurons, input_neurons))
return false;