RadiusMarginQuotient.h
Go to the documentation of this file.
1 /*!
2  *
3  *
4  * \brief Radius Margin Quotient for SVM model selection
5  *
6  *
7  *
8  * \author T.Glasmachers, O.Krause
9  * \date 2012
10  *
11  *
12  * \par Copyright 1995-2017 Shark Development Team
13  *
14  * <BR><HR>
15  * This file is part of Shark.
16  * <http://shark-ml.org/>
17  *
18  * Shark is free software: you can redistribute it and/or modify
19  * it under the terms of the GNU Lesser General Public License as published
20  * by the Free Software Foundation, either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * Shark is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU Lesser General Public License for more details.
27  *
28  * You should have received a copy of the GNU Lesser General Public License
29  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
30  *
31  */
32 #ifndef SHARK_OBJECTIVEFUNCTIONS_RADIUSMARGINQUOTIENT_H
33 #define SHARK_OBJECTIVEFUNCTIONS_RADIUSMARGINQUOTIENT_H
34 
35 
41 
42 namespace shark {
43 
44 
45 ///
46 /// \brief radius margin quotions for binary SVMs
47 ///
48 /// \par
49 /// The RadiusMarginQuotient is the quotient \f$ R^2 / \rho^2 \f$
50 /// of the radius R of the smallest sphere containing the
51 /// training data and the margin \f$\rho\f$ of a binary hard margin
52 /// support vector machine. Both distances depend on the
53 /// kernel function, and thus on its parameters.
54 /// The radius margin quotient is a common objective
55 /// function for the adaptation of the kernel parameters
56 /// of a binary hard-margin SVM.
57 ///
58 template<class InputType, class CacheType = float>
60 {
61 public:
62  typedef CacheType QpFloatType;
63 
66 
69 
70  /// \brief Constructor.
71  RadiusMarginQuotient(DatasetType const& dataset, KernelType* kernel)
72  : mep_kernel(kernel),m_dataset(dataset)
73  {
77  }
78 
79 
80  /// \brief From INameable: return the class name.
81  std::string name() const
82  { return "RadiusMarginQuotient"; }
83 
84  std::size_t numberOfVariables()const{
86  }
87 
88  /// \brief Evaluate the radius margin quotient.
89  ///
90  /// \par
91  /// The parameters are passed into the kernel, and the
92  /// radius-margin quotient is computed w.r.t. the
93  /// kernel-induced metric.
94  double eval(SearchPointType const& parameters) const{
95  SIZE_CHECK(parameters.size() == mep_kernel->numberOfParameters());
96  SHARK_RUNTIME_CHECK(! m_dataset.empty(), "[RadiusMarginQuotient::eval] call setDataset first");
98 
99 
100  mep_kernel->setParameterVector(parameters);
101 
102  Result result = computeRadiusMargin();
103 
104  return result.w2 * result.R2;
105  }
106 
107  /// \brief Evaluate the radius margin quotient and its first derivative.
108  ///
109  /// \par
110  /// The parameters are passed into the kernel, and the
111  /// radius-margin quotient and its derivative are computed
112  /// w.r.t. the kernel-induced metric.
113  double evalDerivative(SearchPointType const& parameters, FirstOrderDerivative& derivative) const{
114  SHARK_RUNTIME_CHECK(! m_dataset.empty(), "[RadiusMarginQuotient::evalDerivative] call setDataset first");
115  SIZE_CHECK(parameters.size() == mep_kernel->numberOfParameters());
117 
118  mep_kernel->setParameterVector(parameters);
119 
120  Result result = computeRadiusMargin();
121 
124  result.w2*(to_diagonal(result.beta)-outer_prod(result.beta,result.beta))
125  -result.R2*outer_prod(result.alpha,result.alpha)
126  );
127 
128 
129  return result.w2 * result.R2;
130  }
131 
132 protected:
133  struct Result{
134  RealVector alpha;
135  RealVector beta;
136  double w2;
137  double R2;
138  };
139 
141  std::size_t ell = m_dataset.numberOfElements();
142 
143  QpStoppingCondition stop;
144  Result result;
145  {
146  KernelMatrixType km(*mep_kernel, m_dataset.inputs());
147  CachedMatrixType cache(&km);
148  typedef CSVMProblem<CachedMatrixType> SVMProblemType;
149  typedef SvmShrinkingProblem<SVMProblemType> ProblemType;
150 
151  SVMProblemType svmProblem(cache,m_dataset.labels(),1e100);
152  ProblemType problem(svmProblem);
153 
154  QpSolver< ProblemType> solver(problem);
156  solver.solve(stop, &prop);
157  result.w2 = 2.0 * prop.value;
158  result.alpha = problem.getUnpermutedAlpha();
159  }
160  {
161  // create and solve the radius problem (also a quadratic program)
162  KernelMatrixType km(*mep_kernel, m_dataset.inputs());
163  CachedMatrixType cache(&km);
164  typedef BoxedSVMProblem<CachedMatrixType> SVMProblemType;
165  typedef SvmShrinkingProblem<SVMProblemType> ProblemType;
166 
167  // Setup the problem
168  RealVector linear(ell);
169  for (std::size_t i=0; i<ell; i++){
170  linear(i) = 0.5 * km(i, i);
171  }
172  SVMProblemType svmProblem(cache,linear,0.0,1.0);
173  ProblemType problem(svmProblem);
174 
175  //solve it
176  QpSolver< ProblemType> solver(problem);
178  solver.solve(stop, &prop);
179  result.R2 = 2.0 * prop.value;
180  result.beta = problem.getUnpermutedAlpha();
181  }
182  return result;
183  }
184 
185  KernelType* mep_kernel; ///< underlying parameterized kernel object
186  DatasetType m_dataset; ///< labeled data for radius and (hard) margin computation
187 
188 };
189 
190 
191 }
192 #endif