rb-libsvm 1.4.2 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +2 -2
- data/ext/libsvm/svm.cpp +103 -86
- data/ext/libsvm/svm.h +2 -2
- data/lib/libsvm/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0cb9d00d4396bbc79e1d5aff34ab0d45f141437e
|
4
|
+
data.tar.gz: b86a3e1c9f2656e0e0cdfab7942458578584d263
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c09e012e812f851cfc18ad75eea8292298f5723c12ab1b36f23adbc1ef1f7c7a58ea63846d16596865ae4dec7ae5eaf2772be35b480ef83c0f7a88d7a5c92d03
|
7
|
+
data.tar.gz: 6cd24bba79c2aed7a106d5d8c9d043f6a3ee59ce2ba8e7b204d04168154c2f11d3795ec181889f709548eee9bd19011bb846753f91ecd0278a44dfbb99b44749
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
4
|
|
5
|
+
## [1.4.2] - 2018-09-15
|
6
|
+
### Changed
|
7
|
+
- Upgrade to LIBSVM 3.23
|
8
|
+
|
9
|
+
## [1.4.2] - 2018-09-02
|
10
|
+
### Changed
|
11
|
+
- bundler requires automatically
|
12
|
+
|
13
|
+
## [1.4.1] - 2018-06-15
|
14
|
+
|
5
15
|
## [1.4.0] - 2015-09-18
|
6
16
|
### Changed
|
7
17
|
- Complete transition to `expect` specs.
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[](http://badge.fury.io/rb/rb-libsvm)
|
4
4
|
[](http://travis-ci.org/febeling/rb-libsvm)
|
5
5
|
|
6
|
-
This package provides
|
6
|
+
This package provides Ruby bindings to the [LIBSVM][] library. SVM
|
7
7
|
is a machine learning and classification algorithm, and LIBSVM is a
|
8
8
|
popular free implementation of it, written by Chih-Chung Chang and
|
9
9
|
Chih-Jen Lin, of National Taiwan University, Taipei. See the book ["Programming
|
@@ -25,7 +25,7 @@ this gem. You should install the original package if you need them.
|
|
25
25
|
It is helpful to consult the [README of the LIBSVM][README] package for
|
26
26
|
reference when configuring the training parameters.
|
27
27
|
|
28
|
-
Currently this package includes libsvm version 3.
|
28
|
+
Currently this package includes libsvm version 3.23.
|
29
29
|
|
30
30
|
## Dependencies
|
31
31
|
|
data/ext/libsvm/svm.cpp
CHANGED
@@ -308,7 +308,7 @@ double Kernel::dot(const svm_node *px, const svm_node *py)
|
|
308
308
|
++py;
|
309
309
|
else
|
310
310
|
++px;
|
311
|
-
}
|
311
|
+
}
|
312
312
|
}
|
313
313
|
return sum;
|
314
314
|
}
|
@@ -337,7 +337,7 @@ double Kernel::k_function(const svm_node *x, const svm_node *y,
|
|
337
337
|
else
|
338
338
|
{
|
339
339
|
if(x->index > y->index)
|
340
|
-
{
|
340
|
+
{
|
341
341
|
sum += y->value * y->value;
|
342
342
|
++y;
|
343
343
|
}
|
@@ -360,7 +360,7 @@ double Kernel::k_function(const svm_node *x, const svm_node *y,
|
|
360
360
|
sum += y->value * y->value;
|
361
361
|
++y;
|
362
362
|
}
|
363
|
-
|
363
|
+
|
364
364
|
return exp(-param.gamma*sum);
|
365
365
|
}
|
366
366
|
case SIGMOID:
|
@@ -368,7 +368,7 @@ double Kernel::k_function(const svm_node *x, const svm_node *y,
|
|
368
368
|
case PRECOMPUTED: //x: test (validation), y: SV
|
369
369
|
return x[(int)(y->value)].value;
|
370
370
|
default:
|
371
|
-
return 0; // Unreachable
|
371
|
+
return 0; // Unreachable
|
372
372
|
}
|
373
373
|
}
|
374
374
|
|
@@ -560,7 +560,7 @@ void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
|
|
560
560
|
int iter = 0;
|
561
561
|
int max_iter = max(10000000, l>INT_MAX/100 ? INT_MAX : 100*l);
|
562
562
|
int counter = min(l,1000)+1;
|
563
|
-
|
563
|
+
|
564
564
|
while(iter < max_iter)
|
565
565
|
{
|
566
566
|
// show progress and do shrinking
|
@@ -585,11 +585,11 @@ void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
|
|
585
585
|
else
|
586
586
|
counter = 1; // do shrinking next iteration
|
587
587
|
}
|
588
|
-
|
588
|
+
|
589
589
|
++iter;
|
590
590
|
|
591
591
|
// update alpha[i] and alpha[j], handle bounds carefully
|
592
|
-
|
592
|
+
|
593
593
|
const Qfloat *Q_i = Q.get_Q(i,active_size);
|
594
594
|
const Qfloat *Q_j = Q.get_Q(j,active_size);
|
595
595
|
|
@@ -608,7 +608,7 @@ void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
|
|
608
608
|
double diff = alpha[i] - alpha[j];
|
609
609
|
alpha[i] += delta;
|
610
610
|
alpha[j] += delta;
|
611
|
-
|
611
|
+
|
612
612
|
if(diff > 0)
|
613
613
|
{
|
614
614
|
if(alpha[j] < 0)
|
@@ -690,7 +690,7 @@ void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
|
|
690
690
|
|
691
691
|
double delta_alpha_i = alpha[i] - old_alpha_i;
|
692
692
|
double delta_alpha_j = alpha[j] - old_alpha_j;
|
693
|
-
|
693
|
+
|
694
694
|
for(int k=0;k<active_size;k++)
|
695
695
|
{
|
696
696
|
G[k] += Q_i[k]*delta_alpha_i + Q_j[k]*delta_alpha_j;
|
@@ -790,7 +790,7 @@ int Solver::select_working_set(int &out_i, int &out_j)
|
|
790
790
|
// j: minimizes the decrease of obj value
|
791
791
|
// (if quadratic coefficeint <= 0, replace it with tau)
|
792
792
|
// -y_j*grad(f)_j < -y_i*grad(f)_i, j in I_low(\alpha)
|
793
|
-
|
793
|
+
|
794
794
|
double Gmax = -INF;
|
795
795
|
double Gmax2 = -INF;
|
796
796
|
int Gmax_idx = -1;
|
@@ -798,7 +798,7 @@ int Solver::select_working_set(int &out_i, int &out_j)
|
|
798
798
|
double obj_diff_min = INF;
|
799
799
|
|
800
800
|
for(int t=0;t<active_size;t++)
|
801
|
-
if(y[t]==+1)
|
801
|
+
if(y[t]==+1)
|
802
802
|
{
|
803
803
|
if(!is_upper_bound(t))
|
804
804
|
if(-G[t] >= Gmax)
|
@@ -874,7 +874,7 @@ int Solver::select_working_set(int &out_i, int &out_j)
|
|
874
874
|
}
|
875
875
|
}
|
876
876
|
|
877
|
-
if(Gmax+Gmax2 < eps)
|
877
|
+
if(Gmax+Gmax2 < eps || Gmin_idx == -1)
|
878
878
|
return 1;
|
879
879
|
|
880
880
|
out_i = Gmax_idx;
|
@@ -895,7 +895,7 @@ bool Solver::be_shrunk(int i, double Gmax1, double Gmax2)
|
|
895
895
|
{
|
896
896
|
if(y[i]==+1)
|
897
897
|
return(G[i] > Gmax2);
|
898
|
-
else
|
898
|
+
else
|
899
899
|
return(G[i] > Gmax1);
|
900
900
|
}
|
901
901
|
else
|
@@ -911,27 +911,27 @@ void Solver::do_shrinking()
|
|
911
911
|
// find maximal violating pair first
|
912
912
|
for(i=0;i<active_size;i++)
|
913
913
|
{
|
914
|
-
if(y[i]==+1)
|
914
|
+
if(y[i]==+1)
|
915
915
|
{
|
916
|
-
if(!is_upper_bound(i))
|
916
|
+
if(!is_upper_bound(i))
|
917
917
|
{
|
918
918
|
if(-G[i] >= Gmax1)
|
919
919
|
Gmax1 = -G[i];
|
920
920
|
}
|
921
|
-
if(!is_lower_bound(i))
|
921
|
+
if(!is_lower_bound(i))
|
922
922
|
{
|
923
923
|
if(G[i] >= Gmax2)
|
924
924
|
Gmax2 = G[i];
|
925
925
|
}
|
926
926
|
}
|
927
|
-
else
|
927
|
+
else
|
928
928
|
{
|
929
|
-
if(!is_upper_bound(i))
|
929
|
+
if(!is_upper_bound(i))
|
930
930
|
{
|
931
931
|
if(-G[i] >= Gmax2)
|
932
932
|
Gmax2 = -G[i];
|
933
933
|
}
|
934
|
-
if(!is_lower_bound(i))
|
934
|
+
if(!is_lower_bound(i))
|
935
935
|
{
|
936
936
|
if(G[i] >= Gmax1)
|
937
937
|
Gmax1 = G[i];
|
@@ -939,7 +939,7 @@ void Solver::do_shrinking()
|
|
939
939
|
}
|
940
940
|
}
|
941
941
|
|
942
|
-
if(unshrink == false && Gmax1 + Gmax2 <= eps*10)
|
942
|
+
if(unshrink == false && Gmax1 + Gmax2 <= eps*10)
|
943
943
|
{
|
944
944
|
unshrink = true;
|
945
945
|
reconstruct_gradient();
|
@@ -1078,7 +1078,7 @@ int Solver_NU::select_working_set(int &out_i, int &out_j)
|
|
1078
1078
|
{
|
1079
1079
|
if(y[j]==+1)
|
1080
1080
|
{
|
1081
|
-
if (!is_lower_bound(j))
|
1081
|
+
if (!is_lower_bound(j))
|
1082
1082
|
{
|
1083
1083
|
double grad_diff=Gmaxp+G[j];
|
1084
1084
|
if (G[j] >= Gmaxp2)
|
@@ -1126,7 +1126,7 @@ int Solver_NU::select_working_set(int &out_i, int &out_j)
|
|
1126
1126
|
}
|
1127
1127
|
}
|
1128
1128
|
|
1129
|
-
if(max(Gmaxp+Gmaxp2,Gmaxn+Gmaxn2) < eps)
|
1129
|
+
if(max(Gmaxp+Gmaxp2,Gmaxn+Gmaxn2) < eps || Gmin_idx == -1)
|
1130
1130
|
return 1;
|
1131
1131
|
|
1132
1132
|
if (y[Gmin_idx] == +1)
|
@@ -1144,14 +1144,14 @@ bool Solver_NU::be_shrunk(int i, double Gmax1, double Gmax2, double Gmax3, doubl
|
|
1144
1144
|
{
|
1145
1145
|
if(y[i]==+1)
|
1146
1146
|
return(-G[i] > Gmax1);
|
1147
|
-
else
|
1147
|
+
else
|
1148
1148
|
return(-G[i] > Gmax4);
|
1149
1149
|
}
|
1150
1150
|
else if(is_lower_bound(i))
|
1151
1151
|
{
|
1152
1152
|
if(y[i]==+1)
|
1153
1153
|
return(G[i] > Gmax2);
|
1154
|
-
else
|
1154
|
+
else
|
1155
1155
|
return(G[i] > Gmax3);
|
1156
1156
|
}
|
1157
1157
|
else
|
@@ -1180,14 +1180,14 @@ void Solver_NU::do_shrinking()
|
|
1180
1180
|
if(!is_lower_bound(i))
|
1181
1181
|
{
|
1182
1182
|
if(y[i]==+1)
|
1183
|
-
{
|
1183
|
+
{
|
1184
1184
|
if(G[i] > Gmax2) Gmax2 = G[i];
|
1185
1185
|
}
|
1186
1186
|
else if(G[i] > Gmax3) Gmax3 = G[i];
|
1187
1187
|
}
|
1188
1188
|
}
|
1189
1189
|
|
1190
|
-
if(unshrink == false && max(Gmax1+Gmax2,Gmax3+Gmax4) <= eps*10)
|
1190
|
+
if(unshrink == false && max(Gmax1+Gmax2,Gmax3+Gmax4) <= eps*10)
|
1191
1191
|
{
|
1192
1192
|
unshrink = true;
|
1193
1193
|
reconstruct_gradient();
|
@@ -1250,12 +1250,12 @@ double Solver_NU::calculate_rho()
|
|
1250
1250
|
r1 = sum_free1/nr_free1;
|
1251
1251
|
else
|
1252
1252
|
r1 = (ub1+lb1)/2;
|
1253
|
-
|
1253
|
+
|
1254
1254
|
if(nr_free2 > 0)
|
1255
1255
|
r2 = sum_free2/nr_free2;
|
1256
1256
|
else
|
1257
1257
|
r2 = (ub2+lb2)/2;
|
1258
|
-
|
1258
|
+
|
1259
1259
|
si->r = (r1+r2)/2;
|
1260
1260
|
return (r1-r2)/2;
|
1261
1261
|
}
|
@@ -1264,7 +1264,7 @@ double Solver_NU::calculate_rho()
|
|
1264
1264
|
// Q matrices for various formulations
|
1265
1265
|
//
|
1266
1266
|
class SVC_Q: public Kernel
|
1267
|
-
{
|
1267
|
+
{
|
1268
1268
|
public:
|
1269
1269
|
SVC_Q(const svm_problem& prob, const svm_parameter& param, const schar *y_)
|
1270
1270
|
:Kernel(prob.l, prob.x, param)
|
@@ -1275,7 +1275,7 @@ public:
|
|
1275
1275
|
for(int i=0;i<prob.l;i++)
|
1276
1276
|
QD[i] = (this->*kernel_function)(i,i);
|
1277
1277
|
}
|
1278
|
-
|
1278
|
+
|
1279
1279
|
Qfloat *get_Q(int i, int len) const
|
1280
1280
|
{
|
1281
1281
|
Qfloat *data;
|
@@ -1324,7 +1324,7 @@ public:
|
|
1324
1324
|
for(int i=0;i<prob.l;i++)
|
1325
1325
|
QD[i] = (this->*kernel_function)(i,i);
|
1326
1326
|
}
|
1327
|
-
|
1327
|
+
|
1328
1328
|
Qfloat *get_Q(int i, int len) const
|
1329
1329
|
{
|
1330
1330
|
Qfloat *data;
|
@@ -1360,7 +1360,7 @@ private:
|
|
1360
1360
|
};
|
1361
1361
|
|
1362
1362
|
class SVR_Q: public Kernel
|
1363
|
-
{
|
1363
|
+
{
|
1364
1364
|
public:
|
1365
1365
|
SVR_Q(const svm_problem& prob, const svm_parameter& param)
|
1366
1366
|
:Kernel(prob.l, prob.x, param)
|
@@ -1390,7 +1390,7 @@ public:
|
|
1390
1390
|
swap(index[i],index[j]);
|
1391
1391
|
swap(QD[i],QD[j]);
|
1392
1392
|
}
|
1393
|
-
|
1393
|
+
|
1394
1394
|
Qfloat *get_Q(int i, int len) const
|
1395
1395
|
{
|
1396
1396
|
Qfloat *data;
|
@@ -1703,7 +1703,7 @@ static decision_function svm_train_one(
|
|
1703
1703
|
|
1704
1704
|
// Platt's binary SVM Probablistic Output: an improvement from Lin et al.
|
1705
1705
|
static void sigmoid_train(
|
1706
|
-
int l, const double *dec_values, const double *labels,
|
1706
|
+
int l, const double *dec_values, const double *labels,
|
1707
1707
|
double& A, double& B)
|
1708
1708
|
{
|
1709
1709
|
double prior1=0, prior0 = 0;
|
@@ -1712,7 +1712,7 @@ static void sigmoid_train(
|
|
1712
1712
|
for (i=0;i<l;i++)
|
1713
1713
|
if (labels[i] > 0) prior1+=1;
|
1714
1714
|
else prior0+=1;
|
1715
|
-
|
1715
|
+
|
1716
1716
|
int max_iter=100; // Maximal number of iterations
|
1717
1717
|
double min_step=1e-10; // Minimal step taken in line search
|
1718
1718
|
double sigma=1e-12; // For numerically strict PD of Hessian
|
@@ -1723,7 +1723,7 @@ static void sigmoid_train(
|
|
1723
1723
|
double fApB,p,q,h11,h22,h21,g1,g2,det,dA,dB,gd,stepsize;
|
1724
1724
|
double newA,newB,newf,d1,d2;
|
1725
1725
|
int iter;
|
1726
|
-
|
1726
|
+
|
1727
1727
|
// Initial Point and Initial Fun Value
|
1728
1728
|
A=0.0; B=log((prior0+1.0)/(prior1+1.0));
|
1729
1729
|
double fval = 0.0;
|
@@ -1833,7 +1833,7 @@ static void multiclass_probability(int k, double **r, double *p)
|
|
1833
1833
|
double **Q=Malloc(double *,k);
|
1834
1834
|
double *Qp=Malloc(double,k);
|
1835
1835
|
double pQp, eps=0.005/k;
|
1836
|
-
|
1836
|
+
|
1837
1837
|
for (t=0;t<k;t++)
|
1838
1838
|
{
|
1839
1839
|
p[t]=1.0/k; // Valid if k = 1
|
@@ -1869,7 +1869,7 @@ static void multiclass_probability(int k, double **r, double *p)
|
|
1869
1869
|
max_error=error;
|
1870
1870
|
}
|
1871
1871
|
if (max_error<eps) break;
|
1872
|
-
|
1872
|
+
|
1873
1873
|
for (t=0;t<k;t++)
|
1874
1874
|
{
|
1875
1875
|
double diff=(-Qp[t]+pQp)/Q[t][t];
|
@@ -1916,7 +1916,7 @@ static void svm_binary_svc_probability(
|
|
1916
1916
|
subprob.l = prob->l-(end-begin);
|
1917
1917
|
subprob.x = Malloc(struct svm_node*,subprob.l);
|
1918
1918
|
subprob.y = Malloc(double,subprob.l);
|
1919
|
-
|
1919
|
+
|
1920
1920
|
k=0;
|
1921
1921
|
for(j=0;j<begin;j++)
|
1922
1922
|
{
|
@@ -1964,19 +1964,19 @@ static void svm_binary_svc_probability(
|
|
1964
1964
|
svm_predict_values(submodel,prob->x[perm[j]],&(dec_values[perm[j]]));
|
1965
1965
|
// ensure +1 -1 order; reason not using CV subroutine
|
1966
1966
|
dec_values[perm[j]] *= submodel->label[0];
|
1967
|
-
}
|
1967
|
+
}
|
1968
1968
|
svm_free_and_destroy_model(&submodel);
|
1969
1969
|
svm_destroy_param(&subparam);
|
1970
1970
|
}
|
1971
1971
|
free(subprob.x);
|
1972
1972
|
free(subprob.y);
|
1973
|
-
}
|
1973
|
+
}
|
1974
1974
|
sigmoid_train(prob->l,dec_values,prob->y,probA,probB);
|
1975
1975
|
free(dec_values);
|
1976
1976
|
free(perm);
|
1977
1977
|
}
|
1978
1978
|
|
1979
|
-
// Return parameter of a Laplace distribution
|
1979
|
+
// Return parameter of a Laplace distribution
|
1980
1980
|
static double svm_svr_probability(
|
1981
1981
|
const svm_problem *prob, const svm_parameter *param)
|
1982
1982
|
{
|
@@ -1992,15 +1992,15 @@ static double svm_svr_probability(
|
|
1992
1992
|
{
|
1993
1993
|
ymv[i]=prob->y[i]-ymv[i];
|
1994
1994
|
mae += fabs(ymv[i]);
|
1995
|
-
}
|
1995
|
+
}
|
1996
1996
|
mae /= prob->l;
|
1997
1997
|
double std=sqrt(2*mae*mae);
|
1998
1998
|
int count=0;
|
1999
1999
|
mae=0;
|
2000
2000
|
for(i=0;i<prob->l;i++)
|
2001
|
-
if (fabs(ymv[i]) > 5*std)
|
2001
|
+
if (fabs(ymv[i]) > 5*std)
|
2002
2002
|
count=count+1;
|
2003
|
-
else
|
2003
|
+
else
|
2004
2004
|
mae+=fabs(ymv[i]);
|
2005
2005
|
mae /= (prob->l-count);
|
2006
2006
|
info("Prob. model for test data: target value = predicted value + z,\nz: Laplace distribution e^(-|z|/sigma)/(2sigma),sigma= %g\n",mae);
|
@@ -2049,8 +2049,8 @@ static void svm_group_classes(const svm_problem *prob, int *nr_class_ret, int **
|
|
2049
2049
|
}
|
2050
2050
|
|
2051
2051
|
//
|
2052
|
-
// Labels are ordered by their first occurrence in the training set.
|
2053
|
-
// However, for two-class sets with -1/+1 labels and -1 appears first,
|
2052
|
+
// Labels are ordered by their first occurrence in the training set.
|
2053
|
+
// However, for two-class sets with -1/+1 labels and -1 appears first,
|
2054
2054
|
// we swap labels to ensure that internally the binary SVM has positive data corresponding to the +1 instances.
|
2055
2055
|
//
|
2056
2056
|
if (nr_class == 2 && label[0] == -1 && label[1] == 1)
|
@@ -2106,7 +2106,7 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2106
2106
|
model->probA = NULL; model->probB = NULL;
|
2107
2107
|
model->sv_coef = Malloc(double *,1);
|
2108
2108
|
|
2109
|
-
if(param->probability &&
|
2109
|
+
if(param->probability &&
|
2110
2110
|
(param->svm_type == EPSILON_SVR ||
|
2111
2111
|
param->svm_type == NU_SVR))
|
2112
2112
|
{
|
@@ -2134,7 +2134,7 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2134
2134
|
model->sv_coef[0][j] = f.alpha[i];
|
2135
2135
|
model->sv_indices[j] = i+1;
|
2136
2136
|
++j;
|
2137
|
-
}
|
2137
|
+
}
|
2138
2138
|
|
2139
2139
|
free(f.alpha);
|
2140
2140
|
}
|
@@ -2150,9 +2150,9 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2150
2150
|
|
2151
2151
|
// group training data of the same class
|
2152
2152
|
svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
|
2153
|
-
if(nr_class == 1)
|
2153
|
+
if(nr_class == 1)
|
2154
2154
|
info("WARNING: training data in only one class. See README for details.\n");
|
2155
|
-
|
2155
|
+
|
2156
2156
|
svm_node **x = Malloc(svm_node *,l);
|
2157
2157
|
int i;
|
2158
2158
|
for(i=0;i<l;i++)
|
@@ -2164,7 +2164,7 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2164
2164
|
for(i=0;i<nr_class;i++)
|
2165
2165
|
weighted_C[i] = param->C;
|
2166
2166
|
for(i=0;i<param->nr_weight;i++)
|
2167
|
-
{
|
2167
|
+
{
|
2168
2168
|
int j;
|
2169
2169
|
for(j=0;j<nr_class;j++)
|
2170
2170
|
if(param->weight_label[i] == label[j])
|
@@ -2176,7 +2176,7 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2176
2176
|
}
|
2177
2177
|
|
2178
2178
|
// train k*(k-1)/2 models
|
2179
|
-
|
2179
|
+
|
2180
2180
|
bool *nonzero = Malloc(bool,l);
|
2181
2181
|
for(i=0;i<l;i++)
|
2182
2182
|
nonzero[i] = false;
|
@@ -2229,11 +2229,11 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2229
2229
|
// build output
|
2230
2230
|
|
2231
2231
|
model->nr_class = nr_class;
|
2232
|
-
|
2232
|
+
|
2233
2233
|
model->label = Malloc(int,nr_class);
|
2234
2234
|
for(i=0;i<nr_class;i++)
|
2235
2235
|
model->label[i] = label[i];
|
2236
|
-
|
2236
|
+
|
2237
2237
|
model->rho = Malloc(double,nr_class*(nr_class-1)/2);
|
2238
2238
|
for(i=0;i<nr_class*(nr_class-1)/2;i++)
|
2239
2239
|
model->rho[i] = f[i].rho;
|
@@ -2262,14 +2262,14 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2262
2262
|
int nSV = 0;
|
2263
2263
|
for(int j=0;j<count[i];j++)
|
2264
2264
|
if(nonzero[start[i]+j])
|
2265
|
-
{
|
2265
|
+
{
|
2266
2266
|
++nSV;
|
2267
2267
|
++total_sv;
|
2268
2268
|
}
|
2269
2269
|
model->nSV[i] = nSV;
|
2270
2270
|
nz_count[i] = nSV;
|
2271
2271
|
}
|
2272
|
-
|
2272
|
+
|
2273
2273
|
info("Total nSV = %d\n",total_sv);
|
2274
2274
|
|
2275
2275
|
model->l = total_sv;
|
@@ -2304,7 +2304,7 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2304
2304
|
int sj = start[j];
|
2305
2305
|
int ci = count[i];
|
2306
2306
|
int cj = count[j];
|
2307
|
-
|
2307
|
+
|
2308
2308
|
int q = nz_start[i];
|
2309
2309
|
int k;
|
2310
2310
|
for(k=0;k<ci;k++)
|
@@ -2316,7 +2316,7 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2316
2316
|
model->sv_coef[i][q++] = f[p].alpha[ci+k];
|
2317
2317
|
++p;
|
2318
2318
|
}
|
2319
|
-
|
2319
|
+
|
2320
2320
|
free(label);
|
2321
2321
|
free(probA);
|
2322
2322
|
free(probB);
|
@@ -2365,7 +2365,7 @@ void svm_cross_validation(const svm_problem *prob, const svm_parameter *param, i
|
|
2365
2365
|
int *index = Malloc(int,l);
|
2366
2366
|
for(i=0;i<l;i++)
|
2367
2367
|
index[i]=perm[i];
|
2368
|
-
for (c=0; c<nr_class; c++)
|
2368
|
+
for (c=0; c<nr_class; c++)
|
2369
2369
|
for(i=0;i<count[c];i++)
|
2370
2370
|
{
|
2371
2371
|
int j = i+rand()%(count[c]-i);
|
@@ -2422,7 +2422,7 @@ void svm_cross_validation(const svm_problem *prob, const svm_parameter *param, i
|
|
2422
2422
|
subprob.l = l-(end-begin);
|
2423
2423
|
subprob.x = Malloc(struct svm_node*,subprob.l);
|
2424
2424
|
subprob.y = Malloc(double,subprob.l);
|
2425
|
-
|
2425
|
+
|
2426
2426
|
k=0;
|
2427
2427
|
for(j=0;j<begin;j++)
|
2428
2428
|
{
|
@@ -2437,7 +2437,7 @@ void svm_cross_validation(const svm_problem *prob, const svm_parameter *param, i
|
|
2437
2437
|
++k;
|
2438
2438
|
}
|
2439
2439
|
struct svm_model *submodel = svm_train(&subprob,param);
|
2440
|
-
if(param->probability &&
|
2440
|
+
if(param->probability &&
|
2441
2441
|
(param->svm_type == C_SVC || param->svm_type == NU_SVC))
|
2442
2442
|
{
|
2443
2443
|
double *prob_estimates=Malloc(double,svm_get_nr_class(submodel));
|
@@ -2451,7 +2451,7 @@ void svm_cross_validation(const svm_problem *prob, const svm_parameter *param, i
|
|
2451
2451
|
svm_free_and_destroy_model(&submodel);
|
2452
2452
|
free(subprob.x);
|
2453
2453
|
free(subprob.y);
|
2454
|
-
}
|
2454
|
+
}
|
2455
2455
|
free(fold_start);
|
2456
2456
|
free(perm);
|
2457
2457
|
}
|
@@ -2521,7 +2521,7 @@ double svm_predict_values(const svm_model *model, const svm_node *x, double* dec
|
|
2521
2521
|
{
|
2522
2522
|
int nr_class = model->nr_class;
|
2523
2523
|
int l = model->l;
|
2524
|
-
|
2524
|
+
|
2525
2525
|
double *kvalue = Malloc(double,l);
|
2526
2526
|
for(i=0;i<l;i++)
|
2527
2527
|
kvalue[i] = Kernel::k_function(x,model->SV[i],model->param);
|
@@ -2544,7 +2544,7 @@ double svm_predict_values(const svm_model *model, const svm_node *x, double* dec
|
|
2544
2544
|
int sj = start[j];
|
2545
2545
|
int ci = model->nSV[i];
|
2546
2546
|
int cj = model->nSV[j];
|
2547
|
-
|
2547
|
+
|
2548
2548
|
int k;
|
2549
2549
|
double *coef1 = model->sv_coef[j-1];
|
2550
2550
|
double *coef2 = model->sv_coef[i];
|
@@ -2582,7 +2582,7 @@ double svm_predict(const svm_model *model, const svm_node *x)
|
|
2582
2582
|
model->param.svm_type == EPSILON_SVR ||
|
2583
2583
|
model->param.svm_type == NU_SVR)
|
2584
2584
|
dec_values = Malloc(double, 1);
|
2585
|
-
else
|
2585
|
+
else
|
2586
2586
|
dec_values = Malloc(double, nr_class*(nr_class-1)/2);
|
2587
2587
|
double pred_result = svm_predict_values(model, x, dec_values);
|
2588
2588
|
free(dec_values);
|
@@ -2612,7 +2612,13 @@ double svm_predict_probability(
|
|
2612
2612
|
pairwise_prob[j][i]=1-pairwise_prob[i][j];
|
2613
2613
|
k++;
|
2614
2614
|
}
|
2615
|
-
|
2615
|
+
if (nr_class == 2)
|
2616
|
+
{
|
2617
|
+
prob_estimates[0] = pairwise_prob[0][1];
|
2618
|
+
prob_estimates[1] = pairwise_prob[1][0];
|
2619
|
+
}
|
2620
|
+
else
|
2621
|
+
multiclass_probability(nr_class,pairwise_prob,prob_estimates);
|
2616
2622
|
|
2617
2623
|
int prob_max_idx = 0;
|
2618
2624
|
for(i=1;i<nr_class;i++)
|
@@ -2624,7 +2630,7 @@ double svm_predict_probability(
|
|
2624
2630
|
free(pairwise_prob);
|
2625
2631
|
return model->label[prob_max_idx];
|
2626
2632
|
}
|
2627
|
-
else
|
2633
|
+
else
|
2628
2634
|
return svm_predict(model, x);
|
2629
2635
|
}
|
2630
2636
|
|
@@ -2643,7 +2649,10 @@ int svm_save_model(const char *model_file_name, const svm_model *model)
|
|
2643
2649
|
FILE *fp = fopen(model_file_name,"w");
|
2644
2650
|
if(fp==NULL) return -1;
|
2645
2651
|
|
2646
|
-
char *old_locale =
|
2652
|
+
char *old_locale = setlocale(LC_ALL, NULL);
|
2653
|
+
if (old_locale) {
|
2654
|
+
old_locale = strdup(old_locale);
|
2655
|
+
}
|
2647
2656
|
setlocale(LC_ALL, "C");
|
2648
2657
|
|
2649
2658
|
const svm_parameter& param = model->param;
|
@@ -2655,23 +2664,23 @@ int svm_save_model(const char *model_file_name, const svm_model *model)
|
|
2655
2664
|
fprintf(fp,"degree %d\n", param.degree);
|
2656
2665
|
|
2657
2666
|
if(param.kernel_type == POLY || param.kernel_type == RBF || param.kernel_type == SIGMOID)
|
2658
|
-
fprintf(fp,"gamma
|
2667
|
+
fprintf(fp,"gamma %.17g\n", param.gamma);
|
2659
2668
|
|
2660
2669
|
if(param.kernel_type == POLY || param.kernel_type == SIGMOID)
|
2661
|
-
fprintf(fp,"coef0
|
2670
|
+
fprintf(fp,"coef0 %.17g\n", param.coef0);
|
2662
2671
|
|
2663
2672
|
int nr_class = model->nr_class;
|
2664
2673
|
int l = model->l;
|
2665
2674
|
fprintf(fp, "nr_class %d\n", nr_class);
|
2666
2675
|
fprintf(fp, "total_sv %d\n",l);
|
2667
|
-
|
2676
|
+
|
2668
2677
|
{
|
2669
2678
|
fprintf(fp, "rho");
|
2670
2679
|
for(int i=0;i<nr_class*(nr_class-1)/2;i++)
|
2671
|
-
fprintf(fp,"
|
2680
|
+
fprintf(fp," %.17g",model->rho[i]);
|
2672
2681
|
fprintf(fp, "\n");
|
2673
2682
|
}
|
2674
|
-
|
2683
|
+
|
2675
2684
|
if(model->label)
|
2676
2685
|
{
|
2677
2686
|
fprintf(fp, "label");
|
@@ -2684,14 +2693,14 @@ int svm_save_model(const char *model_file_name, const svm_model *model)
|
|
2684
2693
|
{
|
2685
2694
|
fprintf(fp, "probA");
|
2686
2695
|
for(int i=0;i<nr_class*(nr_class-1)/2;i++)
|
2687
|
-
fprintf(fp,"
|
2696
|
+
fprintf(fp," %.17g",model->probA[i]);
|
2688
2697
|
fprintf(fp, "\n");
|
2689
2698
|
}
|
2690
2699
|
if(model->probB)
|
2691
2700
|
{
|
2692
2701
|
fprintf(fp, "probB");
|
2693
2702
|
for(int i=0;i<nr_class*(nr_class-1)/2;i++)
|
2694
|
-
fprintf(fp,"
|
2703
|
+
fprintf(fp," %.17g",model->probB[i]);
|
2695
2704
|
fprintf(fp, "\n");
|
2696
2705
|
}
|
2697
2706
|
|
@@ -2710,7 +2719,7 @@ int svm_save_model(const char *model_file_name, const svm_model *model)
|
|
2710
2719
|
for(int i=0;i<l;i++)
|
2711
2720
|
{
|
2712
2721
|
for(int j=0;j<nr_class-1;j++)
|
2713
|
-
fprintf(fp, "%.
|
2722
|
+
fprintf(fp, "%.17g ",sv_coef[j][i]);
|
2714
2723
|
|
2715
2724
|
const svm_node *p = SV[i];
|
2716
2725
|
|
@@ -2764,6 +2773,11 @@ static char* readline(FILE *input)
|
|
2764
2773
|
bool read_model_header(FILE *fp, svm_model* model)
|
2765
2774
|
{
|
2766
2775
|
svm_parameter& param = model->param;
|
2776
|
+
// parameters for training only won't be assigned, but arrays are assigned as NULL for safety
|
2777
|
+
param.nr_weight = 0;
|
2778
|
+
param.weight_label = NULL;
|
2779
|
+
param.weight = NULL;
|
2780
|
+
|
2767
2781
|
char cmd[81];
|
2768
2782
|
while(1)
|
2769
2783
|
{
|
@@ -2788,7 +2802,7 @@ bool read_model_header(FILE *fp, svm_model* model)
|
|
2788
2802
|
}
|
2789
2803
|
}
|
2790
2804
|
else if(strcmp(cmd,"kernel_type")==0)
|
2791
|
-
{
|
2805
|
+
{
|
2792
2806
|
FSCANF(fp,"%80s",cmd);
|
2793
2807
|
int i;
|
2794
2808
|
for(i=0;kernel_type_table[i];i++)
|
@@ -2801,7 +2815,7 @@ bool read_model_header(FILE *fp, svm_model* model)
|
|
2801
2815
|
}
|
2802
2816
|
if(kernel_type_table[i] == NULL)
|
2803
2817
|
{
|
2804
|
-
fprintf(stderr,"unknown kernel function.\n");
|
2818
|
+
fprintf(stderr,"unknown kernel function.\n");
|
2805
2819
|
return false;
|
2806
2820
|
}
|
2807
2821
|
}
|
@@ -2875,7 +2889,10 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2875
2889
|
FILE *fp = fopen(model_file_name,"rb");
|
2876
2890
|
if(fp==NULL) return NULL;
|
2877
2891
|
|
2878
|
-
char *old_locale =
|
2892
|
+
char *old_locale = setlocale(LC_ALL, NULL);
|
2893
|
+
if (old_locale) {
|
2894
|
+
old_locale = strdup(old_locale);
|
2895
|
+
}
|
2879
2896
|
setlocale(LC_ALL, "C");
|
2880
2897
|
|
2881
2898
|
// read parameters
|
@@ -2887,7 +2904,7 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2887
2904
|
model->sv_indices = NULL;
|
2888
2905
|
model->label = NULL;
|
2889
2906
|
model->nSV = NULL;
|
2890
|
-
|
2907
|
+
|
2891
2908
|
// read header
|
2892
2909
|
if (!read_model_header(fp, model))
|
2893
2910
|
{
|
@@ -2900,7 +2917,7 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2900
2917
|
free(model);
|
2901
2918
|
return NULL;
|
2902
2919
|
}
|
2903
|
-
|
2920
|
+
|
2904
2921
|
// read sv_coef and SV
|
2905
2922
|
|
2906
2923
|
int elements = 0;
|
@@ -3037,9 +3054,9 @@ const char *svm_check_parameter(const svm_problem *prob, const svm_parameter *pa
|
|
3037
3054
|
svm_type != EPSILON_SVR &&
|
3038
3055
|
svm_type != NU_SVR)
|
3039
3056
|
return "unknown svm type";
|
3040
|
-
|
3057
|
+
|
3041
3058
|
// kernel_type, degree
|
3042
|
-
|
3059
|
+
|
3043
3060
|
int kernel_type = param->kernel_type;
|
3044
3061
|
if(kernel_type != LINEAR &&
|
3045
3062
|
kernel_type != POLY &&
|
@@ -3092,7 +3109,7 @@ const char *svm_check_parameter(const svm_problem *prob, const svm_parameter *pa
|
|
3092
3109
|
|
3093
3110
|
|
3094
3111
|
// check whether nu-svc is feasible
|
3095
|
-
|
3112
|
+
|
3096
3113
|
if(svm_type == NU_SVC)
|
3097
3114
|
{
|
3098
3115
|
int l = prob->l;
|
@@ -3125,7 +3142,7 @@ const char *svm_check_parameter(const svm_problem *prob, const svm_parameter *pa
|
|
3125
3142
|
++nr_class;
|
3126
3143
|
}
|
3127
3144
|
}
|
3128
|
-
|
3145
|
+
|
3129
3146
|
for(i=0;i<nr_class;i++)
|
3130
3147
|
{
|
3131
3148
|
int n1 = count[i];
|
data/ext/libsvm/svm.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#ifndef _LIBSVM_H
|
2
2
|
#define _LIBSVM_H
|
3
3
|
|
4
|
-
#define LIBSVM_VERSION
|
4
|
+
#define LIBSVM_VERSION 323
|
5
5
|
|
6
6
|
#ifdef __cplusplus
|
7
7
|
extern "C" {
|
@@ -48,7 +48,7 @@ struct svm_parameter
|
|
48
48
|
|
49
49
|
//
|
50
50
|
// svm_model
|
51
|
-
//
|
51
|
+
//
|
52
52
|
struct svm_model
|
53
53
|
{
|
54
54
|
struct svm_parameter param; /* parameter */
|
data/lib/libsvm/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rb-libsvm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- C. Florian Ebeling
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-09-
|
12
|
+
date: 2018-09-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|