rb-libsvm 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -2
- data/LIBSVM-LICENSE +30 -0
- data/MIT-LICENSE +1 -1
- data/README.md +6 -1
- data/examples/text.rb +53 -0
- data/ext/rb-libsvm/svm.cpp +71 -31
- data/ext/rb-libsvm/svm.h +1 -1
- data/lib/libsvm.rb +1 -43
- data/lib/libsvm/node.rb +40 -0
- data/lib/rb-libsvm/version.rb +1 -1
- data/rb-libsvm.gemspec +1 -0
- data/spec/.usage_spec.rb.swp +0 -0
- data/spec/model_spec.rb +79 -79
- data/spec/node_spec.rb +52 -52
- data/spec/parameter_spec.rb +59 -59
- data/spec/problem_spec.rb +30 -30
- data/spec/spec_helper.rb +1 -1
- data/spec/usage_spec.rb +32 -32
- metadata +17 -7
data/.travis.yml
CHANGED
data/LIBSVM-LICENSE
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Copyright (c) 2000-2012 Chih-Chung Chang and Chih-Jen Lin
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions
|
6
|
+
are met:
|
7
|
+
|
8
|
+
1. Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer in the
|
13
|
+
documentation and/or other materials provided with the distribution.
|
14
|
+
|
15
|
+
3. Neither name of copyright holders nor the names of its contributors
|
16
|
+
may be used to endorse or promote products derived from this software
|
17
|
+
without specific prior written permission.
|
18
|
+
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
21
|
+
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
22
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
23
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
24
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
25
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
26
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
27
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
28
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
29
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
30
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -52,9 +52,14 @@ Currently using libsvm version 3.1
|
|
52
52
|
Written by C. Florian Ebeling. This software can be freely used under
|
53
53
|
the terms of the MIT license, see file MIT-LICENSE.
|
54
54
|
|
55
|
+
This package includes the source of LIBSVM, which is free to use under
|
56
|
+
the license in the file LIBSVM-LICENSE.
|
57
|
+
|
55
58
|
## Contributors
|
56
59
|
|
57
|
-
Rimas Silkaitis
|
60
|
+
[Rimas Silkaitis](https://github.com/neovintage)
|
61
|
+
|
62
|
+
[Aleksander Pohl](https://github.com/apohllo)
|
58
63
|
|
59
64
|
### Posts about SVMs and Ruby
|
60
65
|
|
data/examples/text.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# In this example let's have 3 documents. 2 of the documents
|
2
|
+
# will go into our training set and 1 will be used as our
|
3
|
+
# test set
|
4
|
+
#
|
5
|
+
# Before we can actually classify the documents we need to
|
6
|
+
# create integer representations of each of the documents.
|
7
|
+
# The best way to do this would be to use ruby to accomplish
|
8
|
+
# the task.
|
9
|
+
#
|
10
|
+
require 'libsvm'
|
11
|
+
|
12
|
+
# Let take our documents and create word vectors out of them.
|
13
|
+
# I've included labels for these already. 1 signifies that
|
14
|
+
# the document was funny 0 means that it wasn't
|
15
|
+
#
|
16
|
+
documents = [[1, "Why did the chicken cross the road? Because a car was coming"],
|
17
|
+
[0, "You're an elevator tech? I bet that job has its ups and downs"]]
|
18
|
+
|
19
|
+
# Lets create a dictionary of unique words and then we can
|
20
|
+
# create our vectors. This is a very simple example. If
|
21
|
+
# you were doing this in a production system you'd do things
|
22
|
+
# like stemming and removing all punctuation.
|
23
|
+
#
|
24
|
+
dictionary = documents.map(&:last).flatten.uniq
|
25
|
+
dictionary = dictionary.map { |x| x.gsub(/\?|,|\.|\-/,'') }
|
26
|
+
|
27
|
+
training_set = []
|
28
|
+
docments.each do |doc|
|
29
|
+
training_set << [doc.first, Libsvm::Node.features(dictionary.map { |x| doc.include?(x) ? 1 : 0 })]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Lets set up libsvm so that we can test our prediction
|
33
|
+
# using the test set
|
34
|
+
#
|
35
|
+
problem = Libsvm::Problem.new
|
36
|
+
parameter = Libsvm::SvmParameter.new
|
37
|
+
|
38
|
+
parameter.cache_size = 1 # in megabytes
|
39
|
+
parameter.eps = 0.001
|
40
|
+
parameter.c = 10
|
41
|
+
|
42
|
+
# train classifier using training set
|
43
|
+
#
|
44
|
+
problem.set_examples(training_set.map(&:first), training_set.map(&:last))
|
45
|
+
model = Libsvm::Model.train(problem, parameter)
|
46
|
+
|
47
|
+
# Now lets test our classifier using the test set
|
48
|
+
#
|
49
|
+
test_set = [1, "Why did the chicken cross the road? To get the worm"]
|
50
|
+
test_document = test_set.last.split(' ').map{ |x| x.gsub(/\?|,|\.|\-/,'') }
|
51
|
+
|
52
|
+
pred = model.predict(Libsvm::Node.features(dictionary.map{|x| test_document.include?(x) }))
|
53
|
+
puts "Predicted #{pred}"
|
data/ext/rb-libsvm/svm.cpp
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
#include <float.h>
|
6
6
|
#include <string.h>
|
7
7
|
#include <stdarg.h>
|
8
|
+
#include <limits.h>
|
9
|
+
#include <locale.h>
|
8
10
|
#include "svm.h"
|
9
11
|
int libsvm_version = LIBSVM_VERSION;
|
10
12
|
typedef float Qfloat;
|
@@ -42,7 +44,7 @@ static void print_string_stdout(const char *s)
|
|
42
44
|
fflush(stdout);
|
43
45
|
}
|
44
46
|
static void (*svm_print_string) (const char *) = &print_string_stdout;
|
45
|
-
#if
|
47
|
+
#if 0
|
46
48
|
static void info(const char *fmt,...)
|
47
49
|
{
|
48
50
|
char buf[BUFSIZ];
|
@@ -474,7 +476,7 @@ void Solver::reconstruct_gradient()
|
|
474
476
|
nr_free++;
|
475
477
|
|
476
478
|
if(2*nr_free < active_size)
|
477
|
-
info("\
|
479
|
+
info("\nWARNING: using -h 0 may be faster\n");
|
478
480
|
|
479
481
|
if (nr_free*l > 2*active_size*(l-active_size))
|
480
482
|
{
|
@@ -556,9 +558,10 @@ void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
|
|
556
558
|
// optimization step
|
557
559
|
|
558
560
|
int iter = 0;
|
561
|
+
int max_iter = max(10000000, l>INT_MAX/100 ? INT_MAX : 100*l);
|
559
562
|
int counter = min(l,1000)+1;
|
560
|
-
|
561
|
-
while(
|
563
|
+
|
564
|
+
while(iter < max_iter)
|
562
565
|
{
|
563
566
|
// show progress and do shrinking
|
564
567
|
|
@@ -576,7 +579,7 @@ void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
|
|
576
579
|
reconstruct_gradient();
|
577
580
|
// reset active set size and check
|
578
581
|
active_size = l;
|
579
|
-
|
582
|
+
info("*");
|
580
583
|
if(select_working_set(i,j)!=0)
|
581
584
|
break;
|
582
585
|
else
|
@@ -725,6 +728,18 @@ void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
|
|
725
728
|
}
|
726
729
|
}
|
727
730
|
|
731
|
+
if(iter >= max_iter)
|
732
|
+
{
|
733
|
+
if(active_size < l)
|
734
|
+
{
|
735
|
+
// reconstruct the whole gradient to calculate objective value
|
736
|
+
reconstruct_gradient();
|
737
|
+
active_size = l;
|
738
|
+
info("*");
|
739
|
+
}
|
740
|
+
info("\nWARNING: reaching max number of iterations");
|
741
|
+
}
|
742
|
+
|
728
743
|
// calculate rho
|
729
744
|
|
730
745
|
si->rho = calculate_rho();
|
@@ -756,7 +771,7 @@ void Solver::Solve(int l, const QMatrix& Q, const double *p_, const schar *y_,
|
|
756
771
|
si->upper_bound_p = Cp;
|
757
772
|
si->upper_bound_n = Cn;
|
758
773
|
|
759
|
-
|
774
|
+
info("\noptimization finished, #iter = %d\n",iter);
|
760
775
|
|
761
776
|
delete[] p;
|
762
777
|
delete[] y;
|
@@ -929,7 +944,7 @@ void Solver::do_shrinking()
|
|
929
944
|
unshrink = true;
|
930
945
|
reconstruct_gradient();
|
931
946
|
active_size = l;
|
932
|
-
|
947
|
+
info("*");
|
933
948
|
}
|
934
949
|
|
935
950
|
for(i=0;i<active_size;i++)
|
@@ -1448,7 +1463,7 @@ static void solve_c_svc(
|
|
1448
1463
|
sum_alpha += alpha[i];
|
1449
1464
|
|
1450
1465
|
if (Cp==Cn)
|
1451
|
-
|
1466
|
+
info("nu = %f\n", sum_alpha/(Cp*prob->l));
|
1452
1467
|
|
1453
1468
|
for(i=0;i<l;i++)
|
1454
1469
|
alpha[i] *= y[i];
|
@@ -1498,7 +1513,7 @@ static void solve_nu_svc(
|
|
1498
1513
|
alpha, 1.0, 1.0, param->eps, si, param->shrinking);
|
1499
1514
|
double r = si->r;
|
1500
1515
|
|
1501
|
-
|
1516
|
+
info("C = %f\n",1/r);
|
1502
1517
|
|
1503
1518
|
for(i=0;i<l;i++)
|
1504
1519
|
alpha[i] *= y[i]/r;
|
@@ -1575,7 +1590,7 @@ static void solve_epsilon_svr(
|
|
1575
1590
|
alpha[i] = alpha2[i] - alpha2[i+l];
|
1576
1591
|
sum_alpha += fabs(alpha[i]);
|
1577
1592
|
}
|
1578
|
-
|
1593
|
+
info("nu = %f\n",sum_alpha/(param->C*l));
|
1579
1594
|
|
1580
1595
|
delete[] alpha2;
|
1581
1596
|
delete[] linear_term;
|
@@ -1610,7 +1625,7 @@ static void solve_nu_svr(
|
|
1610
1625
|
s.Solve(2*l, SVR_Q(*prob,*param), linear_term, y,
|
1611
1626
|
alpha2, C, C, param->eps, si, param->shrinking);
|
1612
1627
|
|
1613
|
-
|
1628
|
+
info("epsilon = %f\n",-si->r);
|
1614
1629
|
|
1615
1630
|
for(i=0;i<l;i++)
|
1616
1631
|
alpha[i] = alpha2[i] - alpha2[i+l];
|
@@ -1654,7 +1669,7 @@ static decision_function svm_train_one(
|
|
1654
1669
|
break;
|
1655
1670
|
}
|
1656
1671
|
|
1657
|
-
|
1672
|
+
info("obj = %f, rho = %f\n",si.obj,si.rho);
|
1658
1673
|
|
1659
1674
|
// output SVs
|
1660
1675
|
|
@@ -1678,7 +1693,7 @@ static decision_function svm_train_one(
|
|
1678
1693
|
}
|
1679
1694
|
}
|
1680
1695
|
|
1681
|
-
|
1696
|
+
info("nSV = %d, nBSV = %d\n",nSV,nBSV);
|
1682
1697
|
|
1683
1698
|
decision_function f;
|
1684
1699
|
f.alpha = alpha;
|
@@ -2114,7 +2129,10 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2114
2129
|
int *perm = Malloc(int,l);
|
2115
2130
|
|
2116
2131
|
// group training data of the same class
|
2117
|
-
svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
|
2132
|
+
svm_group_classes(prob,&nr_class,&label,&start,&count,perm);
|
2133
|
+
if(nr_class == 1)
|
2134
|
+
info("WARNING: training data in only one class. See README for details.\n");
|
2135
|
+
|
2118
2136
|
svm_node **x = Malloc(svm_node *,l);
|
2119
2137
|
int i;
|
2120
2138
|
for(i=0;i<l;i++)
|
@@ -2132,7 +2150,7 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2132
2150
|
if(param->weight_label[i] == label[j])
|
2133
2151
|
break;
|
2134
2152
|
if(j == nr_class)
|
2135
|
-
fprintf(stderr,"
|
2153
|
+
fprintf(stderr,"WARNING: class label %d specified in weight is not found\n", param->weight_label[i]);
|
2136
2154
|
else
|
2137
2155
|
weighted_C[j] *= param->weight[i];
|
2138
2156
|
}
|
@@ -2232,7 +2250,7 @@ svm_model *svm_train(const svm_problem *prob, const svm_parameter *param)
|
|
2232
2250
|
nz_count[i] = nSV;
|
2233
2251
|
}
|
2234
2252
|
|
2235
|
-
|
2253
|
+
info("Total nSV = %d\n",total_sv);
|
2236
2254
|
|
2237
2255
|
model->l = total_sv;
|
2238
2256
|
model->SV = Malloc(svm_node *,total_sv);
|
@@ -2440,13 +2458,14 @@ double svm_get_svr_probability(const svm_model *model)
|
|
2440
2458
|
|
2441
2459
|
double svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values)
|
2442
2460
|
{
|
2461
|
+
int i;
|
2443
2462
|
if(model->param.svm_type == ONE_CLASS ||
|
2444
2463
|
model->param.svm_type == EPSILON_SVR ||
|
2445
2464
|
model->param.svm_type == NU_SVR)
|
2446
2465
|
{
|
2447
2466
|
double *sv_coef = model->sv_coef[0];
|
2448
2467
|
double sum = 0;
|
2449
|
-
for(
|
2468
|
+
for(i=0;i<model->l;i++)
|
2450
2469
|
sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param);
|
2451
2470
|
sum -= model->rho[0];
|
2452
2471
|
*dec_values = sum;
|
@@ -2458,7 +2477,6 @@ double svm_predict_values(const svm_model *model, const svm_node *x, double* dec
|
|
2458
2477
|
}
|
2459
2478
|
else
|
2460
2479
|
{
|
2461
|
-
int i;
|
2462
2480
|
int nr_class = model->nr_class;
|
2463
2481
|
int l = model->l;
|
2464
2482
|
|
@@ -2583,6 +2601,9 @@ int svm_save_model(const char *model_file_name, const svm_model *model)
|
|
2583
2601
|
FILE *fp = fopen(model_file_name,"w");
|
2584
2602
|
if(fp==NULL) return -1;
|
2585
2603
|
|
2604
|
+
char *old_locale = strdup(setlocale(LC_ALL, NULL));
|
2605
|
+
setlocale(LC_ALL, "C");
|
2606
|
+
|
2586
2607
|
const svm_parameter& param = model->param;
|
2587
2608
|
|
2588
2609
|
fprintf(fp,"svm_type %s\n", svm_type_table[param.svm_type]);
|
@@ -2661,6 +2682,10 @@ int svm_save_model(const char *model_file_name, const svm_model *model)
|
|
2661
2682
|
}
|
2662
2683
|
fprintf(fp, "\n");
|
2663
2684
|
}
|
2685
|
+
|
2686
|
+
setlocale(LC_ALL, old_locale);
|
2687
|
+
free(old_locale);
|
2688
|
+
|
2664
2689
|
if (ferror(fp) != 0 || fclose(fp) != 0) return -1;
|
2665
2690
|
else return 0;
|
2666
2691
|
}
|
@@ -2690,7 +2715,10 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2690
2715
|
{
|
2691
2716
|
FILE *fp = fopen(model_file_name,"rb");
|
2692
2717
|
if(fp==NULL) return NULL;
|
2693
|
-
|
2718
|
+
|
2719
|
+
char *old_locale = strdup(setlocale(LC_ALL, NULL));
|
2720
|
+
setlocale(LC_ALL, "C");
|
2721
|
+
|
2694
2722
|
// read parameters
|
2695
2723
|
|
2696
2724
|
svm_model *model = Malloc(svm_model,1);
|
@@ -2721,6 +2749,9 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2721
2749
|
if(svm_type_table[i] == NULL)
|
2722
2750
|
{
|
2723
2751
|
fprintf(stderr,"unknown svm type.\n");
|
2752
|
+
|
2753
|
+
setlocale(LC_ALL, old_locale);
|
2754
|
+
free(old_locale);
|
2724
2755
|
free(model->rho);
|
2725
2756
|
free(model->label);
|
2726
2757
|
free(model->nSV);
|
@@ -2743,6 +2774,9 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2743
2774
|
if(kernel_type_table[i] == NULL)
|
2744
2775
|
{
|
2745
2776
|
fprintf(stderr,"unknown kernel function.\n");
|
2777
|
+
|
2778
|
+
setlocale(LC_ALL, old_locale);
|
2779
|
+
free(old_locale);
|
2746
2780
|
free(model->rho);
|
2747
2781
|
free(model->label);
|
2748
2782
|
free(model->nSV);
|
@@ -2807,6 +2841,9 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2807
2841
|
else
|
2808
2842
|
{
|
2809
2843
|
fprintf(stderr,"unknown text in model file: [%s]\n",cmd);
|
2844
|
+
|
2845
|
+
setlocale(LC_ALL, old_locale);
|
2846
|
+
free(old_locale);
|
2810
2847
|
free(model->rho);
|
2811
2848
|
free(model->label);
|
2812
2849
|
free(model->nSV);
|
@@ -2879,6 +2916,9 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2879
2916
|
}
|
2880
2917
|
free(line);
|
2881
2918
|
|
2919
|
+
setlocale(LC_ALL, old_locale);
|
2920
|
+
free(old_locale);
|
2921
|
+
|
2882
2922
|
if (ferror(fp) != 0 || fclose(fp) != 0)
|
2883
2923
|
return NULL;
|
2884
2924
|
|
@@ -2888,13 +2928,13 @@ svm_model *svm_load_model(const char *model_file_name)
|
|
2888
2928
|
|
2889
2929
|
void svm_free_model_content(svm_model* model_ptr)
|
2890
2930
|
{
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2931
|
+
if(model_ptr->free_sv && model_ptr->l > 0 && model_ptr->SV != NULL)
|
2932
|
+
free((void *)(model_ptr->SV[0]));
|
2933
|
+
if(model_ptr->sv_coef)
|
2934
|
+
{
|
2935
|
+
for(int i=0;i<model_ptr->nr_class-1;i++)
|
2936
|
+
free(model_ptr->sv_coef[i]);
|
2937
|
+
}
|
2898
2938
|
|
2899
2939
|
free(model_ptr->SV);
|
2900
2940
|
model_ptr->SV = NULL;
|
@@ -2920,12 +2960,12 @@ void svm_free_model_content(svm_model* model_ptr)
|
|
2920
2960
|
|
2921
2961
|
void svm_free_and_destroy_model(svm_model** model_ptr_ptr)
|
2922
2962
|
{
|
2923
|
-
|
2924
|
-
|
2925
|
-
|
2963
|
+
if(model_ptr_ptr != NULL && *model_ptr_ptr != NULL)
|
2964
|
+
{
|
2965
|
+
svm_free_model_content(*model_ptr_ptr);
|
2926
2966
|
free(*model_ptr_ptr);
|
2927
|
-
|
2928
|
-
|
2967
|
+
*model_ptr_ptr = NULL;
|
2968
|
+
}
|
2929
2969
|
}
|
2930
2970
|
|
2931
2971
|
void svm_destroy_param(svm_parameter* param)
|
data/ext/rb-libsvm/svm.h
CHANGED
data/lib/libsvm.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'rb-libsvm/version'
|
2
2
|
require 'rb-libsvm/libsvm'
|
3
|
+
require 'libsvm/node'
|
3
4
|
|
4
5
|
module Libsvm
|
5
|
-
|
6
6
|
module CoreExtensions
|
7
7
|
module Collection
|
8
8
|
def to_example
|
@@ -10,48 +10,6 @@ module Libsvm
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
13
|
-
|
14
|
-
class Node
|
15
|
-
|
16
|
-
class << self
|
17
|
-
|
18
|
-
def features(*vargs)
|
19
|
-
array_of_nodes = []
|
20
|
-
if vargs.size == 1
|
21
|
-
if vargs.first.class == Array
|
22
|
-
vargs.first.each_with_index do |value, index|
|
23
|
-
array_of_nodes << Node.new(index.to_i, value.to_f)
|
24
|
-
end
|
25
|
-
elsif vargs.first.class == Hash
|
26
|
-
vargs.first.each do |index, value|
|
27
|
-
array_of_nodes << Node.new(index.to_i, value.to_f)
|
28
|
-
end
|
29
|
-
else
|
30
|
-
raise(ArgumentError.new("Node features need to be a Hash, Array or Floats"))
|
31
|
-
end
|
32
|
-
else
|
33
|
-
vargs.each_with_index do |value, index|
|
34
|
-
array_of_nodes << Node.new(index.to_i, value.to_f)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
array_of_nodes
|
38
|
-
end
|
39
|
-
|
40
|
-
def [](index, value)
|
41
|
-
new(index, value)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def initialize(index=0, value=0.0)
|
46
|
-
self.index = index
|
47
|
-
self.value = value
|
48
|
-
end
|
49
|
-
|
50
|
-
def ==(other)
|
51
|
-
index == other.index && value == other.value
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
13
|
end
|
56
14
|
|
57
15
|
|
data/lib/libsvm/node.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Libsvm
|
2
|
+
class Node
|
3
|
+
class << self
|
4
|
+
def features(*vargs)
|
5
|
+
array_of_nodes = []
|
6
|
+
if vargs.size == 1
|
7
|
+
if vargs.first.class == Array
|
8
|
+
vargs.first.each_with_index do |value, index|
|
9
|
+
array_of_nodes << Node.new(index.to_i, value.to_f)
|
10
|
+
end
|
11
|
+
elsif vargs.first.class == Hash
|
12
|
+
vargs.first.each do |index, value|
|
13
|
+
array_of_nodes << Node.new(index.to_i, value.to_f)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
raise(ArgumentError.new("Node features need to be a Hash, Array or Floats"))
|
17
|
+
end
|
18
|
+
else
|
19
|
+
vargs.each_with_index do |value, index|
|
20
|
+
array_of_nodes << Node.new(index.to_i, value.to_f)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
array_of_nodes
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](index, value)
|
27
|
+
new(index, value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(index=0, value=0.0)
|
32
|
+
self.index = index
|
33
|
+
self.value = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def ==(other)
|
37
|
+
index == other.index && value == other.value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/rb-libsvm/version.rb
CHANGED
data/rb-libsvm.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
+
|
21
22
|
# specify any dependencies here; for example:
|
22
23
|
s.add_development_dependency('rake-compiler')
|
23
24
|
s.add_development_dependency('rspec', '>= 2.7.0')
|
Binary file
|
data/spec/model_spec.rb
CHANGED
@@ -2,94 +2,94 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
module ModelSpecHelper
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
5
|
+
def create_example
|
6
|
+
Node.features(0.2, 0.3, 0.4, 0.5)
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_problem
|
10
|
+
problem = Problem.new
|
11
|
+
features = [Node.features([0.2,0.3,0.4,0.4]),
|
12
|
+
Node.features([0.1,0.5,0.1,0.9]),
|
13
|
+
Node.features([0.2,0.2,0.6,0.5]),
|
14
|
+
Node.features([0.3,0.1,0.5,0.9])]
|
15
|
+
problem.set_examples([1,2,1,2], features)
|
16
|
+
problem
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_parameter
|
20
|
+
parameter = SvmParameter.new
|
21
|
+
parameter.cache_size = 50 # mb
|
22
|
+
parameter.eps = 0.01
|
23
|
+
parameter.c = 10
|
24
|
+
parameter
|
25
|
+
end
|
26
26
|
|
27
27
|
end
|
28
28
|
|
29
29
|
describe "The Libsvm::Model class interface" do
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
30
|
+
include ModelSpecHelper
|
31
|
+
|
32
|
+
before(:each) do
|
33
|
+
@problem = create_problem
|
34
|
+
@parameter = create_parameter
|
35
|
+
end
|
36
|
+
|
37
|
+
it "results from training on a problem under a certain parameter set" do
|
38
|
+
model = Model.train(@problem,@parameter)
|
39
|
+
model.should_not be_nil
|
40
|
+
end
|
41
|
+
|
42
|
+
it "can do cross-validation" do
|
43
|
+
labels = Model.cross_validation(@problem, @parameter, fold=2)
|
44
|
+
labels.should == [anything, anything, anything, anything]
|
45
|
+
end
|
46
46
|
end
|
47
47
|
|
48
48
|
describe "A saved model" do
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
49
|
+
include ModelSpecHelper
|
50
|
+
|
51
|
+
before(:each) do
|
52
|
+
@filename = "svm_model.model"
|
53
|
+
model = Model.train(create_problem, create_parameter)
|
54
|
+
model.save(@filename)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "can be loaded" do
|
58
|
+
model = Model.load(@filename)
|
59
|
+
model.should_not be_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
after(:each) do
|
63
|
+
File.delete(@filename) rescue nil
|
64
|
+
end
|
65
65
|
end
|
66
66
|
|
67
67
|
describe "An Libsvm model" do
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
68
|
+
include ModelSpecHelper
|
69
|
+
|
70
|
+
before(:each) do
|
71
|
+
@problem = create_problem
|
72
|
+
@parameter = create_parameter
|
73
|
+
@model = Model.train(@problem, @parameter)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "can be saved to a file" do
|
77
|
+
file_path = "svm_model.model"
|
78
|
+
@model.save(file_path)
|
79
|
+
File.exist?(file_path).should be_true
|
80
|
+
end
|
81
|
+
|
82
|
+
it "can be asked for it's svm_type" do
|
83
|
+
@model.svm_type.should == SvmType::C_SVC
|
84
|
+
end
|
85
|
+
|
86
|
+
it "can be asked for it's number of classes (aka. labels)" do
|
87
|
+
@model.classes.should == 2
|
88
|
+
end
|
89
|
+
|
90
|
+
it "can predict" do
|
91
|
+
prediction = @model.predict(create_example)
|
92
|
+
prediction.should_not be_nil
|
93
|
+
end
|
94
94
|
end
|
95
95
|
|
data/spec/node_spec.rb
CHANGED
@@ -1,68 +1,68 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe "construction of a Node" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
it "using the properties" do
|
5
|
+
n = Node.new
|
6
|
+
n.index = 11
|
7
|
+
n.value = 0.11
|
8
|
+
n.index.should == 11
|
9
|
+
n.value.should be_within(0.0001).of(0.11)
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
it "using the :[] method" do
|
13
|
+
n = Node[12, 0.12]
|
14
|
+
n.index.should == 12
|
15
|
+
n.value.should be_within(0.00001).of(0.12)
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
it "using the constructor parameters" do
|
19
|
+
n = Node.new(14, 0.14)
|
20
|
+
n.index.should == 14
|
21
|
+
n.value.should be_within(0.0001).of(0.14)
|
22
|
+
end
|
23
23
|
end
|
24
24
|
|
25
25
|
describe "A Node" do
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
before do
|
27
|
+
@node = Node.new
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
it "can be created" do
|
31
|
+
@node.should_not be_nil
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
it "does not segfault on setting properties" do
|
35
|
+
@node.index = 99
|
36
|
+
@node.index.should == 99
|
37
|
+
@node.value = 3.141
|
38
|
+
@node.value.should be_within(0.00001).of(3.141)
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
it "has inited properties" do
|
42
|
+
@node.index.should == 0
|
43
|
+
@node.value.should be_within(0.00001).of(0)
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
it "class can create nodes from an array" do
|
47
|
+
ary = Node.features([0.1, 0.2, 0.3, 0.4, 0.5])
|
48
|
+
ary.map {|n| n.class.should == Node}
|
49
|
+
ary.map {|n| n.value }.should == [0.1, 0.2, 0.3, 0.4, 0.5]
|
50
|
+
end
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
it "class can create nodes from variable parameters" do
|
53
|
+
ary = Node.features(0.1, 0.2, 0.3, 0.4, 0.5)
|
54
|
+
ary.map {|n| Node.should === n }
|
55
|
+
ary.map {|n| n.value }.should == [0.1, 0.2, 0.3, 0.4, 0.5]
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
it "class can create nodes from hash" do
|
59
|
+
ary = Node.features(3=>0.3, 5=>0.5, 6=>0.6, 10=>1.0)
|
60
|
+
ary.map {|n| n.class.should == Node}
|
61
|
+
ary.map {|n| n.value }.sort.should == [0.3, 0.5, 0.6, 1.0]
|
62
|
+
ary.map {|n| n.index }.sort.should == [3, 5, 6, 10]
|
63
|
+
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
it "implements a value-like equality, not identity-notion" do
|
66
|
+
Node[1, 0.1].should == Node[1, 0.1]
|
67
|
+
end
|
68
68
|
end
|
data/spec/parameter_spec.rb
CHANGED
@@ -1,76 +1,76 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe "A Parameter has accessors for" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
before do
|
5
|
+
@p = Libsvm::SvmParameter.new
|
6
|
+
end
|
7
|
+
it "int svm_type" do
|
8
|
+
SvmType::C_SVC.should == 0
|
9
|
+
@p.svm_type = SvmType::C_SVC
|
10
|
+
@p.svm_type.should == SvmType::C_SVC
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
it "int kernel_type" do
|
14
|
+
KernelType::RBF.should == 2
|
15
|
+
@p.kernel_type = KernelType::RBF
|
16
|
+
@p.kernel_type.should == KernelType::RBF
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
it "int degree" do
|
20
|
+
@p.degree = 99
|
21
|
+
@p.degree.should == 99
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
it "double gamma" do
|
25
|
+
@p.gamma = 0.33
|
26
|
+
@p.gamma.should == 0.33
|
27
|
+
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
it "double coef0" do
|
30
|
+
@p.coef0 = 0.99
|
31
|
+
@p.coef0.should == 0.99
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
it "double cache_size" do
|
35
|
+
@p.cache_size = 0.77
|
36
|
+
@p.cache_size.should == 0.77
|
37
|
+
end
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
it "double eps" do
|
40
|
+
@p.eps = 0.111
|
41
|
+
@p.eps.should == 0.111
|
42
|
+
@p.eps = 0.112
|
43
|
+
@p.eps.should == 0.112
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
it "double C" do
|
47
|
+
@p.c = 3.141
|
48
|
+
@p.c.should == 3.141
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
it "can set and read weights (weight, weight_label, nr_weight members from struct)" do
|
52
|
+
@p.label_weights = {1=> 1.2, 3=>0.2, 5=>0.888}
|
53
|
+
@p.label_weights.should == {1=> 1.2, 3=>0.2, 5=>0.888}
|
54
|
+
end
|
55
55
|
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
it "double nu" do
|
58
|
+
@p.nu = 1.1
|
59
|
+
@p.nu.should == 1.1
|
60
|
+
end
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
it "double p" do
|
63
|
+
@p.p = 0.123
|
64
|
+
@p.p.should == 0.123
|
65
|
+
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
it "int shrinking" do
|
68
|
+
@p.shrinking = 22
|
69
|
+
@p.shrinking.should == 22
|
70
|
+
end
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
it "int probability" do
|
73
|
+
@p.probability = 35
|
74
|
+
@p.probability.should == 35
|
75
|
+
end
|
76
76
|
end
|
data/spec/problem_spec.rb
CHANGED
@@ -1,37 +1,37 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "A Problem" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
before(:each) do
|
5
|
+
@problem = Problem.new
|
6
|
+
@features = [ Node.features(0.2,0.3,0.4,0.4),
|
7
|
+
Node.features(0.1,0.5,0.1,0.9),
|
8
|
+
Node.features(0.2,0.2,0.6,0.5),
|
9
|
+
Node.features(0.3,0.1,0.5,0.9) ]
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
it "examples get stored and retrieved" do
|
13
|
+
@problem.set_examples([1,2,1,2], @features)
|
14
|
+
labels, examples = @problem.examples
|
15
|
+
labels.size.should == 4
|
16
|
+
examples.size.should == 4
|
17
|
+
examples.map {|x|x.size}.should == [4,4,4,4]
|
18
|
+
examples.first.map {|node| node.index}.should == [0,1,2,3]
|
19
|
+
examples.first.map {|node| node.value}.should == [0.2,0.3,0.4,0.4]
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
it "can be populated" do
|
23
|
+
examples = [Node.features(0.2,0.3,0.4,0.4),
|
24
|
+
Node.features(0.1,0.5,0.1,0.9),
|
25
|
+
Node.features(0.2,0.2,0.6,0.5),
|
26
|
+
Node.features(0.3,0.1,0.5,0.9)]
|
27
|
+
@problem.set_examples([1,2,1,2], examples)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "can be set twice over" do
|
31
|
+
features = [Node.features(0.2, 0.3, 0.4, 0.4), Node.features(0.3,0.1,0.5,0.9)]
|
32
|
+
@problem.set_examples([1,2], features)
|
33
|
+
features = [Node.features(0.2, 0.3, 0.4, 0.4), Node.features(0.3,0.1,0.5,0.9)]
|
34
|
+
@problem.set_examples([8,2], features)
|
35
|
+
end
|
29
36
|
|
30
|
-
it "can be set twice over" do
|
31
|
-
features = [Node.features(0.2, 0.3, 0.4, 0.4), Node.features(0.3,0.1,0.5,0.9)]
|
32
|
-
@problem.set_examples([1,2], features)
|
33
|
-
features = [Node.features(0.2, 0.3, 0.4, 0.4), Node.features(0.3,0.1,0.5,0.9)]
|
34
|
-
@problem.set_examples([8,2], features)
|
35
|
-
end
|
36
|
-
|
37
37
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/usage_spec.rb
CHANGED
@@ -1,47 +1,47 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Basic usage" do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
before do
|
5
|
+
@problem = Problem.new
|
6
|
+
@parameter = SvmParameter.new
|
7
|
+
@parameter.cache_size = 1 # mb
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
# "eps is the stopping criterion (we usually use 0.00001 in nu-SVC,
|
10
|
+
# 0.001 in others)." (from README)
|
11
|
+
@parameter.eps = 0.001
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
@parameter.c = 10
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
it "has a nice API" do
|
17
|
+
example = {11 => 0.11, 21 => 0.21, 101 => 0.99 }.to_example
|
18
|
+
example.should == Node.features({11 => 0.11, 21 => 0.21, 101 => 0.99 })
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
it "is as in [PCI,217]" do
|
22
|
+
examples = [ [1,0,1], [-1,0,-1] ].map {|ary| Node.features(ary) }
|
23
|
+
labels = [1, -1]
|
24
|
+
@problem.set_examples(labels, examples)
|
25
25
|
|
26
|
-
|
26
|
+
model = Model.train(@problem, @parameter)
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
pred = model.predict(Node.features(1, 1, 1))
|
29
|
+
pred.should == 1.0
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
pred = model.predict(Node.features(-1, 1, -1))
|
32
|
+
pred.should == -1.0
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
pred = model.predict(Node.features(-1, 55, -1))
|
35
|
+
pred.should == -1.0
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
it "kernel parameter use" do
|
39
|
+
@parameter.kernel_type = SvmParameter::KernelType::RBF
|
40
|
+
examples = [[1, 2, 3], [-2, -2, -2]].map {|ary| Node.features(ary) }
|
41
|
+
@problem.set_examples([1, 2], examples)
|
42
42
|
|
43
|
-
|
43
|
+
model = Model.train(@problem, @parameter)
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
model.predict(Node.features(1, 2, 3)).should == 2
|
46
|
+
end
|
47
47
|
end
|
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.0.
|
4
|
+
version: 1.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2012-05-11 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake-compiler
|
17
|
-
requirement: &
|
17
|
+
requirement: &70287710299640 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70287710299640
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: rspec
|
28
|
-
requirement: &
|
28
|
+
requirement: &70287710298620 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
version: 2.7.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70287710298620
|
37
37
|
description: libsvm and ruby without using swig
|
38
38
|
email:
|
39
39
|
- neovintage@gmail.com
|
@@ -46,9 +46,11 @@ files:
|
|
46
46
|
- .rvmrc
|
47
47
|
- .travis.yml
|
48
48
|
- Gemfile
|
49
|
+
- LIBSVM-LICENSE
|
49
50
|
- MIT-LICENSE
|
50
51
|
- README.md
|
51
52
|
- Rakefile
|
53
|
+
- examples/text.rb
|
52
54
|
- examples/toy.rb
|
53
55
|
- ext/rb-libsvm/extconf.rb
|
54
56
|
- ext/rb-libsvm/libsvm.c
|
@@ -57,8 +59,10 @@ files:
|
|
57
59
|
- ext/rb-libsvm/svm.h
|
58
60
|
- ferret_valgrind.supp
|
59
61
|
- lib/libsvm.rb
|
62
|
+
- lib/libsvm/node.rb
|
60
63
|
- lib/rb-libsvm/version.rb
|
61
64
|
- rb-libsvm.gemspec
|
65
|
+
- spec/.usage_spec.rb.swp
|
62
66
|
- spec/model_spec.rb
|
63
67
|
- spec/node_spec.rb
|
64
68
|
- spec/parameter_spec.rb
|
@@ -77,15 +81,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
81
|
- - ! '>='
|
78
82
|
- !ruby/object:Gem::Version
|
79
83
|
version: '0'
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
hash: 932394419047004720
|
80
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
88
|
none: false
|
82
89
|
requirements:
|
83
90
|
- - ! '>='
|
84
91
|
- !ruby/object:Gem::Version
|
85
92
|
version: '0'
|
93
|
+
segments:
|
94
|
+
- 0
|
95
|
+
hash: 932394419047004720
|
86
96
|
requirements: []
|
87
97
|
rubyforge_project: rb-libsvm
|
88
|
-
rubygems_version: 1.8.
|
98
|
+
rubygems_version: 1.8.10
|
89
99
|
signing_key:
|
90
100
|
specification_version: 3
|
91
101
|
summary: Ruby language bindings for LIBSVM
|