Skip to content

Commit

Permalink
QD is double now. All Q_i[i] are replaced by QD[i]
Browse files Browse the repository at this point in the history
to avoid numerical problems.

struct svm_model is moved to svm.h, so svm_destroy_model
is replaced svm_free_model_content and svm_free_and_destroy_model.

python_old is removed.
  • Loading branch information
popo committed Sep 12, 2010
1 parent 4827e02 commit 1c80a42
Show file tree
Hide file tree
Showing 28 changed files with 253 additions and 6,613 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CXX ?= g++
CFLAGS = -Wall -Wconversion -O3 -fPIC
SHVER = 1
SHVER = 2

all: svm-train svm-predict svm-scale

Expand Down
2 changes: 1 addition & 1 deletion Makefile.win
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CXX = cl.exe
CFLAGS = -nologo -O2 -EHsc -I. -D __WIN32__ -D _CRT_SECURE_NO_DEPRECATE
TARGET = windows

all: $(TARGET)\svm-train.exe $(TARGET)\svm-predict.exe $(TARGET)\svm-scale.exe $(TARGET)\svm-toy.exe
all: $(TARGET)\svm-train.exe $(TARGET)\svm-predict.exe $(TARGET)\svm-scale.exe $(TARGET)\svm-toy.exe lib

$(TARGET)\svm-predict.exe: svm.h svm-predict.c svm.obj
$(CXX) $(CFLAGS) svm-predict.c svm.obj -Fe$(TARGET)\svm-predict.exe
Expand Down
84 changes: 82 additions & 2 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,80 @@ to classify new data.
*NOTE* To avoid wrong parameters, svm_check_parameter() should be
called before svm_train().

struct svm_model stores the model obtained from the training procedure.
It is not recommended to directly access entries in this structure.
Programmers should use the interface functions to get the values.

struct svm_model
{
struct svm_parameter param; /* parameter */
int nr_class; /* number of classes, = 2 in regression/one class svm */
int l; /* total #SV */
struct svm_node **SV; /* SVs (SV[l]) */
double **sv_coef; /* coefficients for SVs in decision functions (sv_coef[k-1][l]) */
double *rho; /* constants in decision functions (rho[k*(k-1)/2]) */
double *probA; /* pairwise probability information */
double *probB;

/* for classification only */

int *label; /* label of each class (label[k]) */
int *nSV; /* number of SVs for each class (nSV[k]) */
/* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
/* XXX */
int free_sv; /* 1 if svm_model is created by svm_load_model*/
/* 0 if svm_model is created by svm_train */
};

param describes the parameters used to obtain the model.

nr_class is the number of classes. It is 2 for regression and one-class SVM.

l is the number of support vectors. SV and sv_coef are support
vectors and the corresponding coefficients, respectively. Assume there are
k classes. For data in class j, the corresponding sv_coef includes (k-1) y*alpha vectors,
where alpha's are solutions 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 for the first j-1 vectors, while y=-1 for the remaining k-j
vectors. For example, if there are 4 classes, sv_coef and SV are 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 svm_train() for an example of assigning values to sv_coef.

rho is the bias term (-b). probA and probB are parameters used in
probability outputs. If there are k classes, there are k*(k-1)/2
binary problems as well as rho, probA, and probB values. They are
aligned in the order of binary problems:
1 vs 2, 1 vs 3, ..., 1 vs k, 2 vs 3, ..., 2 vs k, ..., k-1 vs k.

label contains labels in the training data.

nSV is the number of support vectors in each class.

free_sv is a flag used to determine whether the space of SV should
be released in free_model_content(struct svm_model*) and
free_and_destroy_model(struct svm_model**). If the model is
generated by svm_train(), then SVs point to data in svm_problem
and should not be removed. For example, free_sv is 0 if svm_model
is created by svm_train, but is 0 if created by svm_load_model.

- Function: double svm_predict(const struct svm_model *model,
const struct svm_node *x);

Expand Down Expand Up @@ -530,9 +604,15 @@ to classify new data.
This function returns a pointer to the model read from the file,
or a null pointer if the model could not be loaded.

- Function: void svm_destroy_model(struct svm_model *model);
- Function: void svm_free_model_content(struct svm_model *model_ptr);

This function frees the memory used by the entries in a model structure.

