PyCallを使ってRubyで機械学習(ロジスティック回帰)を実装する

最近Rebuild.fmで聞いた情報で、RubyからPythonを呼べるライブラリの開発が進んでいるらしいという話を聞いた。

まさにRails側からPythonを呼び出すところのコードがちょっとだるいなーと思っている最中だったので、使わない手はない!ということで試してみた。

こちらに開発者のむらけんさんのエントリがあるので参照されたし。

http://tech.speee.jp/entry/2017/03/13/113720

まだ実用段階ではないとスライドには書いてありますが、実用段階になるように貢献したいところ。

まずは準備

alpha版のタグも切られてましたが、ひとまずよく考えずそのままmasterで動かしてみる。

$ git clone git@github.com:mrkn/pycall.git
$ cd pycall
$ bundle install

rubyのコンソールから実行して試してみる。

$ bundle console

> require 'pycall/import'
> include PyCall::Import
> pyimport 'numpy', as: :np
> a = np.array.([1,2,3])
> print(a)
array([1, 2, 3])=> nil

numpyのarrayが使えたっぽいぞ。

ロジスティック回帰を実装してみる

以前にscikit-learnで単純なロジスティック回帰を実装してみたことがあるので、それをそのままPyCallで実現してみる。

http://tech.mof-mof.co.jp/blog/scikit-learn-logistic-regression.html

これはみんな大好きIrisの分類実装なんですが、このエントリに書いてある内容をそのままPyCallの書き方になおすとこんな感じになる。

Pythonオブジェクトのメソッドを実行する際に、かっこの前にドットを記述するルールっぽい。Pythonのベクトル操作をどうやるのかわからなかったのでそこは一旦諦めた。

examples/scikit_learn_logistic_regression.rb

# require "pry"
# require 'byebug'
require 'pycall/import'
include PyCall::Import

pyfrom 'sklearn.datasets', import: :load_iris
pyfrom 'sklearn.linear_model', import: :LogisticRegression

iris = load_iris.()
X = iris['data']
Y = iris['target']

logreg = LogisticRegression.()
estimator = logreg.fit.(X, Y)
result = logreg.predict.([
  [6.5, 3, 1.2, 0.4],
  [3.5, 2.2, 3.1, 1.1]
])
print result
print "\n"

実行すると、1件目のデータはラベル0で、2件目のデータはラベル2で予測された。できたああああ!

$ bundle exec ruby examples/scikit_learn_logistic_regression.rb
array([0, 2])

感想

独特の記法なのでちょっと慣れるのはちょっと大変かも?ですが、基本は機械学習はPythonで実装しておいて、キックするところはRubyから呼べるっていう使い方にするだけでも、画面側がRailsで機械学習エンジンがPythonって場合に、連携部分をシンプルに実装できそう。

素敵なライブラリですね。もうちょっと色々いじってみよう。