Calcerror uses now weighted samples (#10346)
[platform/upstream/opencv.git] / modules / ml / src / ann_mlp.cpp
index fddc0ae..cd10c0d 100644 (file)
 
 namespace cv { namespace ml {
 
+struct SimulatedAnnealingSolver::Impl
+{
+    int refcount;
+
+    const Ptr<SimulatedAnnealingSolverSystem> systemPtr;
+    SimulatedAnnealingSolverSystem& system;
+    RNG rEnergy;
+    double coolingRatio;
+    double initialT;
+    double finalT;
+    int iterPerStep;
+
+    Impl(const Ptr<SimulatedAnnealingSolverSystem>& s) :
+        refcount(1),
+        systemPtr(s),
+        system(*(s.get())),
+        rEnergy(12345)
+    {
+        CV_Assert(!systemPtr.empty());
+        initialT = 2;
+        finalT = 0.1;
+        coolingRatio = 0.95;
+        iterPerStep = 100;
+    }
+
+    inline double energy() { return system.energy(); }
+    inline void changeState() { system.changeState(); }
+    inline void reverseState() { system.reverseState(); }
+
+    void addref() { CV_XADD(&refcount, 1); }
+    void release() { if (CV_XADD(&refcount, -1) == 1) delete this; }
+protected:
+    virtual ~Impl() { CV_Assert(refcount==0); }
+};
 
 struct AnnParams
 {
@@ -53,7 +87,7 @@ struct AnnParams
         rpDW0 = 0.1; rpDWPlus = 1.2; rpDWMinus = 0.5;
         rpDWMin = FLT_EPSILON; rpDWMax = 50.;
         initialT=10;finalT=0.1,coolingRatio=0.95;itePerStep=10;
-
+        rEnergy = cv::RNG(12345);
     }
 
     TermCriteria termCrit;
@@ -72,6 +106,7 @@ struct AnnParams
     double finalT;
     double coolingRatio;
     int itePerStep;
+    RNG rEnergy;
 };
 
 template <typename T>
@@ -80,48 +115,60 @@ inline T inBounds(T val, T min_val, T max_val)
     return std::min(std::max(val, min_val), max_val);
 }
 
-SimulatedAnnealingSolver::~SimulatedAnnealingSolver()
+SimulatedAnnealingSolver::SimulatedAnnealingSolver(const Ptr<SimulatedAnnealingSolverSystem>& system)
 {
-    if (impl) delete impl;
+    impl = new Impl(system);
 }
 
-void SimulatedAnnealingSolver::init()
+SimulatedAnnealingSolver::SimulatedAnnealingSolver(const SimulatedAnnealingSolver& b)
 {
-    impl = new SimulatedAnnealingSolver::Impl();
+    if (b.impl) b.impl->addref();
+    release();
+    impl = b.impl;
+}
+
+void SimulatedAnnealingSolver::release()
+{
+    if (impl) { impl->release(); impl = NULL; }
 }
 
 void SimulatedAnnealingSolver::setIterPerStep(int ite)
 {
+    CV_Assert(impl);
     CV_Assert(ite>0);
     impl->iterPerStep = ite;
 }
 
 int SimulatedAnnealingSolver::run()
 {
+    CV_Assert(impl);
     CV_Assert(impl->initialT>impl->finalT);
     double Ti = impl->initialT;
-    double previousEnergy = energy();
+    double previousEnergy = impl->energy();
     int exchange = 0;
     while (Ti > impl->finalT)
     {
         for (int i = 0; i < impl->iterPerStep; i++)
         {
-            changedState();
-            double newEnergy = energy();
+            impl->changeState();
+            double newEnergy = impl->energy();
             if (newEnergy < previousEnergy)
             {
                 previousEnergy = newEnergy;
+                exchange++;
             }
             else
             {
-                double r = impl->rEnergy.uniform(double(0.0), double(1.0));
-                if (r < exp(-(newEnergy - previousEnergy) / Ti))
+                double r = impl->rEnergy.uniform(0.0, 1.0);
+                if (r < std::exp(-(newEnergy - previousEnergy) / Ti))
                 {
                     previousEnergy = newEnergy;
                     exchange++;
                 }
                 else
-                    reverseChangedState();
+                {
+                    impl->reverseState();
+                }
             }
 
         }
@@ -131,33 +178,43 @@ int SimulatedAnnealingSolver::run()
     return exchange;
 }
 
+void SimulatedAnnealingSolver::setEnergyRNG(const RNG& rng)
+{
+    CV_Assert(impl);
+    impl->rEnergy = rng;
+}
+
 void SimulatedAnnealingSolver::setInitialTemperature(double x)
 {
+    CV_Assert(impl);
     CV_Assert(x>0);
     impl->initialT = x;
-};
+}
 
 void SimulatedAnnealingSolver::setFinalTemperature(double x)
 {
+    CV_Assert(impl);
     CV_Assert(x>0);
     impl->finalT = x;
-};
+}
 
 double SimulatedAnnealingSolver::getFinalTemperature()
 {
+    CV_Assert(impl);
     return impl->finalT;
-};
+}
 
 void SimulatedAnnealingSolver::setCoolingRatio(double x)
 {
+    CV_Assert(impl);
     CV_Assert(x>0 && x<1);
     impl->coolingRatio = x;
-};
+}
 
