/*!
*
*
* \brief Leave-one-out error for C-SVMs
*
*
*
* \author T.Glasmachers
* \date 2011
*
*
* \par Copyright 1995-2017 Shark Development Team
*
*
* This file is part of Shark.
*
*
* Shark is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Shark is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Shark. If not, see .
*
*/
#ifndef SHARK_OBJECTIVEFUNCTIONS_LOOERRORCSVM_H
#define SHARK_OBJECTIVEFUNCTIONS_LOOERRORCSVM_H
#include
#include
#include
#include
#include
#include
#include
namespace shark {
///
/// \brief Leave-one-out error, specifically optimized for C-SVMs.
///
template
class LooErrorCSvm : public AbstractObjectiveFunction< RealVector, double >
{
public:
typedef CacheType QpFloatType;
typedef AbstractKernelFunction KernelType;
typedef LabeledData DatasetType;
/// \brief Constructor.
LooErrorCSvm(DatasetType const& dataset, KernelType* kernel, bool withOffset)
: mep_dataset(&dataset)
, mep_kernel(kernel)
, m_withOffset(withOffset)
{
SHARK_RUNTIME_CHECK(kernel != NULL, "kernel is not allowed to be Null");
m_features |= HAS_VALUE;
}
/// \brief From INameable: return the class name.
std::string name() const
{ return "LooErrorCSvm"; }
std::size_t numberOfVariables()const{
return mep_kernel->numberOfParameters()+1;
}
/// Evaluate the leave-one-out error for the given parameters.
/// These parameters describe the regularization
/// constant and the kernel parameters.
double eval(const RealVector& params){
QpStoppingCondition stop;
return eval(params, stop);
}
/// Evaluate the leave-one-out error for the given parameters.
/// These parameters describe the regularization constant and
/// the kernel parameters. Furthermore, the stopping
/// conditions for the solver are passed as an argument.
double eval(const RealVector& params, QpStoppingCondition &stop){
this->m_evaluationCounter++;
double C = params.back();
mep_kernel->setParameterVector(subrange(params,0,params.size() - 1));
ZeroOneLoss loss;
// prepare the quadratic program
typedef KernelMatrix KernelMatrixType;
typedef CachedMatrix< KernelMatrixType > CachedMatrixType;
typedef CSVMProblem SVMProblemType;
KernelMatrixType km(*mep_kernel, mep_dataset->inputs());
CachedMatrixType matrix(&km);
SVMProblemType svmProblem(matrix,mep_dataset->labels(),C);
std::size_t ell = km.size();
//QpStoppingCondition stop;
if (m_withOffset)
{
// solve the full problem with equality constraint and activated shrinking
typedef SvmProblem ProblemType;
ProblemType problem(svmProblem);
QpSolver< ProblemType > solver(problem);
solver.solve(stop);
RealVector alphaFull(problem.dimensions());
for(std::size_t i = 0; i != problem.dimensions(); ++i){
alphaFull(i) = problem.alpha(i);
}
KernelExpansion svm(mep_kernel,mep_dataset->inputs(),true);
// leave-one-out
//problem.setShrinking(false);
double mistakes = 0;
for (std::size_t i=0; ielement(elementIndex).label;
mistakes += loss(target, svm(mep_dataset->element(elementIndex).input));
problem.activateVariable(i);
}
return mistakes / (double)ell;
}
else
{
// solve the full problem without equality constraint and activated shrinking
typedef BoxConstrainedProblem ProblemType;
ProblemType problem(svmProblem);
QpSolver< ProblemType > solver(problem);
solver.solve(stop);
RealVector alphaFull(problem.dimensions());
for(std::size_t i = 0; i != problem.dimensions(); ++i){
alphaFull(i) = problem.alpha(i);
}
KernelExpansion svm(mep_kernel,mep_dataset->inputs(),false);
// leave-one-out
//problem.setShrinking(false);
double mistakes = 0;
for (std::size_t i=0; ielement(elementIndex).label;
mistakes += loss(target, svm(mep_dataset->element(elementIndex).input));
problem.activateVariable(i);
}
return mistakes / (double)ell;
}
}
private:
/// Compute the SVM offset term (b).
template
double computeBias(Problem const& problem){
double lowerBound = -1e100;
double upperBound = 1e100;
double sum = 0.0;
std::size_t freeVars = 0;
std::size_t ell = problem.dimensions();
for (std::size_t i=0; i 0)
return sum / freeVars;
else
return 0.5 * (lowerBound + upperBound);
}
const DatasetType* mep_dataset;
KernelType* mep_kernel;
bool m_withOffset;
};
}
#endif