mirror of
https://github.com/opencv/opencv.git
synced 2024-11-28 13:10:12 +08:00
updated logistic regression definition
This commit is contained in:
parent
95ea09c3dc
commit
b3b4e83aed
@ -55,35 +55,41 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
LogisticRegressionParams::LogisticRegressionParams()
|
||||
{
|
||||
term_crit = CvTermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 10000, 0.001);
|
||||
term_crit = cv::TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 1000, 0.001);
|
||||
alpha = 0.001;
|
||||
num_iters = 10;
|
||||
num_iters = 1000;
|
||||
norm = LogisticRegression::REG_L2;
|
||||
regularized = 1;
|
||||
train_method = LogisticRegression::BATCH;
|
||||
mini_batch_size = 1;
|
||||
}
|
||||
|
||||
LogisticRegressionParams::LogisticRegressionParams(double _alpha, int _num_iters, int _norm, int _regularized, int _train_method, int _mini_batch_size):
|
||||
alpha(_alpha), num_iters(_num_iters), norm(_norm), regularized(_regularized), train_method(_train_method), mini_batch_size(_mini_batch_size)
|
||||
LogisticRegressionParams::LogisticRegressionParams( double learning_rate, int iters, int train_algo = LogisticRegression::BATCH, int normlization = LogisticRegression::REG_L2, int reg = 1, int mb_size = 5)
|
||||
{
|
||||
term_crit = CvTermCriteria(TermCriteria::COUNT + TermCriteria::EPS, num_iters, 0.001);
|
||||
term_crit = cv::TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, iters, learning_rate);
|
||||
alpha = learning_rate;
|
||||
num_iters = iters;
|
||||
norm = normlization;
|
||||
regularized = reg;
|
||||
train_method = train_algo;
|
||||
mini_batch_size = mb_size;
|
||||
}
|
||||
|
||||
LogisticRegression::LogisticRegression()
|
||||
LogisticRegression::LogisticRegression(const LogisticRegressionParams& pms = LogisticRegressionParams() )
|
||||
{
|
||||
default_model_name = "my_lr";
|
||||
this->params = pms;
|
||||
}
|
||||
|
||||
LogisticRegression::LogisticRegression(cv::InputArray data, cv::InputArray labels, const LogisticRegressionParams& pms)
|
||||
{
|
||||
this->params = pms;
|
||||
default_model_name = "my_lr";
|
||||
this->params = pms;
|
||||
train(data, labels);
|
||||
}
|
||||
|
||||
@ -103,7 +109,7 @@ bool LogisticRegression::train(cv::InputArray data_ip, cv::InputArray labels_ip)
|
||||
// check the number of columns
|
||||
if(_labels_i.cols != 1)
|
||||
{
|
||||
cv::error(Error::StsBadArg, "_labels_i should be a column matrix", "cv::ml::LogisticRegression::train", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "_labels_i should be a column matrix" );
|
||||
}
|
||||
|
||||
// check data type.
|
||||
@ -111,7 +117,7 @@ bool LogisticRegression::train(cv::InputArray data_ip, cv::InputArray labels_ip)
|
||||
|
||||
if((_data_i.type() != CV_32FC1) || (_labels_i.type() != CV_32FC1))
|
||||
{
|
||||
cv::error(Error::StsBadArg, "train: data and labels must be a floating point matrix", "cv::ml::LogisticRegression::train", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "data and labels must be a floating point matrix" );
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
@ -132,12 +138,12 @@ bool LogisticRegression::train(cv::InputArray data_ip, cv::InputArray labels_ip)
|
||||
|
||||
if(num_classes < 2)
|
||||
{
|
||||
cv::error(Error::StsBadArg, "train: data should have atleast 2 classes", "cv::ml::LogisticRegression::train", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "data should have atleast 2 classes" );
|
||||
}
|
||||
|
||||
if(_labels_i.rows != _data_i.rows)
|
||||
{
|
||||
cv::error(Error::StsBadArg, "train: number of rows in data and labels should be the equal", "cv::ml::LogisticRegression::train", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "number of rows in data and labels should be the equal" );
|
||||
}
|
||||
|
||||
|
||||
@ -148,11 +154,17 @@ bool LogisticRegression::train(cv::InputArray data_ip, cv::InputArray labels_ip)
|
||||
cv::Mat new_local_labels;
|
||||
|
||||
int ii=0;
|
||||
cv::Mat new_theta;
|
||||
|
||||
if(num_classes == 2)
|
||||
{
|
||||
labels_l.convertTo(labels, CV_32F);
|
||||
cv::Mat new_theta = compute_batch_gradient(data_t, labels, init_theta);
|
||||
// new_theta = compute_batch_gradient(data_t, labels, init_theta);
|
||||
//currently supported training methods LogisticRegression::BATCH and LogisticRegression::MINI_BATCH
|
||||
if(this->params.train_method == LogisticRegression::BATCH)
|
||||
new_theta = compute_batch_gradient(data_t, labels, init_theta);
|
||||
else
|
||||
new_theta = compute_mini_batch_gradient(data_t, labels, init_theta);
|
||||
thetas = new_theta.t();
|
||||
}
|
||||
else
|
||||
@ -165,9 +177,13 @@ bool LogisticRegression::train(cv::InputArray data_ip, cv::InputArray labels_ip)
|
||||
{
|
||||
new_local_labels = (labels_l == it->second)/255;
|
||||
new_local_labels.convertTo(labels, CV_32F);
|
||||
|
||||
cv::Mat new_theta = compute_batch_gradient(data_t, labels, init_theta);
|
||||
|
||||
|
||||
// new_theta = compute_batch_gradient(data_t, labels, init_theta);
|
||||
// currently supported training methods LogisticRegression::BATCH and LogisticRegression::MINI_BATCH
|
||||
if(this->params.train_method == LogisticRegression::BATCH)
|
||||
new_theta = compute_batch_gradient(data_t, labels, init_theta);
|
||||
else
|
||||
new_theta = compute_mini_batch_gradient(data_t, labels, init_theta);
|
||||
hconcat(new_theta.t(), thetas.row(ii));
|
||||
ii += 1;
|
||||
}
|
||||
@ -176,7 +192,7 @@ bool LogisticRegression::train(cv::InputArray data_ip, cv::InputArray labels_ip)
|
||||
this->learnt_thetas = thetas.clone();
|
||||
if( cvIsNaN( (double)cv::sum(this->learnt_thetas)[0] ) )
|
||||
{
|
||||
cv::error(Error::StsBadArg, "train: check training parameters. Invalid training classifier","cv::ml::LogisticRegression::train", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "check training parameters. Invalid training classifier" );
|
||||
}
|
||||
ok = true;
|
||||
return ok;
|
||||
@ -187,18 +203,17 @@ void LogisticRegression::predict( cv::InputArray _ip_data, cv::OutputArray _outp
|
||||
{
|
||||
/* returns a class of the predicted class
|
||||
class names can be 1,2,3,4, .... etc */
|
||||
|
||||
cv::Mat thetas, data, pred_labs;
|
||||
data = _ip_data.getMat();
|
||||
|
||||
// check if learnt_mats array is populated
|
||||
if(this->learnt_thetas.total()<=0)
|
||||
{
|
||||
cv::error(Error::StsBadArg, "predict: classifier should be trained first", "cv::ml::LogisticRegression::predict", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "classifier should be trained first" );
|
||||
}
|
||||
if(data.type() != CV_32F)
|
||||
{
|
||||
cv::error(Error::StsBadArg, "predict: data must be of floating type","cv::ml::LogisticRegression::predict",__FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "data must be of floating type" );
|
||||
}
|
||||
|
||||
// add a column of ones
|
||||
@ -322,12 +337,12 @@ cv::Mat LogisticRegression::compute_batch_gradient(const cv::Mat& _data, const c
|
||||
// implements batch gradient descent
|
||||
if(this->params.alpha<=0)
|
||||
{
|
||||
cv::error(Error::StsBadArg, "compute_batch_gradient: check training parameters for the classifier","cv::ml::LogisticRegression::compute_batch_gradient", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "check training parameters for the classifier" );
|
||||
}
|
||||
|
||||
if(this->params.num_iters <= 0)
|
||||
{
|
||||
cv::error(Error::StsBadArg,"compute_batch_gradient: number of iterations cannot be zero or a negative number","cv::ml::LogisticRegression::compute_batch_gradient",__FILE__,__LINE__);
|
||||
CV_Error( CV_StsBadArg, "number of iterations cannot be zero or a negative number" );
|
||||
}
|
||||
|
||||
int llambda = 0;
|
||||
@ -352,7 +367,7 @@ cv::Mat LogisticRegression::compute_batch_gradient(const cv::Mat& _data, const c
|
||||
|
||||
if( cvIsNaN( ccost ) )
|
||||
{
|
||||
cv::error(Error::StsBadArg, "compute_batch_gradient: check training parameters. Invalid training classifier","cv::ml::LogisticRegression::compute_batch_gradient", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "check training parameters. Invalid training classifier" );
|
||||
}
|
||||
|
||||
pcal_b = calc_sigmoid((_data*theta_p) - _labels);
|
||||
@ -397,12 +412,12 @@ cv::Mat LogisticRegression::compute_mini_batch_gradient(const cv::Mat& _data, co
|
||||
|
||||
if(this->params.mini_batch_size <= 0 || this->params.alpha == 0)
|
||||
{
|
||||
cv::error(Error::StsBadArg, "compute_mini_batch_gradient: check training parameters for the classifier","cv::ml::LogisticRegression::compute_mini_batch_gradient", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "check training parameters for the classifier" );
|
||||
}
|
||||
|
||||
if(this->params.num_iters <= 0)
|
||||
{
|
||||
cv::error(Error::StsBadArg,"compute_mini_batch_gradient: number of iterations cannot be zero or a negative number","cv::ml::LogisticRegression::compute_mini_batch_gradient",__FILE__,__LINE__);
|
||||
CV_Error( CV_StsBadArg, "number of iterations cannot be zero or a negative number" );
|
||||
}
|
||||
|
||||
cv::Mat pcal_a;
|
||||
@ -418,7 +433,7 @@ cv::Mat LogisticRegression::compute_mini_batch_gradient(const cv::Mat& _data, co
|
||||
lambda_l = 1;
|
||||
}
|
||||
|
||||
for(int i = 0;this->params.term_crit.max_iter;i++)
|
||||
for(int i = 0;this->params.term_crit.maxCount;i++)
|
||||
{
|
||||
if(j+size_b<=_data.rows)
|
||||
{
|
||||
@ -438,7 +453,7 @@ cv::Mat LogisticRegression::compute_mini_batch_gradient(const cv::Mat& _data, co
|
||||
|
||||
if( cvIsNaN( ccost ) == 1)
|
||||
{
|
||||
cv::error(Error::StsBadArg, "compute_mini_batch_gradient: check training parameters. Invalid training classifier","cv::ml::LogisticRegression::compute_mini_batch_gradient", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "check training parameters. Invalid training classifier" );
|
||||
}
|
||||
|
||||
pcal_b = calc_sigmoid((data_d*theta_p) - labels_l);
|
||||
@ -536,8 +551,11 @@ void LogisticRegression::clear()
|
||||
|
||||
void LogisticRegression::write(FileStorage& fs) const
|
||||
{
|
||||
CV_Assert(fs.isOpened() == 1);
|
||||
|
||||
// check if open
|
||||
if(fs.isOpened() == 0)
|
||||
{
|
||||
CV_Error(CV_StsBadArg,"file can't open. Check file path");
|
||||
}
|
||||
string desc = "Logisitic Regression Classifier";
|
||||
fs<<"classifier"<<desc.c_str();
|
||||
fs<<"alpha"<<this->params.alpha;
|
||||
@ -559,7 +577,7 @@ void LogisticRegression::read(const FileNode& fn )
|
||||
// check if empty
|
||||
if(fn.empty())
|
||||
{
|
||||
cv::error(Error::StsBadArg, "read: empty FileNode object","cv::ml::LogisticRegression::read", __FILE__, __LINE__);
|
||||
CV_Error( CV_StsBadArg, "empty FileNode object" );
|
||||
}
|
||||
|
||||
this->params.alpha = (double)fn["alpha"];
|
||||
@ -584,23 +602,7 @@ void LogisticRegression::read(const FileNode& fn )
|
||||
}
|
||||
}
|
||||
|
||||
void LogisticRegression::save(string filepath) const
|
||||
{
|
||||
FileStorage fs;
|
||||
fs.open(filepath.c_str(),FileStorage::WRITE);
|
||||
write(fs);
|
||||
fs.release();
|
||||
|
||||
}
|
||||
void LogisticRegression::load(const string filepath)
|
||||
{
|
||||
FileStorage fs;
|
||||
fs.open(filepath.c_str(),FileStorage::READ);
|
||||
FileNode fn = fs.root();
|
||||
read(fn);
|
||||
}
|
||||
|
||||
cv::Mat LogisticRegression::get_learnt_thetas() const
|
||||
const cv::Mat LogisticRegression::get_learnt_thetas() const
|
||||
{
|
||||
return this->learnt_thetas;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user