00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 #include "svm.h"
00892 #include "mathop.h"
00893 #include <string.h>
00894
00895 struct VlSvm_ {
00896 VlSvmSolverType solver ;
00898 vl_size dimension ;
00899 double * model ;
00900 double bias ;
00901 double biasMultiplier ;
00903
00904 double lambda ;
00905 void const * data ;
00906 vl_size numData ;
00907 double const * labels ;
00908 double const * weights ;
00910 VlSvmDataset * ownDataset ;
00912 VlSvmDiagnosticFunction diagnosticFn ;
00913 void * diagnosticFnData ;
00914 vl_size diagnosticFrequency ;
00916 VlSvmLossFunction lossFn ;
00917 VlSvmLossFunction conjugateLossFn ;
00918 VlSvmLossFunction lossDerivativeFn ;
00919 VlSvmDcaUpdateFunction dcaUpdateFn ;
00920 VlSvmInnerProductFunction innerProductFn ;
00921 VlSvmAccumulateFunction accumulateFn ;
00922
00923 vl_size iteration ;
00924 vl_size maxNumIterations ;
00925 double epsilon ;
00927
00928 VlSvmStatistics statistics ;
00929 double * scores ;
00930
00931
00932 double biasLearningRate ;
00934
00935 double * alpha ;
00936 } ;
00937
00938
00939
00956 VlSvm *
00957 vl_svm_new (VlSvmSolverType type,
00958 double const * data,
00959 vl_size dimension,
00960 vl_size numData,
00961 double const * labels,
00962 double lambda)
00963 {
00964 VlSvmDataset * dataset = vl_svmdataset_new(VL_TYPE_DOUBLE, (void*)data, dimension, numData) ;
00965 VlSvm * self = vl_svm_new_with_dataset (type, dataset, labels, lambda) ;
00966 self->ownDataset = dataset ;
00967 return self ;
00968 }
00969
00979 VlSvm *
00980 vl_svm_new_with_dataset (VlSvmSolverType solver,
00981 VlSvmDataset * dataset,
00982 double const * labels,
00983 double lambda)
00984 {
00985 VlSvm * self = vl_svm_new_with_abstract_data (solver,
00986 dataset,
00987 vl_svmdataset_get_dimension(dataset),
00988 vl_svmdataset_get_num_data(dataset),
00989 labels,
00990 lambda) ;
00991 vl_svm_set_data_functions (self,
00992 vl_svmdataset_get_inner_product_function(dataset),
00993 vl_svmdataset_get_accumulate_function(dataset)) ;
00994 return self ;
00995 }
00996
01013 VlSvm *
01014 vl_svm_new_with_abstract_data (VlSvmSolverType solver,
01015 void * data,
01016 vl_size dimension,
01017 vl_size numData,
01018 double const * labels,
01019 double lambda)
01020 {
01021 VlSvm * self = vl_calloc(1,sizeof(VlSvm)) ;
01022
01023 assert(dimension >= 1) ;
01024 assert(numData >= 1) ;
01025 assert(labels) ;
01026
01027 self->solver = solver ;
01028
01029 self->dimension = dimension ;
01030 self->model = 0 ;
01031 self->bias = 0 ;
01032 self->biasMultiplier = 1.0 ;
01033
01034 self->lambda = lambda ;
01035 self->data = data ;
01036 self->numData = numData ;
01037 self->labels = labels ;
01038
01039 self->diagnosticFrequency = numData ;
01040 self->diagnosticFn = 0 ;
01041 self->diagnosticFnData = 0 ;
01042
01043 self->lossFn = vl_svm_hinge_loss ;
01044 self->conjugateLossFn = vl_svm_hinge_conjugate_loss ;
01045 self->lossDerivativeFn = vl_svm_hinge_loss_derivative ;
01046 self->dcaUpdateFn = vl_svm_hinge_dca_update ;
01047
01048 self->innerProductFn = 0 ;
01049 self->accumulateFn = 0 ;
01050
01051 self->iteration = 0 ;
01052 self->maxNumIterations = VL_MAX((double)numData, vl_ceil_f(10.0 / lambda)) ;
01053 self->epsilon = 1e-2 ;
01054
01055
01056 self->biasLearningRate = 0.01 ;
01057
01058
01059 self->alpha = 0 ;
01060
01061
01062 self->model = vl_calloc(dimension, sizeof(double)) ;
01063 if (self->model == NULL) goto err_alloc ;
01064
01065 if (self->solver == VlSvmSolverSdca) {
01066 self->alpha = vl_calloc(self->numData, sizeof(double)) ;
01067 if (self->alpha == NULL) goto err_alloc ;
01068 }
01069
01070 self->scores = vl_calloc(numData, sizeof(double)) ;
01071 if (self->scores == NULL) goto err_alloc ;
01072
01073 return self ;
01074
01075 err_alloc:
01076 if (self->scores) {
01077 vl_free (self->scores) ;
01078 self->scores = 0 ;
01079 }
01080 if (self->model) {
01081 vl_free (self->model) ;
01082 self->model = 0 ;
01083 }
01084 if (self->alpha) {
01085 vl_free (self->alpha) ;
01086 self->alpha = 0 ;
01087 }
01088 return 0 ;
01089 }
01090
01096 void
01097 vl_svm_delete (VlSvm * self)
01098 {
01099 if (self->model) {
01100 vl_free (self->model) ;
01101 self->model = 0 ;
01102 }
01103 if (self->alpha) {
01104 vl_free (self->alpha) ;
01105 self->alpha = 0 ;
01106 }
01107 if (self->ownDataset) {
01108 vl_svmdataset_delete(self->ownDataset) ;
01109 self->ownDataset = 0 ;
01110 }
01111 vl_free (self) ;
01112 }
01113
01114
01115
01116
01117
01123 void vl_svm_set_epsilon (VlSvm *self, double epsilon)
01124 {
01125 assert(self) ;
01126 assert(epsilon >= 0) ;
01127 self->epsilon = epsilon ;
01128 }
01129
01135 double vl_svm_get_epsilon (VlSvm const *self)
01136 {
01137 assert(self) ;
01138 return self->epsilon ;
01139 }
01140
01148 void vl_svm_set_bias_learning_rate (VlSvm *self, double rate)
01149 {
01150 assert(self) ;
01151 assert(rate > 0) ;
01152 self->biasLearningRate = rate ;
01153 }
01154
01160 double vl_svm_get_bias_learning_rate (VlSvm const *self)
01161 {
01162 assert(self) ;
01163 return self->biasLearningRate ;
01164 }
01165
01174 void vl_svm_set_bias_multiplier (VlSvm * self, double b)
01175 {
01176 assert(self) ;
01177 assert(b >= 0) ;
01178 self->biasMultiplier = b ;
01179 }
01180
01186 double vl_svm_get_bias_multiplier (VlSvm const * self)
01187 {
01188 assert(self) ;
01189 return self->biasMultiplier ;
01190 }
01191
01201 void vl_svm_set_iteration_number (VlSvm *self, vl_uindex n)
01202 {
01203 assert(self) ;
01204 self->iteration = n ;
01205 }
01206
01212 vl_size vl_svm_get_iteration_number (VlSvm const *self)
01213 {
01214 assert(self) ;
01215 return self->iteration ;
01216 }
01217
01223 void vl_svm_set_max_num_iterations (VlSvm *self, vl_size n)
01224 {
01225 assert(self) ;
01226 self->maxNumIterations = n ;
01227 }
01228
01234 vl_size vl_svm_get_max_num_iterations (VlSvm const *self)
01235 {
01236 assert(self) ;
01237 return self->maxNumIterations ;
01238 }
01239
01248 void vl_svm_set_diagnostic_frequency (VlSvm *self, vl_size f)
01249 {
01250 assert(self) ;
01251 assert(f > 0) ;
01252 self->diagnosticFrequency = f ;
01253 }
01254
01260 vl_size vl_svm_get_diagnostic_frequency (VlSvm const *self)
01261 {
01262 assert(self) ;
01263 return self->diagnosticFrequency ;
01264 }
01265
01271 VlSvmSolverType vl_svm_get_solver (VlSvm const * self)
01272 {
01273 assert(self) ;
01274 return self->solver ;
01275 }
01276
01288 void vl_svm_set_lambda (VlSvm * self, double lambda)
01289 {
01290 assert(self) ;
01291 assert(lambda >= 0) ;
01292 self->lambda = lambda ;
01293 }
01294
01300 double vl_svm_get_lambda (VlSvm const * self)
01301 {
01302 assert(self) ;
01303 return self->lambda ;
01304 }
01305
01320 void vl_svm_set_weights (VlSvm * self, double const *weights)
01321 {
01322 assert(self) ;
01323 self->weights = weights ;
01324 }
01325
01331 double const *vl_svm_get_weights (VlSvm const * self)
01332 {
01333 assert(self) ;
01334 return self->weights ;
01335 }
01336
01337
01338
01339
01340
01348 vl_size vl_svm_get_dimension (VlSvm *self)
01349 {
01350 assert(self) ;
01351 return self->dimension ;
01352 }
01353
01361 vl_size vl_svm_get_num_data (VlSvm *self)
01362 {
01363 assert(self) ;
01364 return self->numData ;
01365 }
01366
01374 double const * vl_svm_get_model (VlSvm const *self)
01375 {
01376 assert(self) ;
01377 return self->model ;
01378 }
01379
01389 void vl_svm_set_model (VlSvm *self, double const *model)
01390 {
01391 assert(self) ;
01392 assert(model) ;
01393 memcpy(self->model, model, sizeof(double) * vl_svm_get_dimension(self)) ;
01394 }
01395
01406 void vl_svm_set_bias (VlSvm *self, double b)
01407 {
01408 assert(self);
01409 if (self->biasMultiplier) {
01410 self->bias = b / self->biasMultiplier ;
01411 }
01412 }
01413
01422 double vl_svm_get_bias (VlSvm const *self)
01423 {
01424 assert(self) ;
01425 return self->bias * self->biasMultiplier ;
01426 }
01427
01433 VlSvmStatistics const * vl_svm_get_statistics (VlSvm const *self)
01434 {
01435 assert(self) ;
01436 return &self->statistics ;
01437 }
01438
01448 double const * vl_svm_get_scores (VlSvm const *self)
01449 {
01450 return self->scores ;
01451 }
01452
01453
01454
01455
01456
01478 void
01479 vl_svm_set_diagnostic_function (VlSvm *self, VlSvmDiagnosticFunction f, void *data) {
01480 self->diagnosticFn = f ;
01481 self->diagnosticFnData = data ;
01482 }
01483
01492 void vl_svm_set_data_functions (VlSvm *self, VlSvmInnerProductFunction inner, VlSvmAccumulateFunction acc)
01493 {
01494 assert(self) ;
01495 assert(inner) ;
01496 assert(acc) ;
01497 self->innerProductFn = inner ;
01498 self->accumulateFn = acc ;
01499 }
01500
01509 void vl_svm_set_loss_function (VlSvm *self, VlSvmLossFunction f)
01510 {
01511 assert(self) ;
01512 self->lossFn = f ;
01513 }
01514
01519 void vl_svm_set_loss_derivative_function (VlSvm *self, VlSvmLossFunction f)
01520 {
01521 assert(self) ;
01522 self->lossDerivativeFn = f ;
01523 }
01524
01529 void vl_svm_set_conjugate_loss_function (VlSvm *self, VlSvmLossFunction f)
01530 {
01531 assert(self) ;
01532 self->conjugateLossFn = f ;
01533 }
01534
01539 void vl_svm_set_dca_update_function (VlSvm *self, VlSvmDcaUpdateFunction f)
01540 {
01541 assert(self) ;
01542 self->dcaUpdateFn = f ;
01543 }
01544
01551 void
01552 vl_svm_set_loss (VlSvm *self, VlSvmLossType loss)
01553 {
01554 #define SETLOSS(x,y) \
01555 case VlSvmLoss ## x: \
01556 vl_svm_set_loss_function(self, vl_svm_ ## y ## _loss) ; \
01557 vl_svm_set_loss_derivative_function(self, vl_svm_ ## y ## _loss_derivative) ; \
01558 vl_svm_set_conjugate_loss_function(self, vl_svm_ ## y ## _conjugate_loss) ; \
01559 vl_svm_set_dca_update_function(self, vl_svm_ ## y ## _dca_update) ; \
01560 break;
01561
01562 switch (loss) {
01563 SETLOSS(Hinge, hinge) ;
01564 SETLOSS(Hinge2, hinge2) ;
01565 SETLOSS(L1, l1) ;
01566 SETLOSS(L2, l2) ;
01567 SETLOSS(Logistic, logistic) ;
01568 default:
01569 assert(0) ;
01570 }
01571 }
01572
01573
01574
01575
01576
01602 double
01603 vl_svm_hinge_loss (double inner, double label)
01604 {
01605 return VL_MAX(1 - label * inner, 0.0);
01606 }
01607
01610 double
01611 vl_svm_hinge_loss_derivative (double inner, double label)
01612 {
01613 if (label * inner < 1.0) {
01614 return - label ;
01615 } else {
01616 return 0.0 ;
01617 }
01618 }
01619
01625 double
01626 vl_svm_hinge_conjugate_loss (double u, double label) {
01627 double z = label * u ;
01628 if (-1 <= z && z <= 0) {
01629 return label * u ;
01630 } else {
01631 return VL_INFINITY_D ;
01632 }
01633 }
01634
01637 double
01638 vl_svm_hinge_dca_update (double alpha, double inner, double norm2, double label) {
01639 double palpha = (label - inner) / norm2 + alpha ;
01640 return label * VL_MAX(0, VL_MIN(1, label * palpha)) - alpha ;
01641 }
01642
01645 double
01646 vl_svm_hinge2_loss (double inner,double label)
01647 {
01648 double z = VL_MAX(1 - label * inner, 0.0) ;
01649 return z*z ;
01650 }
01651
01654 double
01655 vl_svm_hinge2_loss_derivative (double inner, double label)
01656 {
01657 if (label * inner < 1.0) {
01658 return 2 * (inner - label) ;
01659 } else {
01660 return 0 ;
01661 }
01662 }
01663
01666 double
01667 vl_svm_hinge2_conjugate_loss (double u, double label) {
01668 if (label * u <= 0) {
01669 return (label + u/4) * u ;
01670 } else {
01671 return VL_INFINITY_D ;
01672 }
01673 }
01674
01677 double
01678 vl_svm_hinge2_dca_update (double alpha, double inner, double norm2, double label) {
01679 double palpha = (label - inner - 0.5*alpha) / (norm2 + 0.5) + alpha ;
01680 return label * VL_MAX(0, label * palpha) - alpha ;
01681 }
01682
01685 double
01686 vl_svm_l1_loss (double inner,double label)
01687 {
01688 return vl_abs_d(label - inner) ;
01689 }
01690
01693 double
01694 vl_svm_l1_loss_derivative (double inner, double label)
01695 {
01696 if (label > inner) {
01697 return - 1.0 ;
01698 } else {
01699 return + 1.0 ;
01700 }
01701 }
01702
01705 double
01706 vl_svm_l1_conjugate_loss (double u, double label) {
01707 if (vl_abs_d(u) <= 1) {
01708 return label*u ;
01709 } else {
01710 return VL_INFINITY_D ;
01711 }
01712 }
01713
01716 double
01717 vl_svm_l1_dca_update (double alpha, double inner, double norm2, double label) {
01718 if (vl_abs_d(alpha) <= 1) {
01719 double palpha = (label - inner) / norm2 + alpha ;
01720 return VL_MAX(-1.0, VL_MIN(1.0, palpha)) - alpha ;
01721 } else {
01722 return VL_INFINITY_D ;
01723 }
01724 }
01725
01728 double
01729 vl_svm_l2_loss (double inner,double label)
01730 {
01731 double z = label - inner ;
01732 return z*z ;
01733 }
01734
01737 double
01738 vl_svm_l2_loss_derivative (double inner, double label)
01739 {
01740 return - 2 * (label - inner) ;
01741 }
01742
01745 double
01746 vl_svm_l2_conjugate_loss (double u, double label) {
01747 return (label + u/4) * u ;
01748 }
01749
01752 double
01753 vl_svm_l2_dca_update (double alpha, double inner, double norm2, double label) {
01754 return (label - inner - 0.5*alpha) / (norm2 + 0.5) ;
01755 }
01756
01759 double
01760 vl_svm_logistic_loss (double inner,double label)
01761 {
01762 double z = label * inner ;
01763 if (z >= 0) {
01764 return log(1.0 + exp(-z)) ;
01765 } else {
01766 return -z + log(exp(z) + 1.0) ;
01767 }
01768 }
01769
01772 double
01773 vl_svm_logistic_loss_derivative (double inner, double label)
01774 {
01775 double z = label * inner ;
01776 double t = 1 / (1 + exp(-z)) ;
01777 return label * (t - 1) ;
01778 }
01779
01780 VL_INLINE double xlogx(double x)
01781 {
01782 if (x <= 1e-10) return 0 ;
01783 return x*log(x) ;
01784 }
01785
01788 double
01789 vl_svm_logistic_conjugate_loss (double u, double label) {
01790 double z = label * u ;
01791 if (-1 <= z && z <= 0) {
01792 return xlogx(-z) + xlogx(1+z) ;
01793 } else {
01794 return VL_INFINITY_D ;
01795 }
01796 }
01797
01800 double
01801 vl_svm_logistic_dca_update (double alpha, double inner, double norm2, double label) {
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831 double df, ddf, der, dder ;
01832 vl_index t ;
01833
01834
01835 double beta1 = 0 ;
01836 double beta2 = 1 ;
01837 double beta = 0.5 ;
01838
01839 for (t = 0 ; t < 5 ; ++t) {
01840 df = log(beta) - log(1-beta) ;
01841 der = norm2 * beta + label * (inner - norm2*alpha) + df ;
01842 if (der >= 0) {
01843 beta2 = beta ;
01844 } else {
01845 beta1 = beta ;
01846 }
01847 beta = 0.5 * (beta1 + beta2) ;
01848 }
01849
01850 #if 1
01851
01852 for (t = 0 ; (t < 2) & (beta > VL_EPSILON_D) & (beta < 1-VL_EPSILON_D) ; ++t) {
01853 df = log(beta) - log(1-beta) ;
01854 ddf = 1 / (beta * (1-beta)) ;
01855 der = norm2 * beta + label * (inner - norm2*alpha) + df ;
01856 dder = norm2 + ddf ;
01857 beta -= der / dder ;
01858 beta = VL_MAX(0, VL_MIN(1, beta)) ;
01859 }
01860 #endif
01861
01862 return label * beta - alpha ;
01863 }
01864
01865
01866
01871 void _vl_svm_update_statistics (VlSvm *self)
01872 {
01873 vl_size i, k ;
01874 double inner, p ;
01875
01876 memset(&self->statistics, 0, sizeof(VlSvmStatistics)) ;
01877
01878 self->statistics.regularizer = self->bias * self->bias ;
01879 for (i = 0; i < self->dimension; i++) {
01880 self->statistics.regularizer += self->model[i] * self->model[i] ;
01881 }
01882 self->statistics.regularizer *= self->lambda * 0.5 ;
01883
01884 for (k = 0; k < self->numData ; k++) {
01885 p = (self->weights) ? self->weights[k] : 1.0 ;
01886 if (p <= 0) continue ;
01887 inner = self->innerProductFn(self->data, k, self->model) ;
01888 inner += self->bias * self->biasMultiplier ;
01889 self->scores[k] = inner ;
01890 self->statistics.loss += p * self->lossFn(inner, self->labels[k]) ;
01891 if (self->solver == VlSvmSolverSdca) {
01892
01893 self->statistics.dualLoss -= p * self->conjugateLossFn(- self->alpha[k] / p, self->labels[k]) ;
01894 }
01895 }
01896
01897 self->statistics.loss /= self->numData ;
01898 self->statistics.objective = self->statistics.regularizer + self->statistics.loss ;
01899
01900 if (self->solver == VlSvmSolverSdca) {
01901 self->statistics.dualLoss /= self->numData ;
01902 self->statistics.dualObjective = - self->statistics.regularizer + self->statistics.dualLoss ;
01903 self->statistics.dualityGap = self->statistics.objective - self->statistics.dualObjective ;
01904 }
01905 }
01906
01907
01908
01909
01910
01911 void _vl_svm_evaluate (VlSvm *self)
01912 {
01913 double startTime = vl_get_cpu_time () ;
01914
01915 _vl_svm_update_statistics (self) ;
01916
01917 self->statistics.elapsedTime = vl_get_cpu_time() - startTime ;
01918 self->statistics.iteration = 0 ;
01919 self->statistics.epoch = 0 ;
01920 self->statistics.status = VlSvmStatusConverged ;
01921
01922 if (self->diagnosticFn) {
01923 self->diagnosticFn(self, self->diagnosticFnData) ;
01924 }
01925 }
01926
01927
01928
01929
01930
01931 void _vl_svm_sdca_train (VlSvm *self)
01932 {
01933 double * norm2 ;
01934 vl_index * permutation ;
01935 vl_uindex i, t ;
01936 double inner, delta, multiplier, p ;
01937
01938 double startTime = vl_get_cpu_time () ;
01939 VlRand * rand = vl_get_rand() ;
01940
01941 norm2 = (double*) vl_calloc(self->numData, sizeof(double));
01942 permutation = vl_calloc(self->numData, sizeof(vl_index)) ;
01943
01944 {
01945 double * buffer = vl_calloc(self->dimension, sizeof(double)) ;
01946 for (i = 0 ; i < (unsigned)self->numData; i++) {
01947 double n2 ;
01948 permutation [i] = i ;
01949 memset(buffer, 0, self->dimension * sizeof(double)) ;
01950 self->accumulateFn (self->data, i, buffer, 1) ;
01951 n2 = self->innerProductFn (self->data, i, buffer) ;
01952 n2 += self->biasMultiplier * self->biasMultiplier ;
01953 norm2[i] = n2 / (self->lambda * self->numData) ;
01954 }
01955 vl_free(buffer) ;
01956 }
01957
01958 for (t = 0 ; 1 ; ++t) {
01959
01960 if (t % self->numData == 0) {
01961
01962
01963 vl_rand_permute_indexes(rand, permutation, self->numData) ;
01964 }
01965
01966
01967 i = permutation[t % self->numData] ;
01968 p = (self->weights) ? self->weights[i] : 1.0 ;
01969 if (p > 0) {
01970 inner = self->innerProductFn(self->data, i, self->model) ;
01971 inner += self->bias * self->biasMultiplier ;
01972 delta = p * self->dcaUpdateFn(self->alpha[i] / p, inner, p * norm2[i], self->labels[i]) ;
01973 } else {
01974 delta = 0 ;
01975 }
01976
01977
01978 if (delta != 0) {
01979 self->alpha[i] += delta ;
01980 multiplier = delta / (self->numData * self->lambda) ;
01981 self->accumulateFn(self->data,i,self->model,multiplier) ;
01982 self->bias += self->biasMultiplier * multiplier;
01983 }
01984
01985
01986 if ((t + 1) % self->diagnosticFrequency == 0 || t + 1 == self->maxNumIterations) {
01987 _vl_svm_update_statistics (self) ;
01988 self->statistics.elapsedTime = vl_get_cpu_time() - startTime ;
01989 self->statistics.iteration = t ;
01990 self->statistics.epoch = t / self->numData ;
01991
01992 self->statistics.status = VlSvmStatusTraining ;
01993 if (self->statistics.dualityGap < self->epsilon) {
01994 self->statistics.status = VlSvmStatusConverged ;
01995 }
01996 else if (t + 1 == self->maxNumIterations) {
01997 self->statistics.status = VlSvmStatusMaxNumIterationsReached ;
01998 }
01999
02000 if (self->diagnosticFn) {
02001 self->diagnosticFn(self, self->diagnosticFnData) ;
02002 }
02003
02004 if (self->statistics.status != VlSvmStatusTraining) {
02005 break ;
02006 }
02007 }
02008 }
02009
02010 vl_free (norm2) ;
02011 vl_free (permutation) ;
02012 }
02013
02014
02015
02016
02017
02018 void _vl_svm_sgd_train (VlSvm *self)
02019 {
02020 vl_index * permutation ;
02021 double * scores ;
02022 double * previousScores ;
02023 vl_uindex i, t, k ;
02024 double inner, gradient, rate, biasRate, p ;
02025 double factor = 1.0 ;
02026 double biasFactor = 1.0 ;
02027 vl_index t0 = VL_MAX(2, vl_ceil_d(1.0 / self->lambda)) ;
02028
02029
02030 double startTime = vl_get_cpu_time () ;
02031 VlRand * rand = vl_get_rand() ;
02032
02033 permutation = vl_calloc(self->numData, sizeof(vl_index)) ;
02034 scores = vl_calloc(self->numData * 2, sizeof(double)) ;
02035 previousScores = scores + self->numData ;
02036
02037 for (i = 0 ; i < (unsigned)self->numData; i++) {
02038 permutation [i] = i ;
02039 previousScores [i] = - VL_INFINITY_D ;
02040 }
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064 for (t = 0 ; 1 ; ++t) {
02065
02066 if (t % self->numData == 0) {
02067
02068
02069 vl_rand_permute_indexes(rand, permutation, self->numData) ;
02070 }
02071
02072
02073 i = permutation[t % self->numData] ;
02074 p = (self->weights) ? self->weights[i] : 1.0 ;
02075 p = VL_MAX(0.0, p) ;
02076 inner = factor * self->innerProductFn(self->data, i, self->model) ;
02077 inner += biasFactor * (self->biasMultiplier * self->bias) ;
02078 gradient = p * self->lossDerivativeFn(inner, self->labels[i]) ;
02079 previousScores[i] = scores[i] ;
02080 scores[i] = inner ;
02081
02082
02083 rate = 1.0 / (self->lambda * (t + t0)) ;
02084 biasRate = rate * self->biasLearningRate ;
02085 factor *= (1.0 - self->lambda * rate) ;
02086 biasFactor *= (1.0 - self->lambda * biasRate) ;
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096 if (gradient != 0) {
02097 self->accumulateFn(self->data, i, self->model, - gradient * rate / factor) ;
02098 self->bias += self->biasMultiplier * (- gradient * biasRate / biasFactor) ;
02099 }
02100
02101
02102 if ((t + 1) % self->diagnosticFrequency == 0 || t + 1 == self->maxNumIterations) {
02103
02104
02105 for (k = 0 ; k < self->dimension ; ++k) self->model[k] *= factor ;
02106 self->bias *= biasFactor;
02107 factor = 1.0 ;
02108 biasFactor = 1.0 ;
02109
02110 _vl_svm_update_statistics (self) ;
02111
02112 for (k = 0 ; k < self->numData ; ++k) {
02113 double delta = scores[k] - previousScores[k] ;
02114 self->statistics.scoresVariation += delta * delta ;
02115 }
02116 self->statistics.scoresVariation = sqrt(self->statistics.scoresVariation) / self->numData ;
02117
02118 self->statistics.elapsedTime = vl_get_cpu_time() - startTime ;
02119 self->statistics.iteration = t ;
02120 self->statistics.epoch = t / self->numData ;
02121
02122 self->statistics.status = VlSvmStatusTraining ;
02123 if (self->statistics.scoresVariation < self->epsilon) {
02124 self->statistics.status = VlSvmStatusConverged ;
02125 }
02126 else if (t + 1 == self->maxNumIterations) {
02127 self->statistics.status = VlSvmStatusMaxNumIterationsReached ;
02128 }
02129
02130 if (self->diagnosticFn) {
02131 self->diagnosticFn(self, self->diagnosticFnData) ;
02132 }
02133
02134 if (self->statistics.status != VlSvmStatusTraining) {
02135 break ;
02136 }
02137 }
02138 }
02139
02140 vl_free (scores) ;
02141 vl_free (permutation) ;
02142 }
02143
02144
02145
02146
02147
02156 void vl_svm_train (VlSvm * self)
02157 {
02158 assert (self) ;
02159 switch (self->solver) {
02160 case VlSvmSolverSdca:
02161 _vl_svm_sdca_train(self) ;
02162 break ;
02163 case VlSvmSolverSgd:
02164 _vl_svm_sgd_train(self) ;
02165 break ;
02166 case VlSvmSolverNone:
02167 _vl_svm_evaluate(self) ;
02168 break ;
02169 default:
02170 assert(0) ;
02171 }
02172 }