Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ankane committed Aug 14, 2019
0 parents commit cb61866
Show file tree
Hide file tree
Showing 14 changed files with 1,933 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/.bundle/
/.yardoc
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.1.0

- First release
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source "https://rubygems.org"

gemspec
24 changes: 24 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
PATH
remote: .
specs:
lightgbm (0.1.0)
ffi

GEM
remote: https://rubygems.org/
specs:
ffi (1.11.1)
minitest (5.11.3)
rake (12.3.3)

PLATFORMS
ruby

DEPENDENCIES
bundler
lightgbm!
minitest (>= 5)
rake

BUNDLED WITH
2.0.2
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# LightGBM

LightGBM for Ruby

## Installation

First, [install LightGBM](https://lightgbm.readthedocs.io/en/latest/Installation-Guide.html).

Add this line to your application’s Gemfile:

```ruby
gem 'lightgbm'
```

Load a model

```ruby
booster = LightGBM::Booster.new(model_file: "model.txt")
```

Predict

```ruby
booster.predict([[1, 2], [3, 4]])
```

## Credits

Thanks to the [xgboost](https://github.com/PairOnAir/xgboost-ruby) gem for serving as an initial reference.

## History

View the [changelog](https://github.com/ankane/lightgbm/blob/master/CHANGELOG.md)

## Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

- [Report bugs](https://github.com/ankane/lightgbm/issues)
- Fix bugs and [submit pull requests](https://github.com/ankane/lightgbm/pulls)
- Write, clarify, or fix documentation
- Suggest or add new features
8 changes: 8 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require "bundler/gem_tasks"
require "rake/testtask"

task default: :test
Rake::TestTask.new do |t|
t.libs << "test"
t.pattern = "test/**/*_test.rb"
end
7 changes: 7 additions & 0 deletions lib/lightgbm.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# dependencies
require "ffi"

# modules
require "lightgbm/booster"
require "lightgbm/ffi"
require "lightgbm/version"
46 changes: 46 additions & 0 deletions lib/lightgbm/booster.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module LightGBM
class Booster
def initialize(model_file:)
@handle = ::FFI::MemoryPointer.new(:pointer)
if model_file
out_num_iterations = ::FFI::MemoryPointer.new(:int)
check_result FFI.LGBM_BoosterCreateFromModelfile(model_file, out_num_iterations, @handle)
end
ObjectSpace.define_finalizer(self, self.class.finalize(handle_pointer))
end

def self.finalize(pointer)
-> { FFI.LGBM_BoosterFree(pointer) }
end

def predict(input)
raise TypeError unless input.is_a?(Array)

singular = input.first.is_a?(Array)
input = [input] unless singular

data = ::FFI::MemoryPointer.new(:float, input.count * input.first.count)
data.put_array_of_float(0, input.flatten)

out_len = ::FFI::MemoryPointer.new(:int64)
out_result = ::FFI::MemoryPointer.new(:double, input.count)
parameter = ""
check_result FFI.LGBM_BoosterPredictForMat(handle_pointer, data, 0, input.count, input.first.count, 1, 0, 0, parameter, out_len, out_result)
out = out_result.read_array_of_double(out_len.read_int64)

singular ? out : out.first
end

private

def check_result(err)
if err != 0
raise FFI.LGBM_GetLastError
end
end

def handle_pointer
@handle.read_pointer
end
end
end
13 changes: 13 additions & 0 deletions lib/lightgbm/ffi.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module LightGBM
module FFI
extend ::FFI::Library
ffi_lib ["lightgbm", "lib_lightgbm.so"]

# https://github.com/microsoft/LightGBM/blob/master/include/LightGBM/c_api.h
attach_function :LGBM_GetLastError, %i[], :string
attach_function :LGBM_BoosterCreate, %i[pointer string pointer], :int
attach_function :LGBM_BoosterCreateFromModelfile, %i[string pointer pointer], :int
attach_function :LGBM_BoosterFree, %i[pointer], :int
attach_function :LGBM_BoosterPredictForMat, %i[pointer pointer int int32 int32 int int int string pointer pointer], :int
end
end
3 changes: 3 additions & 0 deletions lib/lightgbm/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module LightGBM
VERSION = "0.1.0"
end
23 changes: 23 additions & 0 deletions lightgbm.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require_relative "lib/lightgbm/version"

Gem::Specification.new do |spec|
spec.name = "lightgbm"
spec.version = LightGBM::VERSION
spec.summary = "LightGBM for Ruby"
spec.homepage = "https://github.com/ankane/lightgbm"
spec.license = "MIT"

spec.author = "Andrew Kane"
spec.email = "andrew@chartkick.com"

spec.files = Dir["*.{md,txt}", "{lib}/**/*"]
spec.require_path = "lib"

spec.required_ruby_version = ">= 2.4"

spec.add_dependency "ffi"

spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "minitest", ">= 5"
end
15 changes: 15 additions & 0 deletions test/lightgbm_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require_relative "test_helper"

class LightGBMTest < Minitest::Test
def test_load_model
model = LightGBM::Booster.new(model_file: "test/support/model.txt")

x_test = [
[0.04417, 70.0, 2.24, 0, 0.400, 6.871, 47.4, 7.8278, 5, 358, 14.8, 390.86, 6.07],
[0.03537, 34.0, 6.09, 0, 0.433, 6.590, 40.4, 5.4917, 7, 329, 16.1, 395.75, 9.50]
]
preds = model.predict(x_test)
assert_in_delta 28.29122797, preds[0]
assert_in_delta 25.87936514, preds[1]
end
end
Loading

0 comments on commit cb61866

Please sign in to comment.