Commit 832cbef4 authored by Marek Pecha's avatar Marek Pecha
Browse files

Modification allows specified maximal number of iterations

parents
cmake_minimum_required(VERSION 3.7)
project(ML-LIBLINEAR)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/lib)
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
set(SOURCES_BLAS blas/blas.h blas/blasp.h blas/daxpy.c blas/ddot.c blas/dnrm2.c blas/dscal.c)
set(SOURCES_TRON tron.cpp tron.h)
set(SOURCES_LINEAR linear.cpp linear.h)
set(SOURCES_TRAIN ${SOURCES_TRON} ${SOURCES_LINEAR} train.cpp)
set(SOURCES_PREDICT ${SOURCES_TRON} ${SOURCES_LINEAR} predict.c)
add_library(ml-blas SHARED ${SOURCES_BLAS})
add_executable(ml-train ${SOURCES_TRAIN})
target_link_libraries(ml-train blas)
add_executable(ml-predict ${SOURCES_PREDICT})
target_link_libraries(ml-predict blas)
Copyright (c) 2007-2015 The LIBLINEAR Project.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither name of copyright holders nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
CXX ?= g++
CC ?= gcc
CFLAGS = -Wall -Wconversion -O3 -fPIC -fopenmp
# CFLAGS += -DCV_OMP
LIBS = blas/blas.a
SHVER = 3
OS = $(shell uname)
#LIBS = -lblas
all: train predict
lib: linear.o tron.o blas/blas.a
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) -fopenmp $${SHARED_LIB_FLAG} linear.o tron.o blas/blas.a -o liblinear.so.$(SHVER)
train: tron.o linear.o train.c blas/blas.a
$(CXX) $(CFLAGS) -o train train.c tron.o linear.o $(LIBS)
predict: tron.o linear.o predict.c blas/blas.a
$(CXX) $(CFLAGS) -o predict predict.c tron.o linear.o $(LIBS)
tron.o: tron.cpp tron.h
$(CXX) $(CFLAGS) -c -o tron.o tron.cpp
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)
CXX = cl.exe
CFLAGS = /nologo /O2 /EHsc /I. /D _WIN64 /D _CRT_SECURE_NO_DEPRECATE /openmp
TARGET = windows
all: $(TARGET)\train.exe $(TARGET)\predict.exe lib
$(TARGET)\train.exe: tron.obj linear.obj train.c blas\*.c
$(CXX) $(CFLAGS) -Fe$(TARGET)\train.exe tron.obj linear.obj train.c blas\*.c
$(TARGET)\predict.exe: tron.obj linear.obj predict.c blas\*.c
$(CXX) $(CFLAGS) -Fe$(TARGET)\predict.exe tron.obj linear.obj predict.c blas\*.c
linear.obj: linear.cpp linear.h
$(CXX) $(CFLAGS) -c linear.cpp
tron.obj: tron.cpp tron.h
$(CXX) $(CFLAGS) -c tron.cpp
lib: linear.cpp linear.h linear.def tron.obj
$(CXX) $(CFLAGS) -LD linear.cpp tron.obj blas\*.c -Fe$(TARGET)\liblinear -link -DEF:linear.def
clean:
-erase /Q *.obj $(TARGET)\*.exe $(TARGET)\*.dll $(TARGET)\*.exp $(TARGET)\*.lib
This diff is collapsed.
Introduction
============
This extension of liblinear supports multi-core parallel learning by OpenMP.
We applied efficient implementations to train models for multi-core machines.
Currently, -s 0 (solving primal LR), -s 2 (solving primal l2-loss SVM),
-s 1 (solving dual l2-loss SVM), -s 3 (solving dual l1-loss SVM),
and -s 11 (solving primal l2-loss SVR) are supported.
Usage
=====
The usage is the same as liblinear except for the additional option:
-n nr_thread: use nr_thread threads for training (only for -s 0, -s 1, -s 2, -s 3 and -s 11)
Examples
========
> ./train -s 0 -n 8 heart_scale
will run the L2-regularized logistic regression primal solver with 8 threads.
> ./train -s 3 -n 8 heart_scale
will run the L2-regularized l1-loss dual solver with 8 threads.
Differences from LIBLINEAR
==========================
The major changes for the primal solver are to do matrix-vector multiplications in
parallel. The major changes for the dual solver are to calculate the gradients
in parallel, and then do CD (coordinate descent) updates serially.
Details could be seen in the references.
Experimental Results
====================
Time for solving the optimization problems. Other pre- and
post-processing steps not included.
Primal Logistic Regression:
dataset 1-thread 4-threads 8-threads
covtype_scale 1.837 0.491 0.393
epsilon_normalized 114.495 30.030 18.200
rcv1_test.binary 15.118 3.978 2.187
webspam(trigram) 519.574 184.922 116.896
Dual l1-loss SVM:
dataset 1-thread 4-threads 8-threads
covtype_scale 3.420 2.261 2.150
epsilon_normalized 18.945 9.702 8.914
rcv1_test.binary 2.553 1.319 1.091
webspam(trigram) 60.986 28.901 22.843
Dual l2-loss SVM:
dataset 1-thread 4-threads 8-threads
covtype_scale 7.508 5.090 4.771
epsilon_normalized 31.164 20.434 19.691
rcv1_test.binary 3.146 1.982 1.804
webspam(trigram) 47.472 26.726 22.812
Note that the primal and dual results are NOT COMPARABLE because they
solve different problems.
Reference
=========
M.-C. Lee, W.-L. Chiang, and C.-J. Lin.
Fast matrix-vector multiplications for large-scale logistic regression on shared-memory systems.
ICDM 2015
W.-L. Chiang, M.-C. Lee, and C.-J. Lin.
Parallel dual coordinate descent method for large-scale linear classification in multi-core environments.
Technical report, National Taiwan University, 2016
For any questions and comments, please email
cjlin@csie.ntu.edu.tw
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
/* 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
/* blasp.h -- C prototypes for BLAS Ver 1.0 */
/* Jesse Bennett March 23, 2000 */
/* Functions listed in alphabetical order */
#ifdef __cplusplus
extern "C" {
#endif
#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);