2026-08-13 23:48:47 +03:00 | | | //+------------------------------------------------------------------+
|
2026-06-05 22:00:59 +03:00 | | | //| NetEvalution.mqh |
|
| | | //| Copyright DNG® |
|
| | | //| https://www.mql5.com/ru/users/dng |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright DNG®"
|
| | | #property link "https://www.mql5.com/ru/users/dng"
|
| | | #property version "1.00"
|
| | | //---
|
| | | #include "NetGenetic.mqh"
|
| | | //---
|
| | | class CNetEvolution : protected CNetGenetic
|
| | | {
|
| | | protected:
|
| | | virtual bool GetWeights(uint layer) override;
|
| | |
|
| | | public:
|
| | | CNetEvolution() {};
|
| | | ~CNetEvolution() {};
|
| | | //---
|
| | | virtual bool Create(CArrayObj *Description, uint population_size) override;
|
| | | virtual bool SetPopulationSize(uint size) override;
|
| | | virtual bool feedForward(CArrayFloat *inputVals, int window = 1, bool tem = true) override;
|
| | | virtual bool Rewards(CArrayFloat *rewards) override;
|
| | | virtual bool NextGeneration(float mutation, float &average, float &mamximum);
|
| | | virtual bool Load(string file_name, uint population_size, bool common = true) override;
|
| | | virtual bool Save(string file_name, bool common = true);
|
| | | //---
|
| | | virtual bool GetLayerOutput(uint layer, CBufferFloat *&result) override;
|
| | | virtual void getResults(CBufferFloat *&resultVals);
|
| | | };
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::Create(CArrayObj *Description, uint population_size)
|
| | | {
|
| | | if(!CNetGenetic::Create(Description, population_size))
|
| | | return false;
|
| | | float average, maximum;
|
| | | return NextGeneration(0, average, maximum);
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::SetPopulationSize(uint size)
|
| | | {
|
| | | return CNetGenetic::SetPopulationSize(size);
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::feedForward(CArrayFloat *inputVals, int window = 1, bool tem = true)
|
| | | {
|
| | | return CNetGenetic::feedForward(inputVals, window, tem);
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::Rewards(CArrayFloat *rewards)
|
| | | {
|
| | | if(!CNetGenetic::Rewards(rewards))
|
| | | return false;
|
| | | //---
|
| | | v_Probability = v_Rewards - v_Rewards.Mean();
|
| | | v_Probability = v_Probability / MathAbs(v_Probability).Sum();
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::NextGeneration(float mutation, float &average, float &maximum)
|
| | | {
|
| | | maximum = v_Rewards.Max();
|
| | | average = v_Rewards.Mean();
|
| | | mutation = MathMin(mutation, MaxMutation);
|
| | | v_Probability = v_Rewards - v_Rewards.Mean();
|
| | | float Sum = MathAbs(v_Probability).Sum();
|
| | | if(Sum == 0)
|
| | | v_Probability[0] = 1;
|
| | | else
|
| | | v_Probability = v_Probability / Sum;
|
| | | //---
|
| | | for(int l = 1; l < layers.Total(); l++)
|
| | | {
|
| | | CLayer *layer = layers.At(l);
|
| | | if(!layer)
|
| | | return false;
|
| | | if(layer.Total() < (int)i_PopulationSize)
|
| | | if(!CreatePopulation())
|
| | | return false;
|
| | | if(!GetWeights(l))
|
| | | return false;
|
| | | for(uint i = 0; i < i_PopulationSize; i++)
|
| | | {
|
| | | CNeuronBaseOCL* neuron = layer.At(i);
|
| | | if(!neuron)
|
| | | return false;
|
| | | CBufferFloat* weights = neuron.getWeights();
|
| | | if(!!weights)
|
| | | {
|
| | | for(int w = 0; w < weights.Total(); w++)
|
| | | {
|
| | | if(mutation > 0)
|
| | | {
|
| | | int err_code;
|
| | | float random = (float)MathRandomNormal(0.5, 0.5, err_code);
|
| | | if(mutation > random)
|
| | | {
|
| | | if(!weights.Update(w, GenerateWeight((uint)m_Weights.Cols())))
|
| | | {
|
| | | Print("Error of update weights");
|
| | | return false;
|
| | | }
|
| | | continue;
|
| | | }
|
| | | }
|
| | | if(!MathIsValidNumber(m_Weights[0, w]))
|
| | | {
|
| | | if(!weights.Update(w, GenerateWeight((uint)m_Weights.Cols())))
|
| | | {
|
| | | Print("Error of update weights");
|
| | | return false;
|
| | | }
|
| | | continue;
|
| | | }
|
| | | if(!weights.Update(w, m_Weights[0, w] + GenerateWeight((uint)m_Weights.Cols())))
|
| | | {
|
| | | Print("Error of update weights");
|
| | | return false;
|
| | | }
|
| | | }
|
| | | weights.BufferWrite();
|
| | | }
|
| | | if(neuron.Type() != defNeuronConvOCL)
|
| | | continue;
|
| | | CNeuronConvOCL* temp = neuron;
|
| | | weights = temp.GetWeightsConv();
|
| | | for(int w = 0; w < weights.Total(); w++)
|
| | | {
|
| | | if(mutation > 0)
|
| | | {
|
| | | int err_code;
|
| | | float random = (float)MathRandomNormal(0.5, 0.5, err_code);
|
| | | if(mutation > random)
|
| | | {
|
| | | if(!weights.Update(w, GenerateWeight((uint)m_WeightsConv.Cols())))
|
| | | {
|
| | | Print("Error of update weights");
|
| | | return false;
|
| | | }
|
| | | continue;
|
| | | }
|
| | | }
|
| | | if(!MathIsValidNumber(m_WeightsConv[0, w]))
|
| | | {
|
| | | if(!weights.Update(w, GenerateWeight((uint)m_WeightsConv.Cols())))
|
| | | {
|
| | | Print("Error of update weights");
|
| | | return false;
|
| | | }
|
| | | continue;
|
| | | }
|
| | | if(!weights.Update(w, m_WeightsConv[0, w] + GenerateWeight((uint)m_WeightsConv.Cols())))
|
| | | {
|
| | | Print("Error of update weights");
|
| | | return false;
|
| | | }
|
| | | }
|
| | | weights.BufferWrite();
|
| | | }
|
| | | }
|
| | | v_Rewards.Fill(0);
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::GetWeights(uint layer)
|
| | | {
|
| | | if(v_Probability.Sum() == 0)
|
| | | return false;
|
| | | if(!CNetGenetic::GetWeights(layer))
|
| | | return false;
|
| | | //---
|
| | | if(m_Weights.Cols() > 0)
|
| | | {
|
| | | vectorf mean = m_Weights.Mean(0);
|
| | | matrixf temp = matrixf::Zeros(1, m_Weights.Cols());
|
| | | if(!temp.Row(mean, 0))
|
| | | return false;
|
| | | temp = (matrixf::Ones(m_Weights.Rows(), 1)).MatMul(temp);
|
| | | m_Weights = m_Weights - temp;
|
| | | mean = mean + m_Weights.Transpose().MatMul(v_Probability) * lr;
|
| | | if(!m_Weights.Resize(1, m_Weights.Cols()))
|
| | | return false;
|
| | | if(!m_Weights.Row(mean, 0))
|
| | | return false;
|
| | | }
|
| | | //---
|
| | | if(m_WeightsConv.Cols() > 0)
|
| | | {
|
| | | vectorf mean = m_WeightsConv.Mean(0);
|
| | | matrixf temp = matrixf::Zeros(1, m_WeightsConv.Cols());
|
| | | if(!temp.Row(mean, 0))
|
| | | return false;
|
| | | temp = (matrixf::Ones(m_WeightsConv.Rows(), 1)).MatMul(temp);
|
| | | m_WeightsConv = m_WeightsConv - temp;
|
| | | mean = mean + m_WeightsConv.Transpose().MatMul(v_Probability) * lr;
|
| | | if(!m_WeightsConv.Resize(1, m_WeightsConv.Cols()))
|
| | | return false;
|
| | | if(!m_WeightsConv.Row(mean, 0))
|
| | | return false;
|
| | | }
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::Load(string file_name, uint population_size, bool common = true)
|
| | | {
|
| | | if(!CNetGenetic::Load(file_name, population_size, common))
|
| | | return false;
|
| | | v_Rewards.Fill(0);
|
| | | float average, maximum;
|
| | | if(!NextGeneration(0, average, maximum))
|
| | | return false;
|
| | | //---
|
| | | return true;
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::GetLayerOutput(uint layer, CBufferFloat *&result)
|
| | | {
|
| | | return CNet::GetLayerOutput(layer, result);
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | void CNetEvolution::getResults(CBufferFloat *&resultVals)
|
| | | {
|
| | | CNetGenetic::getResults(resultVals);
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | bool CNetEvolution::Save(string file_name, bool common = true)
|
| | | {
|
| | | return CNetGenetic::SaveModel(file_name, -1, common);
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-08-13 23:48:47 +03:00 | | |
|