[liblinear] 09/26: Imported Upstream version 2.01
Christian Kastner
ckk at moszumanska.debian.org
Sun Sep 6 13:33:10 UTC 2015
This is an automated email from the git hooks/post-receive script.
ckk pushed a commit to branch master
in repository liblinear.
commit e4709192e8b28962e0d75d1b2416985b568e35ef
Author: Christian Kastner <ckk at kvr.at>
Date: Fri Sep 4 18:33:32 2015 +0200
Imported Upstream version 2.01
---
COPYRIGHT | 2 +-
Makefile | 17 +-
Makefile.win | 8 +-
README | 79 +++++++-
blas/Makefile | 22 ---
blas/blas.h | 25 ---
blas/blasp.h | 430 -------------------------------------------
blas/daxpy.c | 49 -----
blas/ddot.c | 50 -----
blas/dnrm2.c | 62 -------
blas/dscal.c | 44 -----
linear.cpp | 305 ++++++++++++++++++++++++++++--
linear.def | 3 +
linear.h | 5 +
matlab/Makefile | 25 +--
matlab/README | 14 +-
matlab/libsvmread.c | 7 +-
matlab/libsvmwrite.c | 13 +-
matlab/linear_model_matlab.c | 4 +-
matlab/make.m | 41 ++---
matlab/predict.c | 12 +-
matlab/train.c | 119 +++++++++---
predict.c | 4 +-
python/README | 37 ++++
python/liblinear.py | 76 ++++++--
python/liblinearutil.py | 24 ++-
train.c | 54 +++++-
tron.cpp | 22 ++-
tron.h | 3 +-
windows/liblinear.dll | Bin 155648 -> 0 bytes
windows/libsvmread.mexw64 | Bin 11264 -> 0 bytes
windows/libsvmwrite.mexw64 | Bin 10240 -> 0 bytes
windows/predict.exe | Bin 118784 -> 0 bytes
windows/predict.mexw64 | Bin 16384 -> 0 bytes
windows/train.exe | Bin 155136 -> 0 bytes
windows/train.mexw64 | Bin 61952 -> 0 bytes
36 files changed, 711 insertions(+), 845 deletions(-)
diff --git a/COPYRIGHT b/COPYRIGHT
index 7484947..054c8d0 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,5 +1,5 @@
-Copyright (c) 2007-2013 The LIBLINEAR Project.
+Copyright (c) 2007-2015 The LIBLINEAR Project.
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/Makefile b/Makefile
index 7a74e26..99fdece 100644
--- a/Makefile
+++ b/Makefile
@@ -1,25 +1,24 @@
CXX ?= g++
CC ?= gcc
CFLAGS = -Wall -Wconversion -O3 -fPIC
-LIBS = blas/blas.a
-SHVER = 1
+LIBS =
+SHVER = 3
OS = $(shell uname)
-#LIBS = -lblas
all: train predict
-lib: linear.o tron.o blas/blas.a
+lib: linear.o tron.o
if [ "$(OS)" = "Darwin" ]; then \
SHARED_LIB_FLAG="-dynamiclib -Wl,-install_name,liblinear.so.$(SHVER)"; \
else \
SHARED_LIB_FLAG="-shared -Wl,-soname,liblinear.so.$(SHVER)"; \
fi; \
- $(CXX) $${SHARED_LIB_FLAG} linear.o tron.o blas/blas.a -o liblinear.so.$(SHVER)
+ $(CXX) $${SHARED_LIB_FLAG} linear.o tron.o -o liblinear.so.$(SHVER)
-train: tron.o linear.o train.c blas/blas.a
+train: tron.o linear.o train.c
$(CXX) $(CFLAGS) -o train train.c tron.o linear.o $(LIBS)
-predict: tron.o linear.o predict.c blas/blas.a
+predict: tron.o linear.o predict.c
$(CXX) $(CFLAGS) -o predict predict.c tron.o linear.o $(LIBS)
tron.o: tron.cpp tron.h
@@ -28,10 +27,6 @@ tron.o: tron.cpp tron.h
linear.o: linear.cpp linear.h
$(CXX) $(CFLAGS) -c -o linear.o linear.cpp
-blas/blas.a: blas/*.c blas/*.h
- make -C blas OPTFLAGS='$(CFLAGS)' CC='$(CC)';
-
clean:
- make -C blas clean
make -C matlab clean
rm -f *~ tron.o linear.o train predict liblinear.so.$(SHVER)
diff --git a/Makefile.win b/Makefile.win
index 84aa489..c4ad3bf 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -1,11 +1,5 @@
-#You must ensure nmake.exe, cl.exe, link.exe are in system path.
-#VCVARS32.bat
-#Under dosbox prompt
-#nmake -f Makefile.win
-
-##########################################
CXX = cl.exe
-CFLAGS = -nologo -O2 -EHsc -I. -D __WIN32__ -D _CRT_SECURE_NO_DEPRECATE
+CFLAGS = /nologo /O2 /EHsc /I. /D _WIN64 /D _CRT_SECURE_NO_DEPRECATE
TARGET = windows
all: $(TARGET)\train.exe $(TARGET)\predict.exe
diff --git a/README b/README
index 3a659e0..589d04a 100644
--- a/README
+++ b/README
@@ -123,7 +123,7 @@ options:
-s 1, 3, 4 and 7
Dual maximal violation <= eps; similar to libsvm (default 0.1)
-s 5 and 6
- |f'(w)|_inf <= eps*min(pos,neg)/l*|f'(w0)|_inf,
+ |f'(w)|_1 <= eps*min(pos,neg)/l*|f'(w0)|_1,
where f is the primal function (default 0.01)
-s 12 and 13\n"
|f'(alpha)|_1 <= eps |f'(alpha0)|,
@@ -131,11 +131,16 @@ options:
-B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)
-wi weight: weights adjust the parameter C of different classes (see README for details)
-v n: n-fold cross validation mode
+-C : find parameter C (only for -s 0 and 2)
-q : quiet mode (no outputs)
Option -v randomly splits the data into n parts and calculates cross
validation accuracy on them.
+Option -C conducts cross validation under different C values and finds
+the best one. This options is supported only by -s 0 and -s 2. If
+the solver is not specified, -s 2 is used.
+
Formulations:
For L2-regularized logistic regression (-s 0), we solve
@@ -241,10 +246,27 @@ Train a logistic regression model.
> train -v 5 -e 0.001 data_file
-Do five-fold cross-validation using L2-loss svm.
+Do five-fold cross-validation using L2-loss SVM.
Use a smaller stopping tolerance 0.001 than the default
0.1 if you want more accurate solutions.
+> train -C data_file
+
+Conduct cross validation many times by L2-loss SVM
+and find the parameter C which achieves the best cross
+validation accuracy.
+
+> train -C -s 0 -v 3 -c 0.5 -e 0.0001 data_file
+
+For parameter selection by -C, users can specify other
+solvers (currently -s 0 and -s 2 are supported) and
+different number of CV folds. Further, users can use
+the -c option to specify the smallest C value of the
+search range. This setting is useful when users want
+to rerun the parameter selection procedure from a
+specified C under a different setting, such as a stricter
+stopping tolerance -e 0.0001 in the above example.
+
> train -c 10 -w1 2 -w2 5 -w3 2 four_class_data_file
Train four classifiers:
@@ -407,6 +429,22 @@ Library Usage
The format of prob is same as that for train().
+- Function: void find_parameter_C(const struct problem *prob,
+ const struct parameter *param, int nr_fold, double start_C,
+ double max_C, double *best_C, double *best_rate);
+
+ This function is similar to cross_validation. However, instead of
+ conducting cross validation under a specified parameter C, it
+ conducts cross validation many times under parameters C = start_C,
+ 2*start_C, 4*start_C, 8*start_C, ..., and finds the best one with
+ the highest cross validation accuracy.
+
+ If start_C <= 0, then this procedure calculates a small enough C
+ for prob as the start_C. The procedure stops when the models of
+ all folds become stable or C reaches max_C. The best C and the
+ corresponding accuracy are assigned to *best_C and *best_rate,
+ respectively.
+
- Function: double predict(const model *model_, const feature_node *x);
For a classification model, the predicted class for x is returned.
@@ -418,11 +456,11 @@ Library Usage
This function gives nr_w decision values in the array dec_values.
nr_w=1 if regression is applied or the number of classes is two. An exception is
- multi-class svm by Crammer and Singer (-s 4), where nr_w = 2 if there are two classes. For all other situations, nr_w is the
+ multi-class SVM by Crammer and Singer (-s 4), where nr_w = 2 if there are two classes. For all other situations, nr_w is the
number of classes.
We implement one-vs-the rest multi-class strategy (-s 0,1,2,3,5,6,7)
- and multi-class svm by Crammer and Singer (-s 4) for multi-class SVM.
+ and multi-class SVM by Crammer and Singer (-s 4) for multi-class SVM.
The class with the highest decision value is returned.
- Function: double predict_probability(const struct model *model_,
@@ -448,6 +486,24 @@ Library Usage
This function outputs the name of labels into an array called label.
For a regression model, label is unchanged.
+- Function: double get_decfun_coef(const struct model *model_, int feat_idx,
+ int label_idx);
+
+ This function gives the coefficient for the feature with feature index =
+ feat_idx and the class with label index = label_idx. Note that feat_idx
+ starts from 1, while label_idx starts from 0. If feat_idx is not in the
+ valid range (1 to nr_feature), then a zero value will be returned. For
+ classification models, if label_idx is not in the valid range (0 to
+ nr_class-1), then a zero value will be returned; for regression models,
+ label_idx is ignored.
+
+- Function: double get_decfun_bias(const struct model *model_, int label_idx);
+
+ This function gives the bias term corresponding to the class with the
+ label_idx. For classification models, if label_idx is not in a valid range
+ (0 to nr_class-1), then a zero value will be returned; for regression
+ models, label_idx is ignored.
+
- Function: const char *check_parameter(const struct problem *prob,
const struct parameter *param);
@@ -456,6 +512,16 @@ Library Usage
train() and cross_validation(). It returns NULL if the
parameters are feasible, otherwise an error message is returned.
+- Function: int check_probability_model(const struct model *model);
+
+ This function returns 1 if the model supports probability output;
+ otherwise, it returns 0.
+
+- Function: int check_regression_model(const struct model *model);
+
+ This function returns 1 if the model is a regression model; otherwise
+ it returns 0.
+
- Function: int save_model(const char *model_file_name,
const struct model *model_);
@@ -495,7 +561,7 @@ Visual C++, use the following steps:
1. Open a dos command box and change to liblinear directory. If
environment variables of VC++ have not been set, type
-"C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
+""C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64\vcvars64.bat""
You may have to modify the above command according which version of
VC++ or where it is installed.
@@ -504,6 +570,9 @@ VC++ or where it is installed.
nmake -f Makefile.win clean all
+2. (Optional) To build 32-bit windows binaries, you must
+ (1) Setup "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\vcvars32.bat" instead of vcvars64.bat
+ (2) Change CFLAGS in Makefile.win: /D _WIN64 to /D _WIN32
MATLAB/OCTAVE Interface
=======================
diff --git a/blas/Makefile b/blas/Makefile
deleted file mode 100644
index 895fd24..0000000
--- a/blas/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-AR = ar rcv
-RANLIB = ranlib
-
-HEADERS = blas.h blasp.h
-FILES = dnrm2.o daxpy.o ddot.o dscal.o
-
-CFLAGS = $(OPTFLAGS)
-FFLAGS = $(OPTFLAGS)
-
-blas: $(FILES) $(HEADERS)
- $(AR) blas.a $(FILES)
- $(RANLIB) blas.a
-
-clean:
- - rm -f *.o
- - rm -f *.a
- - rm -f *~
-
-.c.o:
- $(CC) $(CFLAGS) -c $*.c
-
-
diff --git a/blas/blas.h b/blas/blas.h
deleted file mode 100644
index 558893a..0000000
--- a/blas/blas.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* blas.h -- C header file for BLAS Ver 1.0 */
-/* Jesse Bennett March 23, 2000 */
-
-/** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
-
- - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */
-
-#ifndef BLAS_INCLUDE
-#define BLAS_INCLUDE
-
-/* Data types specific to BLAS implementation */
-typedef struct { float r, i; } fcomplex;
-typedef struct { double r, i; } dcomplex;
-typedef int blasbool;
-
-#include "blasp.h" /* Prototypes for all BLAS functions */
-
-#define FALSE 0
-#define TRUE 1
-
-/* Macro functions */
-#define MIN(a,b) ((a) <= (b) ? (a) : (b))
-#define MAX(a,b) ((a) >= (b) ? (a) : (b))
-
-#endif
diff --git a/blas/blasp.h b/blas/blasp.h
deleted file mode 100644
index 745836d..0000000
--- a/blas/blasp.h
+++ /dev/null
@@ -1,430 +0,0 @@
-/* blasp.h -- C prototypes for BLAS Ver 1.0 */
-/* Jesse Bennett March 23, 2000 */
-
-/* Functions listed in alphabetical order */
-
-#ifdef F2C_COMPAT
-
-void cdotc_(fcomplex *dotval, int *n, fcomplex *cx, int *incx,
- fcomplex *cy, int *incy);
-
-void cdotu_(fcomplex *dotval, int *n, fcomplex *cx, int *incx,
- fcomplex *cy, int *incy);
-
-double sasum_(int *n, float *sx, int *incx);
-
-double scasum_(int *n, fcomplex *cx, int *incx);
-
-double scnrm2_(int *n, fcomplex *x, int *incx);
-
-double sdot_(int *n, float *sx, int *incx, float *sy, int *incy);
-
-double snrm2_(int *n, float *x, int *incx);
-
-void zdotc_(dcomplex *dotval, int *n, dcomplex *cx, int *incx,
- dcomplex *cy, int *incy);
-
-void zdotu_(dcomplex *dotval, int *n, dcomplex *cx, int *incx,
- dcomplex *cy, int *incy);
-
-#else
-
-fcomplex cdotc_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy);
-
-fcomplex cdotu_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy);
-
-float sasum_(int *n, float *sx, int *incx);
-
-float scasum_(int *n, fcomplex *cx, int *incx);
-
-float scnrm2_(int *n, fcomplex *x, int *incx);
-
-float sdot_(int *n, float *sx, int *incx, float *sy, int *incy);
-
-float snrm2_(int *n, float *x, int *incx);
-
-dcomplex zdotc_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy);
-
-dcomplex zdotu_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy);
-
-#endif
-
-/* Remaining functions listed in alphabetical order */
-
-int caxpy_(int *n, fcomplex *ca, fcomplex *cx, int *incx, fcomplex *cy,
- int *incy);
-
-int ccopy_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy);
-
-int cgbmv_(char *trans, int *m, int *n, int *kl, int *ku,
- fcomplex *alpha, fcomplex *a, int *lda, fcomplex *x, int *incx,
- fcomplex *beta, fcomplex *y, int *incy);
-
-int cgemm_(char *transa, char *transb, int *m, int *n, int *k,
- fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b, int *ldb,
- fcomplex *beta, fcomplex *c, int *ldc);
-
-int cgemv_(char *trans, int *m, int *n, fcomplex *alpha, fcomplex *a,
- int *lda, fcomplex *x, int *incx, fcomplex *beta, fcomplex *y,
- int *incy);
-
-int cgerc_(int *m, int *n, fcomplex *alpha, fcomplex *x, int *incx,
- fcomplex *y, int *incy, fcomplex *a, int *lda);
-
-int cgeru_(int *m, int *n, fcomplex *alpha, fcomplex *x, int *incx,
- fcomplex *y, int *incy, fcomplex *a, int *lda);
-
-int chbmv_(char *uplo, int *n, int *k, fcomplex *alpha, fcomplex *a,
- int *lda, fcomplex *x, int *incx, fcomplex *beta, fcomplex *y,
- int *incy);
-
-int chemm_(char *side, char *uplo, int *m, int *n, fcomplex *alpha,
- fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta,
- fcomplex *c, int *ldc);
-
-int chemv_(char *uplo, int *n, fcomplex *alpha, fcomplex *a, int *lda,
- fcomplex *x, int *incx, fcomplex *beta, fcomplex *y, int *incy);
-
-int cher_(char *uplo, int *n, float *alpha, fcomplex *x, int *incx,
- fcomplex *a, int *lda);
-
-int cher2_(char *uplo, int *n, fcomplex *alpha, fcomplex *x, int *incx,
- fcomplex *y, int *incy, fcomplex *a, int *lda);
-
-int cher2k_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha,
- fcomplex *a, int *lda, fcomplex *b, int *ldb, float *beta,
- fcomplex *c, int *ldc);
-
-int cherk_(char *uplo, char *trans, int *n, int *k, float *alpha,
- fcomplex *a, int *lda, float *beta, fcomplex *c, int *ldc);
-
-int chpmv_(char *uplo, int *n, fcomplex *alpha, fcomplex *ap, fcomplex *x,
- int *incx, fcomplex *beta, fcomplex *y, int *incy);
-
-int chpr_(char *uplo, int *n, float *alpha, fcomplex *x, int *incx,
- fcomplex *ap);
-
-int chpr2_(char *uplo, int *n, fcomplex *alpha, fcomplex *x, int *incx,
- fcomplex *y, int *incy, fcomplex *ap);
-
-int crotg_(fcomplex *ca, fcomplex *cb, float *c, fcomplex *s);
-
-int cscal_(int *n, fcomplex *ca, fcomplex *cx, int *incx);
-
-int csscal_(int *n, float *sa, fcomplex *cx, int *incx);
-
-int cswap_(int *n, fcomplex *cx, int *incx, fcomplex *cy, int *incy);
-
-int csymm_(char *side, char *uplo, int *m, int *n, fcomplex *alpha,
- fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta,
- fcomplex *c, int *ldc);
-
-int csyr2k_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha,
- fcomplex *a, int *lda, fcomplex *b, int *ldb, fcomplex *beta,
- fcomplex *c, int *ldc);
-
-int csyrk_(char *uplo, char *trans, int *n, int *k, fcomplex *alpha,
- fcomplex *a, int *lda, fcomplex *beta, fcomplex *c, int *ldc);
-
-int ctbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
- fcomplex *a, int *lda, fcomplex *x, int *incx);
-
-int ctbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
- fcomplex *a, int *lda, fcomplex *x, int *incx);
-
-int ctpmv_(char *uplo, char *trans, char *diag, int *n, fcomplex *ap,
- fcomplex *x, int *incx);
-
-int ctpsv_(char *uplo, char *trans, char *diag, int *n, fcomplex *ap,
- fcomplex *x, int *incx);
-
-int ctrmm_(char *side, char *uplo, char *transa, char *diag, int *m,
- int *n, fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b,
- int *ldb);
-
-int ctrmv_(char *uplo, char *trans, char *diag, int *n, fcomplex *a,
- int *lda, fcomplex *x, int *incx);
-
-int ctrsm_(char *side, char *uplo, char *transa, char *diag, int *m,
- int *n, fcomplex *alpha, fcomplex *a, int *lda, fcomplex *b,
- int *ldb);
-
-int ctrsv_(char *uplo, char *trans, char *diag, int *n, fcomplex *a,
- int *lda, fcomplex *x, int *incx);
-
-int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy,
- int *incy);
-
-int dcopy_(int *n, double *sx, int *incx, double *sy, int *incy);
-
-int dgbmv_(char *trans, int *m, int *n, int *kl, int *ku,
- double *alpha, double *a, int *lda, double *x, int *incx,
- double *beta, double *y, int *incy);
-
-int dgemm_(char *transa, char *transb, int *m, int *n, int *k,
- double *alpha, double *a, int *lda, double *b, int *ldb,
- double *beta, double *c, int *ldc);
-
-int dgemv_(char *trans, int *m, int *n, double *alpha, double *a,
- int *lda, double *x, int *incx, double *beta, double *y,
- int *incy);
-
-int dger_(int *m, int *n, double *alpha, double *x, int *incx,
- double *y, int *incy, double *a, int *lda);
-
-int drot_(int *n, double *sx, int *incx, double *sy, int *incy,
- double *c, double *s);
-
-int drotg_(double *sa, double *sb, double *c, double *s);
-
-int dsbmv_(char *uplo, int *n, int *k, double *alpha, double *a,
- int *lda, double *x, int *incx, double *beta, double *y,
- int *incy);
-
-int dscal_(int *n, double *sa, double *sx, int *incx);
-
-int dspmv_(char *uplo, int *n, double *alpha, double *ap, double *x,
- int *incx, double *beta, double *y, int *incy);
-
-int dspr_(char *uplo, int *n, double *alpha, double *x, int *incx,
- double *ap);
-
-int dspr2_(char *uplo, int *n, double *alpha, double *x, int *incx,
- double *y, int *incy, double *ap);
-
-int dswap_(int *n, double *sx, int *incx, double *sy, int *incy);
-
-int dsymm_(char *side, char *uplo, int *m, int *n, double *alpha,
- double *a, int *lda, double *b, int *ldb, double *beta,
- double *c, int *ldc);
-
-int dsymv_(char *uplo, int *n, double *alpha, double *a, int *lda,
- double *x, int *incx, double *beta, double *y, int *incy);
-
-int dsyr_(char *uplo, int *n, double *alpha, double *x, int *incx,
- double *a, int *lda);
-
-int dsyr2_(char *uplo, int *n, double *alpha, double *x, int *incx,
- double *y, int *incy, double *a, int *lda);
-
-int dsyr2k_(char *uplo, char *trans, int *n, int *k, double *alpha,
- double *a, int *lda, double *b, int *ldb, double *beta,
- double *c, int *ldc);
-
-int dsyrk_(char *uplo, char *trans, int *n, int *k, double *alpha,
- double *a, int *lda, double *beta, double *c, int *ldc);
-
-int dtbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
- double *a, int *lda, double *x, int *incx);
-
-int dtbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
- double *a, int *lda, double *x, int *incx);
-
-int dtpmv_(char *uplo, char *trans, char *diag, int *n, double *ap,
- double *x, int *incx);
-
-int dtpsv_(char *uplo, char *trans, char *diag, int *n, double *ap,
- double *x, int *incx);
-
-int dtrmm_(char *side, char *uplo, char *transa, char *diag, int *m,
- int *n, double *alpha, double *a, int *lda, double *b,
- int *ldb);
-
-int dtrmv_(char *uplo, char *trans, char *diag, int *n, double *a,
- int *lda, double *x, int *incx);
-
-int dtrsm_(char *side, char *uplo, char *transa, char *diag, int *m,
- int *n, double *alpha, double *a, int *lda, double *b,
- int *ldb);
-
-int dtrsv_(char *uplo, char *trans, char *diag, int *n, double *a,
- int *lda, double *x, int *incx);
-
-
-int saxpy_(int *n, float *sa, float *sx, int *incx, float *sy, int *incy);
-
-int scopy_(int *n, float *sx, int *incx, float *sy, int *incy);
-
-int sgbmv_(char *trans, int *m, int *n, int *kl, int *ku,
- float *alpha, float *a, int *lda, float *x, int *incx,
- float *beta, float *y, int *incy);
-
-int sgemm_(char *transa, char *transb, int *m, int *n, int *k,
- float *alpha, float *a, int *lda, float *b, int *ldb,
- float *beta, float *c, int *ldc);
-
-int sgemv_(char *trans, int *m, int *n, float *alpha, float *a,
- int *lda, float *x, int *incx, float *beta, float *y,
- int *incy);
-
-int sger_(int *m, int *n, float *alpha, float *x, int *incx,
- float *y, int *incy, float *a, int *lda);
-
-int srot_(int *n, float *sx, int *incx, float *sy, int *incy,
- float *c, float *s);
-
-int srotg_(float *sa, float *sb, float *c, float *s);
-
-int ssbmv_(char *uplo, int *n, int *k, float *alpha, float *a,
- int *lda, float *x, int *incx, float *beta, float *y,
- int *incy);
-
-int sscal_(int *n, float *sa, float *sx, int *incx);
-
-int sspmv_(char *uplo, int *n, float *alpha, float *ap, float *x,
- int *incx, float *beta, float *y, int *incy);
-
-int sspr_(char *uplo, int *n, float *alpha, float *x, int *incx,
- float *ap);
-
-int sspr2_(char *uplo, int *n, float *alpha, float *x, int *incx,
- float *y, int *incy, float *ap);
-
-int sswap_(int *n, float *sx, int *incx, float *sy, int *incy);
-
-int ssymm_(char *side, char *uplo, int *m, int *n, float *alpha,
- float *a, int *lda, float *b, int *ldb, float *beta,
- float *c, int *ldc);
-
-int ssymv_(char *uplo, int *n, float *alpha, float *a, int *lda,
- float *x, int *incx, float *beta, float *y, int *incy);
-
-int ssyr_(char *uplo, int *n, float *alpha, float *x, int *incx,
- float *a, int *lda);
-
-int ssyr2_(char *uplo, int *n, float *alpha, float *x, int *incx,
- float *y, int *incy, float *a, int *lda);
-
-int ssyr2k_(char *uplo, char *trans, int *n, int *k, float *alpha,
- float *a, int *lda, float *b, int *ldb, float *beta,
- float *c, int *ldc);
-
-int ssyrk_(char *uplo, char *trans, int *n, int *k, float *alpha,
- float *a, int *lda, float *beta, float *c, int *ldc);
-
-int stbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
- float *a, int *lda, float *x, int *incx);
-
-int stbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
- float *a, int *lda, float *x, int *incx);
-
-int stpmv_(char *uplo, char *trans, char *diag, int *n, float *ap,
- float *x, int *incx);
-
-int stpsv_(char *uplo, char *trans, char *diag, int *n, float *ap,
- float *x, int *incx);
-
-int strmm_(char *side, char *uplo, char *transa, char *diag, int *m,
- int *n, float *alpha, float *a, int *lda, float *b,
- int *ldb);
-
-int strmv_(char *uplo, char *trans, char *diag, int *n, float *a,
- int *lda, float *x, int *incx);
-
-int strsm_(char *side, char *uplo, char *transa, char *diag, int *m,
- int *n, float *alpha, float *a, int *lda, float *b,
- int *ldb);
-
-int strsv_(char *uplo, char *trans, char *diag, int *n, float *a,
- int *lda, float *x, int *incx);
-
-int zaxpy_(int *n, dcomplex *ca, dcomplex *cx, int *incx, dcomplex *cy,
- int *incy);
-
-int zcopy_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy);
-
-int zdscal_(int *n, double *sa, dcomplex *cx, int *incx);
-
-int zgbmv_(char *trans, int *m, int *n, int *kl, int *ku,
- dcomplex *alpha, dcomplex *a, int *lda, dcomplex *x, int *incx,
- dcomplex *beta, dcomplex *y, int *incy);
-
-int zgemm_(char *transa, char *transb, int *m, int *n, int *k,
- dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b, int *ldb,
- dcomplex *beta, dcomplex *c, int *ldc);
-
-int zgemv_(char *trans, int *m, int *n, dcomplex *alpha, dcomplex *a,
- int *lda, dcomplex *x, int *incx, dcomplex *beta, dcomplex *y,
- int *incy);
-
-int zgerc_(int *m, int *n, dcomplex *alpha, dcomplex *x, int *incx,
- dcomplex *y, int *incy, dcomplex *a, int *lda);
-
-int zgeru_(int *m, int *n, dcomplex *alpha, dcomplex *x, int *incx,
- dcomplex *y, int *incy, dcomplex *a, int *lda);
-
-int zhbmv_(char *uplo, int *n, int *k, dcomplex *alpha, dcomplex *a,
- int *lda, dcomplex *x, int *incx, dcomplex *beta, dcomplex *y,
- int *incy);
-
-int zhemm_(char *side, char *uplo, int *m, int *n, dcomplex *alpha,
- dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta,
- dcomplex *c, int *ldc);
-
-int zhemv_(char *uplo, int *n, dcomplex *alpha, dcomplex *a, int *lda,
- dcomplex *x, int *incx, dcomplex *beta, dcomplex *y, int *incy);
-
-int zher_(char *uplo, int *n, double *alpha, dcomplex *x, int *incx,
- dcomplex *a, int *lda);
-
-int zher2_(char *uplo, int *n, dcomplex *alpha, dcomplex *x, int *incx,
- dcomplex *y, int *incy, dcomplex *a, int *lda);
-
-int zher2k_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha,
- dcomplex *a, int *lda, dcomplex *b, int *ldb, double *beta,
- dcomplex *c, int *ldc);
-
-int zherk_(char *uplo, char *trans, int *n, int *k, double *alpha,
- dcomplex *a, int *lda, double *beta, dcomplex *c, int *ldc);
-
-int zhpmv_(char *uplo, int *n, dcomplex *alpha, dcomplex *ap, dcomplex *x,
- int *incx, dcomplex *beta, dcomplex *y, int *incy);
-
-int zhpr_(char *uplo, int *n, double *alpha, dcomplex *x, int *incx,
- dcomplex *ap);
-
-int zhpr2_(char *uplo, int *n, dcomplex *alpha, dcomplex *x, int *incx,
- dcomplex *y, int *incy, dcomplex *ap);
-
-int zrotg_(dcomplex *ca, dcomplex *cb, double *c, dcomplex *s);
-
-int zscal_(int *n, dcomplex *ca, dcomplex *cx, int *incx);
-
-int zswap_(int *n, dcomplex *cx, int *incx, dcomplex *cy, int *incy);
-
-int zsymm_(char *side, char *uplo, int *m, int *n, dcomplex *alpha,
- dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta,
- dcomplex *c, int *ldc);
-
-int zsyr2k_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha,
- dcomplex *a, int *lda, dcomplex *b, int *ldb, dcomplex *beta,
- dcomplex *c, int *ldc);
-
-int zsyrk_(char *uplo, char *trans, int *n, int *k, dcomplex *alpha,
- dcomplex *a, int *lda, dcomplex *beta, dcomplex *c, int *ldc);
-
-int ztbmv_(char *uplo, char *trans, char *diag, int *n, int *k,
- dcomplex *a, int *lda, dcomplex *x, int *incx);
-
-int ztbsv_(char *uplo, char *trans, char *diag, int *n, int *k,
- dcomplex *a, int *lda, dcomplex *x, int *incx);
-
-int ztpmv_(char *uplo, char *trans, char *diag, int *n, dcomplex *ap,
- dcomplex *x, int *incx);
-
-int ztpsv_(char *uplo, char *trans, char *diag, int *n, dcomplex *ap,
- dcomplex *x, int *incx);
-
-int ztrmm_(char *side, char *uplo, char *transa, char *diag, int *m,
- int *n, dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b,
- int *ldb);
-
-int ztrmv_(char *uplo, char *trans, char *diag, int *n, dcomplex *a,
- int *lda, dcomplex *x, int *incx);
-
-int ztrsm_(char *side, char *uplo, char *transa, char *diag, int *m,
- int *n, dcomplex *alpha, dcomplex *a, int *lda, dcomplex *b,
- int *ldb);
-
-int ztrsv_(char *uplo, char *trans, char *diag, int *n, dcomplex *a,
- int *lda, dcomplex *x, int *incx);
diff --git a/blas/daxpy.c b/blas/daxpy.c
deleted file mode 100644
index 58f345a..0000000
--- a/blas/daxpy.c
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "blas.h"
-
-int daxpy_(int *n, double *sa, double *sx, int *incx, double *sy,
- int *incy)
-{
- long int i, m, ix, iy, nn, iincx, iincy;
- register double ssa;
-
- /* constant times a vector plus a vector.
- uses unrolled loop for increments equal to one.
- jack dongarra, linpack, 3/11/78.
- modified 12/3/93, array(1) declarations changed to array(*) */
-
- /* Dereference inputs */
- nn = *n;
- ssa = *sa;
- iincx = *incx;
- iincy = *incy;
-
- if( nn > 0 && ssa != 0.0 )
- {
- if (iincx == 1 && iincy == 1) /* code for both increments equal to 1 */
- {
- m = nn-3;
- for (i = 0; i < m; i += 4)
- {
- sy[i] += ssa * sx[i];
- sy[i+1] += ssa * sx[i+1];
- sy[i+2] += ssa * sx[i+2];
- sy[i+3] += ssa * sx[i+3];
- }
- for ( ; i < nn; ++i) /* clean-up loop */
- sy[i] += ssa * sx[i];
- }
- else /* code for unequal increments or equal increments not equal to 1 */
- {
- ix = iincx >= 0 ? 0 : (1 - nn) * iincx;
- iy = iincy >= 0 ? 0 : (1 - nn) * iincy;
- for (i = 0; i < nn; i++)
- {
- sy[iy] += ssa * sx[ix];
- ix += iincx;
- iy += iincy;
- }
- }
- }
-
- return 0;
-} /* daxpy_ */
diff --git a/blas/ddot.c b/blas/ddot.c
deleted file mode 100644
index a64a280..0000000
--- a/blas/ddot.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "blas.h"
-
-double ddot_(int *n, double *sx, int *incx, double *sy, int *incy)
-{
- long int i, m, nn, iincx, iincy;
- double stemp;
- long int ix, iy;
-
- /* forms the dot product of two vectors.
- uses unrolled loops for increments equal to one.
- jack dongarra, linpack, 3/11/78.
- modified 12/3/93, array(1) declarations changed to array(*) */
-
- /* Dereference inputs */
- nn = *n;
- iincx = *incx;
- iincy = *incy;
-
- stemp = 0.0;
- if (nn > 0)
- {
- if (iincx == 1 && iincy == 1) /* code for both increments equal to 1 */
- {
- m = nn-4;
- for (i = 0; i < m; i += 5)
- stemp += sx[i] * sy[i] + sx[i+1] * sy[i+1] + sx[i+2] * sy[i+2] +
- sx[i+3] * sy[i+3] + sx[i+4] * sy[i+4];
-
- for ( ; i < nn; i++) /* clean-up loop */
- stemp += sx[i] * sy[i];
- }
- else /* code for unequal increments or equal increments not equal to 1 */
- {
- ix = 0;
- iy = 0;
- if (iincx < 0)
- ix = (1 - nn) * iincx;
- if (iincy < 0)
- iy = (1 - nn) * iincy;
- for (i = 0; i < nn; i++)
- {
- stemp += sx[ix] * sy[iy];
- ix += iincx;
- iy += iincy;
- }
- }
- }
-
- return stemp;
-} /* ddot_ */
diff --git a/blas/dnrm2.c b/blas/dnrm2.c
deleted file mode 100644
index e50cdf7..0000000
--- a/blas/dnrm2.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#include <math.h> /* Needed for fabs() and sqrt() */
-#include "blas.h"
-
-double dnrm2_(int *n, double *x, int *incx)
-{
- long int ix, nn, iincx;
- double norm, scale, absxi, ssq, temp;
-
-/* DNRM2 returns the euclidean norm of a vector via the function
- name, so that
-
- DNRM2 := sqrt( x'*x )
-
- -- This version written on 25-October-1982.
- Modified on 14-October-1993 to inline the call to SLASSQ.
- Sven Hammarling, Nag Ltd. */
-
- /* Dereference inputs */
- nn = *n;
- iincx = *incx;
-
- if( nn > 0 && iincx > 0 )
- {
- if (nn == 1)
- {
- norm = fabs(x[0]);
- }
- else
- {
- scale = 0.0;
- ssq = 1.0;
-
- /* The following loop is equivalent to this call to the LAPACK
- auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
-
- for (ix=(nn-1)*iincx; ix>=0; ix-=iincx)
- {
- if (x[ix] != 0.0)
- {
- absxi = fabs(x[ix]);
- if (scale < absxi)
- {
- temp = scale / absxi;
- ssq = ssq * (temp * temp) + 1.0;
- scale = absxi;
- }
- else
- {
- temp = absxi / scale;
- ssq += temp * temp;
- }
- }
- }
- norm = scale * sqrt(ssq);
- }
- }
- else
- norm = 0.0;
-
- return norm;
-
-} /* dnrm2_ */
diff --git a/blas/dscal.c b/blas/dscal.c
deleted file mode 100644
index a0eca0c..0000000
--- a/blas/dscal.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "blas.h"
-
-int dscal_(int *n, double *sa, double *sx, int *incx)
-{
- long int i, m, nincx, nn, iincx;
- double ssa;
-
- /* scales a vector by a constant.
- uses unrolled loops for increment equal to 1.
- jack dongarra, linpack, 3/11/78.
- modified 3/93 to return if incx .le. 0.
- modified 12/3/93, array(1) declarations changed to array(*) */
-
- /* Dereference inputs */
- nn = *n;
- iincx = *incx;
- ssa = *sa;
-
- if (nn > 0 && iincx > 0)
- {
- if (iincx == 1) /* code for increment equal to 1 */
- {
- m = nn-4;
- for (i = 0; i < m; i += 5)
- {
- sx[i] = ssa * sx[i];
- sx[i+1] = ssa * sx[i+1];
- sx[i+2] = ssa * sx[i+2];
- sx[i+3] = ssa * sx[i+3];
- sx[i+4] = ssa * sx[i+4];
- }
- for ( ; i < nn; ++i) /* clean-up loop */
- sx[i] = ssa * sx[i];
- }
- else /* code for increment not equal to 1 */
- {
- nincx = nn * iincx;
- for (i = 0; i < nincx; i += iincx)
- sx[i] = ssa * sx[i];
- }
- }
-
- return 0;
-} /* dscal_ */
diff --git a/linear.cpp b/linear.cpp
index 6843833..deb0169 100644
--- a/linear.cpp
+++ b/linear.cpp
@@ -27,6 +27,7 @@ static void print_string_stdout(const char *s)
fputs(s,stdout);
fflush(stdout);
}
+static void print_null(const char *s) {}
static void (*liblinear_print_string) (const char *) = &print_string_stdout;
@@ -1010,7 +1011,7 @@ static void solve_l2r_l1l2_svr(
double d, G, H;
double Gmax_old = INF;
double Gmax_new, Gnorm1_new;
- double Gnorm1_init;
+ double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration
double *beta = new double[l];
double *QD = new double[l];
double *y = prob->y;
@@ -1409,7 +1410,7 @@ static void solve_l1r_l2_svc(
double d, G_loss, G, H;
double Gmax_old = INF;
double Gmax_new, Gnorm1_new;
- double Gnorm1_init;
+ double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration
double d_old, d_diff;
double loss_old, loss_new;
double appxcond, cond;
@@ -1699,7 +1700,7 @@ static void solve_l1r_lr(
double sigma = 0.01;
double w_norm, w_norm_new;
double z, G, H;
- double Gnorm1_init;
+ double Gnorm1_init = -1.0; // Gnorm1_init is initialized at the first iteration
double Gmax_old = INF;
double Gmax_new, Gnorm1_new;
double QP_Gmax_old = INF;
@@ -2051,8 +2052,8 @@ static void transpose(const problem *prob, feature_node **x_space_ret, problem *
int i;
int l = prob->l;
int n = prob->n;
- long int nnz = 0;
- long int *col_ptr = new long int [n+1];
+ size_t nnz = 0;
+ size_t *col_ptr = new size_t [n+1];
feature_node *x_space;
prob_col->l = l;
prob_col->n = n;
@@ -2180,14 +2181,18 @@ static void group_classes(const problem *prob, int *nr_class_ret, int **label_re
static void train_one(const problem *prob, const parameter *param, double *w, double Cp, double Cn)
{
- double eps=param->eps;
+ //inner and outer tolerances for TRON
+ double eps = param->eps;
+ double eps_cg = 0.1;
+ if(param->init_sol != NULL)
+ eps_cg = 0.5;
+
int pos = 0;
int neg = 0;
for(int i=0;i<prob->l;i++)
if(prob->y[i] > 0)
pos++;
neg = prob->l - pos;
-
double primal_solver_tol = eps*max(min(pos,neg), 1)/prob->l;
function *fun_obj=NULL;
@@ -2204,7 +2209,7 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
C[i] = Cn;
}
fun_obj=new l2r_lr_fun(prob, C);
- TRON tron_obj(fun_obj, primal_solver_tol);
+ TRON tron_obj(fun_obj, primal_solver_tol, eps_cg);
tron_obj.set_print_string(liblinear_print_string);
tron_obj.tron(w);
delete fun_obj;
@@ -2222,7 +2227,7 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
C[i] = Cn;
}
fun_obj=new l2r_l2_svc_fun(prob, C);
- TRON tron_obj(fun_obj, primal_solver_tol);
+ TRON tron_obj(fun_obj, primal_solver_tol, eps_cg);
tron_obj.set_print_string(liblinear_print_string);
tron_obj.tron(w);
delete fun_obj;
@@ -2287,6 +2292,36 @@ static void train_one(const problem *prob, const parameter *param, double *w, do
}
}
+// Calculate the initial C for parameter selection
+static double calc_start_C(const problem *prob, const parameter *param)
+{
+ int i;
+ double xTx,max_xTx;
+ max_xTx = 0;
+ for(i=0; i<prob->l; i++)
+ {
+ xTx = 0;
+ feature_node *xi=prob->x[i];
+ while(xi->index != -1)
+ {
+ double val = xi->value;
+ xTx += val*val;
+ xi++;
+ }
+ if(xTx > max_xTx)
+ max_xTx = xTx;
+ }
+
+ double min_C = 1.0;
+ if(param->solver_type == L2R_LR)
+ min_C = 1.0 / (prob->l * max_xTx);
+ else if(param->solver_type == L2R_L2LOSS_SVC)
+ min_C = 1.0 / (2 * prob->l * max_xTx);
+
+ return pow( 2, floor(log(min_C) / log(2.0)) );
+}
+
+
//
// Interface functions
//
@@ -2305,14 +2340,14 @@ model* train(const problem *prob, const parameter *param)
model_->param = *param;
model_->bias = prob->bias;
- if(param->solver_type == L2R_L2LOSS_SVR ||
- param->solver_type == L2R_L1LOSS_SVR_DUAL ||
- param->solver_type == L2R_L2LOSS_SVR_DUAL)
+ if(check_regression_model(model_))
{
model_->w = Malloc(double, w_size);
+ for(i=0; i<w_size; i++)
+ model_->w[i] = 0;
model_->nr_class = 2;
model_->label = NULL;
- train_one(prob, param, &model_->w[0], 0, 0);
+ train_one(prob, param, model_->w, 0, 0);
}
else
{
@@ -2382,8 +2417,15 @@ model* train(const problem *prob, const parameter *param)
sub_prob.y[k] = +1;
for(; k<sub_prob.l; k++)
sub_prob.y[k] = -1;
+
+ if(param->init_sol != NULL)
+ for(i=0;i<w_size;i++)
+ model_->w[i] = param->init_sol[i];
+ else
+ for(i=0;i<w_size;i++)
+ model_->w[i] = 0;
- train_one(&sub_prob, param, &model_->w[0], weighted_C[0], weighted_C[1]);
+ train_one(&sub_prob, param, model_->w, weighted_C[0], weighted_C[1]);
}
else
{
@@ -2402,6 +2444,13 @@ model* train(const problem *prob, const parameter *param)
for(; k<sub_prob.l; k++)
sub_prob.y[k] = -1;
+ if(param->init_sol != NULL)
+ for(j=0;j<w_size;j++)
+ w[j] = param->init_sol[j*nr_class+i];
+ else
+ for(j=0;j<w_size;j++)
+ w[j] = 0;
+
train_one(&sub_prob, param, w, weighted_C[i], param->C);
for(int j=0;j<w_size;j++)
@@ -2482,6 +2531,158 @@ void cross_validation(const problem *prob, const parameter *param, int nr_fold,
free(perm);
}
+void find_parameter_C(const problem *prob, const parameter *param, int nr_fold, double start_C, double max_C, double *best_C, double *best_rate)
+{
+ // variables for CV
+ int i;
+ int *fold_start;
+ int l = prob->l;
+ int *perm = Malloc(int, l);
+ double *target = Malloc(double, prob->l);
+ struct problem *subprob = Malloc(problem,nr_fold);
+
+ // variables for warm start
+ double ratio = 2;
+ double **prev_w = Malloc(double*, nr_fold);
+ for(i = 0; i < nr_fold; i++)
+ prev_w[i] = NULL;
+ int num_unchanged_w = 0;
+ struct parameter param1 = *param;
+ void (*default_print_string) (const char *) = liblinear_print_string;
+
+ if (nr_fold > l)
+ {
+ nr_fold = l;
+ fprintf(stderr,"WARNING: # folds > # data. Will use # folds = # data instead (i.e., leave-one-out cross validation)\n");
+ }
+ fold_start = Malloc(int,nr_fold+1);
+ for(i=0;i<l;i++) perm[i]=i;
+ for(i=0;i<l;i++)
+ {
+ int j = i+rand()%(l-i);
+ swap(perm[i],perm[j]);
+ }
+ for(i=0;i<=nr_fold;i++)
+ fold_start[i]=i*l/nr_fold;
+
+ for(i=0;i<nr_fold;i++)
+ {
+ int begin = fold_start[i];
+ int end = fold_start[i+1];
+ int j,k;
+
+ subprob[i].bias = prob->bias;
+ subprob[i].n = prob->n;
+ subprob[i].l = l-(end-begin);
+ subprob[i].x = Malloc(struct feature_node*,subprob[i].l);
+ subprob[i].y = Malloc(double,subprob[i].l);
+
+ k=0;
+ for(j=0;j<begin;j++)
+ {
+ subprob[i].x[k] = prob->x[perm[j]];
+ subprob[i].y[k] = prob->y[perm[j]];
+ ++k;
+ }
+ for(j=end;j<l;j++)
+ {
+ subprob[i].x[k] = prob->x[perm[j]];
+ subprob[i].y[k] = prob->y[perm[j]];
+ ++k;
+ }
+
+ }
+
+ *best_rate = 0;
+ if(start_C <= 0)
+ start_C = calc_start_C(prob,param);
+ param1.C = start_C;
+
+ while(param1.C <= max_C)
+ {
+ //Output diabled for running CV at a particular C
+ set_print_string_function(&print_null);
+
+ for(i=0; i<nr_fold; i++)
+ {
+ int j;
+ int begin = fold_start[i];
+ int end = fold_start[i+1];
+
+ param1.init_sol = prev_w[i];
+ struct model *submodel = train(&subprob[i],¶m1);
+
+ int total_w_size;
+ if(submodel->nr_class == 2)
+ total_w_size = subprob[i].n;
+ else
+ total_w_size = subprob[i].n * submodel->nr_class;
+
+ if(prev_w[i] == NULL)
+ {
+ prev_w[i] = Malloc(double, total_w_size);
+ for(j=0; j<total_w_size; j++)
+ prev_w[i][j] = submodel->w[j];
+ }
+ else if(num_unchanged_w >= 0)
+ {
+ double norm_w_diff = 0;
+ for(j=0; j<total_w_size; j++)
+ {
+ norm_w_diff += (submodel->w[j] - prev_w[i][j])*(submodel->w[j] - prev_w[i][j]);
+ prev_w[i][j] = submodel->w[j];
+ }
+ norm_w_diff = sqrt(norm_w_diff);
+
+ if(norm_w_diff > 1e-15)
+ num_unchanged_w = -1;
+ }
+ else
+ {
+ for(j=0; j<total_w_size; j++)
+ prev_w[i][j] = submodel->w[j];
+ }
+
+ for(j=begin; j<end; j++)
+ target[perm[j]] = predict(submodel,prob->x[perm[j]]);
+
+ free_and_destroy_model(&submodel);
+ }
+ set_print_string_function(default_print_string);
+
+ int total_correct = 0;
+ for(i=0; i<prob->l; i++)
+ if(target[i] == prob->y[i])
+ ++total_correct;
+ double current_rate = (double)total_correct/prob->l;
+ if(current_rate > *best_rate)
+ {
+ *best_C = param1.C;
+ *best_rate = current_rate;
+ }
+
+ info("log2c=%7.2f\trate=%g\n",log(param1.C)/log(2.0),100.0*current_rate);
+ num_unchanged_w++;
+ if(num_unchanged_w == 3)
+ break;
+ param1.C = param1.C*ratio;
+ }
+
+ if(param1.C > max_C && max_C > start_C)
+ info("warning: maximum C reached.\n");
+ free(fold_start);
+ free(perm);
+ free(target);
+ for(i=0; i<nr_fold; i++)
+ {
+ free(subprob[i].x);
+ free(subprob[i].y);
+ free(prev_w[i]);
+ }
+ free(prev_w);
+ free(subprob);
+}
+
double predict_values(const struct model *model_, const struct feature_node *x, double *dec_values)
{
int idx;
@@ -2512,9 +2713,7 @@ double predict_values(const struct model *model_, const struct feature_node *x,
if(nr_class==2)
{
- if(model_->param.solver_type == L2R_L2LOSS_SVR ||
- model_->param.solver_type == L2R_L1LOSS_SVR_DUAL ||
- model_->param.solver_type == L2R_L2LOSS_SVR_DUAL)
+ if(check_regression_model(model_))
return dec_values[0];
else
return (dec_values[0]>0)?model_->label[0]:model_->label[1];
@@ -2596,7 +2795,11 @@ int save_model(const char *model_file_name, const struct model *model_)
FILE *fp = fopen(model_file_name,"w");
if(fp==NULL) return -1;
- char *old_locale = strdup(setlocale(LC_ALL, NULL));
+ char *old_locale = setlocale(LC_ALL, NULL);
+ if (old_locale)
+ {
+ old_locale = strdup(old_locale);
+ }
setlocale(LC_ALL, "C");
int nr_w;
@@ -2651,7 +2854,11 @@ struct model *load_model(const char *model_file_name)
model_->label = NULL;
- char *old_locale = strdup(setlocale(LC_ALL, NULL));
+ char *old_locale = setlocale(LC_ALL, NULL);
+ if (old_locale)
+ {
+ old_locale = strdup(old_locale);
+ }
setlocale(LC_ALL, "C");
char cmd[81];
@@ -2764,6 +2971,53 @@ void get_labels(const model *model_, int* label)
label[i] = model_->label[i];
}
+// use inline here for better performance (around 20% faster than the non-inline one)
+static inline double get_w_value(const struct model *model_, int idx, int label_idx)
+{
+ int nr_class = model_->nr_class;
+ int solver_type = model_->param.solver_type;
+ const double *w = model_->w;
+
+ if(idx < 0 || idx > model_->nr_feature)
+ return 0;
+ if(check_regression_model(model_))
+ return w[idx];
+ else
+ {
+ if(label_idx < 0 || label_idx >= nr_class)
+ return 0;
+ if(nr_class == 2 && solver_type != MCSVM_CS)
+ {
+ if(label_idx == 0)
+ return w[idx];
+ else
+ return -w[idx];
+ }
+ else
+ return w[idx*nr_class+label_idx];
+ }
+}
+
+// feat_idx: starting from 1 to nr_feature
+// label_idx: starting from 0 to nr_class-1 for classification models;
+// for regression models, label_idx is ignored.
+double get_decfun_coef(const struct model *model_, int feat_idx, int label_idx)
+{
+ if(feat_idx > model_->nr_feature)
+ return 0;
+ return get_w_value(model_, feat_idx-1, label_idx);
+}
+
+double get_decfun_bias(const struct model *model_, int label_idx)
+{
+ int bias_idx = model_->nr_feature;
+ double bias = model_->bias;
+ if(bias <= 0)
+ return 0;
+ else
+ return bias*get_w_value(model_, bias_idx, label_idx);
+}
+
void free_model_content(struct model *model_ptr)
{
if(model_ptr->w != NULL)
@@ -2788,6 +3042,8 @@ void destroy_param(parameter* param)
free(param->weight_label);
if(param->weight != NULL)
free(param->weight);
+ if(param->init_sol != NULL)
+ free(param->init_sol);
}
const char *check_parameter(const problem *prob, const parameter *param)
@@ -2814,6 +3070,10 @@ const char *check_parameter(const problem *prob, const parameter *param)
&& param->solver_type != L2R_L1LOSS_SVR_DUAL)
return "unknown solver type";
+ if(param->init_sol != NULL
+ && param->solver_type != L2R_LR && param->solver_type != L2R_L2LOSS_SVC)
+ return "Initial-solution specification supported only for solver L2R_LR and L2R_L2LOSS_SVC";
+
return NULL;
}
@@ -2824,6 +3084,13 @@ int check_probability_model(const struct model *model_)
model_->param.solver_type==L1R_LR);
}
+int check_regression_model(const struct model *model_)
+{
+ return (model_->param.solver_type==L2R_L2LOSS_SVR ||
+ model_->param.solver_type==L2R_L1LOSS_SVR_DUAL ||
+ model_->param.solver_type==L2R_L2LOSS_SVR_DUAL);
+}
+
void set_print_string_function(void (*print_func)(const char*))
{
if (print_func == NULL)
diff --git a/linear.def b/linear.def
index 2425996..96e2620 100644
--- a/linear.def
+++ b/linear.def
@@ -16,3 +16,6 @@ EXPORTS
check_parameter @14
check_probability_model @15
set_print_string_function @16
+ get_decfun_coef @17
+ get_decfun_bias @18
+ check_regression_model @19
diff --git a/linear.h b/linear.h
index 22a3567..bc6aaf8 100644
--- a/linear.h
+++ b/linear.h
@@ -32,6 +32,7 @@ struct parameter
int *weight_label;
double* weight;
double p;
+ double *init_sol;
};
struct model
@@ -46,6 +47,7 @@ struct model
struct model* train(const struct problem *prob, const struct parameter *param);
void cross_validation(const struct problem *prob, const struct parameter *param, int nr_fold, double *target);
+void find_parameter_C(const struct problem *prob, const struct parameter *param, int nr_fold, double start_C, double max_C, double *best_C, double *best_rate);
double predict_values(const struct model *model_, const struct feature_node *x, double* dec_values);
double predict(const struct model *model_, const struct feature_node *x);
@@ -57,6 +59,8 @@ struct model *load_model(const char *model_file_name);
int get_nr_feature(const struct model *model_);
int get_nr_class(const struct model *model_);
void get_labels(const struct model *model_, int* label);
+double get_decfun_coef(const struct model *model_, int feat_idx, int label_idx);
+double get_decfun_bias(const struct model *model_, int label_idx);
void free_model_content(struct model *model_ptr);
void free_and_destroy_model(struct model **model_ptr_ptr);
@@ -64,6 +68,7 @@ void destroy_param(struct parameter *param);
const char *check_parameter(const struct problem *prob, const struct parameter *param);
int check_probability_model(const struct model *model);
+int check_regression_model(const struct model *model);
void set_print_string_function(void (*print_func) (const char*));
#ifdef __cplusplus
diff --git a/matlab/Makefile b/matlab/Makefile
index f05fab4..e0db5f6 100644
--- a/matlab/Makefile
+++ b/matlab/Makefile
@@ -7,33 +7,24 @@ CC ?= gcc
CFLAGS = -Wall -Wconversion -O3 -fPIC -I$(MATLABDIR)/extern/include -I..
MEX = $(MATLABDIR)/bin/mex
-MEX_OPTION = CC\#$(CXX) CXX\#$(CXX) CFLAGS\#"$(CFLAGS)" CXXFLAGS\#"$(CFLAGS)"
+MEX_OPTION = CC="$(CXX)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CFLAGS)"
# comment the following line if you use MATLAB on a 32-bit computer
MEX_OPTION += -largeArrayDims
MEX_EXT = $(shell $(MATLABDIR)/bin/mexext)
-OCTAVEDIR ?= /usr/include/octave
-OCTAVE_MEX = env CC=$(CXX) mkoctfile
-OCTAVE_MEX_OPTION = --mex
-OCTAVE_MEX_EXT = mex
-OCTAVE_CFLAGS = -Wall -O3 -fPIC -I$(OCTAVEDIR) -I..
-
all: matlab
matlab: binary
octave:
- @make MEX="$(OCTAVE_MEX)" MEX_OPTION="$(OCTAVE_MEX_OPTION)" \
- MEX_EXT="$(OCTAVE_MEX_EXT)" CFLAGS="$(OCTAVE_CFLAGS)" \
- binary
-
+ @echo "please type make under Octave"
binary: train.$(MEX_EXT) predict.$(MEX_EXT) libsvmread.$(MEX_EXT) libsvmwrite.$(MEX_EXT)
-train.$(MEX_EXT): train.c ../linear.h ../tron.o ../linear.o linear_model_matlab.o ../blas/blas.a
- $(MEX) $(MEX_OPTION) train.c ../tron.o ../linear.o linear_model_matlab.o ../blas/blas.a
+train.$(MEX_EXT): train.c ../linear.h ../tron.o ../linear.o linear_model_matlab.o
+ $(MEX) $(MEX_OPTION) train.c ../tron.o ../linear.o linear_model_matlab.o
-predict.$(MEX_EXT): predict.c ../linear.h ../tron.o ../linear.o linear_model_matlab.o ../blas/blas.a
- $(MEX) $(MEX_OPTION) predict.c ../tron.o ../linear.o linear_model_matlab.o ../blas/blas.a
+predict.$(MEX_EXT): predict.c ../linear.h ../tron.o ../linear.o linear_model_matlab.o
+ $(MEX) $(MEX_OPTION) predict.c ../tron.o ../linear.o linear_model_matlab.o
libsvmread.$(MEX_EXT): libsvmread.c
$(MEX) $(MEX_OPTION) libsvmread.c
@@ -50,9 +41,5 @@ linear_model_matlab.o: linear_model_matlab.c ../linear.h
../tron.o: ../tron.cpp ../tron.h
make -C .. tron.o
-../blas/blas.a: ../blas/*.c ../blas/*.h
- make -C ../blas OPTFLAGS='$(CFLAGS)' CC='$(CC)';
-
clean:
- make -C ../blas clean
rm -f *~ *.o *.mex* *.obj ../linear.o ../tron.o
diff --git a/matlab/README b/matlab/README
index 00e1358..f53f435 100644
--- a/matlab/README
+++ b/matlab/README
@@ -117,7 +117,7 @@ The 'train' function returns a model which can be used for future
prediction. It is a structure and is organized as [Parameters, nr_class,
nr_feature, bias, Label, w]:
- -Parameters: Parameters
+ -Parameters: Parameters (now only solver type is provided)
-nr_class: number of classes; = 2 for regression
-nr_feature: number of features in training data (without including the bias term)
-bias: If >= 0, we assume one additional feature is added to the end
@@ -131,7 +131,12 @@ nr_feature, bias, Label, w]:
If the '-v' option is specified, cross validation is conducted and the
returned model is just a scalar: cross-validation accuracy for
-classification and mean-squared error for regression.
+classification and mean-squared error for regression. If the '-C' option
+is specified, the best parameter C is found by cross validation. The
+returned model is a two dimensional vector, where the first value is
+the best C and the second value is the corresponding cross-validation
+accuracy. The parameter selection utility is supported by only -s 0
+and -s 2.
Result of Prediction
====================
@@ -184,6 +189,11 @@ For probability estimates, you need '-b 1' only in the testing phase:
matlab> [predict_label, accuracy, prob_estimates] = predict(heart_scale_label, heart_scale_inst, model, '-b 1');
+Use the best parameter to train (only supported by -s 0 and -s 2):
+
+matlab> best = train(heart_scale_label, heart_scale_inst, '-C -s 0');
+matlab> model = train(heart_scale_label, heart_scale_inst, sprintf('-c %f -s 0', best(1))); % use the same solver: -s 0
+
Additional Information
======================
diff --git a/matlab/libsvmread.c b/matlab/libsvmread.c
index a6365d1..d2fe0f5 100644
--- a/matlab/libsvmread.c
+++ b/matlab/libsvmread.c
@@ -56,14 +56,13 @@ static char* readline(FILE *input)
// read in a problem (in libsvm format)
void read_problem(const char *filename, int nlhs, mxArray *plhs[])
{
- int max_index, min_index, inst_max_index, i;
- long elements, k;
+ int max_index, min_index, inst_max_index;
+ size_t elements, k, i, l=0;
FILE *fp = fopen(filename,"r");
- int l = 0;
char *endptr;
mwIndex *ir, *jc;
double *labels, *samples;
-
+
if(fp == NULL)
{
mexPrintf("can't open input file %s\n",filename);
diff --git a/matlab/libsvmwrite.c b/matlab/libsvmwrite.c
index d7fae76..9c93fd3 100644
--- a/matlab/libsvmwrite.c
+++ b/matlab/libsvmwrite.c
@@ -26,9 +26,8 @@ static void fake_answer(int nlhs, mxArray *plhs[])
void libsvmwrite(const char *filename, const mxArray *label_vec, const mxArray *instance_mat)
{
FILE *fp = fopen(filename,"w");
- int i, k, low, high, l;
- mwIndex *ir, *jc;
- int label_vector_row_num;
+ mwIndex *ir, *jc, k, low, high;
+ size_t i, l, label_vector_row_num;
double *samples, *labels;
mxArray *instance_mat_col; // instance sparse matrix in column format
@@ -52,8 +51,8 @@ void libsvmwrite(const char *filename, const mxArray *label_vec, const mxArray *
}
// the number of instance
- l = (int) mxGetN(instance_mat_col);
- label_vector_row_num = (int) mxGetM(label_vec);
+ l = mxGetN(instance_mat_col);
+ label_vector_row_num = mxGetM(label_vec);
if(label_vector_row_num!=l)
{
@@ -71,9 +70,9 @@ void libsvmwrite(const char *filename, const mxArray *label_vec, const mxArray *
{
fprintf(fp,"%g", labels[i]);
- low = (int) jc[i], high = (int) jc[i+1];
+ low = jc[i], high = jc[i+1];
for(k=low;k<high;k++)
- fprintf(fp," %ld:%g", ir[k]+1, samples[k]);
+ fprintf(fp," %lu:%g", (size_t)ir[k]+1, samples[k]);
fprintf(fp,"\n");
}
diff --git a/matlab/linear_model_matlab.c b/matlab/linear_model_matlab.c
index 7b5129e..f11b451 100644
--- a/matlab/linear_model_matlab.c
+++ b/matlab/linear_model_matlab.c
@@ -1,6 +1,6 @@
#include <stdlib.h>
#include <string.h>
-#include "../linear.h"
+#include "linear.h"
#include "mex.h"
@@ -145,7 +145,7 @@ const char *matlab_matrix_to_model(struct model *model_, const mxArray *matlab_s
// bias
ptr = mxGetPr(rhs[id]);
- model_->bias = (int)ptr[0];
+ model_->bias = ptr[0];
id++;
if(model_->bias>=0)
diff --git a/matlab/make.m b/matlab/make.m
index 3a01890..7e14eb4 100644
--- a/matlab/make.m
+++ b/matlab/make.m
@@ -1,21 +1,20 @@
-% This make.m is for MATLAB and OCTAVE under Windows, Mac, and Unix
-
-try
- Type = ver;
- % This part is for OCTAVE
- if(strcmp(Type(1).Name, 'Octave') == 1)
- mex libsvmread.c
- mex libsvmwrite.c
- mex train.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/*.c
- mex predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/*.c
- % This part is for MATLAB
- % Add -largeArrayDims on 64-bit machines of MATLAB
- else
- mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmread.c
- mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmwrite.c
- mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims train.c linear_model_matlab.c ../linear.cpp ../tron.cpp "../blas/*.c"
- mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp "../blas/*.c"
- end
-catch
- fprintf('If make.m fails, please check README about detailed instructions.\n');
-end
+% This make.m is for MATLAB and OCTAVE under Windows, Mac, and Unix
+
+try
+ % This part is for OCTAVE
+ if(exist('OCTAVE_VERSION', 'builtin'))
+ mex libsvmread.c
+ mex libsvmwrite.c
+ mex -I.. train.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
+ mex -I.. predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
+ % This part is for MATLAB
+ % Add -largeArrayDims on 64-bit machines of MATLAB
+ else
+ mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmread.c
+ mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmwrite.c
+ mex CFLAGS="\$CFLAGS -std=c99" -I.. -largeArrayDims train.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
+ mex CFLAGS="\$CFLAGS -std=c99" -I.. -largeArrayDims predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
+ end
+catch
+ fprintf('If make.m fails, please check README about detailed instructions.\n');
+end
diff --git a/matlab/predict.c b/matlab/predict.c
index 36c6046..e0ee5bd 100644
--- a/matlab/predict.c
+++ b/matlab/predict.c
@@ -1,7 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "../linear.h"
+#include "linear.h"
#include "mex.h"
#include "linear_model_matlab.h"
@@ -23,8 +23,8 @@ int col_format_flag;
void read_sparse_instance(const mxArray *prhs, int index, struct feature_node *x, int feature_number, double bias)
{
- int i, j, low, high;
- mwIndex *ir, *jc;
+ int j;
+ mwIndex *ir, *jc, low, high, i;
double *samples;
ir = mxGetIr(prhs);
@@ -33,7 +33,7 @@ void read_sparse_instance(const mxArray *prhs, int index, struct feature_node *x
// each column is one instance
j = 0;
- low = (int) jc[index], high = (int) jc[index+1];
+ low = jc[index], high = jc[index+1];
for(i=low; i<high && (int) (ir[i])<feature_number; i++)
{
x[j].index = (int) ir[i]+1;
@@ -176,9 +176,7 @@ void do_predict(int nlhs, mxArray *plhs[], const mxArray *prhs[], struct model *
++total;
}
- if(model_->param.solver_type==L2R_L2LOSS_SVR ||
- model_->param.solver_type==L2R_L1LOSS_SVR_DUAL ||
- model_->param.solver_type==L2R_L2LOSS_SVR_DUAL)
+ if(check_regression_model(model_))
{
info("Mean squared error = %g (regression)\n",error/total);
info("Squared correlation coefficient = %g (regression)\n",
diff --git a/matlab/train.c b/matlab/train.c
index 1301ed5..5c3ef4a 100644
--- a/matlab/train.c
+++ b/matlab/train.c
@@ -1,9 +1,8 @@
-#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include "../linear.h"
+#include "linear.h"
#include "mex.h"
#include "linear_model_matlab.h"
@@ -60,6 +59,7 @@ void exit_with_help()
"-B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)\n"
"-wi weight: weights adjust the parameter C of different classes (see README for details)\n"
"-v n: n-fold cross validation mode\n"
+ "-C : find parameter C (only for -s 0 and 2)\n"
"-q : quiet mode (no outputs)\n"
"col:\n"
" if 'col' is setted, training_instance_matrix is parsed in column format, otherwise is in row format\n"
@@ -71,11 +71,28 @@ struct parameter param; // set by parse_command_line
struct problem prob; // set by read_problem
struct model *model_;
struct feature_node *x_space;
-int cross_validation_flag;
+int flag_cross_validation;
+int flag_find_C;
+int flag_C_specified;
+int flag_solver_specified;
int col_format_flag;
int nr_fold;
double bias;
+
+void do_find_parameter_C(double *best_C, double *best_rate)
+{
+ double start_C;
+ double max_C = 1024;
+ if (flag_C_specified)
+ start_C = param.C;
+ else
+ start_C = -1.0;
+ find_parameter_C(&prob, ¶m, nr_fold, start_C, max_C, best_C, best_rate);
+ mexPrintf("Best C = %lf CV accuracy = %g%%\n", *best_C, 100.0**best_rate);
+}
+
+
double do_cross_validation()
{
int i;
@@ -101,8 +118,8 @@ double do_cross_validation()
sumyy += y*y;
sumvy += v*y;
}
- printf("Cross Validation Mean squared error = %g\n",total_error/prob.l);
- printf("Cross Validation Squared correlation coefficient = %g\n",
+ mexPrintf("Cross Validation Mean squared error = %g\n",total_error/prob.l);
+ mexPrintf("Cross Validation Squared correlation coefficient = %g\n",
((prob.l*sumvy-sumv*sumy)*(prob.l*sumvy-sumv*sumy))/
((prob.l*sumvv-sumv*sumv)*(prob.l*sumyy-sumy*sumy))
);
@@ -113,7 +130,7 @@ double do_cross_validation()
for(i=0;i<prob.l;i++)
if(target[i] == prob.y[i])
++total_correct;
- printf("Cross Validation Accuracy = %g%%\n",100.0*total_correct/prob.l);
+ mexPrintf("Cross Validation Accuracy = %g%%\n",100.0*total_correct/prob.l);
retval = 100.0*total_correct/prob.l;
}
@@ -137,8 +154,12 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
param.nr_weight = 0;
param.weight_label = NULL;
param.weight = NULL;
- cross_validation_flag = 0;
+ param.init_sol = NULL;
+ flag_cross_validation = 0;
col_format_flag = 0;
+ flag_C_specified = 0;
+ flag_solver_specified = 0;
+ flag_find_C = 0;
bias = -1;
@@ -166,15 +187,17 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
{
if(argv[i][0] != '-') break;
++i;
- if(i>=argc && argv[i-1][1] != 'q') // since option -q has no parameter
+ if(i>=argc && argv[i-1][1] != 'q' && argv[i-1][1] != 'C') // since options -q and -C have no parameter
return 1;
switch(argv[i-1][1])
{
case 's':
param.solver_type = atoi(argv[i]);
+ flag_solver_specified = 1;
break;
case 'c':
param.C = atof(argv[i]);
+ flag_C_specified = 1;
break;
case 'p':
param.p = atof(argv[i]);
@@ -186,7 +209,7 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
bias = atof(argv[i]);
break;
case 'v':
- cross_validation_flag = 1;
+ flag_cross_validation = 1;
nr_fold = atoi(argv[i]);
if(nr_fold < 2)
{
@@ -205,6 +228,10 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
print_func = &print_null;
i--;
break;
+ case 'C':
+ flag_find_C = 1;
+ i--;
+ break;
default:
mexPrintf("unknown option\n");
return 1;
@@ -213,6 +240,23 @@ int parse_command_line(int nrhs, const mxArray *prhs[], char *model_file_name)
set_print_string_function(print_func);
+ // default solver for parameter selection is L2R_L2LOSS_SVC
+ if(flag_find_C)
+ {
+ if(!flag_cross_validation)
+ nr_fold = 5;
+ if(!flag_solver_specified)
+ {
+ mexPrintf("Solver not specified. Using -s 2\n");
+ param.solver_type = L2R_L2LOSS_SVC;
+ }
+ else if(param.solver_type != L2R_LR && param.solver_type != L2R_L2LOSS_SVC)
+ {
+ mexPrintf("Warm-start parameter search only available for -s 0 and -s 2\n");
+ return 1;
+ }
+ }
+
if(param.eps == INF)
{
switch(param.solver_type)
@@ -252,9 +296,10 @@ static void fake_answer(int nlhs, mxArray *plhs[])
int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
{
- int i, j, k, low, high;
- mwIndex *ir, *jc;
- int elements, max_index, num_samples, label_vector_row_num;
+ mwIndex *ir, *jc, low, high, k;
+ // using size_t due to the output type of matlab functions
+ size_t i, j, l, elements, max_index, label_vector_row_num;
+ mwSize num_samples;
double *samples, *labels;
mxArray *instance_mat_col; // instance sparse matrix in column format
@@ -279,10 +324,11 @@ int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
}
// the number of instance
- prob.l = (int) mxGetN(instance_mat_col);
- label_vector_row_num = (int) mxGetM(label_vec);
+ l = mxGetN(instance_mat_col);
+ label_vector_row_num = mxGetM(label_vec);
+ prob.l = (int) l;
- if(label_vector_row_num!=prob.l)
+ if(label_vector_row_num!=l)
{
mexPrintf("Length of label vector does not match # of instances.\n");
return -1;
@@ -294,23 +340,23 @@ int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
ir = mxGetIr(instance_mat_col);
jc = mxGetJc(instance_mat_col);
- num_samples = (int) mxGetNzmax(instance_mat_col);
+ num_samples = mxGetNzmax(instance_mat_col);
- elements = num_samples + prob.l*2;
- max_index = (int) mxGetM(instance_mat_col);
+ elements = num_samples + l*2;
+ max_index = mxGetM(instance_mat_col);
- prob.y = Malloc(double, prob.l);
- prob.x = Malloc(struct feature_node*, prob.l);
+ prob.y = Malloc(double, l);
+ prob.x = Malloc(struct feature_node*, l);
x_space = Malloc(struct feature_node, elements);
prob.bias=bias;
j = 0;
- for(i=0;i<prob.l;i++)
+ for(i=0;i<l;i++)
{
prob.x[i] = &x_space[j];
prob.y[i] = labels[i];
- low = (int) jc[i], high = (int) jc[i+1];
+ low = jc[i], high = jc[i+1];
for(k=low;k<high;k++)
{
x_space[j].index = (int) ir[k]+1;
@@ -319,7 +365,7 @@ int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
}
if(prob.bias>=0)
{
- x_space[j].index = max_index+1;
+ x_space[j].index = (int) max_index+1;
x_space[j].value = prob.bias;
j++;
}
@@ -327,9 +373,9 @@ int read_problem_sparse(const mxArray *label_vec, const mxArray *instance_mat)
}
if(prob.bias>=0)
- prob.n = max_index+1;
+ prob.n = (int) max_index+1;
else
- prob.n = max_index;
+ prob.n = (int) max_index;
return 0;
}
@@ -356,12 +402,20 @@ void mexFunction( int nlhs, mxArray *plhs[],
{
int err=0;
- if(!mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1])) {
+ if(!mxIsDouble(prhs[0]) || !mxIsDouble(prhs[1]))
+ {
mexPrintf("Error: label vector and instance matrix must be double\n");
fake_answer(nlhs, plhs);
return;
}
+ if(mxIsSparse(prhs[0]))
+ {
+ mexPrintf("Error: label vector should not be in sparse format");
+ fake_answer(nlhs, plhs);
+ return;
+ }
+
if(parse_command_line(nrhs, prhs, NULL))
{
exit_with_help();
@@ -396,7 +450,18 @@ void mexFunction( int nlhs, mxArray *plhs[],
return;
}
- if(cross_validation_flag)
+ if (flag_find_C)
+ {
+ double best_C, best_rate, *ptr;
+
+ do_find_parameter_C(&best_C, &best_rate);
+
+ plhs[0] = mxCreateDoubleMatrix(2, 1, mxREAL);
+ ptr = mxGetPr(plhs[0]);
+ ptr[0] = best_C;
+ ptr[1] = best_rate;
+ }
+ else if(flag_cross_validation)
{
double *ptr;
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
diff --git a/predict.c b/predict.c
index c5b3f1d..a043181 100644
--- a/predict.c
+++ b/predict.c
@@ -158,9 +158,7 @@ void do_predict(FILE *input, FILE *output)
sumpt += predict_label*target_label;
++total;
}
- if(model_->param.solver_type==L2R_L2LOSS_SVR ||
- model_->param.solver_type==L2R_L1LOSS_SVR_DUAL ||
- model_->param.solver_type==L2R_L2LOSS_SVR_DUAL)
+ if(check_regression_model(model_))
{
info("Mean squared error = %g (regression)\n",error/total);
info("Squared correlation coefficient = %g (regression)\n",
diff --git a/python/README b/python/README
index e12b298..47e0b4a 100644
--- a/python/README
+++ b/python/README
@@ -205,6 +205,36 @@ LIBLINEAR shared library:
>>> nr_class = model_.get_nr_class()
>>> class_labels = model_.get_labels()
>>> is_prob_model = model_.is_probability_model()
+ >>> is_regression_model = model_.is_regression_model()
+
+ The decision function is W*x + b, where
+ W is an nr_class-by-nr_feature matrix, and
+ b is a vector of size nr_class.
+ To access W_kj (i.e., coefficient for the k-th class and the j-th feature)
+ and b_k (i.e., bias for the k-th class), use the following functions.
+
+ >>> W_kj = model_.get_decfun_coef(feat_idx=j, label_idx=k)
+ >>> b_k = model_.get_decfun_bias(label_idx=k)
+
+ We also provide a function to extract w_k (i.e., the k-th row of W) and
+ b_k directly as follows.
+
+ >>> [w_k, b_k] = model_.get_decfun(label_idx=k)
+
+ Note that w_k is a Python list of length nr_feature, which means that
+ w_k[0] = W_k1.
+ For regression models, W is just a vector of length nr_feature. Either
+ set label_idx=0 or omit the label_idx parameter to access the coefficients.
+
+ >>> W_j = model_.get_decfun_coef(feat_idx=j)
+ >>> b = model_.get_decfun_bias()
+ >>> [W, b] = model_.get_decfun()
+
+ Note that in get_decfun_coef, get_decfun_bias, and get_decfun, feat_idx
+ starts from 1, while label_idx starts from 0. If label_idx is not in the
+ valid range (0 to nr_class-1), then a NaN will be returned; and if feat_idx
+ is not in the valid range (1 to nr_feature), then a zero value will be
+ returned. For regression models, label_idx is ignored.
Utility Functions
=================
@@ -247,6 +277,11 @@ The above command loads
structure. If '-v' is specified, cross validation is
conducted and the returned model is just a scalar: cross-validation
accuracy for classification and mean-squared error for regression.
+ If the '-C' option is specified, the best parameter C is found
+ by cross validation. The returned model is a tuple of the best C
+ and the corresponding cross-validation accuracy. The parameter
+ selection utility is supported by only -s 0 and -s 2.
+
To train the same data many times with different
parameters, the second and the third ways should be faster..
@@ -260,6 +295,8 @@ The above command loads
>>> m = train(prob, '-w1 5 -c 5')
>>> m = train(prob, param)
>>> CV_ACC = train(y, x, '-v 3')
+ >>> best_C, best_rate = train(y, x, '-C -s 0')
+ >>> m = train(y, x, '-c {0} -s 0'.format(best_C)) # use the same solver: -s 0
- Function: predict
diff --git a/python/liblinear.py b/python/liblinear.py
index a207c49..d650062 100644
--- a/python/liblinear.py
+++ b/python/liblinear.py
@@ -5,12 +5,18 @@ from ctypes.util import find_library
from os import path
import sys
+__all__ = ['liblinear', 'feature_node', 'gen_feature_nodearray', 'problem',
+ 'parameter', 'model', 'toPyModel', 'L2R_LR', 'L2R_L2LOSS_SVC_DUAL',
+ 'L2R_L2LOSS_SVC', 'L2R_L1LOSS_SVC_DUAL', 'MCSVM_CS',
+ 'L1R_L2LOSS_SVC', 'L1R_LR', 'L2R_LR_DUAL', 'L2R_L2LOSS_SVR',
+ 'L2R_L2LOSS_SVR_DUAL', 'L2R_L1LOSS_SVR_DUAL', 'print_null']
+
try:
dirname = path.dirname(path.abspath(__file__))
if sys.platform == 'win32':
liblinear = CDLL(path.join(dirname, r'..\windows\liblinear.dll'))
else:
- liblinear = CDLL(path.join(dirname, '../liblinear.so.1'))
+ liblinear = CDLL(path.join(dirname, '../liblinear.so.3'))
except:
# For unix the prefix 'lib' is not considered.
if find_library('linear'):
@@ -20,13 +26,17 @@ except:
else:
raise Exception('LIBLINEAR library not found.')
-# Construct constants
-SOLVER_TYPE = ['L2R_LR', 'L2R_L2LOSS_SVC_DUAL', 'L2R_L2LOSS_SVC', 'L2R_L1LOSS_SVC_DUAL',\
- 'MCSVM_CS', 'L1R_L2LOSS_SVC', 'L1R_LR', 'L2R_LR_DUAL', \
- None, None, None, \
- 'L2R_L2LOSS_SVR', 'L2R_L2LOSS_SVR_DUAL', 'L2R_L1LOSS_SVR_DUAL']
-for i, s in enumerate(SOLVER_TYPE):
- if s is not None: exec("%s = %d" % (s , i))
+L2R_LR = 0
+L2R_L2LOSS_SVC_DUAL = 1
+L2R_L2LOSS_SVC = 2
+L2R_L1LOSS_SVC_DUAL = 3
+MCSVM_CS = 4
+L1R_L2LOSS_SVC = 5
+L1R_LR = 6
+L2R_LR_DUAL = 7
+L2R_L2LOSS_SVR = 11
+L2R_L2LOSS_SVR_DUAL = 12
+L2R_L1LOSS_SVR_DUAL = 13
PRINT_STRING_FUN = CFUNCTYPE(None, c_char_p)
def print_null(s):
@@ -117,8 +127,8 @@ class problem(Structure):
class parameter(Structure):
- _names = ["solver_type", "eps", "C", "nr_weight", "weight_label", "weight", "p"]
- _types = [c_int, c_double, c_double, c_int, POINTER(c_int), POINTER(c_double), c_double]
+ _names = ["solver_type", "eps", "C", "nr_weight", "weight_label", "weight", "p", "init_sol"]
+ _types = [c_int, c_double, c_double, c_int, POINTER(c_int), POINTER(c_double), c_double, POINTER(c_double)]
_fields_ = genFields(_names, _types)
def __init__(self, options = None):
@@ -142,10 +152,14 @@ class parameter(Structure):
self.C = 1
self.p = 0.1
self.nr_weight = 0
- self.weight_label = (c_int * 0)()
- self.weight = (c_double * 0)()
+ self.weight_label = None
+ self.weight = None
+ self.init_sol = None
self.bias = -1
- self.cross_validation = False
+ self.flag_cross_validation = False
+ self.flag_C_specified = False
+ self.flag_solver_specified = False
+ self.flag_find_C = False
self.nr_fold = 0
self.print_func = cast(None, PRINT_STRING_FUN)
@@ -166,9 +180,11 @@ class parameter(Structure):
if argv[i] == "-s":
i = i + 1
self.solver_type = int(argv[i])
+ self.flag_solver_specified = True
elif argv[i] == "-c":
i = i + 1
self.C = float(argv[i])
+ self.flag_C_specified = True
elif argv[i] == "-p":
i = i + 1
self.p = float(argv[i])
@@ -180,18 +196,20 @@ class parameter(Structure):
self.bias = float(argv[i])
elif argv[i] == "-v":
i = i + 1
- self.cross_validation = 1
+ self.flag_cross_validation = 1
self.nr_fold = int(argv[i])
if self.nr_fold < 2 :
raise ValueError("n-fold cross validation: n must >= 2")
elif argv[i].startswith("-w"):
i = i + 1
self.nr_weight += 1
- nr_weight = self.nr_weight
weight_label += [int(argv[i-1][2:])]
weight += [float(argv[i])]
elif argv[i] == "-q":
self.print_func = PRINT_STRING_FUN(print_null)
+ elif argv[i] == "-C":
+ self.flag_find_C = True
+
else :
raise ValueError("Wrong options")
i += 1
@@ -203,6 +221,16 @@ class parameter(Structure):
self.weight[i] = weight[i]
self.weight_label[i] = weight_label[i]
+ # default solver for parameter selection is L2R_L2LOSS_SVC
+ if self.flag_find_C:
+ if not self.flag_cross_validation:
+ self.nr_fold = 5
+ if not self.flag_solver_specified:
+ self.solver_type = L2R_L2LOSS_SVC
+ self.flag_solver_specified = True
+ elif self.solver_type not in [L2R_LR, L2R_L2LOSS_SVC]:
+ raise ValueError("Warm-start parameter search only available for -s 0 and -s 2")
+
if self.eps == float('inf'):
if self.solver_type in [L2R_LR, L2R_L2LOSS_SVC]:
self.eps = 0.01
@@ -240,9 +268,23 @@ class model(Structure):
liblinear.get_labels(self, labels)
return labels[:nr_class]
+ def get_decfun_coef(self, feat_idx, label_idx=0):
+ return liblinear.get_decfun_coef(self, feat_idx, label_idx)
+
+ def get_decfun_bias(self, label_idx=0):
+ return liblinear.get_decfun_bias(self, label_idx)
+
+ def get_decfun(self, label_idx=0):
+ w = [liblinear.get_decfun_coef(self, feat_idx, label_idx) for feat_idx in range(1, self.nr_feature+1)]
+ b = liblinear.get_decfun_bias(self, label_idx)
+ return (w, b)
+
def is_probability_model(self):
return (liblinear.check_probability_model(self) == 1)
+ def is_regression_model(self):
+ return (liblinear.check_regression_model(self) == 1)
+
def toPyModel(model_ptr):
"""
toPyModel(model_ptr) -> model
@@ -256,6 +298,7 @@ def toPyModel(model_ptr):
return m
fillprototype(liblinear.train, POINTER(model), [POINTER(problem), POINTER(parameter)])
+fillprototype(liblinear.find_parameter_C, None, [POINTER(problem), POINTER(parameter), c_int, c_double, c_double, POINTER(c_double), POINTER(c_double)])
fillprototype(liblinear.cross_validation, None, [POINTER(problem), POINTER(parameter), c_int, POINTER(c_double)])
fillprototype(liblinear.predict_values, c_double, [POINTER(model), POINTER(feature_node), POINTER(c_double)])
@@ -268,10 +311,13 @@ fillprototype(liblinear.load_model, POINTER(model), [c_char_p])
fillprototype(liblinear.get_nr_feature, c_int, [POINTER(model)])
fillprototype(liblinear.get_nr_class, c_int, [POINTER(model)])
fillprototype(liblinear.get_labels, None, [POINTER(model), POINTER(c_int)])
+fillprototype(liblinear.get_decfun_coef, c_double, [POINTER(model), c_int, c_int])
+fillprototype(liblinear.get_decfun_bias, c_double, [POINTER(model), c_int])
fillprototype(liblinear.free_model_content, None, [POINTER(model)])
fillprototype(liblinear.free_and_destroy_model, None, [POINTER(POINTER(model))])
fillprototype(liblinear.destroy_param, None, [POINTER(parameter)])
fillprototype(liblinear.check_parameter, c_char_p, [POINTER(problem), POINTER(parameter)])
fillprototype(liblinear.check_probability_model, c_int, [POINTER(model)])
+fillprototype(liblinear.check_regression_model, c_int, [POINTER(model)])
fillprototype(liblinear.set_print_string_function, None, [CFUNCTYPE(None, c_char_p)])
diff --git a/python/liblinearutil.py b/python/liblinearutil.py
index d63e088..5ba5efa 100644
--- a/python/liblinearutil.py
+++ b/python/liblinearutil.py
@@ -3,6 +3,12 @@
import os, sys
sys.path = [os.path.dirname(os.path.abspath(__file__))] + sys.path
from liblinear import *
+from liblinear import __all__ as liblinear_all
+from ctypes import c_double
+
+__all__ = ['svm_read_problem', 'load_model', 'save_model', 'evaluations',
+ 'train', 'predict'] + liblinear_all
+
def svm_read_problem(data_file_name):
"""
@@ -144,7 +150,21 @@ def train(arg1, arg2=None, arg3=None):
if err_msg :
raise ValueError('Error: %s' % err_msg)
- if param.cross_validation:
+ if param.flag_find_C:
+ nr_fold = param.nr_fold
+ best_C = c_double()
+ best_rate = c_double()
+ max_C = 1024
+ if param.flag_C_specified:
+ start_C = param.C
+ else:
+ start_C = -1.0
+ liblinear.find_parameter_C(prob, param, nr_fold, start_C, max_C, best_C, best_rate)
+ print("Best C = %lf CV accuracy = %g%%\n"% (best_C.value, 100.0*best_rate.value))
+ return best_C.value,best_rate.value
+
+
+ elif param.flag_cross_validation:
l, nr_fold = prob.l, param.nr_fold
target = (c_double * l)()
liblinear.cross_validation(prob, param, nr_fold, target)
@@ -241,7 +261,7 @@ def predict(y, x, m, options=""):
y = [0] * len(x)
ACC, MSE, SCC = evaluations(y, pred_labels)
l = len(y)
- if solver_type in [L2R_L2LOSS_SVR, L2R_L2LOSS_SVR_DUAL, L2R_L1LOSS_SVR_DUAL]:
+ if m.is_regression_model():
info("Mean squared error = %g (regression)" % MSE)
info("Squared correlation coefficient = %g (regression)" % SCC)
else:
diff --git a/train.c b/train.c
index d388175..53f6dbb 100644
--- a/train.c
+++ b/train.c
@@ -49,6 +49,7 @@ void exit_with_help()
"-B bias : if bias >= 0, instance x becomes [x; bias]; if < 0, no bias term added (default -1)\n"
"-wi weight: weights adjust the parameter C of different classes (see README for details)\n"
"-v n: n-fold cross validation mode\n"
+ "-C : find parameter C (only for -s 0 and 2)\n"
"-q : quiet mode (no outputs)\n"
);
exit(1);
@@ -84,12 +85,16 @@ static char* readline(FILE *input)
void parse_command_line(int argc, char **argv, char *input_file_name, char *model_file_name);
void read_problem(const char *filename);
void do_cross_validation();
+void do_find_parameter_C();
struct feature_node *x_space;
struct parameter param;
struct problem prob;
struct model* model_;
int flag_cross_validation;
+int flag_find_C;
+int flag_C_specified;
+int flag_solver_specified;
int nr_fold;
double bias;
@@ -109,7 +114,11 @@ int main(int argc, char **argv)
exit(1);
}
- if(flag_cross_validation)
+ if (flag_find_C)
+ {
+ do_find_parameter_C();
+ }
+ else if(flag_cross_validation)
{
do_cross_validation();
}
@@ -132,6 +141,19 @@ int main(int argc, char **argv)
return 0;
}
+void do_find_parameter_C()
+{
+ double start_C, best_C, best_rate;
+ double max_C = 1024;
+ if (flag_C_specified)
+ start_C = param.C;
+ else
+ start_C = -1.0;
+ printf("Doing parameter search with %d-fold cross validation.\n", nr_fold);
+ find_parameter_C(&prob, ¶m, nr_fold, start_C, max_C, &best_C, &best_rate);
+ printf("Best C = %lf CV accuracy = %g%%\n", best_C, 100.0*best_rate);
+}
+
void do_cross_validation()
{
int i;
@@ -186,7 +208,11 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
param.nr_weight = 0;
param.weight_label = NULL;
param.weight = NULL;
+ param.init_sol = NULL;
flag_cross_validation = 0;
+ flag_C_specified = 0;
+ flag_solver_specified = 0;
+ flag_find_C = 0;
bias = -1;
// parse options
@@ -199,10 +225,12 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
{
case 's':
param.solver_type = atoi(argv[i]);
+ flag_solver_specified = 1;
break;
case 'c':
param.C = atof(argv[i]);
+ flag_C_specified = 1;
break;
case 'p':
@@ -240,6 +268,11 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
i--;
break;
+ case 'C':
+ flag_find_C = 1;
+ i--;
+ break;
+
default:
fprintf(stderr,"unknown option: -%c\n", argv[i-1][1]);
exit_with_help();
@@ -267,6 +300,23 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
sprintf(model_file_name,"%s.model",p);
}
+ // default solver for parameter selection is L2R_L2LOSS_SVC
+ if(flag_find_C)
+ {
+ if(!flag_cross_validation)
+ nr_fold = 5;
+ if(!flag_solver_specified)
+ {
+ fprintf(stderr, "Solver not specified. Using -s 2\n");
+ param.solver_type = L2R_L2LOSS_SVC;
+ }
+ else if(param.solver_type != L2R_LR && param.solver_type != L2R_L2LOSS_SVC)
+ {
+ fprintf(stderr, "Warm-start parameter search only available for -s 0 and -s 2\n");
+ exit_with_help();
+ }
+ }
+
if(param.eps == INF)
{
switch(param.solver_type)
@@ -300,7 +350,7 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
void read_problem(const char *filename)
{
int max_index, inst_max_index, i;
- long int elements, j;
+ size_t elements, j;
FILE *fp = fopen(filename,"r");
char *endptr;
char *idx, *val, *label;
diff --git a/tron.cpp b/tron.cpp
index 7d1fd6e..3ea60f6 100644
--- a/tron.cpp
+++ b/tron.cpp
@@ -41,10 +41,11 @@ void TRON::info(const char *fmt,...)
(*tron_print_string)(buf);
}
-TRON::TRON(const function *fun_obj, double eps, int max_iter)
+TRON::TRON(const function *fun_obj, double eps, double eps_cg, int max_iter)
{
this->fun_obj=const_cast<function *>(fun_obj);
this->eps=eps;
+ this->eps_cg=eps_cg;
this->max_iter=max_iter;
tron_print_string = default_print;
}
@@ -68,23 +69,28 @@ void TRON::tron(double *w)
int search = 1, iter = 1, inc = 1;
double *s = new double[n];
double *r = new double[n];
- double *w_new = new double[n];
double *g = new double[n];
+ // calculate gradient norm at w=0 for stopping condition.
+ double *w0 = new double[n];
for (i=0; i<n; i++)
- w[i] = 0;
+ w0[i] = 0;
+ fun_obj->fun(w0);
+ fun_obj->grad(w0, g);
+ double gnorm0 = dnrm2_(&n, g, &inc);
+ delete [] w0;
f = fun_obj->fun(w);
fun_obj->grad(w, g);
delta = dnrm2_(&n, g, &inc);
- double gnorm1 = delta;
- double gnorm = gnorm1;
+ double gnorm = delta;
- if (gnorm <= eps*gnorm1)
+ if (gnorm <= eps*gnorm0)
search = 0;
iter = 1;
+ double *w_new = new double[n];
while (iter <= max_iter && search)
{
cg_iter = trcg(delta, g, s, r);
@@ -130,7 +136,7 @@ void TRON::tron(double *w)
fun_obj->grad(w, g);
gnorm = dnrm2_(&n, g, &inc);
- if (gnorm <= eps*gnorm1)
+ if (gnorm <= eps*gnorm0)
break;
}
if (f < -1.0e+32)
@@ -172,7 +178,7 @@ int TRON::trcg(double delta, double *g, double *s, double *r)
r[i] = -g[i];
d[i] = r[i];
}
- cgtol = 0.1*dnrm2_(&n, g, &inc);
+ cgtol = eps_cg*dnrm2_(&n, g, &inc);
int cg_iter = 0;
rTr = ddot_(&n, r, &inc, r, &inc);
diff --git a/tron.h b/tron.h
index 3045c2e..56002dc 100644
--- a/tron.h
+++ b/tron.h
@@ -15,7 +15,7 @@ public:
class TRON
{
public:
- TRON(const function *fun_obj, double eps = 0.1, int max_iter = 1000);
+ TRON(const function *fun_obj, double eps = 0.1, double eps_cg = 0.1, int max_iter = 1000);
~TRON();
void tron(double *w);
@@ -26,6 +26,7 @@ private:
double norm_inf(int n, double *x);
double eps;
+ double eps_cg;
int max_iter;
function *fun_obj;
void info(const char *fmt,...);
diff --git a/windows/liblinear.dll b/windows/liblinear.dll
deleted file mode 100644
index 345e8a0..0000000
Binary files a/windows/liblinear.dll and /dev/null differ
diff --git a/windows/libsvmread.mexw64 b/windows/libsvmread.mexw64
deleted file mode 100644
index 61cd009..0000000
Binary files a/windows/libsvmread.mexw64 and /dev/null differ
diff --git a/windows/libsvmwrite.mexw64 b/windows/libsvmwrite.mexw64
deleted file mode 100644
index 6d7c319..0000000
Binary files a/windows/libsvmwrite.mexw64 and /dev/null differ
diff --git a/windows/predict.exe b/windows/predict.exe
deleted file mode 100644
index 510800e..0000000
Binary files a/windows/predict.exe and /dev/null differ
diff --git a/windows/predict.mexw64 b/windows/predict.mexw64
deleted file mode 100644
index dcb7c37..0000000
Binary files a/windows/predict.mexw64 and /dev/null differ
diff --git a/windows/train.exe b/windows/train.exe
deleted file mode 100644
index 8f481de..0000000
Binary files a/windows/train.exe and /dev/null differ
diff --git a/windows/train.mexw64 b/windows/train.mexw64
deleted file mode 100644
index c3a7d8b..0000000
Binary files a/windows/train.mexw64 and /dev/null differ
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/liblinear.git
More information about the debian-science-commits
mailing list