//+------------------------------------------------------------------+ //| FQF.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" //+------------------------------------------------------------------+ //| Includes | //+------------------------------------------------------------------+ #include "..\NeuroNet_DNG\NeuroNet.mqh" //--- #define defFQF 0x7792 /// &resultVals); ///< Method to get results of feed forward process.@param[out] resultVals Array of result values int getAction(void); ///< Method to get results of feed forward process.@param[out] resultVals Array of result values int getSample(void); float getRecentAverageError() { return recentAverageError; } ///< Method to check quality of study. @return Average error bool Save(string file_name, datetime time, bool common = true) { return CNet::Save(file_name, getRecentAverageError(), (float)iUpdateTarget, 0, time, common); } ///< Save method. @param[in] file_name File name to save @param[in] error Average error @param[in] undefine Undefined percent @param[in] Foecast percent @param[in] time Last study time @param[in] common Common flag virtual bool Save(const int file_handle); virtual bool Load(string file_name, datetime &time, bool common = true); ///< Load method. @param[in] file_name File name to save @param[out] error Average error @param[out] undefine Undefined percent @param[out] Foecast percent @param[out] time Last study time @param[in] common Common flag virtual bool Load(const int file_handle); //--- virtual int Type(void) const { return defFQF; }///< Identificator of class.@return Type of class virtual bool TrainMode(bool flag) { return CNet::TrainMode(flag); } ///< Set Training Mode Flag virtual bool GetLayerOutput(uint layer, CBufferFloat *&result) ///< Retutn Output data of layer. @param[in] layer Number of layer @param[out] return Buffer with data { return CNet::GetLayerOutput(layer, result); } //--- virtual void SetUpdateTarget(uint batch) { iUpdateTarget = batch; } virtual bool UpdateTarget(string file_name); virtual bool WeightsUpdate(CFQF *net, float tau) { return CNet::WeightsUpdate((CNet*) net, tau); } //--- virtual void SetOpenCL(COpenCLMy *obj); virtual COpenCLMy* GetOpenCL(void) { return opencl; } //--- Soft Actor-Critic virtual bool GetLogProbs(vector &log_probs) { return CNet::GetLogProbs(log_probs); } virtual bool AlphasGradient(CNet *PolicyNet) { return CNet::AlphasGradient(PolicyNet);} virtual bool CalcLogProbs(CBufferFloat *buffer) { return CNet::CalcLogProbs(buffer); } //--- virtual bool Clear(void) { return CNet::Clear(); } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CFQF::CFQF(void) : iUpdateTarget(1000) { cTargetNet.Create(NULL); Create(NULL); cTargetNet.SetOpenCL(opencl); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CFQF::~CFQF() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFQF::Create(CArrayObj *Description) { if(!CNet::Create(Description)) return false; cTargetNet.Create(NULL); cTargetNet.SetOpenCL(opencl); //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFQF::backProp(CBufferFloat *targetVals, float discount = 0.9f, CArrayFloat *nextState = NULL, int window = 1, bool tem = true, CBufferFloat *SecondInput=NULL, CBufferFloat *SecondGradient=NULL) { //--- if(!targetVals) return false; //--- if(cTargetNet.GetOpenCL()!=opencl) cTargetNet.SetOpenCL(opencl); if(!!nextState && discount!=0.0f) { vectorf target; if(!targetVals.GetData(target) || target.Size() <= 0) return false; if(!cTargetNet.feedForward((CArrayFloat*)nextState, window, tem,(CArrayFloat*)NULL)) return false; cTargetNet.getResults(targetVals); if(!targetVals) return false; target = target + discount * targetVals.Maximum(); if(!targetVals.AssignArray(target)) return false; } //--- if(iCountBackProp >= iUpdateTarget) { #ifdef FileName if(UpdateTarget(FileName + ".nnw")) #else if(UpdateTarget("FQF.upd")) #endif iCountBackProp = 0; } else iCountBackProp++; //--- return CNet::backProp(targetVals,SecondInput,SecondGradient); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CFQF::getResults(CBufferFloat *&resultVals) { CNet::getResults(resultVals); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CFQF::getResults(vector &resultVals) { CNet::getResults(resultVals); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CFQF::getAction(void) { vector temp; CNet::getResults(temp); //--- return (int)temp.ArgMax(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CFQF::getSample(void) { CBufferFloat* resultVals; CNet::getResults(resultVals); if(!resultVals) return -1; vectorf temp; if(!resultVals.GetData(temp)) { delete resultVals; return -1; } delete resultVals; //--- temp = temp / temp.Max(); if(!temp.Activation(temp, AF_SOFTMAX)) return -1; temp = temp.CumSum(); int err_code; float random = (float)MathRandomNormal(0.5, 0.5, err_code); if(random >= 1) random = temp.Max(); for(int i = 0; i < (int)temp.Size(); i++) if(random <= temp[i] && temp[i] > 0) return i; //--- return -1; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFQF::UpdateTarget(string file_name) { if(!Save(file_name, 0, false)) return false; float error, undefine, forecast; datetime time; if(!cTargetNet.Load(file_name, error, undefine, forecast, time, false)) return false; iCountBackProp = 0; if(cTargetNet.GetOpenCL()!=opencl) cTargetNet.SetOpenCL(opencl); //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFQF::Save(const int file_handle) { if(!CNet::Save(file_handle)) return false; if(FileWriteInteger(file_handle, (int)iUpdateTarget) < INT_VALUE) return false; //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFQF::Load(const int file_handle) { if(!CNet::Load(file_handle)) return false; if(FileIsEnding(file_handle)) return true; iUpdateTarget = (uint)FileReadInteger(file_handle); if(!UpdateTarget("FQF.upd")) return false; iCountBackProp = 0; if(cTargetNet.GetOpenCL()!=opencl) cTargetNet.SetOpenCL(opencl); //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFQF::Load(string file_name, datetime &time, bool common = true) { float undefine, forecast; if(!CNet::Load(file_name, recentAverageError, undefine, forecast, time, common) || !cTargetNet.Load(file_name, recentAverageError, undefine, forecast, time, common)) return false; iUpdateTarget = (uint)undefine; if(cTargetNet.GetOpenCL()!=opencl) cTargetNet.SetOpenCL(opencl); //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CFQF::SetOpenCL(COpenCLMy *obj) { CNet::SetOpenCL(obj); cTargetNet.SetOpenCL(obj); } //+------------------------------------------------------------------+