- Function: void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr);

This function frees the memory used by a model.
This function frees the memory used by a model and destroys the model
structure. This function is equivalent to svm_destroy_model, which
is deprecated after version 3.0.

- Function: void svm_destroy_param(struct svm_parameter *param);

Expand Down
Binary file modified java/libsvm.jar
Binary file not shown.
52 changes: 26 additions & 26 deletions java/libsvm/svm.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ void swap_index(int i, int j)
//
abstract class QMatrix {
abstract float[] get_Q(int column, int len);
abstract float[] get_QD();
abstract double[] get_QD();
abstract void swap_index(int i, int j);
};

Expand All @@ -143,7 +143,7 @@ abstract class Kernel extends QMatrix {
private final double coef0;

abstract float[] get_Q(int column, int len);
abstract float[] get_QD();
abstract double[] get_QD();

void swap_index(int i, int j)
{
Expand Down Expand Up @@ -309,7 +309,7 @@ class Solver {
byte[] alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE
double[] alpha;
QMatrix Q;
float[] QD;
double[] QD;
double eps;
double Cp,Cn;
double[] p;
Expand Down Expand Up @@ -501,7 +501,7 @@ void Solve(int l, QMatrix Q, double[] p_, byte[] y_,

if(y[i]!=y[j])
{
double quad_coef = Q_i[i]+Q_j[j]+2*Q_i[j];
double quad_coef = QD[i]+QD[j]+2*Q_i[j];
if (quad_coef <= 0)
quad_coef = 1e-12;
double delta = (-G[i]-G[j])/quad_coef;
Expand Down Expand Up @@ -544,7 +544,7 @@ void Solve(int l, QMatrix Q, double[] p_, byte[] y_,
}
else
{
double quad_coef = Q_i[i]+Q_j[j]-2*Q_i[j];
double quad_coef = QD[i]+QD[j]-2*Q_i[j];
if (quad_coef <= 0)
quad_coef = 1e-12;
double delta = (G[i]-G[j])/quad_coef;
Expand Down Expand Up @@ -707,7 +707,7 @@ int select_working_set(int[] working_set)
if (grad_diff > 0)
{
double obj_diff;
double quad_coef=Q_i[i]+QD[j]-2.0*y[i]*Q_i[j];
double quad_coef = QD[i]+QD[j]-2.0*y[i]*Q_i[j];
if (quad_coef > 0)
obj_diff = -(grad_diff*grad_diff)/quad_coef;
else
Expand All @@ -731,7 +731,7 @@ int select_working_set(int[] working_set)
if (grad_diff > 0)
{
double obj_diff;
double quad_coef=Q_i[i]+QD[j]+2.0*y[i]*Q_i[j];
double quad_coef = QD[i]+QD[j]+2.0*y[i]*Q_i[j];
if (quad_coef > 0)
obj_diff = -(grad_diff*grad_diff)/quad_coef;
else
Expand Down Expand Up @@ -953,7 +953,7 @@ int select_working_set(int[] working_set)
if (grad_diff > 0)
{
double obj_diff;
double quad_coef = Q_ip[ip]+QD[j]-2*Q_ip[j];
double quad_coef = QD[ip]+QD[j]-2*Q_ip[j];
if (quad_coef > 0)
obj_diff = -(grad_diff*grad_diff)/quad_coef;
else
Expand All @@ -977,7 +977,7 @@ int select_working_set(int[] working_set)
if (grad_diff > 0)
{
double obj_diff;
double quad_coef = Q_in[in]+QD[j]-2*Q_in[j];
double quad_coef = QD[in]+QD[j]-2*Q_in[j];
if (quad_coef > 0)
obj_diff = -(grad_diff*grad_diff)/quad_coef;
else
Expand Down Expand Up @@ -1135,16 +1135,16 @@ class SVC_Q extends Kernel
{
private final byte[] y;
private final Cache cache;
private final float[] QD;
private final double[] QD;

SVC_Q(svm_problem prob, svm_parameter param, byte[] y_)
{
super(prob.l, prob.x, param);
y = (byte[])y_.clone();
cache = new Cache(prob.l,(long)(param.cache_size*(1<<20)));
QD = new float[prob.l];
QD = new double[prob.l];
for(int i=0;i<prob.l;i++)
QD[i]= (float)kernel_function(i,i);
QD[i] = kernel_function(i,i);
}

float[] get_Q(int i, int len)
Expand All @@ -1159,7 +1159,7 @@ float[] get_Q(int i, int len)
return data[0];
}

float[] get_QD()
double[] get_QD()
{
return QD;
}
Expand All @@ -1169,22 +1169,22 @@ void swap_index(int i, int j)
cache.swap_index(i,j);
super.swap_index(i,j);
do {byte _=y[i]; y[i]=y[j]; y[j]=_;} while(false);
do {float _=QD[i]; QD[i]=QD[j]; QD[j]=_;} while(false);
do {double _=QD[i]; QD[i]=QD[j]; QD[j]=_;} while(false);
}
}

class ONE_CLASS_Q extends Kernel
{
private final Cache cache;
private final float[] QD;
private final double[] QD;

ONE_CLASS_Q(svm_problem prob, svm_parameter param)
{
super(prob.l, prob.x, param);
cache = new Cache(prob.l,(long)(param.cache_size*(1<<20)));
QD = new float[prob.l];
QD = new double[prob.l];
for(int i=0;i<prob.l;i++)
QD[i]= (float)kernel_function(i,i);
QD[i] = kernel_function(i,i);
}

float[] get_Q(int i, int len)
Expand All @@ -1199,7 +1199,7 @@ float[] get_Q(int i, int len)
return data[0];
}

float[] get_QD()
double[] get_QD()
{
return QD;
}
Expand All @@ -1208,7 +1208,7 @@ void swap_index(int i, int j)
{
cache.swap_index(i,j);
super.swap_index(i,j);
do {float _=QD[i]; QD[i]=QD[j]; QD[j]=_;} while(false);
do {double _=QD[i]; QD[i]=QD[j]; QD[j]=_;} while(false);
}
}

Expand All @@ -1220,14 +1220,14 @@ class SVR_Q extends Kernel
private final int[] index;
private int next_buffer;
private float[][] buffer;
private final float[] QD;
private final double[] QD;

SVR_Q(svm_problem prob, svm_parameter param)
{
super(prob.l, prob.x, param);
l = prob.l;
cache = new Cache(l,(long)(param.cache_size*(1<<20)));
QD = new float[2*l];
QD = new double[2*l];
sign = new byte[2*l];
index = new int[2*l];
for(int k=0;k<l;k++)
Expand All @@ -1236,7 +1236,7 @@ class SVR_Q extends Kernel
sign[k+l] = -1;
index[k] = k;
index[k+l] = k;
QD[k] = (float)kernel_function(k,k);
QD[k] = kernel_function(k,k);
QD[k+l] = QD[k];
}
buffer = new float[2][2*l];
Expand All @@ -1247,7 +1247,7 @@ void swap_index(int i, int j)
{
do {byte _=sign[i]; sign[i]=sign[j]; sign[j]=_;} while(false);
do {int _=index[i]; index[i]=index[j]; index[j]=_;} while(false);
do {float _=QD[i]; QD[i]=QD[j]; QD[j]=_;} while(false);
do {double _=QD[i]; QD[i]=QD[j]; QD[j]=_;} while(false);
}

float[] get_Q(int i, int len)
Expand All @@ -1269,7 +1269,7 @@ float[] get_Q(int i, int len)
return buf;
}

float[] get_QD()
double[] get_QD()
{
return QD;
}
Expand Down Expand Up @@ -1311,7 +1311,7 @@ private static void solve_c_svc(svm_problem prob, svm_parameter param,
{
alpha[i] = 0;
minus_ones[i] = -1;
if(prob.y[i] > 0) y[i] = +1; else y[i]=-1;
if(prob.y[i] > 0) y[i] = +1; else y[i] = -1;
}

Solver s = new Solver();
Expand Down Expand Up @@ -1669,7 +1669,7 @@ private static void multiclass_probability(int k, double[][] r, double[] p)
int t,j;
int iter = 0, max_iter=Math.max(100,k);
double[][] Q=new double[k][k];
double[] Qp= new double[k];
double[] Qp=new double[k];
double pQp, eps=0.005/k;

for (t=0;t<k;t++)
Expand Down
Loading

0 comments on commit 1c80a42

Please sign in to comment.