numo-liblinear 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbd4a8fc87f4ae430183e396e9977337f31b0f3abe565045f7216cd49c30857d
4
- data.tar.gz: 03b97573731e979cda4d3e4d71b6647a6e16b3133fb9227be366292b80135986
3
+ metadata.gz: e365bea9ec3f7879a2eb5ca59356a5687b5f9991d850838e1667f3eff4177727
4
+ data.tar.gz: e6943a95893d8ecbe8e7d1b690829e20c20820148f120ed3f6c6e0c5892043ad
5
5
  SHA512:
6
- metadata.gz: 139cacb7349ebf5bee31b2292aa1de97eefbdc565affd44390359bf25a91e806d402c7d4104015fd1d6eba9b030b9fda5a7307f00923eaf259e90737559f1391
7
- data.tar.gz: cc50ab17ba43f8d59f83c97daa50d0da5750473fd0b65913b51223b253157b058464b17c7b499e240496c2065eb2f7ef12cb161575bfbce53eb2ceb117967b22
6
+ metadata.gz: 4ec40f71737aa4bbea21726b7c38c2f66c1c8e98967c4098b6bb910bf54010becb48218fd1bee441a2d8fe5290d1a7114ecf06426ef2826c7b473186e757185a
7
+ data.tar.gz: 133e1114abeccd511a38c785afeac8122d12cfa00e082e7384df067b13cec42050740b8d1f9a7669cadd9934985d7786f8bc7d13c6a56342a40b440474cb57d9
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ # 2.3.0
2
+ - Update bundled LIBLINEAR to 2.46
3
+
1
4
  # 2.2.1
2
5
  - Fix build failure with Xcode 14 and Ruby 3.1.x.
3
6
 
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2019-2022 Atsushi Tatsuma
1
+ Copyright (c) 2019-2023 Atsushi Tatsuma
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) 2019-2022 Atsushi Tatsuma
2
+ * Copyright (c) 2019-2023 Atsushi Tatsuma
3
3
  * All rights reserved.
4
4
  *
5
5
  * Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) 2019-2022 Atsushi Tatsuma
2
+ * Copyright (c) 2019-2023 Atsushi Tatsuma
3
3
  * All rights reserved.
4
4
  *
5
5
  * Redistribution and use in source and binary forms, with or without
@@ -1,5 +1,5 @@
1
1
 
2
- Copyright (c) 2007-2022 The LIBLINEAR Project.
2
+ Copyright (c) 2007-2023 The LIBLINEAR Project.
3
3
  All rights reserved.
4
4
 
5
5
  Redistribution and use in source and binary forms, with or without
@@ -2155,75 +2155,59 @@ static int solve_l1r_lr(const problem *prob_col, const parameter *param, double
2155
2155
  return newton_iter;
2156
2156
  }
2157
2157
 
2158
- struct heap {
2159
- enum HEAP_TYPE { MIN, MAX };
2160
- int _size;
2161
- HEAP_TYPE _type;
2162
- feature_node* a;
2158
+ static int compare_feature_node(const void *a, const void *b)
2159
+ {
2160
+ double a_value = (*(feature_node *)a).value;
2161
+ double b_value = (*(feature_node *)b).value;
2162
+ int a_index = (*(feature_node *)a).index;
2163
+ int b_index = (*(feature_node *)b).index;
2163
2164
 
2164
- heap(int max_size, HEAP_TYPE type)
2165
- {
2166
- _size = 0;
2167
- a = new feature_node[max_size];
2168
- _type = type;
2169
- }
2170
- ~heap()
2171
- {
2172
- delete [] a;
2173
- }
2174
- bool cmp(const feature_node& left, const feature_node& right)
2175
- {
2176
- if(_type == MIN)
2177
- return left.value > right.value;
2178
- else
2179
- return left.value < right.value;
2180
- }
2181
- int size()
2182
- {
2183
- return _size;
2184
- }
2185
- void push(feature_node node)
2165
+ if(a_value < b_value)
2166
+ return -1;
2167
+ else if(a_value == b_value)
2186
2168
  {
2187
- a[_size] = node;
2188
- _size++;
2189
- int i = _size-1;
2190
- while(i)
2191
- {
2192
- int p = (i-1)/2;
2193
- if(cmp(a[p], a[i]))
2194
- {
2195
- swap(a[i], a[p]);
2196
- i = p;
2197
- }
2198
- else
2199
- break;
2200
- }
2169
+ if(a_index < b_index)
2170
+ return -1;
2171
+ else if(a_index == b_index)
2172
+ return 0;
2201
2173
  }
2202
- void pop()
2203
- {
2204
- _size--;
2205
- a[0] = a[_size];
2206
- int i = 0;
2207
- while(i*2+1 < _size)
2174
+ return 1;
2175
+ }
2176
+
2177
+ // elements before the returned index are < pivot, while those after are >= pivot
2178
+ static int partition(feature_node *nodes, int low, int high)
2179
+ {
2180
+ int i;
2181
+ int index;
2182
+
2183
+ swap(nodes[low + rand()%(high-low+1)], nodes[high]); // select and move pivot to the end
2184
+
2185
+ index = low;
2186
+ for(i = low; i < high; i++)
2187
+ if (compare_feature_node(&nodes[i], &nodes[high]) == -1)
2208
2188
  {
2209
- int l = i*2+1;
2210
- int r = i*2+2;
2211
- if(r < _size && cmp(a[l], a[r]))
2212
- l = r;
2213
- if(cmp(a[i], a[l]))
2214
- {
2215
- swap(a[i], a[l]);
2216
- i = l;
2217
- }
2218
- else
2219
- break;
2189
+ swap(nodes[index], nodes[i]);
2190
+ index++;
2220
2191
  }
2221
- }
2222
- feature_node top()
2223
- {
2224
- return a[0];
2225
- }
2226
- };
2192
+
2193
+ swap(nodes[high], nodes[index]);
2194
+ return index;
2195
+ }
2196
+
2197
+ // rearrange nodes so that nodes[:k] contains nodes with the k smallest values.
2198
+ static void quick_select_min_k(feature_node *nodes, int low, int high, int k)
2199
+ {
2200
+ int pivot;
2201
+ if(low == high)
2202
+ return;
2203
+ pivot = partition(nodes, low, high);
2204
+ if(pivot == k)
2205
+ return;
2206
+ else if(k-1 < pivot)
2207
+ return quick_select_min_k(nodes, low, pivot-1, k);
2208
+ else
2209
+ return quick_select_min_k(nodes, pivot+1, high, k);
2210
+ }
2227
2211
 
