14 #ifndef MLPACK_METHODS_LINEAR_SVM_LINEAR_SVM_FUNCTION_IMPL_HPP 15 #define MLPACK_METHODS_LINEAR_SVM_LINEAR_SVM_FUNCTION_IMPL_HPP 26 template <
typename MatType>
28 const MatType& dataset,
29 const arma::Row<size_t>& labels,
30 const size_t numClasses,
33 const bool fitIntercept) :
34 dataset(math::
MakeAlias(const_cast<MatType&>(dataset), false)),
35 numClasses(numClasses),
38 fitIntercept(fitIntercept)
41 initialPoint *= 0.005;
52 template <
typename MatType>
55 const size_t featureSize,
56 const size_t numClasses,
57 const bool fitIntercept)
62 weights.randn(featureSize + 1, numClasses);
64 weights.randn(featureSize, numClasses);
73 template <
typename MatType>
75 const arma::Row<size_t>& labels,
76 arma::sp_mat& groundTruth)
84 arma::uvec rowPointers(labels.n_elem);
85 arma::uvec colPointers(labels.n_elem + 1);
92 for (
size_t i = 0; i < labels.n_elem; ++i)
94 rowPointers(i) = labels(i);
95 colPointers(i + 1) = i + 1;
100 values.ones(labels.n_elem);
103 groundTruth = arma::sp_mat(rowPointers, colPointers, values, numClasses,
110 template <
typename MatType>
114 arma::uvec ordering = arma::shuffle(arma::linspace<arma::uvec>(0,
115 dataset.n_cols - 1, dataset.n_cols));
118 arma::mat newData = dataset.cols(ordering);
120 dataset = std::move(newData);
123 arma::uvec reverseOrdering(ordering.n_elem);
124 for (
size_t i = 0; i < ordering.n_elem; ++i)
125 reverseOrdering[ordering[i]] = i;
127 arma::umat newLocations(2, groundTruth.n_nonzero);
128 arma::vec values(groundTruth.n_nonzero);
129 arma::sp_mat::const_iterator it = groundTruth.begin();
131 while (it != groundTruth.end())
133 newLocations(0, loc) = reverseOrdering(it.col());
134 newLocations(1, loc) = it.row();
141 groundTruth = arma::sp_mat(newLocations, values, groundTruth.n_rows,
145 template <
typename MatType>
147 const arma::mat& parameters)
155 double loss, regularization;
163 scores = parameters.t() * dataset;
172 scores = parameters.rows(0, dataset.n_rows - 1).t() * dataset
173 + arma::repmat(parameters.row(dataset.n_rows).t(), 1,
182 arma::mat margin = scores - (arma::repmat(arma::ones(numClasses).t()
183 * (scores % groundTruth), numClasses, 1)) + delta
184 - (delta * groundTruth);
187 loss = arma::accu(arma::clamp(margin, 0.0, DBL_MAX)) / dataset.n_cols;
190 regularization = 0.5 * lambda * arma::dot(parameters, parameters);
192 return loss + regularization;
195 template <
typename MatType>
197 const arma::mat& parameters,
198 const size_t firstId,
199 const size_t batchSize)
201 const size_t lastId = firstId + batchSize - 1;
204 double loss, regularization, cost;
212 scores = parameters.t() * dataset.cols(firstId, lastId);
216 scores = parameters.rows(0, dataset.n_rows - 1).t()
217 * dataset.cols(firstId, lastId)
218 + arma::repmat(parameters.row(dataset.n_rows).t(), 1,
222 arma::mat margin = scores - (arma::repmat(arma::ones(numClasses).t()
223 * (scores % groundTruth.cols(firstId, lastId)), numClasses, 1))
224 + delta - (delta * groundTruth.cols(firstId, lastId));
227 loss = arma::accu(arma::clamp(margin, 0.0, DBL_MAX));
231 regularization = 0.5 * lambda * arma::dot(parameters, parameters);
233 cost = loss + regularization;
237 template <
typename MatType>
238 template <
typename GradType>
240 const arma::mat& parameters,
253 scores = parameters.t() * dataset;
257 scores = parameters.rows(0, dataset.n_rows - 1).t() * dataset
258 + arma::repmat(parameters.row(dataset.n_rows).t(), 1,
262 arma::mat margin = scores - (arma::repmat(arma::ones(numClasses).t()
263 * (scores % groundTruth), numClasses, 1)) + delta
264 - (delta * groundTruth);
268 arma::mat mask = margin.for_each([](arma::mat::elem_type& val)
269 { val = (val > 0) ? 1: 0; });
271 arma::mat difference = groundTruth
272 % (-arma::repmat(arma::sum(mask), numClasses, 1)) + mask;
284 gradient = dataset * difference.t();
288 gradient.set_size(arma::size(parameters));
289 gradient.submat(0, 0, parameters.n_rows - 2, parameters.n_cols - 1) =
290 dataset * difference.t();
291 gradient.row(parameters.n_rows - 1) =
292 arma::ones<arma::rowvec>(dataset.n_cols) * difference.t();
295 gradient /= dataset.n_cols;
298 gradient += lambda * parameters;
301 template <
typename MatType>
302 template <
typename GradType>
304 const arma::mat& parameters,
305 const size_t firstId,
307 const size_t batchSize)
309 const size_t lastId = firstId + batchSize - 1;
317 scores = parameters.t() * dataset.cols(firstId, lastId);
321 scores = parameters.rows(0, dataset.n_rows - 1).t()
322 * dataset.cols(firstId, lastId)
323 + arma::repmat(parameters.row(dataset.n_rows).t(), 1, batchSize);
326 arma::mat margin = scores - (arma::repmat(arma::ones(numClasses).t()
327 * (scores % groundTruth.cols(firstId, lastId)), numClasses, 1))
328 + delta - (delta * groundTruth.cols(firstId, lastId));
332 arma::mat mask = margin.for_each([](arma::mat::elem_type& val)
333 { val = (val > 0) ? 1: 0; });
335 arma::mat difference = groundTruth.cols(firstId, lastId)
336 % (-arma::repmat(arma::sum(mask), numClasses, 1)) + mask;
341 gradient = dataset.cols(firstId, lastId) * difference.t();
345 gradient.set_size(arma::size(parameters));
346 gradient.submat(0, 0, parameters.n_rows - 2, parameters.n_cols - 1) =
347 dataset.cols(firstId, lastId) * difference.t();
348 gradient.row(parameters.n_rows - 1) =
349 arma::ones<arma::rowvec>(batchSize) * difference.t();
352 gradient /= batchSize;
355 gradient += lambda * parameters;
358 template <
typename MatType>
359 template <
typename GradType>
361 const arma::mat& parameters,
362 GradType& gradient)
const 364 double loss, regularization, cost;
371 scores = parameters.t() * dataset;
375 scores = parameters.rows(0, dataset.n_rows - 1).t() * dataset
376 + arma::repmat(parameters.row(dataset.n_rows).t(), 1,
380 arma::mat margin = scores - (arma::repmat(arma::ones(numClasses).t()
381 * (scores % groundTruth), numClasses, 1)) + delta
382 - (delta * groundTruth);
386 arma::mat mask = margin.for_each([](arma::mat::elem_type& val)
387 { val = (val > 0) ? 1: 0; });
389 arma::mat difference = groundTruth
390 % (-arma::repmat(arma::sum(mask), numClasses, 1)) + mask;
395 gradient = dataset * difference.t();
399 gradient.set_size(arma::size(parameters));
400 gradient.submat(0, 0, parameters.n_rows - 2, parameters.n_cols - 1) =
401 dataset * difference.t();
402 gradient.row(parameters.n_rows - 1) =
403 arma::ones<arma::rowvec>(dataset.n_cols) * difference.t();
406 gradient /= dataset.n_cols;
409 gradient += lambda * parameters;
412 loss = arma::accu(arma::clamp(margin, 0.0, DBL_MAX));
413 loss /= dataset.n_cols;
416 regularization = 0.5 * lambda * arma::dot(parameters, parameters);
418 cost = loss + regularization;
422 template <
typename MatType>
423 template <
typename GradType>
425 const arma::mat& parameters,
426 const size_t firstId,
428 const size_t batchSize)
const 430 const size_t lastId = firstId + batchSize - 1;
433 double loss, regularization, cost;
441 scores = parameters.t() * dataset.cols(firstId, lastId);
445 scores = parameters.rows(0, dataset.n_rows - 1).t()
446 * dataset.cols(firstId, lastId)
447 + arma::repmat(parameters.row(dataset.n_rows).t(), 1, dataset.n_cols);
450 arma::mat margin = scores - (arma::repmat(arma::ones(numClasses).t()
451 * (scores % groundTruth.cols(firstId, lastId)), numClasses, 1))
452 + delta - (delta * groundTruth.cols(firstId, lastId));
456 arma::mat mask = margin.for_each([](arma::mat::elem_type& val)
457 { val = (val > 0) ? 1: 0; });
459 arma::mat difference = groundTruth.cols(firstId, lastId)
460 % (-arma::repmat(arma::sum(mask), numClasses, 1)) + mask;
465 gradient = dataset.cols(firstId, lastId) * difference.t();
469 gradient.set_size(arma::size(parameters));
470 gradient.submat(0, 0, parameters.n_rows - 2, parameters.n_cols - 1) =
471 dataset.cols(firstId, lastId) * difference.t();
472 gradient.row(parameters.n_rows - 1) =
473 arma::ones<arma::rowvec>(batchSize) * difference.t();
476 gradient /= batchSize;
480 gradient += lambda * parameters;
483 loss = arma::accu(arma::clamp(margin.cols(firstId, lastId), 0.0, DBL_MAX));
487 regularization = 0.5 * lambda * arma::dot(parameters, parameters);
489 cost = loss + regularization;
493 template <
typename MatType>
498 return dataset.n_cols;
505 #endif // MLPACK_METHODS_LINEAR_SVM_LINEAR_SVM_FUNCTION_IMPL_HPP
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
void GetGroundTruthMatrix(const arma::Row< size_t > &labels, arma::sp_mat &groundTruth)
Constructs the ground truth label matrix with the passed labels.
Definition: linear_svm_function_impl.hpp:74
double EvaluateWithGradient(const arma::mat ¶meters, GradType &gradient) const
Evaluate the gradient of the hinge loss function, following the LinearFunctionType requirements on th...
Definition: linear_svm_function_impl.hpp:360
void Gradient(const arma::mat ¶meters, GradType &gradient)
Evaluate the gradient of the hinge loss function following the LinearFunctionType requirements on the...
Definition: linear_svm_function_impl.hpp:239
LinearSVMFunction(const MatType &dataset, const arma::Row< size_t > &labels, const size_t numClasses, const double lambda=0.0001, const double delta=1.0, const bool fitIntercept=false)
Construct the Linear SVM objective function with given parameters.
Definition: linear_svm_function_impl.hpp:27
double Evaluate(const arma::mat ¶meters)
Evaluate the hinge loss function for all the datapoints.
Definition: linear_svm_function_impl.hpp:146
size_t NumFunctions() const
Return the number of functions.
Definition: linear_svm_function_impl.hpp:494
void ClearAlias(arma::Mat< ElemType > &mat)
Clear an alias so that no data is overwritten.
Definition: make_alias.hpp:110
void Shuffle()
Shuffle the dataset.
Definition: linear_svm_function_impl.hpp:111
arma::Cube< ElemType > MakeAlias(arma::Cube< ElemType > &input, const bool strict=true)
Make an alias of a dense cube.
Definition: make_alias.hpp:24
static void InitializeWeights(arma::mat &weights, const size_t featureSize, const size_t numClasses, const bool fitIntercept=false)
Initialize Linear SVM weights (trainable parameters) with the given parameters.
Definition: linear_svm_function_impl.hpp:53