/*! * * * \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