rb-libsvm 1.0.5 → 1.0.6

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.
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