2228
2212
  // A two-level coordinate descent algorithm for
2229
2213
  // a scaled one-class SVM dual problem
@@ -2262,11 +2246,12 @@ static int solve_oneclass_svm(const problem *prob, const parameter *param, doubl
2262
2246
  int max_iter = 1000;
2263
2247
  int active_size = l;
2264
2248
 
2265
- double negGmax; // max { -grad(f)_i | alpha_i < 1 }
2266
- double negGmin; // min { -grad(f)_i | alpha_i > 0 }
2267
-
2268
- int *most_violating_i = new int[l];
2269
- int *most_violating_j = new int[l];
2249
+ double negGmax; // max { -grad(f)_i | i in Iup }
2250
+ double negGmin; // min { -grad(f)_i | i in Ilow }
2251
+ // Iup = { i | alpha_i < 1 }, Ilow = { i | alpha_i > 0 }
2252
+ feature_node *max_negG_of_Iup = new feature_node[l];
2253
+ feature_node *min_negG_of_Ilow = new feature_node[l];
2254
+ feature_node node;
2270
2255
 
2271
2256
  int n = (int)(nu*l); // # of alpha's at upper bound
2272
2257
  for(i=0; i<n; i++)
@@ -2328,9 +2313,8 @@ static int solve_oneclass_svm(const problem *prob, const parameter *param, doubl
2328
2313
  }
2329
2314
 
2330
2315
  max_inner_iter = max(active_size/10, 1);
2331
- struct heap min_heap = heap(max_inner_iter, heap::MIN);
2332
- struct heap max_heap = heap(max_inner_iter, heap::MAX);
2333
- struct feature_node node;
2316
+ int len_Iup = 0;
2317
+ int len_Ilow = 0;
2334
2318
  for(s=0; s<active_size; s++)
2335
2319
  {
2336
2320
  i = index[s];
@@ -2339,44 +2323,28 @@ static int solve_oneclass_svm(const problem *prob, const parameter *param, doubl
2339
2323
 
2340
2324
  if (alpha[i] < 1)
2341
2325
  {
2342
- if (min_heap.size() < max_inner_iter)
2343
- min_heap.push(node);
2344
- else if (min_heap.top().value < node.value)
2345
- {
2346
- min_heap.pop();
2347
- min_heap.push(node);
2348
- }
2326
+ max_negG_of_Iup[len_Iup] = node;
2327
+ len_Iup++;
2349
2328
  }
2350
2329
 
2351
2330
  if (alpha[i] > 0)
2352
2331
  {
2353
- if (max_heap.size() < max_inner_iter)
2354
- max_heap.push(node);
2355
- else if (max_heap.top().value > node.value)
2356
- {
2357
- max_heap.pop();
2358
- max_heap.push(node);
2359
- }
2332
+ min_negG_of_Ilow[len_Ilow] = node;
2333
+ len_Ilow++;
2360
2334
  }
2361
2335
  }
2362
- max_inner_iter = min(min_heap.size(), max_heap.size());
2363
- while (max_heap.size() > max_inner_iter)
2364
- max_heap.pop();
2365
- while (min_heap.size() > max_inner_iter)
2366
- min_heap.pop();
2336
+ max_inner_iter = min(max_inner_iter, min(len_Iup, len_Ilow));
2367
2337
 
2368
- for (s=max_inner_iter-1; s>=0; s--)
2369
- {
2370
- most_violating_i[s] = min_heap.top().index;
2371
- most_violating_j[s] = max_heap.top().index;
2372
- min_heap.pop();
2373
- max_heap.pop();
2374
- }
2338
+ quick_select_min_k(max_negG_of_Iup, 0, len_Iup-1, len_Iup-max_inner_iter);
2339
+ qsort(&(max_negG_of_Iup[len_Iup-max_inner_iter]), max_inner_iter, sizeof(struct feature_node), compare_feature_node);
2340
+
2341
+ quick_select_min_k(min_negG_of_Ilow, 0, len_Ilow-1, max_inner_iter);
2342
+ qsort(min_negG_of_Ilow, max_inner_iter, sizeof(struct feature_node), compare_feature_node);
2375
2343
 
2376
2344
  for (s=0; s<max_inner_iter; s++)
2377
2345
  {
2378
- i = most_violating_i[s];
2379
- j = most_violating_j[s];
2346
+ i = max_negG_of_Iup[len_Iup-s-1].index;
2347
+ j = min_negG_of_Ilow[s].index;
2380
2348
 
2381
2349
  if ((alpha[i] == 0 && alpha[j] == 0) ||
2382
2350
  (alpha[i] == 1 && alpha[j] == 1))
@@ -2484,15 +2452,14 @@ static int solve_oneclass_svm(const problem *prob, const parameter *param, doubl
2484
2452
  *rho = sum_free/nr_free;
2485
2453
  else
2486
2454
  *rho = (ub + lb)/2;
2487
-
2488
2455
  info("rho = %lf\n", *rho);
2489
2456
 
2490
2457
  delete [] QD;
2491
2458
  delete [] G;
2492
2459
  delete [] index;
2493
2460
  delete [] alpha;
2494
- delete [] most_violating_i;
2495
- delete [] most_violating_j;
2461
+ delete [] max_negG_of_Iup;
2462
+ delete [] min_negG_of_Ilow;
2496
2463
 
2497
2464
  return iter;
2498
2465
  }
@@ -3678,10 +3645,10 @@ double get_decfun_rho(const struct model *model_)
3678
3645
 
3679
3646
  void free_model_content(struct model *model_ptr)
3680
3647
  {
3681
- if(model_ptr->w != NULL)
3682
- free(model_ptr->w);
3683
- if(model_ptr->label != NULL)
3684
- free(model_ptr->label);
3648
+ free(model_ptr->w);
3649
+ model_ptr->w = NULL;
3650
+ free(model_ptr->label);
3651
+ model_ptr->label = NULL;
3685
3652
  }
3686
3653
 
3687
3654
  void free_and_destroy_model(struct model **model_ptr_ptr)
@@ -3691,17 +3658,18 @@ void free_and_destroy_model(struct model **model_ptr_ptr)
3691
3658
  {
3692
3659
  free_model_content(model_ptr);
3693
3660
  free(model_ptr);
3661
+ *model_ptr_ptr = NULL;
3694
3662
  }
3695
3663
  }
3696
3664
 
3697
3665
  void destroy_param(parameter* param)
3698
3666
  {
3699
- if(param->weight_label != NULL)
3700
- free(param->weight_label);
3701
- if(param->weight != NULL)
3702
- free(param->weight);
3703
- if(param->init_sol != NULL)
3704
- free(param->init_sol);
3667
+ free(param->weight_label);
3668
+ param->weight_label = NULL;
3669
+ free(param->weight);
3670
+ param->weight = NULL;
3671
+ free(param->init_sol);
3672
+ param->init_sol = NULL;
3705
3673
  }
3706
3674
 
3707
3675
  const char *check_parameter(const problem *prob, const parameter *param)
@@ -1,7 +1,7 @@
1
1
  #ifndef _LIBLINEAR_H
2
2
  #define _LIBLINEAR_H
3
3
 
4
- #define LIBLINEAR_VERSION 245
4
+ #define LIBLINEAR_VERSION 246
5
5
 
6
6
  #ifdef __cplusplus
7
7
  extern "C" {
@@ -3,6 +3,6 @@
3
3
  module Numo
4
4
  module Liblinear
5
5
  # The version of Numo::Liblienar you are using.
6
- VERSION = '2.2.1'
6
+ VERSION = '2.3.0'
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numo-liblinear
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-27 00:00:00.000000000 Z
11
+ date: 2023-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray