opencv 派生类LogisticRegressionImpl 没有完全实现基类LogisticRegression纯虚函数,为什么能够正常使用基类定义的纯虚函数?

kxuehen 发布于 2016/04/29 15:11
阅读 377
收藏 0

派生类中没有完全实现基类中的纯虚函数,为什么能够使用基类的纯虚函数?下面是opencv的一个使用例子和部分源代码。不知道opencv是如何处理的,各位帮忙指点一下吧。

opencv 机器学习头文件ml.hpp 定义LogisticRegression类代码


class CV_EXPORTS_W LogisticRegression : public StatModel
{
public:

    /** Learning rate. */
    /** @see setLearningRate */
    CV_WRAP virtual double getLearningRate() const = 0; 
    /** @copybrief getLearningRate @see getLearningRate */
    CV_WRAP virtual void setLearningRate(double val) = 0; 

    /** Number of iterations. */
    /** @see setIterations */
    CV_WRAP virtual int getIterations() const = 0; 
    /** @copybrief getIterations @see getIterations */
    CV_WRAP virtual void setIterations(int val) = 0; 

    /** Kind of regularization to be applied. See LogisticRegression::RegKinds. */
    /** @see setRegularization */
    CV_WRAP virtual int getRegularization() const = 0; 
    /** @copybrief getRegularization @see getRegularization */
    CV_WRAP virtual void setRegularization(int val) = 0; 

    /** Kind of training method used. See LogisticRegression::Methods. */
    /** @see setTrainMethod */
    CV_WRAP virtual int getTrainMethod() const = 0; 
    /** @copybrief getTrainMethod @see getTrainMethod */
    CV_WRAP virtual void setTrainMethod(int val) = 0; 

    /** Specifies the number of training samples taken in each step of Mini-Batch Gradient
    Descent. Will only be used if using LogisticRegression::MINI_BATCH training algorithm. It
    has to take values less than the total number of training samples. */
    /** @see setMiniBatchSize */
    CV_WRAP virtual int getMiniBatchSize() const = 0; 
    /** @copybrief getMiniBatchSize @see getMiniBatchSize */
    CV_WRAP virtual void setMiniBatchSize(int val) = 0; 

    /** Termination criteria of the algorithm. */
    /** @see setTermCriteria */
    CV_WRAP virtual TermCriteria getTermCriteria() const = 0; 
    /** @copybrief getTermCriteria @see getTermCriteria */
    CV_WRAP virtual void setTermCriteria(TermCriteria val) = 0; 

    //! Regularization kinds
    enum RegKinds {
       REG_DISABLE = -1, //!< Regularization disabled
        REG_L1 = 0, //!< %L1 norm
        REG_L2 = 1 //!< %L2 norm
    };

    //! Training methods
    enum Methods {
        BATCH = 0,
        MINI_BATCH = 1 //!< Set MiniBatchSize to a positive integer when using this method.
    };

    /** @brief Predicts responses for input samples and returns a float type.

    @param samples The input data for the prediction algorithm. Matrix [m x n], where each row
        contains variables (features) of one object being classified. Should have data type CV_32F.
    @param results Predicted labels as a column matrix of type CV_32S.
    @param flags Not used.
     */
    CV_WRAP virtual float predict( InputArray samples, OutputArray results=noArray(), int flags=0 ) const = 0;

    /** @brief This function returns the trained paramters arranged across rows.

    For a two class classifcation problem, it returns a row matrix. It returns learnt paramters of
    the Logistic Regression as a matrix of type CV_32F.
     */
    CV_WRAP virtual Mat get_learnt_thetas() const = 0;

    /** @brief Creates empty model.

    Creates Logistic Regression model with parameters given.
     */
    CV_WRAP static Ptr<LogisticRegression> create();
};
opencv LogisticRegression的派生类LogisticRegressionImpl定义代码


class LogisticRegressionImpl : public LogisticRegression
{
public:

    LogisticRegressionImpl() { } 
    virtual ~LogisticRegressionImpl() {}

    CV_IMPL_PROPERTY(double, LearningRate, params.alpha)
    CV_IMPL_PROPERTY(int, Iterations, params.num_iters)
    CV_IMPL_PROPERTY(int, Regularization, params.norm)
    CV_IMPL_PROPERTY(int, TrainMethod, params.train_method)
    CV_IMPL_PROPERTY(int, MiniBatchSize, params.mini_batch_size)
    CV_IMPL_PROPERTY(TermCriteria, TermCriteria, params.term_crit)

    virtual bool train( const Ptr<TrainData>& trainData, int=0 );
    virtual float predict(InputArray samples, OutputArray results, int) const;
    virtual void clear();
    virtual void write(FileStorage& fs) const;
    virtual void read(const FileNode& fn);
    virtual Mat get_learnt_thetas() const;
    virtual int getVarCount() const { return learnt_thetas.cols; }
    virtual bool isTrained() const { return !learnt_thetas.empty(); }
    virtual bool isClassifier() const { return true; }
    virtual String getDefaultName() const { return "opencv_ml_lr"; }
protected:
    Mat calc_sigmoid(const Mat& data) const;
    double compute_cost(const Mat& _data, const Mat& _labels, const Mat& _init_theta);
    void compute_gradient(const Mat& _data, const Mat& _labels, const Mat &_theta, const double _lambda, Mat & _gradient
    Mat batch_gradient_descent(const Mat& _data, const Mat& _labels, const Mat& _init_theta);
    Mat mini_batch_gradient_descent(const Mat& _data, const Mat& _labels, const Mat& _init_theta);
    bool set_label_map(const Mat& _labels_i);
    Mat remap_labels(const Mat& _labels_i, const map<int, int>& lmap) const;
protected:
    LrParams params;
    Mat learnt_thetas;
    map<int, int> forward_mapper;
    map<int, int> reverse_mapper;
    Mat labels_o;
    Mat labels_n;
};

可以看出下面等纯虚函数没有被实现,但是在实际使用中这些函数是能够正常工作的。

CV_WRAP virtual double getLearningRate() const = 0;
本人怀疑和LogisticRegressionImpl定义中下面的代码有关, 因为下面6个代码分别和没有实现的纯虚函数有关,不知道CV_IMPL_PROPERTY宏是如何实现定义纯虚函数的。

CV_IMPL_PROPERTY(double, LearningRate, params.alpha)
    CV_IMPL_PROPERTY(int, Iterations, params.num_iters)
    CV_IMPL_PROPERTY(int, Regularization, params.norm)
    CV_IMPL_PROPERTY(int, TrainMethod, params.train_method)
    CV_IMPL_PROPERTY(int, MiniBatchSize, params.mini_batch_size)
    CV_IMPL_PROPERTY(TermCriteria, TermCriteria, params.term_crit)




加载中
0
kxuehen
kxuehen

问题找到了,opencv就是利用了CV_IMPL_PROPERTY宏定义进行get和set开头的内联函数的定义。所以在派生类中还是有积累纯虚函数的定义的。

返回顶部
顶部