void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_DATA, IN_LABELS, IN_LAMBDA, IN_END} ; enum {OUT_MODEL = 0} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; double biasMultiplier = 0 ; double lambda ; void * data ; void * preconditioner = NULL ; vl_size preconditionerDimension = 0 ; mxClassID dataClass ; vl_type dataType ; vl_size numSamples ; vl_size dimension ; vl_size numIterations = 0 ; vl_uindex startingIteration = 1 ; vl_uint32 * permutation = NULL ; vl_size permutationSize = 0 ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 3) { vlmxError(vlmxErrInvalidArgument, "At least three arguments are required.") ; } else if (nout > 2) { vlmxError(vlmxErrInvalidArgument, "Too many output arguments."); } dataClass = mxGetClassID(IN(DATA)) ; if (! vlmxIsMatrix (IN(DATA), -1, -1) || ! vlmxIsReal (IN(DATA))) { vlmxError(vlmxErrInvalidArgument, "DATA must be a real matrix.") ; } data = mxGetData (IN(DATA)) ; dimension = mxGetM(IN(DATA)) ; numSamples = mxGetN(IN(DATA)) ; switch (dataClass) { case mxSINGLE_CLASS : dataType = VL_TYPE_FLOAT ; break ; case mxDOUBLE_CLASS : dataType = VL_TYPE_DOUBLE ; break ; default: vlmxError(vlmxErrInvalidArgument, "DATA must be either SINGLE or DOUBLE.") ; } if (mxGetClassID(IN(LABELS)) != mxINT8_CLASS) { vlmxError(vlmxErrInvalidArgument, "LABELS must be INT8.") ; } if (! vlmxIsVector(IN(LABELS), numSamples)) { vlmxError(vlmxErrInvalidArgument, "LABELS is not a vector of dimension compatible with DATA.") ; } if (! vlmxIsPlainScalar(IN(LAMBDA))) { vlmxError(vlmxErrInvalidArgument, "LAMBDA is not a plain scalar.") ; } lambda = *mxGetPr(IN(LAMBDA)) ; while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_bias_multiplier : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "BIASMULTIPLIER is not a plain scalar.") ; } biasMultiplier = *mxGetPr(optarg) ; break ; case opt_num_iterations : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "NUMITERATIONS is not a plain scalar.") ; } if (*mxGetPr(optarg) < 0) { vlmxError(vlmxErrInvalidArgument, "NUMITERATIONS is negative.") ; } numIterations = (vl_size) *mxGetPr(optarg) ; break ; case opt_starting_iteration : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "STARTINGITERATION is not a plain scalar.") ; } if (*mxGetPr(optarg) < 1) { vlmxError(vlmxErrInvalidArgument, "STARTINGITERATION is smaller than 1.") ; } startingIteration = (vl_size) *mxGetPr(optarg) ; break ; case opt_starting_model : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || !mxIsNumeric(optarg)) { vlmxError(vlmxErrInvalidArgument, "STARTINGMODEL is not a real vector.") ; } OUT(MODEL) = mxDuplicateArray(optarg) ; break ; case opt_permutation : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || mxGetClassID(optarg) != mxUINT32_CLASS) { vlmxError(vlmxErrInvalidArgument, "PERMUTATION is not a UINT32 vector.") ; } permutationSize = mxGetNumberOfElements(optarg) ; permutation = mxMalloc(sizeof(vl_uint32) * permutationSize) ; { /* adjust indexing */ vl_uint32 const * matlabPermutation = mxGetData(optarg) ; vl_uindex k ; for (k = 0 ; k < permutationSize ; ++k) { permutation[k] = matlabPermutation[k] - 1 ; if (permutation[k] >= numSamples) { vlmxError(vlmxErrInconsistentData, "Permutation indexes out of bounds: PERMUTATION(%d) = %d > %d = number of data samples.", k + 1, permutation[k] + 1, numSamples) ; } } } break ; case opt_preconditioner : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || !mxIsNumeric(optarg)) { vlmxError(vlmxErrInvalidArgument, "PRECONDITIONER is not a real vector.") ; } if (mxGetClassID(optarg) != dataClass) { vlmxError(vlmxErrInvalidArgument, "PRECODNITIONER storage class does not match the data.") ; } preconditioner = mxGetData(optarg) ; preconditionerDimension = mxGetNumberOfElements(optarg) ; break ; case opt_verbose : ++ verbose ; break ; } } if (preconditioner && preconditionerDimension != (dimension + (biasMultiplier > 0))) { vlmxError(vlmxErrInvalidArgument, "PRECONDITIONER has incompatible dimension.") ; } if (numIterations == 0) { numIterations = (vl_size) 10 / (lambda + 1) ; } if (! OUT(MODEL)) { OUT(MODEL) = mxCreateNumericMatrix(dimension + (biasMultiplier > 0), 1, dataClass, mxREAL) ; } else { if (mxGetClassID(OUT(MODEL)) != dataClass) { vlmxError(vlmxErrInvalidArgument, "STARTINGMODEL is not of the same class of DATA.") ; } if (mxGetNumberOfElements(OUT(MODEL)) != dimension + (biasMultiplier > 0)) { vlmxError(vlmxErrInvalidArgument, "STARTINGMODEL has incompatible dimension.") ; } } if (verbose) { mexPrintf("vl_pegasos: Lambda = %g\n", lambda) ; mexPrintf("vl_pegasos: BiasMultiplier = %g\n", biasMultiplier) ; mexPrintf("vl_pegasos: NumIterations = %d\n", numIterations) ; mexPrintf("vl_pegasos: permutation size = %d\n", permutationSize) ; mexPrintf("vl_pegasos: using preconditioner = %s\n", VL_YESNO(preconditioner)) ; } switch (dataType) { case VL_TYPE_FLOAT : vl_pegasos_train_binary_svm_f((float *)mxGetData(OUT(MODEL)), (float const *)mxGetPr(IN(DATA)), dimension, numSamples, (vl_int8 const *)mxGetData(IN(LABELS)), lambda, biasMultiplier, startingIteration, numIterations, NULL, permutation, permutationSize, (float const*)preconditioner) ; break ; case VL_TYPE_DOUBLE: vl_pegasos_train_binary_svm_d((double *)mxGetData(OUT(MODEL)), (double const *)mxGetData(IN(DATA)), dimension, numSamples, (vl_int8 const *)mxGetData(IN(LABELS)), lambda, biasMultiplier, startingIteration, numIterations, NULL, permutation, permutationSize, (double const *)preconditioner) ; break ; } if (permutation) vl_free(permutation) ; }
/* driver */ void mexFunction (int nout VL_UNUSED, mxArray * out[], int nin, const mxArray * in[]) { enum {IN_DATA = 0, IN_MEANS, IN_COVARIANCES, IN_PRIORS, IN_END} ; enum {OUT_ENC} ; int opt ; int next = IN_END ; mxArray const *optarg ; vl_size numClusters = 10; vl_size dimension ; vl_size numData ; int flags = 0 ; void * covariances = NULL; void * means = NULL; void * priors = NULL; void * data = NULL ; int verbosity = 0 ; vl_type dataType ; mxClassID classID ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 4) { vlmxError (vlmxErrInvalidArgument, "At least four arguments required."); } if (nout > 1) { vlmxError (vlmxErrInvalidArgument, "At most one output argument."); } classID = mxGetClassID (IN(DATA)) ; switch (classID) { case mxSINGLE_CLASS: dataType = VL_TYPE_FLOAT ; break ; case mxDOUBLE_CLASS: dataType = VL_TYPE_DOUBLE ; break ; default: vlmxError (vlmxErrInvalidArgument, "DATA is neither of class SINGLE or DOUBLE.") ; } if (mxGetClassID (IN(MEANS)) != classID) { vlmxError(vlmxErrInvalidArgument, "MEANS is not of the same class as DATA.") ; } if (mxGetClassID (IN(COVARIANCES)) != classID) { vlmxError(vlmxErrInvalidArgument, "COVARIANCES is not of the same class as DATA.") ; } if (mxGetClassID (IN(PRIORS)) != classID) { vlmxError(vlmxErrInvalidArgument, "PRIORS is not of the same class as DATA.") ; } dimension = mxGetM (IN(DATA)) ; numData = mxGetN (IN(DATA)) ; numClusters = mxGetN (IN(MEANS)) ; if (dimension == 0) { vlmxError (vlmxErrInvalidArgument, "SIZE(DATA,1) is zero.") ; } if (!vlmxIsMatrix(IN(MEANS), dimension, numClusters)) { vlmxError (vlmxErrInvalidArgument, "MEANS is not a matrix or does not have the right size.") ; } if (!vlmxIsMatrix(IN(COVARIANCES), dimension, numClusters)) { vlmxError (vlmxErrInvalidArgument, "COVARIANCES is not a matrix or does not have the right size.") ; } if (!vlmxIsVector(IN(PRIORS), numClusters)) { vlmxError (vlmxErrInvalidArgument, "PRIORS is not a vector or does not have the right size.") ; } if (!vlmxIsMatrix(IN(DATA), dimension, numData)) { vlmxError (vlmxErrInvalidArgument, "DATA is not a matrix or does not have the right size.") ; } while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbosity ; break ; case opt_normalized: flags |= VL_FISHER_FLAG_NORMALIZED ; break ; case opt_square_root: flags |= VL_FISHER_FLAG_SQUARE_ROOT ; break ; case opt_improved: flags |= VL_FISHER_FLAG_IMPROVED ; break ; case opt_fast: flags |= VL_FISHER_FLAG_FAST ; break ; default : abort() ; } } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ data = mxGetPr(IN(DATA)) ; means = mxGetPr(IN(MEANS)) ; covariances = mxGetPr(IN(COVARIANCES)) ; priors = mxGetPr(IN(PRIORS)) ; if (verbosity) { mexPrintf("vl_fisher: num data: %d\n", numData) ; mexPrintf("vl_fisher: num clusters: %d\n", numClusters) ; mexPrintf("vl_fisher: data dimension: %d\n", dimension) ; mexPrintf("vl_fisher: code dimension: %d\n", numClusters * dimension) ; mexPrintf("vl_fisher: normalized: %s\n", VL_YESNO(flags & VL_FISHER_FLAG_NORMALIZED)) ; mexPrintf("vl_fisher: square root: %s\n", VL_YESNO(flags & VL_FISHER_FLAG_SQUARE_ROOT)) ; mexPrintf("vl_fisher: normalized: %s\n", VL_YESNO(flags & VL_FISHER_FLAG_NORMALIZED)) ; mexPrintf("vl_fisher: fast: %s\n", VL_YESNO(flags & VL_FISHER_FLAG_FAST)) ; } /* -------------------------------------------------------------- */ /* Encoding */ /* -------------------------------------------------------------- */ OUT(ENC) = mxCreateNumericMatrix (dimension * numClusters * 2, 1, classID, mxREAL) ; vl_fisher_encode (mxGetData(OUT(ENC)), dataType, means, dimension, numClusters, covariances, priors, data, numData, flags) ; }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_DATA, IN_LABELS, IN_LAMBDA, IN_END} ; enum {OUT_MODEL = 0, OUT_BIAS, OUT_INFO} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; mxArray *inputModel = NULL; VlSvmPegasos* svm = NULL ; vl_bool freeModel = VL_TRUE ; vl_size dataDimension ; vl_uint32* matlabPermutation ; void * data ; mxClassID dataClass ; vl_type dataType ; vl_size numSamples ; vl_uint32 * permutation = NULL ; vl_size permutationSize = 0 ; DiagnosticsDispatcher* disp ; VlSvmDatasetInnerProduct innerProduct = NULL ; VlSvmDatasetAccumulator accumulator = NULL ; /* maps */ VlSvmDatasetFeatureMap mapFunc = NULL ; /* Homkermap */ VlHomogeneousKernelType kernelType = VlHomogeneousKernelChi2 ; VlHomogeneousKernelMapWindowType windowType = VlHomogeneousKernelMapWindowRectangular ; double gamma = 1.0 ; int n = 0 ; double period = -1 ; VlSvmDataset* dataset ; vl_bool homkermap = VL_FALSE ; void * map = NULL ; VL_USE_MATLAB_ENV ; disp = (DiagnosticsDispatcher*) vl_malloc(sizeof(DiagnosticsDispatcher)) ; disp->diagnosticsHandle = NULL ; disp->callerRef = NULL ; disp->verbose = 0 ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 3) { vlmxError(vlmxErrInvalidArgument, "At least three arguments are required.") ; } else if (nout > 3) { vlmxError(vlmxErrInvalidArgument, "Too many output arguments."); } dataClass = mxGetClassID(IN(DATA)) ; if (! vlmxIsMatrix (IN(DATA), -1, -1) || ! vlmxIsReal (IN(DATA))) { vlmxError(vlmxErrInvalidArgument, "DATA must be a real matrix.") ; } data = mxGetData (IN(DATA)) ; dataDimension = mxGetM(IN(DATA)) ; numSamples = mxGetN(IN(DATA)) ; /* Get order of the HOMKERMAP, if used. */ while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { if (opt == opt_homkermap) { homkermap = VL_TRUE ; if (! vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "N is not a scalar.") ; } n = *mxGetPr(optarg) ; if (n < 0) { vlmxError(vlmxErrInvalidArgument, "N is negative.") ; } } } next = IN_END ; if (! vlmxIsVector(IN(LABELS), numSamples)) { vlmxError(vlmxErrInvalidArgument, "LABELS is not a vector of dimension compatible with DATA.") ; } switch (dataClass) { case mxSINGLE_CLASS : dataType = VL_TYPE_FLOAT ; break ; case mxDOUBLE_CLASS : dataType = VL_TYPE_DOUBLE ; break ; default: vlmxError(vlmxErrInvalidArgument, "DATA must be either SINGLE or DOUBLE.") ; } if (mxGetClassID(IN(LABELS)) != mxINT8_CLASS) { vlmxError(vlmxErrInvalidArgument, "LABELS must be INT8.") ; } if (! vlmxIsPlainScalar(IN(LAMBDA))) { vlmxError(vlmxErrInvalidArgument, "LAMBDA is not a plain scalar.") ; } svm = vl_svmpegasos_new ((2*n + 1)*dataDimension,*mxGetPr(IN(LAMBDA))) ; while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_bias_multiplier : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "BIASMULTIPLIER is not a plain scalar.") ; } vl_svmpegasos_set_bias_multiplier(svm, *mxGetPr(optarg)) ; break ; case opt_max_iterations : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "MAXITERATIONS is not a plain scalar.") ; } if (*mxGetPr(optarg) < 0) { vlmxError(vlmxErrInvalidArgument, "MAXITERATIONS is negative.") ; } vl_svmpegasos_set_maxiterations(svm, (vl_size) *mxGetPr(optarg)) ; break ; case opt_epsilon : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "EPSILON is not a plain scalar.") ; } if (*mxGetPr(optarg) < 0) { vlmxError(vlmxErrInvalidArgument, "EPSILON is negative.") ; } vl_svmpegasos_set_epsilon(svm, (double) *mxGetPr(optarg)) ; break ; case opt_starting_iteration : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "STARTINGITERATION is not a plain scalar.") ; } if (*mxGetPr(optarg) < 1) { vlmxError(vlmxErrInvalidArgument, "STARTINGITERATION is smaller than 1.") ; } vl_svmpegasos_set_iterations(svm, (vl_size) *mxGetPr(optarg) - 1) ; break ; case opt_starting_model : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || mxGetClassID(optarg) != mxDOUBLE_CLASS) { vlmxError(vlmxErrInvalidArgument, "STARTINGMODEL is not a real vector.") ; } inputModel = mxDuplicateArray(optarg) ; vl_svmpegasos_set_model(svm,(double*) mxGetData(inputModel)) ; freeModel = VL_FALSE ; break ; case opt_starting_bias : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "STARTINGBIAS is not a plain scalar.") ; } vl_svmpegasos_set_bias(svm, (double) *mxGetPr(optarg)) ; break ; case opt_permutation : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || mxGetClassID(optarg) != mxUINT32_CLASS) { vlmxError(vlmxErrInvalidArgument, "PERMUTATION is not a UINT32 vector.") ; } permutationSize = mxGetNumberOfElements(optarg) ; permutation = mxMalloc(sizeof(vl_uint32) * permutationSize) ; matlabPermutation = mxGetData(optarg) ; { /* adjust indexing */ vl_uindex k ; for (k = 0 ; k < permutationSize ; ++k) { permutation[k] = matlabPermutation[k] - 1 ; if (permutation[k] >= numSamples) { vlmxError(vlmxErrInconsistentData, "Permutation indexes out of bounds: PERMUTATION(%d) = %d > %d = number of data samples.", k + 1, permutation[k] + 1, numSamples) ; } } } vl_svmpegasos_set_permutation(svm,permutation,permutationSize) ; break ; case opt_bias_learningrate : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "BIASLEARNINGRATE is not a plain scalar.") ; } if (mxGetClassID(optarg) != mxDOUBLE_CLASS) { vlmxError(vlmxErrInvalidArgument, "BIASLEARNINGRATE must be double.") ; } vl_svmpegasos_set_bias_learningrate(svm, (double)*mxGetPr(optarg)) ; break ; case opt_diagnostic : if( !mxIsClass( optarg , "function_handle")) { mexErrMsgTxt("DIAGNOSTICSFUNCTION must be a function handle."); } disp->diagnosticsHandle = (mxArray*)(optarg) ; break ; case opt_diagnostic_caller_ref : disp->callerRef = (mxArray*)(optarg) ; break ; case opt_energy_freq : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "ENERGYFREQ is not a plain scalar.") ; } vl_svmpegasos_set_energy_frequency (svm, (vl_size)*mxGetPr(optarg)) ; break ; case opt_verbose : ++ verbose ; disp->verbose = 1 ; break ; case opt_KINTERS: case opt_KL1: kernelType = VlHomogeneousKernelIntersection ; break ; case opt_KCHI2: kernelType = VlHomogeneousKernelChi2 ; break ; case opt_KJS: kernelType = VlHomogeneousKernelJS ; break ; case opt_period: if (! vlmxIsPlainScalar(optarg)){ vlmxError(vlmxErrInvalidArgument, "PERIOD is not a scalar.") ; } period = *mxGetPr(optarg) ; if (period <= 0) { vlmxError(vlmxErrInvalidArgument, "PERIOD is not positive.") ; } break ; case opt_gamma: if (! vlmxIsPlainScalar(optarg)){ vlmxError(vlmxErrInvalidArgument, "GAMMA is not a scalar.") ; } gamma = *mxGetPr(optarg) ; if (gamma <= 0) { vlmxError(vlmxErrInvalidArgument, "GAMMA is not positive.") ; } break ; case opt_window: if (! vlmxIsString(optarg,-1)){ vlmxError(vlmxErrInvalidArgument, "WINDOW is not a string.") ; } else { char buffer [1024] ; mxGetString(optarg, buffer, sizeof(buffer) / sizeof(char)) ; if (vl_string_casei_cmp("uniform", buffer) == 0) { windowType = VlHomogeneousKernelMapWindowUniform ; } else if (vl_string_casei_cmp("rectangular", buffer) == 0) { windowType = VlHomogeneousKernelMapWindowRectangular ; } else { vlmxError(vlmxErrInvalidArgument, "WINDOW=%s is not recognized.", buffer) ; } } break ; } } if (verbose) { mexPrintf("vl_pegasos: Lambda = %g\n", svm->lambda) ; mexPrintf("vl_pegasos: BiasMultiplier = %g\n", svm->biasMultiplier) ; mexPrintf("vl_pegasos: MaxIterations = %d\n", svm->maxIterations) ; mexPrintf("vl_pegasos: permutation size = %d\n", permutationSize) ; } switch (dataType) { case VL_TYPE_FLOAT : innerProduct = (VlSvmDatasetInnerProduct)&vl_svmdataset_innerproduct_f ; accumulator = (VlSvmDatasetAccumulator)&vl_svmdataset_accumulator_f ; break ; case VL_TYPE_DOUBLE: innerProduct = (VlSvmDatasetInnerProduct)&vl_svmdataset_innerproduct_d ; accumulator = (VlSvmDatasetAccumulator)&vl_svmdataset_accumulator_d ; break ; } dataset = vl_svmdataset_new(data,dataDimension) ; if (homkermap) { map = vl_homogeneouskernelmap_new (kernelType, gamma, n, period, windowType) ; mapFunc = (VlSvmDatasetFeatureMap)&vl_homogeneouskernelmap_evaluate_d ; vl_svmdataset_set_map(dataset,map,mapFunc,2*n + 1) ; } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ if (disp->diagnosticsHandle) { vl_svmpegasos_set_diagnostic (svm, (VlSvmDiagnostics)&diagnosticDispatcher, disp) ; } vl_svmpegasos_train (svm,dataset, numSamples,innerProduct, accumulator, (vl_int8 const *)mxGetData(IN(LABELS))) ; /* ----------------------------------------------------------------- * Output * -------------------------------------------------------------- */ if (nout >= 1) { double * tempBuffer ; mwSize dims[2] ; dims[0] = svm->dimension ; dims[1] = 1 ; out[OUT_MODEL] = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxREAL) ; tempBuffer = (double*) mxGetData(out[OUT_MODEL]) ; memcpy(tempBuffer,svm->model,svm->dimension * sizeof(double)) ; } if (nout >= 2) { double * tempBuffer ; mwSize dims[2] ; dims[0] = 1 ; dims[1] = 1 ; out[OUT_BIAS] = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxREAL) ; tempBuffer = (double*) mxGetData(out[OUT_BIAS]) ; *tempBuffer = svm->bias ; } if (nout == 3) { out[OUT_INFO] = createInfoStruct(svm) ; } if (homkermap) { vl_homogeneouskernelmap_delete(map); } vl_svmdataset_delete(dataset) ; vl_svmpegasos_delete(svm,freeModel) ; vl_free(disp) ; }