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 CHANGED
@@ -1,2 +1,4 @@
1
- rvm: 1.9.2
2
-
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2004-2008 Caspar Florian Ebeling
1
+ Copyright (c) 2004-2012 Caspar Florian Ebeling
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
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}"
@@ -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 1
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("\nWarning: using -h 0 may be faster\n");
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(1)
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
- // info("*");
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
- // info("\noptimization finished, #iter = %d\n",iter);
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
- // info("*");
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
- // info("nu = %f\n", sum_alpha/(Cp*prob->l));
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
- // info("C = %f\n",1/r);
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
- // info("nu = %f\n",sum_alpha/(param->C*l));
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
- // info("epsilon = %f\n",-si->r);
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
- // info("obj = %f, rho = %f\n",si.obj,si.rho);
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
- // info("nSV = %d, nBSV = %d\n",nSV,nBSV);
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,"warning: class label %d specified in weight is not found\n", param->weight_label[i]);
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
- // info("Total nSV = %d\n",total_sv);
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(int i=0;i<model->l;i++)
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
- if(model_ptr->free_sv && model_ptr->l > 0 && model_ptr->SV != NULL)
2892
- free((void *)(model_ptr->SV[0]));
2893
- if(model_ptr->sv_coef)
2894
- {
2895
- for(int i=0;i<model_ptr->nr_class-1;i++)
2896
- free(model_ptr->sv_coef[i]);
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
- if(model_ptr_ptr != NULL && *model_ptr_ptr != NULL)
2924
- {
2925
- svm_free_model_content(*model_ptr_ptr);
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
- *model_ptr_ptr = NULL;
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
@@ -1,7 +1,7 @@
1
1
  #ifndef _LIBSVM_H
2
2
  #define _LIBSVM_H
3
3
 
4
- #define LIBSVM_VERSION 310
4
+ #define LIBSVM_VERSION 312
5
5
 
6
6
  #ifdef __cplusplus
7
7
  extern "C" {
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
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Libsvm
2
- VERSION = "1.0.5"
2
+ VERSION = "1.0.6"
3
3
  end
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
- 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
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
- 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
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
- 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
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
- 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
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
- 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
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
- 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
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
- 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
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
- before do
27
- @node = Node.new
28
- end
26
+ before do
27
+ @node = Node.new
28
+ end
29
29
 
30
- it "can be created" do
31
- @node.should_not be_nil
32
- end
30
+ it "can be created" do
31
+ @node.should_not be_nil
32
+ end
33
33
 
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
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
- it "has inited properties" do
42
- @node.index.should == 0
43
- @node.value.should be_within(0.00001).of(0)
44
- end
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
- 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
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
- 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
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
- 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
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
- it "implements a value-like equality, not identity-notion" do
66
- Node[1, 0.1].should == Node[1, 0.1]
67
- end
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
@@ -1,76 +1,76 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe "A Parameter has accessors for" do
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
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
- 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
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
- it "int degree" do
20
- @p.degree = 99
21
- @p.degree.should == 99
22
- end
19
+ it "int degree" do
20
+ @p.degree = 99
21
+ @p.degree.should == 99
22
+ end
23
23
 
24
- it "double gamma" do
25
- @p.gamma = 0.33
26
- @p.gamma.should == 0.33
27
- end
24
+ it "double gamma" do
25
+ @p.gamma = 0.33
26
+ @p.gamma.should == 0.33
27
+ end
28
28
 
29
- it "double coef0" do
30
- @p.coef0 = 0.99
31
- @p.coef0.should == 0.99
32
- end
29
+ it "double coef0" do
30
+ @p.coef0 = 0.99
31
+ @p.coef0.should == 0.99
32
+ end
33
33
 
34
- it "double cache_size" do
35
- @p.cache_size = 0.77
36
- @p.cache_size.should == 0.77
37
- end
34
+ it "double cache_size" do
35
+ @p.cache_size = 0.77
36
+ @p.cache_size.should == 0.77
37
+ end
38
38
 
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
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
- it "double C" do
47
- @p.c = 3.141
48
- @p.c.should == 3.141
49
- end
46
+ it "double C" do
47
+ @p.c = 3.141
48
+ @p.c.should == 3.141
49
+ end
50
50
 
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
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
- it "double nu" do
58
- @p.nu = 1.1
59
- @p.nu.should == 1.1
60
- end
57
+ it "double nu" do
58
+ @p.nu = 1.1
59
+ @p.nu.should == 1.1
60
+ end
61
61
 
62
- it "double p" do
63
- @p.p = 0.123
64
- @p.p.should == 0.123
65
- end
62
+ it "double p" do
63
+ @p.p = 0.123
64
+ @p.p.should == 0.123
65
+ end
66
66
 
67
- it "int shrinking" do
68
- @p.shrinking = 22
69
- @p.shrinking.should == 22
70
- end
67
+ it "int shrinking" do
68
+ @p.shrinking = 22
69
+ @p.shrinking.should == 22
70
+ end
71
71
 
72
- it "int probability" do
73
- @p.probability = 35
74
- @p.probability.should == 35
75
- end
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
- 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
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
- 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
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
- 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
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
@@ -5,6 +5,6 @@ require 'libsvm'
5
5
  include Libsvm
6
6
 
7
7
  RSpec.configure do |config|
8
- config.color_enabled = true
8
+ config.color_enabled = true
9
9
  # config.formatter = 'documentation'
10
10
  end
data/spec/usage_spec.rb CHANGED
@@ -1,47 +1,47 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Basic usage" do
4
- before do
5
- @problem = Problem.new
6
- @parameter = SvmParameter.new
7
- @parameter.cache_size = 1 # mb
4
+ before do
5
+ @problem = Problem.new
6
+ @parameter = SvmParameter.new
7
+ @parameter.cache_size = 1 # mb
8
8
 
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
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
- @parameter.c = 10
14
- end
13
+ @parameter.c = 10
14
+ end
15
15
 
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
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
- 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)
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
- model = Model.train(@problem, @parameter)
26
+ model = Model.train(@problem, @parameter)
27
27
 
28
- pred = model.predict(Node.features(1, 1, 1))
29
- pred.should == 1.0
28
+ pred = model.predict(Node.features(1, 1, 1))
29
+ pred.should == 1.0
30
30
 
31
- pred = model.predict(Node.features(-1, 1, -1))
32
- pred.should == -1.0
31
+ pred = model.predict(Node.features(-1, 1, -1))
32
+ pred.should == -1.0
33
33
 
34
- pred = model.predict(Node.features(-1, 55, -1))
35
- pred.should == -1.0
36
- end
34
+ pred = model.predict(Node.features(-1, 55, -1))
35
+ pred.should == -1.0
36
+ end
37
37
 
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)
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
- model = Model.train(@problem, @parameter)
43
+ model = Model.train(@problem, @parameter)
44
44
 
45
- model.predict(Node.features(1, 2, 3)).should == 2
46
- end
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.5
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: 2011-12-07 00:00:00.000000000Z
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: &2153848920 !ruby/object:Gem::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: *2153848920
25
+ version_requirements: *70287710299640
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rspec
28
- requirement: &2153848420 !ruby/object:Gem::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: *2153848420
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.11
98
+ rubygems_version: 1.8.10
89
99
  signing_key:
90
100
  specification_version: 3
91
101
  summary: Ruby language bindings for LIBSVM