Skip to content

Commit 50d51dc

Browse files
committed
[ossvm] OSSVM implementation for binary classification
This commit provides the OSSVM implementation as proposed by [1]. For usage through LibSVM’s executable, it provides the additional `-l` option for the lambda regularization parameters described in Equation (11) of the paper [1]. The `-l` option is only accepted when the kernel type is RBF, i.e., when `-t 2` is provided. Note: Although in the paper [1] it is presented that the lambda regularization parameter can be up to `C * mp`, in which `C` is the SVM cost parameter and `mp` is the number of positive training instances on the training set, to facilitate usage, `-l` option accepts a value in the interval `[0, 1)` which is linearly mapped to the interval `[0, C*mp)`. Value of the lambda parameters equals to 1 is not accepted, as explained in the second paragraph after Proposition 1 in the paper [1]. This commit also adjusts the Python wrap for usage. [1] Mendes Júnior, Pedro Ribeiro; Boult, Terrance E.; Wainer, Jacques; and Rocha, Anderson de Rezende (2021), “Open-Set Support Vector Machines”, to appear in IEEE Transactions on Systems, Man, and Cybernetics: Systems. URL: https://pedrormjunior.github.io/OSSVM.html
1 parent 5f4a812 commit 50d51dc

6 files changed

Lines changed: 30 additions & 3 deletions

File tree

README

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ options:
153153
-g gamma : set gamma in kernel function (default 1/num_features)
154154
-r coef0 : set coef0 in kernel function (default 0)
155155
-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
156+
-l lamb : set the parameter lambda of SSVM (C-SVC) for open-set recognition (default -1)
156157
-n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
157158
-p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
158159
-m cachesize : set cache memory size in MB (default 100)
@@ -385,6 +386,7 @@ to classify new data.
385386
double cache_size; /* in MB */
386387
double eps; /* stopping criteria */
387388
double C; /* for C_SVC, EPSILON_SVR, and NU_SVR */
389+
double lamb; /* for SSVM (open-set recognition) */
388390
int nr_weight; /* for C_SVC */
389391
int *weight_label; /* for C_SVC */
390392
double* weight; /* for C_SVC */

python/svm.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,10 @@ def __init__(self, y, x, isKernel=False):
224224

225225
class svm_parameter(Structure):
226226
_names = ["svm_type", "kernel_type", "degree", "gamma", "coef0",
227-
"cache_size", "eps", "C", "nr_weight", "weight_label", "weight",
227+
"cache_size", "eps", "C", "lamb", "nr_weight", "weight_label", "weight",
228228
"nu", "p", "shrinking", "probability"]
229229
_types = [c_int, c_int, c_int, c_double, c_double,
230-
c_double, c_double, c_double, c_int, POINTER(c_int), POINTER(c_double),
230+
c_double, c_double, c_double, c_double, c_int, POINTER(c_int), POINTER(c_double),
231231
c_double, c_double, c_int, c_int]
232232
_fields_ = genFields(_names, _types)
233233

@@ -255,6 +255,7 @@ def set_to_default_values(self):
255255
self.nu = 0.5
256256
self.cache_size = 100
257257
self.C = 1
258+
self.lamb = -1
258259
self.eps = 0.001
259260
self.p = 0.1
260261
self.shrinking = 1
@@ -304,6 +305,9 @@ def parse_options(self, options):
304305
elif argv[i] == "-c":
305306
i = i + 1
306307
self.C = float(argv[i])
308+
elif argv[i] == "-l":
309+
i = i + 1
310+
self.lamb = float(argv[i])
307311
elif argv[i] == "-e":
308312
i = i + 1
309313
self.eps = float(argv[i])

python/svmutil.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def svm_train(arg1, arg2=None, arg3=None):
7474
-g gamma : set gamma in kernel function (default 1/num_features)
7575
-r coef0 : set coef0 in kernel function (default 0)
7676
-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
77+
-l lamb : set the parameter lamb of SSVM (C-SVC) for open-set recognition (default -1)
7778
-n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
7879
-p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
7980
-m cachesize : set cache memory size in MB (default 100)

