/*! * * * \brief Radius Margin Quotient for SVM model selection * * * * \author T.Glasmachers, O.Krause * \date 2012 * * * \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_RADIUSMARGINQUOTIENT_H #define SHARK_OBJECTIVEFUNCTIONS_RADIUSMARGINQUOTIENT_H #include #include #include #include #include namespace shark { /// /// \brief radius margin quotions for binary SVMs /// /// \par /// The RadiusMarginQuotient is the quotient \f$ R^2 / \rho^2 \f$ /// of the radius R of the smallest sphere containing the /// training data and the margin \f$\rho\f$ of a binary hard margin /// support vector machine. Both distances depend on the /// kernel function, and thus on its parameters. /// The radius margin quotient is a common objective /// function for the adaptation of the kernel parameters /// of a binary hard-margin SVM. /// template class RadiusMarginQuotient : public AbstractObjectiveFunction< RealVector, double > { public: typedef CacheType QpFloatType; typedef KernelMatrix KernelMatrixType; typedef CachedMatrix< KernelMatrixType > CachedMatrixType; typedef LabeledData DatasetType; typedef AbstractKernelFunction KernelType; /// \brief Constructor. RadiusMarginQuotient(DatasetType const& dataset, KernelType* kernel) : mep_kernel(kernel),m_dataset(dataset) { m_features |= HAS_VALUE; if (mep_kernel->hasFirstParameterDerivative()) m_features |= HAS_FIRST_DERIVATIVE; } /// \brief From INameable: return the class name. std::string name() const { return "RadiusMarginQuotient"; } std::size_t numberOfVariables()const{ return mep_kernel->numberOfParameters(); } /// \brief Evaluate the radius margin quotient. /// /// \par /// The parameters are passed into the kernel, and the /// radius-margin quotient is computed w.r.t. the /// kernel-induced metric. double eval(SearchPointType const& parameters) const{ SIZE_CHECK(parameters.size() == mep_kernel->numberOfParameters()); SHARK_RUNTIME_CHECK(! m_dataset.empty(), "[RadiusMarginQuotient::eval] call setDataset first"); m_evaluationCounter++; mep_kernel->setParameterVector(parameters); Result result = computeRadiusMargin(); return result.w2 * result.R2; } /// \brief Evaluate the radius margin quotient and its first derivative. /// /// \par /// The parameters are passed into the kernel, and the /// radius-margin quotient and its derivative are computed /// w.r.t. the kernel-induced metric. double evalDerivative(SearchPointType const& parameters, FirstOrderDerivative& derivative) const{ SHARK_RUNTIME_CHECK(! m_dataset.empty(), "[RadiusMarginQuotient::evalDerivative] call setDataset first"); SIZE_CHECK(parameters.size() == mep_kernel->numberOfParameters()); m_evaluationCounter++; mep_kernel->setParameterVector(parameters); Result result = computeRadiusMargin(); derivative = calculateKernelMatrixParameterDerivative( *mep_kernel, m_dataset.inputs(), result.w2*(to_diagonal(result.beta)-outer_prod(result.beta,result.beta)) -result.R2*outer_prod(result.alpha,result.alpha) ); return result.w2 * result.R2; } protected: struct Result{ RealVector alpha; RealVector beta; double w2; double R2; }; Result computeRadiusMargin()const{ std::size_t ell = m_dataset.numberOfElements(); QpStoppingCondition stop; Result result; { KernelMatrixType km(*mep_kernel, m_dataset.inputs()); CachedMatrixType cache(&km); typedef CSVMProblem SVMProblemType; typedef SvmShrinkingProblem ProblemType; SVMProblemType svmProblem(cache,m_dataset.labels(),1e100); ProblemType problem(svmProblem); QpSolver< ProblemType> solver(problem); QpSolutionProperties prop; solver.solve(stop, &prop); result.w2 = 2.0 * prop.value; result.alpha = problem.getUnpermutedAlpha(); } { // create and solve the radius problem (also a quadratic program) KernelMatrixType km(*mep_kernel, m_dataset.inputs()); CachedMatrixType cache(&km); typedef BoxedSVMProblem SVMProblemType; typedef SvmShrinkingProblem ProblemType; // Setup the problem RealVector linear(ell); for (std::size_t i=0; i solver(problem); QpSolutionProperties prop; solver.solve(stop, &prop); result.R2 = 2.0 * prop.value; result.beta = problem.getUnpermutedAlpha(); } return result; } KernelType* mep_kernel; ///< underlying parameterized kernel object DatasetType m_dataset; ///< labeled data for radius and (hard) margin computation }; } #endif