-class SimulatedAnnealingANN_MLP : public ml::SimulatedAnnealingSolver
+class SimulatedAnnealingANN_MLP : public SimulatedAnnealingSolverSystem
 {
-public:
-    ml::ANN_MLP *nn;
+protected:
+    ml::ANN_MLPnn;
     Ptr<ml::TrainData> data;
     int nbVariables;
     vector<double*> adrVariables;
@@ -165,32 +222,37 @@ public:
     RNG rIndex;
     double varTmp;
     int index;
-
-    SimulatedAnnealingANN_MLP(ml::ANN_MLP *x, Ptr<ml::TrainData> d) : nn(x), data(d)
+public:
+    SimulatedAnnealingANN_MLP(ml::ANN_MLP& x, const Ptr<ml::TrainData>& d) : nn(x), data(d)
     {
         initVarMap();
-    };
-    void changedState()
+    }
+    ~SimulatedAnnealingANN_MLP() {}
+protected:
+    void changeState()
     {
         index = rIndex.uniform(0, nbVariables);
         double dv = rVar.uniform(-1.0, 1.0);
         varTmp = *adrVariables[index];
         *adrVariables[index] = dv;
-    };
-    void reverseChangedState()
+    }
+
+    void reverseState()
     {
         *adrVariables[index] = varTmp;
-    };
-    double energy() { return nn->calcError(data, false, noArray()); }
+    }
+
+    double energy() const { return nn.calcError(data, false, noArray()); }
+
 protected:
     void initVarMap()
     {
-        Mat l = nn->getLayerSizes();
+        Mat l = nn.getLayerSizes();
         nbVariables = 0;
         adrVariables.clear();
         for (int i = 1; i < l.rows-1; i++)
         {
-            Mat w = nn->getWeights(i);
+            Mat w = nn.getWeights(i);
             for (int j = 0; j < w.rows; j++)
             {
                 for (int k = 0; k < w.cols; k++, nbVariables++)
@@ -274,6 +336,13 @@ void ANN_MLP::setAnnealItePerStep(int val)
     this_->setAnnealItePerStep(val);
 }
 
+void ANN_MLP::setAnnealEnergyRNG(const RNG& rng)
+{
+    ANN_MLP_ANNEAL* this_ = dynamic_cast<ANN_MLP_ANNEAL*>(this);
+    if (!this_)
+        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
+    this_->setAnnealEnergyRNG(rng);
+}
 
 class ANN_MLPImpl : public ANN_MLP_ANNEAL
 {
@@ -301,6 +370,9 @@ public:
     CV_IMPL_PROPERTY(double, AnnealCoolingRatio, params.coolingRatio)
     CV_IMPL_PROPERTY(int, AnnealItePerStep, params.itePerStep)
 
+    //CV_IMPL_PROPERTY(RNG, AnnealEnergyRNG, params.rEnergy)
+    inline void setAnnealEnergyRNG(const RNG& val) { params.rEnergy = val; }
+
     void clear()
     {
         min_val = max_val = min_val1 = max_val1 = 0.;
@@ -333,21 +405,6 @@ public:
                 param2 = 0.1;
             params.bpMomentScale = std::min(param2, 1.);
         }
-/*        else if (method == ANN_MLP::ANNEAL)
-        {
-            if (param1 <= 0)
-                param1 = 10;
-            if (param2 <= 0 || param2>param1)
-                param2 = 0.1;
-            if (param3 <= 0 || param3 >=1)
-                param3 = 0.95;
-            if (param4 <= 0)
-                param4 = 10;
-            params.initialT = param1;
-            params.finalT = param2;
-            params.coolingRatio = param3;
-            params.itePerStep = param4;
-        }*/
     }
 
     int getTrainMethod() const
@@ -1018,7 +1075,8 @@ public:
     }
     int train_anneal(const Ptr<TrainData>& trainData)
     {
-        SimulatedAnnealingANN_MLP t(this, trainData);
+        SimulatedAnnealingSolver t(Ptr<SimulatedAnnealingANN_MLP>(new SimulatedAnnealingANN_MLP(*this, trainData)));
+        t.setEnergyRNG(params.rEnergy);
         t.setFinalTemperature(params.finalT);
         t.setInitialTemperature(params.initialT);
         t.setCoolingRatio(params.coolingRatio);
@@ -1665,70 +1723,6 @@ Ptr<ANN_MLP> ANN_MLP::load(const String& filepath)
     return ann;
 }
 
-double ANN_MLP_ANNEAL::getAnnealInitialT() const
-{
-    const ANN_MLPImpl* this_ = dynamic_cast<const ANN_MLPImpl*>(this);
-    if (!this_)
-        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
-    return this_->getAnnealInitialT();
-}
-
-void ANN_MLP_ANNEAL::setAnnealInitialT(double val)
-{
-    ANN_MLPImpl* this_ = dynamic_cast< ANN_MLPImpl*>(this);
-    if (!this_)
-        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
-    this_->setAnnealInitialT(val);
-}
-
-double ANN_MLP_ANNEAL::getAnnealFinalT() const
-{
-    const ANN_MLPImpl* this_ = dynamic_cast<const ANN_MLPImpl*>(this);
-    if (!this_)
-        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
-    return this_->getAnnealFinalT();
-}
-
-void ANN_MLP_ANNEAL::setAnnealFinalT(double val)
-{
-    ANN_MLPImpl* this_ = dynamic_cast<ANN_MLPImpl*>(this);
-    if (!this_)
-        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
-    this_->setAnnealFinalT(val);
-}
-
-double ANN_MLP_ANNEAL::getAnnealCoolingRatio() const
-{
-    const ANN_MLPImpl* this_ = dynamic_cast<const ANN_MLPImpl*>(this);
-    if (!this_)
-        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
-    return this_->getAnnealCoolingRatio();
-}
-
-void ANN_MLP_ANNEAL::setAnnealCoolingRatio(double val)
-{
-    ANN_MLPImpl* this_ = dynamic_cast< ANN_MLPImpl*>(this);
-    if (!this_)
-        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
-    this_->setAnnealInitialT(val);
-}
-
-int ANN_MLP_ANNEAL::getAnnealItePerStep() const
-{
-    const ANN_MLPImpl* this_ = dynamic_cast<const ANN_MLPImpl*>(this);
-    if (!this_)
-        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
-    return this_->getAnnealItePerStep();
-}
-
-void ANN_MLP_ANNEAL::setAnnealItePerStep(int val)
-{
-    ANN_MLPImpl* this_ = dynamic_cast<ANN_MLPImpl*>(this);
-    if (!this_)
-        CV_Error(Error::StsNotImplemented, "the class is not ANN_MLP_ANNEAL");
-    this_->setAnnealInitialT(val);
-}
-
 }}
 
 /* End of file. */