lightgbm 0.1.8 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3b86686bc4575d069e469fb9c8911e93c7dcfb7622a415dc3e7ebee301947c3
4
- data.tar.gz: a186cca11d4838fd13573b14ea154fff174804b31ae45236130c30a24f55ff7b
3
+ metadata.gz: 5fb9ecd85bab15bf4edcf200de81cb1d4a70a743810ca67ca77e28c957d492c8
4
+ data.tar.gz: 56b063a0ba3f1a2db796e701f5e1d96625b4f03340defd540b160552aa24e577
5
5
  SHA512:
6
- metadata.gz: 32ef8f452075bcf4441b8e0fcf68e63332c42da61445301ecd0a85b51b2af1b7a730da0810e1b182ff5fdfe184884242a5489469d16e0e9a717d19bb145eb095
7
- data.tar.gz: 41b76c5ac174b75ce4e4f21477e4d32a9607b550e70448dde2797a765813d08a6c75de2f7f6d04ea79b4e9fa8afd768d097be516781e27e4eee4f982af364dc0
6
+ metadata.gz: 69085b60d683816b9286f504c7901b969d8070d0fe3e8dacc7efd4beff99cdf0fca9f094b45235cb4119ea8a19e570c0463d8a21d947f6c0c412c3b41bc1f6a9
7
+ data.tar.gz: 3e5274aefd850b3590cedbb58e09c96152fe0c166f6a929b373c850fd3c39ee3fcbfdd4b5609c8da22dd019dca1658f6784c5b6e2bd1cc5791507ee10617d57c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## 0.2.3 (2021-03-09)
2
+
3
+ - Added ARM shared library for Mac
4
+
5
+ ## 0.2.2 (2020-12-07)
6
+
7
+ - Updated LightGBM to 3.1.1
8
+
9
+ ## 0.2.1 (2020-11-15)
10
+
11
+ - Updated LightGBM to 3.1.0
12
+
13
+ ## 0.2.0 (2020-08-31)
14
+
15
+ - Updated LightGBM to 3.0.0
16
+ - Made `best_iteration` and `eval_hist` consistent with Python
17
+
18
+ ## 0.1.9 (2020-06-10)
19
+
20
+ - Added support for Rover
21
+ - Improved performance of Numo datasets
22
+
1
23
  ## 0.1.8 (2020-05-09)
2
24
 
3
25
  - Improved error message when OpenMP not found on Mac
data/LICENSE.txt CHANGED
@@ -1,22 +1,22 @@
1
- Copyright (c) 2019 Andrew Kane
1
+ The MIT License (MIT)
2
2
 