svm-train.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ void exit_with_help()
2929
"-g gamma : set gamma in kernel function (default 1/num_features)\n"
3030
"-r coef0 : set coef0 in kernel function (default 0)\n"
3131
"-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)\n"
32+
"-l lamb : set the parameter lambda of SSVM (C-SVC) for open-set recognition (default -1)\n"
3233
"-n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)\n"
3334
"-p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)\n"
3435
"-m cachesize : set cache memory size in MB (default 100)\n"
@@ -172,6 +173,7 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
172173
param.nu = 0.5;
173174
param.cache_size = 100;
174175
param.C = 1;
176+
param.lamb = -1;
175177
param.eps = 1e-3;
176178
param.p = 0.1;
177179
param.shrinking = 1;
@@ -213,6 +215,9 @@ void parse_command_line(int argc, char **argv, char *input_file_name, char *mode
213215
case 'c':
214216
param.C = atof(argv[i]);
215217
break;
218+
case 'l':
219+
param.lamb = atof(argv[i]);
220+
break;
216221
case 'e':
217222
param.eps = atof(argv[i]);
218223
break;

svm.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1447,9 +1447,10 @@ static void solve_c_svc(
14471447

14481448
int i;
14491449

1450+
double alpha_epsilon = param->lamb >= 0 ? param->lamb * param->C : 0;
14501451
for(i=0;i<l;i++)
14511452
{
1452-
alpha[i] = 0;
1453+
alpha[i] = prob->y[i] > 0 ? alpha_epsilon : 0;
14531454
minus_ones[i] = -1;
14541455
if(prob->y[i] > 0) y[i] = +1; else y[i] = -1;
14551456
}
@@ -2669,6 +2670,8 @@ int svm_save_model(const char *model_file_name, const svm_model *model)
26692670
if(param.kernel_type == POLY || param.kernel_type == SIGMOID)
26702671
fprintf(fp,"coef0 %.17g\n", param.coef0);
26712672

2673+
fprintf(fp,"lamb %g\n", param.lamb);
2674+
26722675
int nr_class = model->nr_class;
26732676
int l = model->l;
26742677
fprintf(fp, "nr_class %d\n", nr_class);
@@ -2825,6 +2828,8 @@ bool read_model_header(FILE *fp, svm_model* model)
28252828
FSCANF(fp,"%lf",&param.gamma);
28262829
else if(strcmp(cmd,"coef0")==0)
28272830
FSCANF(fp,"%lf",&param.coef0);
2831+
else if(strcmp(cmd,"lamb")==0)
2832+
FSCANF(fp,"%lf",&param.lamb);
28282833
else if(strcmp(cmd,"nr_class")==0)
28292834
FSCANF(fp,"%d",&model->nr_class);
28302835
else if(strcmp(cmd,"total_sv")==0)
@@ -3086,6 +3091,15 @@ const char *svm_check_parameter(const svm_problem *prob, const svm_parameter *pa
30863091
if(param->C <= 0)
30873092
return "C <= 0";
30883093

3094+
if(param->lamb < 0 && param->lamb != -1)
3095+
return "lamb < 0 and lamb != -1";
3096+
if(param->lamb >= 1)
3097+
return "lamb >= 1";
3098+
if(param->lamb >= 0 && svm_type != C_SVC)
3099+
return "lamb >= 0 and svm_type != C_SVC";
3100+
if(param->lamb >= 0 && kernel_type != RBF)
3101+
return "lamb > 0 and kernel_type != RBF";
3102+
30893103
if(svm_type == NU_SVC ||
30903104
svm_type == ONE_CLASS ||
30913105
svm_type == NU_SVR)

svm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct svm_parameter
3737
double cache_size; /* in MB */
3838
double eps; /* stopping criteria */
3939
double C; /* for C_SVC, EPSILON_SVR and NU_SVR */
40+
double lamb; /* for SSVM (open-set recognition) */
4041
int nr_weight; /* for C_SVC */
4142
int *weight_label; /* for C_SVC */
4243
double* weight; /* for C_SVC */

0 commit comments

Comments
 (0)