Q: Some courses which have used libsvm as a tool
See the change log.
You can download earlier versions here.
Please cite the following paper:
Chih-Chung Chang and Chih-Jen Lin, LIBSVM : a library for support vector machines. ACM Transactions on Intelligent Systems and Technology, 2:27:1--27:27, 2011. Software available at http://www.csie.ntu.edu.tw/~cjlin/libsvm
The bibtex format is
@article{CC01a, author = {Chang, Chih-Chung and Lin, Chih-Jen}, title = {{LIBSVM}: A library for support vector machines}, journal = {ACM Transactions on Intelligent Systems and Technology}, volume = {2}, issue = {3}, year = {2011}, pages = {27:1--27:27}, note = {Software available at \url{http://www.csie.ntu.edu.tw/~cjlin/libsvm}} }
We have "the modified BSD license," so it is very easy to use libsvm in your software. Please check the COPYRIGHT file in detail. Basically you need to
Yes, see libsvm tools
This usually happens if you compile the code on one machine and run it on another which has incompatible libraries. Try to recompile the program on that machine or use static linking.
Build it as a project by choosing "Win32 Project." On the other hand, for "svm-train" and "svm-predict" you want to choose "Win32 Console Project." After libsvm 2.5, you can also use the file Makefile.win. See details in README.
If you are not using Makefile.win and see the following link error
LIBCMTD.lib(wwincrt0.obj) : error LNK2001: unresolved external symbol _wWinMain@16you may have selected a wrong project type.
You need to open a command window and type svmtrain.exe to see all options. Some examples are in README file.
"." means every 1,000 iterations (or every #data iterations is your #data is less than 1,000). "*" means that after iterations of using a smaller shrunk problem, we reset to use the whole set. See the implementation document for details.
Very likely the program consumes too much memory than what the operating system can provide. Try a smaller data and see if the program still crashes.
The easiest way is to use Makefile.win. See details in README. Alternatively, you can use Visual C++. Here is the example using Visual Studio 2013:
If you are using a version before 3.18, probably you see a warning message like
svm.cpp:2730: warning: ignoring return value of int fscanf(FILE*, const char*, ...), declared with attribute warn_unused_resultThis is not a problem; see this page for more details of ubuntu systems. To disable the warning message you can replace
CFLAGS = -Wall -Wconversion -O3 -fPICwith
CFLAGS = -Wall -Wconversion -O3 -fPIC -U_FORTIFY_SOURCEin Makefile.
After version 3.18, we have a better setting so that such warning messages do not appear.
For portability, we use only features defined in ISO C89. Note that features in ISO C99 may not be available everywhere. Even the newest gcc lacks some features in C99 (see http://gcc.gnu.org/c99status.html for details). If the situation changes in the future, we might consider using these newer features.
libsvm uses the so called "sparse" format where zero values do not need to be stored. Hence a data with attributes
1 0 2 0is represented as
1:1 3:2
Currently libsvm supports only numerical data. You may have to change non-numerical data to numerical. For example, you can use several binary attributes to represent a categorical attribute.
This is a controversial issue. The kernel evaluation (i.e. inner product) of sparse vectors is slower so the total training time can be at least twice or three times of that using the dense format. However, we cannot support only dense format as then we CANNOT handle extremely sparse cases. Simplicity of the code is another concern. Right now we decide to support the sparse format only.
We assume that you have '\n' in the end of each line. So please press enter in the end of your last line.
The svm-train program in libsvm conducts only a simple check of the input data. To do a detailed check, after libsvm 2.85, you can use the python script tools/checkdata.py. See tools/README for details.
We don't officially support this. But, currently LIBSVM is able to process data in the following format:
1 1:2 2:1 # your commentsNote that the character ":" should not appear in your comments.
It depends on your data format. A simple way is to use libsvmwrite in the libsvm matlab/octave interface. Take a CSV (comma-separated values) file in UCI machine learning repository as an example. We download SPECTF.train. Labels are in the first column. The following steps produce a file in the libsvm format.
matlab> SPECTF = csvread('SPECTF.train'); % read a csv file matlab> labels = SPECTF(:, 1); % labels from the 1st column matlab> features = SPECTF(:, 2:end); matlab> features_sparse = sparse(features); % features must be in a sparse matrix matlab> libsvmwrite('SPECTFlibsvm.train', labels, features_sparse);The tranformed data are stored in SPECTFlibsvm.train.
Alternatively, you can use convert.c to convert CSV format to libsvm format.
obj is the optimal objective value of the dual SVM problem. rho is the bias term in the decision function sgn(w^Tx - rho). nSV and nBSV are number of support vectors and bounded support vectors (i.e., alpha_i = C). nu-svm is a somewhat equivalent form of C-SVM where C is replaced by nu. nu simply shows the corresponding parameter. More details are in libsvm document.
In the model file, after parameters and other informations such as labels , each line represents a support vector.
Support vectors are listed in the order of "labels" shown earlier.
(i.e., those from the first class in the "labels" list are
grouped first, and so on.)
If k is the total number of classes,
in front of a support vector in class j, there are
k-1 coefficients
y*alpha where alpha are dual solution of the
following two class problems:
1 vs j, 2 vs j, ..., j-1 vs j, j vs j+1, j vs j+2, ..., j vs k
and y=1 in first j-1 coefficients, y=-1 in the remaining
k-j coefficients.
For example, if there are 4 classes, the file looks like:
+-+-+-+--------------------+ |1|1|1| | |v|v|v| SVs from class 1 | |2|3|4| | +-+-+-+--------------------+ |1|2|2| | |v|v|v| SVs from class 2 | |2|3|4| | +-+-+-+--------------------+ |1|2|3| | |v|v|v| SVs from class 3 | |3|3|4| | +-+-+-+--------------------+ |1|2|3| | |v|v|v| SVs from class 4 | |4|4|4| | +-+-+-+--------------------+See also an illustration using MATLAB/OCTAVE.
We have float as the default as you can store more numbers in the cache. In general this is good enough but for few difficult cases (e.g. C very very large) where solutions are huge numbers, it might be possible that the numerical precision is not enough using only float.
No, libsvm solves linear/nonlinear SVMs by the same way. Some tricks may save training/testing time if the linear kernel is used, so libsvm is NOT particularly efficient for linear SVM, especially when C is large and the number of data is much larger than the number of attributes. You can either
S. S. Keerthi and C.-J. Lin. Asymptotic behaviors of support vector machines with Gaussian kernel . Neural Computation, 15(2003), 1667-1689.
Please also see our SVM guide on the discussion of using RBF and linear kernels.
This usually happens when the data are overfitted. If attributes of your data are in large ranges, try to scale them. Then the region of appropriate parameters may be larger. Note that there is a scale program in libsvm.
Yes, you can do the following:
> svm-scale -s scaling_parameters train_data > scaled_train_data > svm-scale -r scaling_parameters test_data > scaled_test_data
In general this does not happen, but we have observed in some rare situations, the output of svm-scale.exe directed to a file (by ">") has wrong encoding. That is, the file is not an ASCII file, so cannot be used for training/prediction. Please let us know if this happens as at this moment we don't clearly see how to fix the problem.
For the linear scaling method, if the RBF kernel is used and parameter selection is conducted, there is no difference. Assume Mi and mi are respectively the maximal and minimal values of the ith attribute. Scaling to [0,1] means
x'=(x-mi)/(Mi-mi)For [-1,1],
x''=2(x-mi)/(Mi-mi)-1.In the RBF kernel,
x'-y'=(x-y)/(Mi-mi), x''-y''=2(x-y)/(Mi-mi).Hence, using (C,g) on the [0,1]-scaled data is the same as (C,g/2) on the [-1,1]-scaled data.
Though the performance is the same, the computational time may be different. For data with many zero entries, [0,1]-scaling keeps the sparsity of input data and hence may save the time.
Try to use the model selection tool grid.py in the tools directory find out good parameters. To see the importance of model selection, please see our guide for beginners: A practical guide to support vector classification
Yes, there is a -wi options. For example, if you use
> svm-train -s 0 -c 10 -w1 1 -w-1 5 data_file
the penalty for class "-1" is larger. Note that this -w option is for C-SVC only.
Basically they are the same thing but with different parameters. The range of C is from zero to infinity but nu is always between [0,1]. A nice property of nu is that it is related to the ratio of support vectors and the ratio of the training error.
You may want to check your data. Each training/testing data must be in one line. It cannot be separated. In addition, you have to remove empty lines.
In theory libsvm guarantees to converge. Therefore, this means you are handling ill-conditioned situations (e.g. too large/small parameters) so numerical difficulties occur.
You may get better numerical stability by replacing
typedef float Qfloat;in svm.cpp with
typedef double Qfloat;That is, elements in the kernel cache are stored in double instead of single. However, this means fewer elements can be put in the kernel cache.
For large problems, please specify enough cache size (i.e., -m). Slow convergence may happen for some difficult cases (e.g. -c is large). You can try to use a looser stopping tolerance with -e. If that still doesn't work, you may train only a subset of the data. You can use the program subset.py in the directory "tools" to obtain a random subset.
If you have extremely large data and face this difficulty, please contact us. We will be happy to discuss possible solutions.
When using large -e, you may want to check if -h 0 (no shrinking) or -h 1 (shrinking) is faster. See a related question below.
If the number of iterations is high, then shrinking often helps. However, if the number of iterations is small (e.g., you specify a large -e), then probably using -h 0 (no shrinking) is better. See the implementation document for details.
We print out decision values for regression. For classification, we solve several binary SVMs for multi-class cases. You can obtain values by easily calling the subroutine svm_predict_values. Their corresponding labels can be obtained from svm_get_labels. Details are in README of libsvm package.
If you are using MATLAB/OCTAVE interface, svmpredict can directly give you decision values. Please see matlab/README for details.
We do not recommend the following. But if you would like to get values for TWO-class classification with labels +1 and -1 (note: +1 and -1 but not things like 5 and 10) in the easiest way, simply add
printf("%f\n", dec_values[0]*model->label[0]);after the line
svm_predict_values(model, x, dec_values);of the file svm.cpp. Positive (negative) decision values correspond to data predicted as +1 (-1).
The distance is |decision_value| / |w|. We have |w|^2 = w^Tw = alpha^T Q alpha = 2*(dual_obj + sum alpha_i). Thus in svm.cpp please find the place where we calculate the dual objective value (i.e., the subroutine Solve()) and add a statement to print w^Tw. More precisely, here is what you need to do
On 32-bit machines, the maximum addressable memory is 4GB. The Linux kernel uses 3:1 split which means user space is 3G and kernel space is 1G. Although there are 3G user space, the maximum dynamic allocation memory is 2G. So, if you specify -m near 2G, the memory will be exhausted. And svm-train will fail when it asks more memory. For more details, please read this article.
The easiest solution is to switch to a 64-bit machine. Otherwise, there are two ways to solve this. If your machine supports Intel's PAE (Physical Address Extension), you can turn on the option HIGHMEM64G in Linux kernel which uses 4G:4G split for kernel and user space. If you don't, you can try a software `tub' which can eliminate the 2G boundary for dynamic allocated memory. The `tub' is available at http://www.bitwagon.com/tub.html.
For commend-line users, use the -q option:
> ./svm-train -q heart_scale
For library users, set the global variable
extern void (*svm_print_string) (const char *);to specify the output format. You can disable the output by the following steps:
void print_null(const char *s) {}
svm_print_string = &print_null;
#if 1 void info(const char *fmt,...)to
#if 0 void info(const char *fmt,...)
An example is "LIBSVM for string data" in LIBSVM Tools.
The reason why we have two functions is as follows. For the RBF kernel exp(-g |xi - xj|^2), if we calculate xi - xj first and then the norm square, there are 3n operations. Thus we consider exp(-g (|xi|^2 - 2dot(xi,xj) +|xj|^2)) and by calculating all |xi|^2 in the beginning, the number of operations is reduced to 2n. This is for the training. For prediction we cannot do this so a regular subroutine using that 3n operations is needed. The easiest way to have your own kernel is to put the same code in these two subroutines by replacing any kernel.
It is one-against-one. We chose it after doing the following comparison: C.-W. Hsu and C.-J. Lin. A comparison of methods for multi-class support vector machines , IEEE Transactions on Neural Networks, 13(2002), 415-425.
"1-against-the rest" is a good method whose performance is comparable to "1-against-1." We do the latter simply because its training time is shorter.
It is extremely easy. Taking c-svc for example, to solve
min_{w,b} w^Tw/2 + C \sum max(0, 1- (y_i w^Tx_i+b))^2,
only two places of svm.cpp have to be changed. First, modify the following line of solve_c_svc from
s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y, alpha, Cp, Cn, param->eps, si, param->shrinking);to
s.Solve(l, SVC_Q(*prob,*param,y), minus_ones, y, alpha, INF, INF, param->eps, si, param->shrinking);Second, in the class of SVC_Q, declare C as a private variable:
double C;In the constructor replace
for(int i=0;i<prob.l;i++) QD[i]= (Qfloat)(this->*kernel_function)(i,i);with
this->C = param.C; for(int i=0;i<prob.l;i++) QD[i]= (Qfloat)(this->*kernel_function)(i,i)+0.5/C;Then in the subroutine get_Q, after the for loop, add
if(i >= start && i < len) data[i] += 0.5/C;
For one-class svm, the modification is exactly the same. For SVR, you don't need an if statement like the above. Instead, you only need a simple assignment:
data[real_i] += 0.5/C;
For large linear L2-loss SVM, please use LIBLINEAR.
At optimum, some training instances should satisfy w^Tx - rho = 0. However, numerically they may be slightly smaller than zero Then they are wrongly counted as training errors. You can use a smaller stopping tolerance (by the -e option) to make this problem less serious.
This issue does not occur for nu-SVC for two-class classification. We have that
This rarely happens, but few users reported the problem. It seems that their computers for training libsvm have the VPN client running. The VPN software has some bugs and causes this problem. Please try to close or disconnect the VPN client.
This situation may occur before version 3.17. Nothing is wrong. Very likely you have two labels +1/-1 and the first instance in your data has -1. We give the following explanation.
Internally class labels are ordered by their first occurrence in the training set. For a k-class data, internally labels are 0, ..., k-1, and each two-class SVM considers pair (i, j) with i < j. Then class i is treated as positive (+1) and j as negative (-1). For example, if the data set has labels +5/+10 and +10 appears first, then internally the +5 versus +10 SVM problem has +10 as positive (+1) and +5 as negative (-1).
By this setting, if you have labels +1 and -1, it's possible that internally they correspond to -1 and +1, respectively. Some new users have been confused about this, so after version 3.17, if the data set has only two labels +1 and -1, internally we ensure +1 to be before -1. Then class +1 is always treated as positive in the SVM problem. Note that this is for two-class data only (the data must include both +1 and -1 labels).
Any value is ok. In this situation, what you will use is the output file of svm-predict, which gives predicted class labels.
To use OpenMP, check that your compiler supports it. For GCC, version 4.2 or later is needed.
In Makefile, there are the lines
# Uncomment the following lines to enable parallelization with OpenMP # CFLAGS += -fopenmp # SHARED_LIB_FLAG += -fopenmpUncomment the latter two lines and rebuild the package for using OpenMP.
Kernel evaluations in training/testing will be parallelized. We show an example of running this modification on an 8-core machine using the data set real-sim:
8 cores:
%setenv OMP_NUM_THREADS 8 %time svm-train -c 8 -g 0.5 -m 1000 real-sim 175.90sec1 core:
%setenv OMP_NUM_THREADS 1 %time svm-train -c 8 -g 0.5 -m 1000 real-sim 588.89secFor this data, kernel evaluations take 91% of training time. In the above example, we assume you use csh. For bash, use
export OMP_NUM_THREADS=8instead.
For Windows, in Makefile.win there are the lines
# Uncomment the following lines to enable parallelization with OpenMP # CFLAGS = /nologo /O2 /EHsc /I. /D _WIN64 /D _CRT_SECURE_NO_DEPRECATE /openmpUncomment the latter line and rebuild the package to use OpenMP.
Now consider tbb (thread building blocks). Thank Rob Ward for the following instructions. First the tbb package must be installed. On Ubuntu this can be done by
apt-get install -y libtbb-devIn svm.cpp, add
#include <atomic> #include <execution> #include "tbb/iterators.h"in the beginning. Then the loops mentioned earlier should be as follows. In class SVC_Q of svm.cpp,
std::for_each(std::execution::par, tbb::counting_iterator<int>(start), tbb::counting_iterator<int>(len), [this, i, data](int j){ data[j] = (Qfloat)(y[i] * y[j] * (this->*kernel_function)(i, j)); });In class SVR_Q of svm.cpp,
std::for_each(std::execution::par, tbb::counting_iterator<int>(0), tbb::counting_iterator<int>(l), [this, i, data, real_i](int j){ data[j] = (Qfloat)(this->*kernel_function)(real_i, j); });In svm_predict_values() of svm.cpp, for SVR and ONE_CLASS,
std::atomic<double> sum = 0; std::for_each(std::execution::par, tbb::counting_iterator<int>(0), tbb::counting_iterator<int>(model->l), [&sum, sv_coef, x, model](int i){ sum += sv_coef[i] * Kernel::k_function(x, model->SV[i], model->param); });and for SVC
std::for_each(std::execution::par, tbb::counting_iterator<int>(0), tbb::counting_iterator<int>(l), [kvalue, x, model](int i){ kvalue[i] = Kernel::k_function(x, model->SV[i], model->param); });
It's very simple. Since version 3.13, you can use the function
void svm_get_sv_indices(const struct svm_model *model, int *sv_indices)to get indices of support vectors. For example, in svm-train.c, after
model = svm_train(&prob, ¶m);you can add
int nr_sv = svm_get_nr_sv(model); int *sv_indices = Malloc(int, nr_sv); svm_get_sv_indices(model, sv_indices); for (int i=0; i<nr_sv; i++) printf("instance %d is a support vector\n", sv_indices[i]);
If you use matlab interface, you can directly check
model.sv_indices
Although sv_indices is a member of the model structure to indicate support vectors in the training set, we do not store its contents in the model file. The model file is mainly used in the future for prediction, so it is basically independent from training data. Thus storing sv_indices is not necessary. Users should find support vectors right after the training process. See the previous FAQ.
Cross validation is used for selecting good parameters. After finding them, you want to re-train the whole data without the -v option.
Due to random partitions of the data, on different systems CV accuracy values may be different.
If you use GNU C library or a recent Visual C++ library, the default seed 1 is considered. Thus you always get the same result of running svm-train -v. To have different seeds, you can add the following code in svm-train.c:
#include <time.h>and in the beginning of main(),
srand(time(0));Alternatively, if you would like to use a fixed seed, you can have
srand(1);
For Java, the random number generator is initialized using the time information. So results of two CV runs are different. To fix the seed, after version 3.1 (released in mid 2011), you can add
svm.rand.setSeed(0);in the main() function of svm_train.java.
If you use CV to select parameters, it is recommended to use identical folds under different parameters. In this case, you can consider fixing the seed.
This problem shouldn't happen after version 2.85. If you are using earlier versions, please download the latest one.
Warning: empty z range [62.5:62.5], adjusting to [61.875:63.125] Notice: cannot contour non grid data!
Nothing is wrong and please disregard the message. It is from gnuplot when drawing the contour.
In general we suggest you to try the RBF kernel first. A recent result by Keerthi and Lin ( download paper here) shows that if RBF is used with model selection, then there is no need to consider the linear kernel. The kernel matrix using sigmoid may not be positive definite and in general it's accuracy is not better than RBF. (see the paper by Lin and Lin ( download paper here). Polynomial kernels are ok but if a high degree is used, numerical difficulties tend to happen (thinking about dth power of (<1) goes to 0 and (>1) goes to infinity).
LIBSVM implements "one-against-one" multi-class method, so there are k(k-1)/2 binary models, where k is the number of classes.
We can consider two ways to conduct parameter selection.
Chen, Lin, and Schölkopf, A tutorial on nu-support vector machines. Applied Stochastic Models in Business and Industry, 21(2005), 111-136,
they have experimentally shown that the two methods give similar performance. Therefore, currently the parameter selection in LIBSVM takes the second approach by considering the same parameters for all k(k-1)/2 models.
You have pre-specified true positive rate in mind and then search for parameters which achieve similar cross-validation accuracy.
For MATLAB, please see another question in FAQ.
For using shell scripts, please check the code written by Bjarte Johansen
To construct this probability model, we internally conduct a cross validation, which is more time consuming than a regular training. Hence, in general you do parameter selection first without -b 1. You only use -b 1 when good parameters have been selected. In other words, you avoid using -b 1 and -v together.
There is absolutely no reason the probability outputs guarantee you better accuracy. The main purpose of this option is to provide you the probability estimates, but not to boost prediction accuracy. From our experience, after proper parameter selections, in general with and without -b have similar accuracy. Occasionally there are some differences. It is not recommended to compare the two under just a fixed parameter set as more differences will be observed.
Let's just consider two-class classification here. After probability information is obtained in training, we do not have
prob > = 0.5 if and only if decision value >= 0.
So predictions may be different with -b 0 and 1.
For Microsoft windows, first press the "print screen" key on the keyboard. Open "Microsoft Paint" (included in Windows) and press "ctrl-v." Then you can clip the part of picture which you want. For X windows, you can use the program "xv" or "import" to grab the picture of the svm-toy window.
The program svm-toy assumes both attributes (i.e. x-axis and y-axis values) are in (0,1). Hence you want to scale your data to between a small positive number and a number less than but very close to 1. Moreover, class labels must be 1, 2, or 3 (not 1.0, 2.0 or anything else).
Taking windows/svm-toy.cpp as an example, you need to modify it and the difference from the original file is as the following: (for five classes of data)
30,32c30 < RGB(200,0,200), < RGB(0,160,0), < RGB(160,0,0) --- > RGB(200,0,200) 39c37 < HBRUSH brush1, brush2, brush3, brush4, brush5; --- > HBRUSH brush1, brush2, brush3; 113,114d110 < brush4 = CreateSolidBrush(colors[7]); < brush5 = CreateSolidBrush(colors[8]); 155,157c151 < else if(v==3) return brush3; < else if(v==4) return brush4; < else return brush5; --- > else return brush3; 325d318 < int colornum = 5; 327c320 < svm_node *x_space = new svm_node[colornum * prob.l]; --- > svm_node *x_space = new svm_node[3 * prob.l]; 333,338c326,331 < x_space[colornum * i].index = 1; < x_space[colornum * i].value = q->x; < x_space[colornum * i + 1].index = 2; < x_space[colornum * i + 1].value = q->y; < x_space[colornum * i + 2].index = -1; < prob.x[i] = &x_space[colornum * i]; --- > x_space[3 * i].index = 1; > x_space[3 * i].value = q->x; > x_space[3 * i + 1].index = 2; > x_space[3 * i + 1].value = q->y; > x_space[3 * i + 2].index = -1; > prob.x[i] = &x_space[3 * i]; 397c390 < if(current_value > 5) current_value = 1; --- > if(current_value > 3) current_value = 1;
They are the same thing. We just rewrote the C++ code in Java.
This depends on the VM you used. We have seen good VM which leads the Java version to be quite competitive with the C++ code. (though still slower)
You should try to increase the maximum Java heap size. For example,
java -Xmx2048m -classpath libsvm.jar svm_train ...sets the maximum heap size to 2048M.
Unlike C, Java does not have a preprocessor built-in. However, we need some macros (see first 3 lines of svm.m4).
Yes, here are some examples:
$ export CLASSPATH=$CLASSPATH:~/libsvm-2.91/java/libsvm.jar $ ./jython Jython 2.1a3 on java1.3.0 (JIT: jitc) Type "copyright", "credits" or "license" for more information. >>> from libsvm import * >>> dir() ['__doc__', '__name__', 'svm', 'svm_model', 'svm_node', 'svm_parameter', 'svm_problem'] >>> x1 = [svm_node(index=1,value=1)] >>> x2 = [svm_node(index=1,value=-1)] >>> param = svm_parameter(svm_type=0,kernel_type=2,gamma=1,cache_size=40,eps=0.001,C=1,nr_weight=0,shrinking=1) >>> prob = svm_problem(l=2,y=[1,-1],x=[x1,x2]) >>> model = svm.svm_train(prob,param) * optimization finished, #iter = 1 nu = 1.0 obj = -1.018315639346838, rho = 0.0 nSV = 2, nBSV = 2 Total nSV = 2 >>> svm.svm_predict(model,x1) 1.0 >>> svm.svm_predict(model,x2) -1.0 >>> svm.svm_save_model("test.model",model)
Your compiler version may not be supported/compatible for MATLAB. Please check this MATLAB page first and then specify the version number. For example, if g++ X.Y is supported, replace
CXX ?= g++in the Makefile with
CXX = g++-X.YNote that you should have = instead of ?= to ensure that the specified compiler is used.
Please make sure that you use the -largeArrayDims option in make.m. For example,
mex -largeArrayDims -O -c svm.cppMoreover, if you use Microsoft Visual Studio, probabally it is not properly installed. See the explanation here.
It is extremely easy to do scaling under MATLAB. The following one-line code scale each feature to the range of [0,1]:
(data - repmat(min(data,[],1),size(data,1),1))*spdiags(1./(max(data,[],1)-min(data,[],1))',0,size(data,2),size(data,2))This setting is capable to handle large-scale sparse sets (with non-negative feature values) because repmat() won't generate a large dense matrix.
One can do this by a simple loop. See the following example:
bestcv = 0; for log2c = -1:3, for log2g = -4:1, cmd = ['-v 5 -c ', num2str(2^log2c), ' -g ', num2str(2^log2g)]; cv = svmtrain(heart_scale_label, heart_scale_inst, cmd); if (cv >= bestcv), bestcv = cv; bestc = 2^log2c; bestg = 2^log2g; end fprintf('%g %g %g (best c=%g, g=%g, rate=%g)\n', log2c, log2g, cv, bestc, bestg, bestcv); end endYou may adjust the parameter range in the above loops.
Fabrizio Lacalandra of University of Pisa reported this issue. It seems the problem is caused by the screen output. If you disable the info function using
#if 0,then the problem may be solved.
First, you must modify svm.cpp. Check the following faq, How can I use OpenMP to parallelize LIBSVM on a multicore/shared-memory computer?
To build the MATLAB/Octave interface, we recommend using make.m. You must append '-fopenmp' to CXXFLAGS and add '-lgomp' to mex options in make.m. See details below.
For MATLAB users, the modified code is:
mex CFLAGS="\$CFLAGS -std=c99" CXXFLAGS="\$CXXFLAGS -fopenmp" -largeArrayDims -I.. -lgomp svmtrain.c ../svm.cpp svm_model_matlab.c mex CFLAGS="\$CFLAGS -std=c99" CXXFLAGS="\$CXXFLAGS -fopenmp" -largeArrayDims -I.. -lgomp svmpredict.c ../svm.cpp svm_model_matlab.c
For Octave users, the modified code is:
setenv('CXXFLAGS', '-fopenmp') mex -I.. -lgomp svmtrain.c ../svm.cpp svm_model_matlab.c mex -I.. -lgomp svmpredict.c ../svm.cpp svm_model_matlab.c
If make.m fails under matlab and you use Makefile to compile the codes, you must modify two files:
You must append '-fopenmp' to CFLAGS in ../Makefile for C/C++ codes:
CFLAGS = -Wall -Wconversion -O3 -fPIC -fopenmp -I$(MATLABDIR)/extern/include -I..and add '-lgomp' to MEX_OPTION in Makefile for the matlab/octave interface:
MEX_OPTION += -lgomp
To run the code, you must specify the number of threads. For example, before executing matlab/octave, you run
> export OMP_NUM_THREADS=8 > matlabHere we assume Bash is used. Unfortunately, we do not know yet how to specify the number of threads within MATLAB/Octave. Our experiments show that
>> setenv('OMP_NUM_THREADS', '8');does not work. Please contact us if you see how to solve this problem. On the other hand, you can specify the number of threads in the source code (thanks to comments from Ricardo Santiago-mozos):
#pragma omp parallel for private(i) num_threads(8)
Let's start from the binary class and assume you have two labels -1 and +1. After obtaining the model from calling svmtrain, do the following to have w and b:
w = model.SVs' * model.sv_coef; b = -model.rho; if model.Label(1) == -1 w = -w; b = -b; endIf you do regression or one-class SVM, then the if statement is not needed.
For multi-class SVM, we illustrate the setting in the following example of running the iris data, which have 3 classes
> [y, x] = libsvmread('../../htdocs/libsvmtools/datasets/multiclass/iris.scale'); > m = svmtrain(y, x, '-t 0') m = Parameters: [5x1 double] nr_class: 3 totalSV: 42 rho: [3x1 double] Label: [3x1 double] ProbA: [] ProbB: [] nSV: [3x1 double] sv_coef: [42x2 double] SVs: [42x4 double]sv_coef is like:
+-+-+--------------------+ |1|1| | |v|v| SVs from class 1 | |2|3| | +-+-+--------------------+ |1|2| | |v|v| SVs from class 2 | |2|3| | +-+-+--------------------+ |1|2| | |v|v| SVs from class 3 | |3|3| | +-+-+--------------------+so we need to see nSV of each classes.
> m.nSV ans = 3 21 18Suppose the goal is to find the vector w of classes 1 vs 3. Then y_i alpha_i of training 1 vs 3 are
> coef = [m.sv_coef(1:3,2); m.sv_coef(25:42,1)];and SVs are:
> SVs = [m.SVs(1:3,:); m.SVs(25:42,:)];Hence, w is
> w = SVs'*coef;For rho,
> m.rho ans = 1.1465 0.3682 -1.9969 > b = -m.rho(2);because rho is arranged by 1vs2 1vs3 2vs3.
Yes, after libsvm 2.86, the matlab interface works on OCTAVE as well. Please use make.m by typing
>> makeunder OCTAVE.
The easiest way is to rename the svmtrain binary file (e.g., svmtrain.mexw32 on 32-bit windows) to a different name (e.g., svmtrain2.mexw32).
The error usually happens when there are missing runtime components such as MSVCR100.dll on your Windows platform. You can use tools such as Dependency Walker to find missing library files.
For example, if the pre-built MEX files are compiled by Visual C++ 2010, you must have installed Microsoft Visual C++ Redistributable Package 2010 (vcredist_x86.exe). You can easily find the freely available file from Microsoft's web site.
For 64bit Windows, the situation is similar. If the pre-built files are by Visual C++ 2008, then you must have Microsoft Visual C++ Redistributable Package 2008 (vcredist_x64.exe).
Please use code in the following directory. The following example shows how to train and test the problem dna (training and testing).
Load, train and predict data:
[trainY trainX] = libsvmread('./dna.scale'); [testY testX] = libsvmread('./dna.scale.t'); model = ovrtrain(trainY, trainX, '-c 8 -g 4'); [pred ac decv] = ovrpredict(testY, testX, model); fprintf('Accuracy = %g%%\n', ac * 100);Conduct CV on a grid of parameters
bestcv = 0; for log2c = -1:2:3, for log2g = -4:2:1, cmd = ['-q -c ', num2str(2^log2c), ' -g ', num2str(2^log2g)]; cv = get_cv_ac(trainY, trainX, cmd, 3); if (cv >= bestcv), bestcv = cv; bestc = 2^log2c; bestg = 2^log2g; end fprintf('%g %g %g (best c=%g, g=%g, rate=%g)\n', log2c, log2g, cv, bestc, bestg, bestcv); end end
We assume that in a matlab command window you change directory to libsvm/matlab and type
>> makeWe discuss the following situations.
Reason: "make" looks for a C++ compiler, but no compiler is found. To get one, you can
Reason: Since Apple Inc. only ships llsvm-gcc instead of gcc-4.2, llvm-gcc-4.2 cannot be found.
If you are using Xcode 4.2-4.6, a related solution is offered at http://www.mathworks.com/matlabcentral/answers/94092.
On the other hand, for Xcode 5 (including Xcode 4.2-4.6), in a Matlab command window, enter
CC='llvm-gcc-4.2' CXX='llvm-g++-4.2'to
CC='llvm-gcc' CXX='llvm-g++'
This may be due to that Octave's math.h file does not refer to the correct location of Visual Studio's math.h. Please see this nice page for detailed instructions.