3
- MIT License
3
+ Copyright (c) Microsoft Corporation
4
+ Copyright (c) 2019-2020 Andrew Kane
4
5
 
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
12
 
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
15
 
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [LightGBM](https://github.com/microsoft/LightGBM) - high performance gradient boosting - for Ruby
4
4
 
5
- [![Build Status](https://travis-ci.org/ankane/lightgbm.svg?branch=master)](https://travis-ci.org/ankane/lightgbm)
5
+ [![Build Status](https://github.com/ankane/lightgbm/workflows/build/badge.svg?branch=master)](https://github.com/ankane/lightgbm/actions)
6
6
 
7
7
  ## Installation
8
8
 
@@ -129,16 +129,22 @@ Data can be an array of arrays
129
129
  [[1, 2, 3], [4, 5, 6]]
130
130
  ```
131
131
 
132
- Or a Daru data frame
132
+ Or a Numo array
133
133
 
134
134
  ```ruby
135
- Daru::DataFrame.from_csv("houses.csv")
135
+ Numo::NArray.cast([[1, 2, 3], [4, 5, 6]])
136
+ ```
137
+
138
+ Or a Rover data frame
139
+
140
+ ```ruby
141
+ Rover.read_csv("houses.csv")
136
142
  ```
137
143
 
138
- Or a Numo NArray
144
+ Or a Daru data frame
139
145
 
140
146
  ```ruby
141
- Numo::DFloat.new(3, 2).seq
147
+ Daru::DataFrame.from_csv("houses.csv")
142
148
  ```
143
149
 
144
150
  ## Helpful Resources
data/lib/lightgbm.rb CHANGED
@@ -19,7 +19,12 @@ module LightGBM
19
19
  class << self
20
20
  attr_accessor :ffi_lib
21
21
  end
22
- lib_name = "lib_lightgbm.#{::FFI::Platform::LIBSUFFIX}"
22
+ lib_name =
23
+ if RbConfig::CONFIG["host_os"] =~ /darwin/i && RbConfig::CONFIG["host_cpu"] =~ /arm/i
24
+ "lib_lightgbm.arm64.#{::FFI::Platform::LIBSUFFIX}"
25
+ else
26
+ "lib_lightgbm.#{::FFI::Platform::LIBSUFFIX}"
27
+ end
23
28
  vendor_lib = File.expand_path("../vendor/#{lib_name}", __dir__)
24
29
  self.ffi_lib = [lib_name, "lib_lightgbm.so", vendor_lib]
25
30
 
@@ -61,16 +66,14 @@ module LightGBM
61
66
  # print results
62
67
  messages = []
63
68
 
69
+ eval_valid = booster.eval_valid
64
70
  if valid_contain_train
65
- # not sure why reversed in output
66
- booster.eval_train.reverse.each do |res|
67
- messages << "%s's %s: %g" % [res[0], res[1], res[2]]
68
- end
71
+ eval_valid = eval_valid + booster.eval_train
69
72
  end
70
-
71
- eval_valid = booster.eval_valid
72
73
  # not sure why reversed in output
73
- eval_valid.reverse.each do |res|
74
+ eval_valid.reverse!
75
+
76
+ eval_valid.each do |res|
74
77
  messages << "%s's %s: %g" % [res[0], res[1], res[2]]
75
78
  end
76
79
 
@@ -188,8 +191,7 @@ module LightGBM
188
191
  # use best iteration from first metric if not stopped early
189
192
  best_iteration ||= best_iter[best_iter.keys.first]
190
193
  eval_hist.each_key do |k|
191
- # TODO uncomment for 0.2.0
192
- # eval_hist[k] = eval_hist[k].first(best_iteration + 1)
194
+ eval_hist[k] = eval_hist[k].first(best_iteration + 1)
193
195
  end
194
196
  end
195
197
 
@@ -39,11 +39,12 @@ module LightGBM
39
39
  buffer_len = 1 << 20
40
40
  out_len = ::FFI::MemoryPointer.new(:int64)
41
41
  out_str = ::FFI::MemoryPointer.new(:char, buffer_len)
42
- check_result FFI.LGBM_BoosterDumpModel(handle_pointer, start_iteration, num_iteration, buffer_len, out_len, out_str)
42
+ feature_importance_type = 0 # TODO add option
43
+ check_result FFI.LGBM_BoosterDumpModel(handle_pointer, start_iteration, num_iteration, feature_importance_type, buffer_len, out_len, out_str)
43
44
  actual_len = read_int64(out_len)
44
45
  if actual_len > buffer_len
45
46
  out_str = ::FFI::MemoryPointer.new(:char, actual_len)
46
- check_result FFI.LGBM_BoosterDumpModel(handle_pointer, start_iteration, num_iteration, actual_len, out_len, out_str)
47
+ check_result FFI.LGBM_BoosterDumpModel(handle_pointer, start_iteration, num_iteration, feature_importance_type, actual_len, out_len, out_str)
47
48
  end
48
49
  out_str.read_string
49
50
  end
@@ -86,11 +87,12 @@ module LightGBM
86
87
  buffer_len = 1 << 20
87
88
  out_len = ::FFI::MemoryPointer.new(:int64)
88
89
  out_str = ::FFI::MemoryPointer.new(:char, buffer_len)
89
- check_result FFI.LGBM_BoosterSaveModelToString(handle_pointer, start_iteration, num_iteration, buffer_len, out_len, out_str)
90
+ feature_importance_type = 0 # TODO add option
91
+ check_result FFI.LGBM_BoosterSaveModelToString(handle_pointer, start_iteration, num_iteration, feature_importance_type, buffer_len, out_len, out_str)
90
92
  actual_len = read_int64(out_len)
91
93
  if actual_len > buffer_len
92
94
  out_str = ::FFI::MemoryPointer.new(:char, actual_len)
93
- check_result FFI.LGBM_BoosterSaveModelToString(handle_pointer, start_iteration, num_iteration, actual_len, out_len, out_str)
95
+ check_result FFI.LGBM_BoosterSaveModelToString(handle_pointer, start_iteration, num_iteration, feature_importance_type, actual_len, out_len, out_str)
94
96
  end
95
97
  out_str.read_string
96
98
  end
@@ -115,7 +117,7 @@ module LightGBM
115
117
  end
116
118
 
117
119
  # TODO support different prediction types
118
- def predict(input, num_iteration: nil, **params)
120
+ def predict(input, start_iteration: nil, num_iteration: nil, **params)
119
121
  input =
120
122
  if daru?(input)
121
123
  input.map_rows(&:to_a)
@@ -126,6 +128,7 @@ module LightGBM
126
128
  singular = !input.first.is_a?(Array)
127
129
  input = [input] if singular
128
130
 
131
+ start_iteration ||= 0
129
132
  num_iteration ||= best_iteration
130
133
  num_class ||= num_class()
131
134
 
@@ -136,7 +139,7 @@ module LightGBM
136
139
 
137
140
  out_len = ::FFI::MemoryPointer.new(:int64)
138
141
  out_result = ::FFI::MemoryPointer.new(:double, num_class * input.count)
139
- check_result FFI.LGBM_BoosterPredictForMat(handle_pointer, data, 1, input.count, input.first.count, 1, 0, num_iteration, params_str(params), out_len, out_result)
142
+ check_result FFI.LGBM_BoosterPredictForMat(handle_pointer, data, 1, input.count, input.first.count, 1, 0, start_iteration, num_iteration, params_str(params), out_len, out_result)
140
143
  out = out_result.read_array_of_double(read_int64(out_len))
141
144
  out = out.each_slice(num_class).to_a if num_class > 1
142
145
 
@@ -145,7 +148,8 @@ module LightGBM
145
148
 
146
149
  def save_model(filename, num_iteration: nil, start_iteration: 0)
147
150
  num_iteration ||= best_iteration
148
- check_result FFI.LGBM_BoosterSaveModel(handle_pointer, start_iteration, num_iteration, filename)
151
+ feature_importance_type = 0 # TODO add
152
+ check_result FFI.LGBM_BoosterSaveModel(handle_pointer, start_iteration, num_iteration, feature_importance_type, filename)
149
153
  self # consistent with Python API
150
154
  end
151
155
 
@@ -175,10 +179,12 @@ module LightGBM
175
179
  def eval_names
176
180
  eval_counts ||= eval_counts()
177
181
  out_len = ::FFI::MemoryPointer.new(:int)
182
+ out_buffer_len = ::FFI::MemoryPointer.new(:size_t)
178
183
  out_strs = ::FFI::MemoryPointer.new(:pointer, eval_counts)
179
- str_ptrs = eval_counts.times.map { ::FFI::MemoryPointer.new(:char, 255) }
184
+ buffer_len = 255
185
+ str_ptrs = eval_counts.times.map { ::FFI::MemoryPointer.new(:char, buffer_len) }
180
186
  out_strs.write_array_of_pointer(str_ptrs)
181
- check_result FFI.LGBM_BoosterGetEvalNames(handle_pointer, out_len, out_strs)
187
+ check_result FFI.LGBM_BoosterGetEvalNames(handle_pointer, eval_counts, out_len, buffer_len, out_buffer_len, out_strs)
182
188
  str_ptrs.map(&:read_string)
183
189
  end
184
190
 
@@ -27,10 +27,13 @@ module LightGBM
27
27
  def feature_names
28
28
  # must preallocate space
29
29
  num_feature_names = ::FFI::MemoryPointer.new(:int)
30
- out_strs = ::FFI::MemoryPointer.new(:pointer, 1000)
31
- str_ptrs = 1000.times.map { ::FFI::MemoryPointer.new(:char, 255) }
30
+ out_buffer_len = ::FFI::MemoryPointer.new(:size_t)
31
+ len = 1000
32
+ out_strs = ::FFI::MemoryPointer.new(:pointer, len)
33
+ buffer_len = 255
34
+ str_ptrs = len.times.map { ::FFI::MemoryPointer.new(:char, buffer_len) }
32
35
  out_strs.write_array_of_pointer(str_ptrs)
33
- check_result FFI.LGBM_DatasetGetFeatureNames(handle_pointer, out_strs, num_feature_names)
36
+ check_result FFI.LGBM_DatasetGetFeatureNames(handle_pointer, len, num_feature_names, buffer_len, out_buffer_len, out_strs)
34
37
  str_ptrs[0, num_feature_names.read_int].map(&:read_string)
35
38
  end
36
39
 
@@ -130,18 +133,23 @@ module LightGBM
130
133
  elsif daru?(data)
131
134
  nrow, ncol = data.shape
132
135
  flat_data = data.map_rows(&:to_a).flatten
133
- elsif narray?(data)
136
+ elsif numo?(data) || rover?(data)
137
+ data = data.to_numo if rover?(data)
134
138
  nrow, ncol = data.shape
135
- flat_data = data.flatten.to_a
136
139
  else
137
140
  nrow = data.count
138
141
  ncol = data.first.count
139
142
  flat_data = data.flatten
140
143
  end
141
144
 
142
- handle_missing(flat_data)
143
145
  c_data = ::FFI::MemoryPointer.new(:double, nrow * ncol)
144
- c_data.write_array_of_double(flat_data)
146
+ if numo?(data)
147
+ c_data.write_bytes(data.cast_to(Numo::DFloat).to_string)
148
+ else
149
+ handle_missing(flat_data)
150
+ c_data.write_array_of_double(flat_data)
151
+ end
152
+
145
153
  check_result FFI.LGBM_DatasetCreateFromMat(c_data, 1, nrow, ncol, 1, parameters, reference, @handle)
146
154
  end
147
155
  ObjectSpace.define_finalizer(self, self.class.finalize(handle_pointer)) unless used_indices
data/lib/lightgbm/ffi.rb CHANGED
@@ -5,7 +5,7 @@ module LightGBM
5
5
  begin
6
6
  ffi_lib LightGBM.ffi_lib
7
7
  rescue LoadError => e
8
- if e.message.include?("Library not loaded: /usr/local/opt/libomp/lib/libomp.dylib") && e.message.include?("Reason: image not found")
8
+ if ["/usr/local", "/opt/homebrew"].any? { |v| e.message.include?("Library not loaded: #{v}/opt/libomp/lib/libomp.dylib") } && e.message.include?("Reason: image not found")
9
9
  raise LoadError, "OpenMP not found. Run `brew install libomp`"
10
10
  else
11
11
  raise e
@@ -23,7 +23,7 @@ module LightGBM
23
23
  attach_function :LGBM_DatasetCreateFromMat, %i[pointer int int32 int32 int string pointer pointer], :int
24
24
  attach_function :LGBM_DatasetGetSubset, %i[pointer pointer int32 string pointer], :int
25
25
  attach_function :LGBM_DatasetSetFeatureNames, %i[pointer pointer int], :int
26
- attach_function :LGBM_DatasetGetFeatureNames, %i[pointer pointer pointer], :int
26
+ attach_function :LGBM_DatasetGetFeatureNames, %i[pointer int pointer size_t pointer pointer], :int
27
27
  attach_function :LGBM_DatasetFree, %i[pointer], :int
28
28
  attach_function :LGBM_DatasetSaveBinary, %i[pointer string], :int
29
29
  attach_function :LGBM_DatasetDumpText, %i[pointer string], :int
@@ -44,13 +44,13 @@ module LightGBM
44
44
  attach_function :LGBM_BoosterNumModelPerIteration, %i[pointer pointer], :int
45
45
  attach_function :LGBM_BoosterNumberOfTotalModel, %i[pointer pointer], :int
46
46
  attach_function :LGBM_BoosterGetEvalCounts, %i[pointer pointer], :int
47
- attach_function :LGBM_BoosterGetEvalNames, %i[pointer pointer pointer], :int
47
+ attach_function :LGBM_BoosterGetEvalNames, %i[pointer int pointer size_t pointer pointer], :int
48
48
  attach_function :LGBM_BoosterGetNumFeature, %i[pointer pointer], :int
49
49
  attach_function :LGBM_BoosterGetEval, %i[pointer int pointer pointer], :int
50
- attach_function :LGBM_BoosterPredictForMat, %i[pointer pointer int int32 int32 int int int string pointer pointer], :int
51
- attach_function :LGBM_BoosterSaveModel, %i[pointer int int string], :int
52
- attach_function :LGBM_BoosterSaveModelToString, %i[pointer int int int64 pointer pointer], :int
53
- attach_function :LGBM_BoosterDumpModel, %i[pointer int int int64 pointer pointer], :int
50
+ attach_function :LGBM_BoosterPredictForMat, %i[pointer pointer int int32 int32 int int int int string pointer pointer], :int
51
+ attach_function :LGBM_BoosterSaveModel, %i[pointer int int int string], :int
52
+ attach_function :LGBM_BoosterSaveModelToString, %i[pointer int int int int64 pointer pointer], :int
53
+ attach_function :LGBM_BoosterDumpModel, %i[pointer int int int int64 pointer pointer], :int
54
54
  attach_function :LGBM_BoosterFeatureImportance, %i[pointer int int pointer], :int
55
55
  end
56
56
  end
@@ -37,8 +37,12 @@ module LightGBM
37
37
  defined?(Daru::DataFrame) && data.is_a?(Daru::DataFrame)
38
38
  end
39
39
 
40
- def narray?(data)
40
+ def numo?(data)
41
41
  defined?(Numo::NArray) && data.is_a?(Numo::NArray)
42
42
  end
43
+
44
+ def rover?(data)
45
+ defined?(Rover::DataFrame) && data.is_a?(Rover::DataFrame)
46
+ end
43
47
  end
44
48
  end
@@ -1,3 +1,3 @@
1
1
  module LightGBM
2
- VERSION = "0.1.8"
2
+ VERSION = "0.2.3"
3
3
  end
Binary file
Binary file
Binary file
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lightgbm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-09 00:00:00.000000000 Z
11
+ date: 2021-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -24,63 +24,7 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: minitest
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '5'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '5'
69
- - !ruby/object:Gem::Dependency
70
- name: daru
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- description:
27
+ description:
84
28
  email: andrew@chartkick.com
85
29
  executables: []
86
30
  extensions: []
@@ -100,6 +44,7 @@ files:
100
44
  - lib/lightgbm/utils.rb
101
45
  - lib/lightgbm/version.rb
102
46
  - vendor/LICENSE
47
+ - vendor/lib_lightgbm.arm64.dylib
103
48
  - vendor/lib_lightgbm.dll
104
49
  - vendor/lib_lightgbm.dylib
105
50
  - vendor/lib_lightgbm.so
@@ -107,7 +52,7 @@ homepage: https://github.com/ankane/lightgbm
107
52
  licenses:
108
53
  - MIT
109
54
  metadata: {}
110
- post_install_message:
55
+ post_install_message:
111
56
  rdoc_options: []
112
57
  require_paths:
113
58
  - lib
@@ -122,8 +67,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
67
  - !ruby/object:Gem::Version
123
68
  version: '0'
124
69
  requirements: []
125
- rubygems_version: 3.1.2
126
- signing_key:
70
+ rubygems_version: 3.2.3
71
+ signing_key:
127
72
  specification_version: 4
128
73
  summary: High performance gradient boosting for Ruby
129
74
  test_files: []