Commit f3c4a6aa authored by Marina Noskova's avatar Marina Noskova

Rename parameters lambda, gamma0 and c.

parent 02cd8cf0
...@@ -1511,9 +1511,9 @@ The gradient descent show amazing performance for large-scale problems, reducing ...@@ -1511,9 +1511,9 @@ The gradient descent show amazing performance for large-scale problems, reducing
The classifier has 5 parameters. These are The classifier has 5 parameters. These are
- model type, - model type,
- margin type, - margin type,
- \f$\lambda\f$ (strength of restrictions on outliers), - marginRegularization (\f$\lambda\f$),
- \f$\gamma_0\f$ (initial step size), - initialStepSize (\f$\gamma_0\f$),
- \f$c\f$ (power coefficient for decreasing of step size), - stepDecreasingPower (\f$c\f$),
- and termination criteria. - and termination criteria.
The model type may have one of the following values: \ref SGD and \ref ASGD. The model type may have one of the following values: \ref SGD and \ref ASGD.
...@@ -1538,27 +1538,27 @@ The margin type may have one of the following values: \ref SOFT_MARGIN or \ref H ...@@ -1538,27 +1538,27 @@ The margin type may have one of the following values: \ref SOFT_MARGIN or \ref H
- In the general case (if you know nothing about linear separability of your sets), use SOFT_MARGIN. - In the general case (if you know nothing about linear separability of your sets), use SOFT_MARGIN.
The other parameters may be described as follows: The other parameters may be described as follows:
- \f$\lambda\f$ parameter is responsible for weights decreasing at each step and for the strength of restrictions on outliers - marginRegularization parameter is responsible for weights decreasing at each step and for the strength of restrictions on outliers
(the less the parameter, the less probability that an outlier will be ignored). (the less the parameter, the less probability that an outlier will be ignored).
Recommended value for SGD model is 0.0001, for ASGD model is 0.00001. Recommended value for SGD model is 0.0001, for ASGD model is 0.00001.
- \f$\gamma_0\f$ parameter is the initial value for the step size \f$\gamma(t)\f$. - initialStepSize parameter is the initial value for the step size \f$\gamma(t)\f$.
You will have to find the best \f$\gamma_0\f$ for your problem. You will have to find the best \f$\gamma_0\f$ for your problem.
- \f$c\f$ is the power parameter for \f$\gamma(t)\f$ decreasing by the formula, mentioned above. - stepDecreasingPower is the power parameter for \f$\gamma(t)\f$ decreasing by the formula, mentioned above.
Recommended value for SGD model is 1, for ASGD model is 0.75. Recommended value for SGD model is 1, for ASGD model is 0.75.
- Termination criteria can be TermCriteria::COUNT, TermCriteria::EPS or TermCriteria::COUNT + TermCriteria::EPS. - Termination criteria can be TermCriteria::COUNT, TermCriteria::EPS or TermCriteria::COUNT + TermCriteria::EPS.
You will have to find the best termination criteria for your problem. You will have to find the best termination criteria for your problem.
Note that the parameters \f$\lambda\f$, \f$\gamma_0\f$, and \f$c\f$ should be positive. Note that the parameters marginRegularization, initialStepSize, and stepDecreasingPower should be positive.
To use SVMSGD algorithm do as follows: To use SVMSGD algorithm do as follows:
- first, create the SVMSGD object. - first, create the SVMSGD object.
- then set parameters (model type, margin type, \f$\lambda\f$, \f$\gamma_0\f$, \f$c\f$) using the functions - then set parameters (model type, margin type, marginRegularization, initialStepSize, stepDecreasingPower) using the functions
setSvmsgdType(), setMarginType(), setLambda(), setGamma0(), and setC(), or the function setOptimalParameters(). setSvmsgdType(), setMarginType(), setMarginRegularization(), setInitialStepSize(), and setStepDecreasingPower(), or the function setOptimalParameters().
- then the SVM model can be trained using the train features and the correspondent labels by the method train(). - then the SVM model can be trained using the train features and the correspondent labels by the method train().
...@@ -1618,16 +1618,16 @@ public: ...@@ -1618,16 +1618,16 @@ public:
/** @brief Function sets optimal parameters values for chosen SVM SGD model. /** @brief Function sets optimal parameters values for chosen SVM SGD model.
* If chosen type is ASGD, function sets the following values for parameters of model: * If chosen type is ASGD, function sets the following values for parameters of model:
* \f$\lambda = 0.00001\f$; * marginRegularization = 0.00001;
* \f$\gamma_0 = 0.05\f$; * initialStepSize = 0.05;
* \f$c = 0.75\f$; * stepDecreasingPower = 0.75;
* termCrit.maxCount = 100000; * termCrit.maxCount = 100000;
* termCrit.epsilon = 0.00001; * termCrit.epsilon = 0.00001;
* *
* If SGD: * If SGD:
* \f$\lambda = 0.0001\f$; * marginRegularization = 0.0001;
* \f$\gamma_0 = 0.05\f$; * initialStepSize = 0.05;
* \f$c = 1\f$; * stepDecreasingPower = 1;
* termCrit.maxCount = 100000; * termCrit.maxCount = 100000;
* termCrit.epsilon = 0.00001; * termCrit.epsilon = 0.00001;
* @param svmsgdType is the type of SVMSGD classifier. Legal values are SvmsgdType::SGD and SvmsgdType::ASGD. * @param svmsgdType is the type of SVMSGD classifier. Legal values are SvmsgdType::SGD and SvmsgdType::ASGD.
...@@ -1650,23 +1650,23 @@ public: ...@@ -1650,23 +1650,23 @@ public:
CV_WRAP virtual void setMarginType(int marginType) = 0; CV_WRAP virtual void setMarginType(int marginType) = 0;
/** @brief Parameter \f$\lambda\f$ of a %SVMSGD optimization problem. Default value is 0. */ /** @brief Parameter marginRegularization of a %SVMSGD optimization problem. Default value is 0. */
/** @see setLambda */ /** @see setMarginRegularization */
CV_WRAP virtual float getLambda() const = 0; CV_WRAP virtual float getMarginRegularization() const = 0;
/** @copybrief getLambda @see getLambda */ /** @copybrief getMarginRegularization @see getMarginRegularization */
CV_WRAP virtual void setLambda(float lambda) = 0; CV_WRAP virtual void setMarginRegularization(float marginRegularization) = 0;
/** @brief Parameter \f$\gamma_0\f$ of a %SVMSGD optimization problem. Default value is 0. */ /** @brief Parameter \f$\gamma_0\f$ of a %SVMSGD optimization problem. Default value is 0. */
/** @see setGamma0 */ /** @see setInitialStepSize */
CV_WRAP virtual float getGamma0() const = 0; CV_WRAP virtual float getInitialStepSize() const = 0;
/** @copybrief getGamma0 @see getGamma0 */ /** @copybrief getInitialStepSize @see getInitialStepSize */
CV_WRAP virtual void setGamma0(float gamma0) = 0; CV_WRAP virtual void setInitialStepSize(float InitialStepSize) = 0;
/** @brief Parameter \f$c\f$ of a %SVMSGD optimization problem. Default value is 0. */ /** @brief Parameter stepDecreasingPower of a %SVMSGD optimization problem. Default value is 0. */
/** @see setC */ /** @see setStepDecreasingPower */
CV_WRAP virtual float getC() const = 0; CV_WRAP virtual float getStepDecreasingPower() const = 0;
/** @copybrief getC @see getC */ /** @copybrief getStepDecreasingPower @see getStepDecreasingPower */
CV_WRAP virtual void setC(float c) = 0; CV_WRAP virtual void setStepDecreasingPower(float stepDecreasingPower) = 0;
/** @brief Termination criteria of the training algorithm. /** @brief Termination criteria of the training algorithm.
You can specify the maximum number of iterations (maxCount) and/or how much the error could You can specify the maximum number of iterations (maxCount) and/or how much the error could
......
...@@ -91,13 +91,13 @@ public: ...@@ -91,13 +91,13 @@ public:
CV_IMPL_PROPERTY(int, SvmsgdType, params.svmsgdType) CV_IMPL_PROPERTY(int, SvmsgdType, params.svmsgdType)
CV_IMPL_PROPERTY(int, MarginType, params.marginType) CV_IMPL_PROPERTY(int, MarginType, params.marginType)
CV_IMPL_PROPERTY(float, Lambda, params.lambda) CV_IMPL_PROPERTY(float, MarginRegularization, params.marginRegularization)
CV_IMPL_PROPERTY(float, Gamma0, params.gamma0) CV_IMPL_PROPERTY(float, InitialStepSize, params.initialStepSize)
CV_IMPL_PROPERTY(float, C, params.c) CV_IMPL_PROPERTY(float, StepDecreasingPower, params.stepDecreasingPower)
CV_IMPL_PROPERTY_S(cv::TermCriteria, TermCriteria, params.termCrit) CV_IMPL_PROPERTY_S(cv::TermCriteria, TermCriteria, params.termCrit)
private: private:
void updateWeights(InputArray sample, bool isPositive, float gamma, Mat &weights); void updateWeights(InputArray sample, bool isPositive, float stepSize, Mat &weights);
std::pair<bool,bool> areClassesEmpty(Mat responses); std::pair<bool,bool> areClassesEmpty(Mat responses);
...@@ -122,9 +122,9 @@ private: ...@@ -122,9 +122,9 @@ private:
// Parameters for learning // Parameters for learning
struct SVMSGDParams struct SVMSGDParams
{ {
float lambda; //regularization float marginRegularization;
float gamma0; //learning rate float initialStepSize;
float c; float stepDecreasingPower;
TermCriteria termCrit; TermCriteria termCrit;
int svmsgdType; int svmsgdType;
int marginType; int marginType;
...@@ -166,8 +166,7 @@ void SVMSGDImpl::normalizeSamples(Mat &samples, Mat &average, float &multiplier) ...@@ -166,8 +166,7 @@ void SVMSGDImpl::normalizeSamples(Mat &samples, Mat &average, float &multiplier)
average = Mat(1, featuresCount, samples.type()); average = Mat(1, featuresCount, samples.type());
for (int featureIndex = 0; featureIndex < featuresCount; featureIndex++) for (int featureIndex = 0; featureIndex < featuresCount; featureIndex++)
{ {
Scalar scalAverage = mean(samples.col(featureIndex)); average.at<float>(featureIndex) = static_cast<float>(mean(samples.col(featureIndex))[0]);
average.at<float>(featureIndex) = static_cast<float>(scalAverage[0]);
} }
for (int sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++) for (int sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++)
...@@ -193,7 +192,7 @@ void SVMSGDImpl::makeExtendedTrainSamples(const Mat &trainSamples, Mat &extended ...@@ -193,7 +192,7 @@ void SVMSGDImpl::makeExtendedTrainSamples(const Mat &trainSamples, Mat &extended
cv::hconcat(normalizedTrainSamples, onesCol, extendedTrainSamples); cv::hconcat(normalizedTrainSamples, onesCol, extendedTrainSamples);
} }
void SVMSGDImpl::updateWeights(InputArray _sample, bool firstClass, float gamma, Mat& weights) void SVMSGDImpl::updateWeights(InputArray _sample, bool firstClass, float stepSize, Mat& weights)
{ {
Mat sample = _sample.getMat(); Mat sample = _sample.getMat();
...@@ -202,18 +201,18 @@ void SVMSGDImpl::updateWeights(InputArray _sample, bool firstClass, float gamma, ...@@ -202,18 +201,18 @@ void SVMSGDImpl::updateWeights(InputArray _sample, bool firstClass, float gamma,
if ( sample.dot(weights) * response > 1) if ( sample.dot(weights) * response > 1)
{ {
// Not a support vector, only apply weight decay // Not a support vector, only apply weight decay
weights *= (1.f - gamma * params.lambda); weights *= (1.f - stepSize * params.marginRegularization);
} }
else else
{ {
// It's a support vector, add it to the weights // It's a support vector, add it to the weights
weights -= (gamma * params.lambda) * weights - (gamma * response) * sample; weights -= (stepSize * params.marginRegularization) * weights - (stepSize * response) * sample;
} }
} }
float SVMSGDImpl::calcShift(InputArray _samples, InputArray _responses) const float SVMSGDImpl::calcShift(InputArray _samples, InputArray _responses) const
{ {
float distanceToClasses[2] = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max() }; float margin[2] = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
Mat trainSamples = _samples.getMat(); Mat trainSamples = _samples.getMat();
int trainSamplesCount = trainSamples.rows; int trainSamplesCount = trainSamples.rows;
...@@ -225,18 +224,18 @@ float SVMSGDImpl::calcShift(InputArray _samples, InputArray _responses) const ...@@ -225,18 +224,18 @@ float SVMSGDImpl::calcShift(InputArray _samples, InputArray _responses) const
Mat currentSample = trainSamples.row(samplesIndex); Mat currentSample = trainSamples.row(samplesIndex);
float dotProduct = static_cast<float>(currentSample.dot(weights_)); float dotProduct = static_cast<float>(currentSample.dot(weights_));
bool firstClass = isPositive(trainResponses.at<float>(samplesIndex)); bool positive = isPositive(trainResponses.at<float>(samplesIndex));
int index = firstClass ? 0 : 1; int index = positive ? 0 : 1;
float signToMul = firstClass ? 1.f : -1.f; float signToMul = positive ? 1.f : -1.f;
float curDistance = dotProduct * signToMul; float curMargin = dotProduct * signToMul;
if (curDistance < distanceToClasses[index]) if (curMargin < margin[index])
{ {
distanceToClasses[index] = curDistance; margin[index] = curMargin;
} }
} }
return -(distanceToClasses[0] - distanceToClasses[1]) / 2.f; return -(margin[0] - margin[1]) / 2.f;
} }
bool SVMSGDImpl::train(const Ptr<TrainData>& data, int) bool SVMSGDImpl::train(const Ptr<TrainData>& data, int)
...@@ -292,9 +291,9 @@ bool SVMSGDImpl::train(const Ptr<TrainData>& data, int) ...@@ -292,9 +291,9 @@ bool SVMSGDImpl::train(const Ptr<TrainData>& data, int)
Mat currentSample = extendedTrainSamples.row(randomNumber); Mat currentSample = extendedTrainSamples.row(randomNumber);
float gamma = params.gamma0 * std::pow((1 + params.lambda * params.gamma0 * (float)iter), (-params.c)); //update gamma float stepSize = params.initialStepSize * std::pow((1 + params.marginRegularization * params.initialStepSize * (float)iter), (-params.stepDecreasingPower)); //update stepSize
updateWeights( currentSample, isPositive(trainResponses.at<float>(randomNumber)), gamma, extendedWeights ); updateWeights( currentSample, isPositive(trainResponses.at<float>(randomNumber)), stepSize, extendedWeights );
//average weights (only for ASGD model) //average weights (only for ASGD model)
if (params.svmsgdType == ASGD) if (params.svmsgdType == ASGD)
...@@ -370,7 +369,7 @@ bool SVMSGDImpl::isClassifier() const ...@@ -370,7 +369,7 @@ bool SVMSGDImpl::isClassifier() const
&& &&
(params.marginType == SOFT_MARGIN || params.marginType == HARD_MARGIN) (params.marginType == SOFT_MARGIN || params.marginType == HARD_MARGIN)
&& &&
(params.lambda > 0) && (params.gamma0 > 0) && (params.c >= 0); (params.marginRegularization > 0) && (params.initialStepSize > 0) && (params.stepDecreasingPower >= 0);
} }
bool SVMSGDImpl::isTrained() const bool SVMSGDImpl::isTrained() const
...@@ -423,9 +422,9 @@ void SVMSGDImpl::writeParams( FileStorage& fs ) const ...@@ -423,9 +422,9 @@ void SVMSGDImpl::writeParams( FileStorage& fs ) const
fs << "marginType" << marginTypeStr; fs << "marginType" << marginTypeStr;
fs << "lambda" << params.lambda; fs << "marginRegularization" << params.marginRegularization;
fs << "gamma0" << params.gamma0; fs << "initialStepSize" << params.initialStepSize;
fs << "c" << params.c; fs << "stepDecreasingPower" << params.stepDecreasingPower;
fs << "term_criteria" << "{:"; fs << "term_criteria" << "{:";
if( params.termCrit.type & TermCriteria::EPS ) if( params.termCrit.type & TermCriteria::EPS )
...@@ -467,14 +466,14 @@ void SVMSGDImpl::readParams( const FileNode& fn ) ...@@ -467,14 +466,14 @@ void SVMSGDImpl::readParams( const FileNode& fn )
params.marginType = marginType; params.marginType = marginType;
CV_Assert ( fn["lambda"].isReal() ); CV_Assert ( fn["marginRegularization"].isReal() );
params.lambda = (float)fn["lambda"]; params.marginRegularization = (float)fn["marginRegularization"];
CV_Assert ( fn["gamma0"].isReal() ); CV_Assert ( fn["initialStepSize"].isReal() );
params.gamma0 = (float)fn["gamma0"]; params.initialStepSize = (float)fn["initialStepSize"];
CV_Assert ( fn["c"].isReal() ); CV_Assert ( fn["stepDecreasingPower"].isReal() );
params.c = (float)fn["c"]; params.stepDecreasingPower = (float)fn["stepDecreasingPower"];
FileNode tcnode = fn["term_criteria"]; FileNode tcnode = fn["term_criteria"];
if( !tcnode.empty() ) if( !tcnode.empty() )
...@@ -504,9 +503,9 @@ SVMSGDImpl::SVMSGDImpl() ...@@ -504,9 +503,9 @@ SVMSGDImpl::SVMSGDImpl()
params.marginType = -1; params.marginType = -1;
// Parameters for learning // Parameters for learning
params.lambda = 0; // regularization params.marginRegularization = 0; // regularization
params.gamma0 = 0; // learning rate (ideally should be large at beginning and decay each iteration) params.initialStepSize = 0; // learning rate (ideally should be large at beginning and decay each iteration)
params.c = 0; params.stepDecreasingPower = 0;
TermCriteria _termCrit(TermCriteria::COUNT + TermCriteria::EPS, 0, 0); TermCriteria _termCrit(TermCriteria::COUNT + TermCriteria::EPS, 0, 0);
params.termCrit = _termCrit; params.termCrit = _termCrit;
...@@ -520,9 +519,9 @@ void SVMSGDImpl::setOptimalParameters(int svmsgdType, int marginType) ...@@ -520,9 +519,9 @@ void SVMSGDImpl::setOptimalParameters(int svmsgdType, int marginType)
params.svmsgdType = SGD; params.svmsgdType = SGD;
params.marginType = (marginType == SOFT_MARGIN) ? SOFT_MARGIN : params.marginType = (marginType == SOFT_MARGIN) ? SOFT_MARGIN :
(marginType == HARD_MARGIN) ? HARD_MARGIN : -1; (marginType == HARD_MARGIN) ? HARD_MARGIN : -1;
params.lambda = 0.0001f; params.marginRegularization = 0.0001f;
params.gamma0 = 0.05f; params.initialStepSize = 0.05f;
params.c = 1.f; params.stepDecreasingPower = 1.f;
params.termCrit = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100000, 0.00001); params.termCrit = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100000, 0.00001);
break; break;
...@@ -530,9 +529,9 @@ void SVMSGDImpl::setOptimalParameters(int svmsgdType, int marginType) ...@@ -530,9 +529,9 @@ void SVMSGDImpl::setOptimalParameters(int svmsgdType, int marginType)
params.svmsgdType = ASGD; params.svmsgdType = ASGD;
params.marginType = (marginType == SOFT_MARGIN) ? SOFT_MARGIN : params.marginType = (marginType == SOFT_MARGIN) ? SOFT_MARGIN :
(marginType == HARD_MARGIN) ? HARD_MARGIN : -1; (marginType == HARD_MARGIN) ? HARD_MARGIN : -1;
params.lambda = 0.00001f; params.marginRegularization = 0.00001f;
params.gamma0 = 0.05f; params.initialStepSize = 0.05f;
params.c = 0.75f; params.stepDecreasingPower = 0.75f;
params.termCrit = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100000, 0.00001); params.termCrit = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100000, 0.00001);
break; break;
......
...@@ -469,9 +469,9 @@ int CV_MLBaseTest::train( int testCaseIdx ) ...@@ -469,9 +469,9 @@ int CV_MLBaseTest::train( int testCaseIdx )
int marginType = str_to_margin_type( marginTypeStr ); int marginType = str_to_margin_type( marginTypeStr );
m->setMarginType(marginType); m->setMarginType(marginType);
m->setLambda(modelParamsNode["lambda"]); m->setMarginRegularization(modelParamsNode["marginRegularization"]);
m->setGamma0(modelParamsNode["gamma0"]); m->setInitialStepSize(modelParamsNode["initialStepSize"]);
m->setC(modelParamsNode["c"]); m->setStepDecreasingPower(modelParamsNode["stepDecreasingPower"]);
m->setTermCriteria(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 10000, 0.00001)); m->setTermCriteria(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 10000, 0.00001));
model = m; model = m;
} }
......
...@@ -200,7 +200,6 @@ void CV_SVMSGDTrainTest::run( int /*start_from*/ ) ...@@ -200,7 +200,6 @@ void CV_SVMSGDTrainTest::run( int /*start_from*/ )
} }
float err = (float)errCount / testSamplesCount; float err = (float)errCount / testSamplesCount;
std::cout << "err " << err << std::endl;
if ( err > precision ) if ( err > precision )
{ {
......
...@@ -28,7 +28,7 @@ struct Data ...@@ -28,7 +28,7 @@ struct Data
bool doTrain(const Mat samples, const Mat responses, Mat &weights, float &shift); bool doTrain(const Mat samples, const Mat responses, Mat &weights, float &shift);
//function finds two points for drawing line (wx = 0) //function finds two points for drawing line (wx = 0)
bool findPointsForLine(const Mat &weights, float shift, Point (&points)[2], int width, int height); bool findPointsForLine(const Mat &weights, float shift, Point points[], int width, int height);
// function finds cross point of line (wx = 0) and segment ( (y = HEIGHT, 0 <= x <= WIDTH) or (x = WIDTH, 0 <= y <= HEIGHT) ) // function finds cross point of line (wx = 0) and segment ( (y = HEIGHT, 0 <= x <= WIDTH) or (x = WIDTH, 0 <= y <= HEIGHT) )
bool findCrossPointWithBorders(const Mat &weights, float shift, const std::pair<Point,Point> &segment, Point &crossPoint); bool findCrossPointWithBorders(const Mat &weights, float shift, const std::pair<Point,Point> &segment, Point &crossPoint);
...@@ -119,7 +119,7 @@ bool findCrossPointWithBorders(const Mat &weights, float shift, const std::pair< ...@@ -119,7 +119,7 @@ bool findCrossPointWithBorders(const Mat &weights, float shift, const std::pair<
return false; return false;
} }
bool findPointsForLine(const Mat &weights, float shift, Point (&points)[2], int width, int height) bool findPointsForLine(const Mat &weights, float shift, Point points[2], int width, int height)
{ {
if (weights.empty()) if (weights.empty())
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment