🛠️

Rubyの機械学習ライブラリまとめ

2021/02/14に公開

はじめに

最近では、機械学習関連Gemが多く開発され、Rubyでも機械学習できるようになってきました。代表的なものを、ざっくりとまとめてみました。

まとめ情報

いきなりですが、この記事は私の偏見で選んだものですので、他のまとめ情報も紹介します。もっとも大きなのがAndrei Beliankou (arbox) さんのまとめリポジトリです。色んなものが紹介されています。

https://github.com/arbox/machine-learning-with-ruby

Railsエンジニアにとっては、SearchkickやStrong Migrationsで有名な、Andrew Kane (ankane) さんも、機械学習関連のGemを多く作成しています。C/C++のAPIが提供されている、他言語の機械学習ライブラリを、FFI/Fiddle/Riceでラップして、Rubyで使えるようにしています。ankaneさん自身が書かれた、それらGemのまとめ記事があります。

https://ankane.org/new-ml-gems

https://ankane.org/more-ml-gems

ベクトル・行列・線形代数

PythonでいうところのNumPyですが、Numo::NArrayとNumo::Linalgがオススメです。先に紹介した、ankaneさんのGemでもNumo::NArrayに対応しています。NumPyでできることは、だいたいNumo::NArrayでできます。NumPyの使用経験がある方は、Numo vs numpyを見ると使えるようになると思います。

https://ruby-numo.github.io/narray/

逆行列を求めたり固有値分解したりとなると、Numo::Linalgが必要になります。numpy.linalgやscipy.linalgに相当します。Numo::Linalgは、BLAS/LAPACKをバックエンドライブリとして使用します。Intel MKLやOpenBLASなど様々ありますが、Gemをインストールする際に選択できます。

https://github.com/ruby-numo/numo-linalg/blob/master/doc/select-backend.md

ただ、requireするだけでいい感じにバックエンドライブリを読み込んでほしい、という気持ちもあります。そのためにautoloaderがあります。普通にgemコマンドでインストールして、

$ gem install numo-linalg

autoloaderをrequireします。これでいい感じにバックエンドライブリを読み込みます。

require 'numo/linalg/autoloader'

autoloaderの仕組みは /usr/local/lib などのバックエンドライブリが置いてありそうなところから、Intel MKLなどのライブラリを探すという仕組みです(ルートから全ディレクトリを探すととても重いので置いてありそうなところだけ)。しかし、OSやライブラリ配置は人それぞれなので、百発百中ではなく、ライブラリを発見できないことがあります。この問題に対して、Numo::OpenBLASを作りました。

https://github.com/yoshoku/numo-openblas

Gemをインストールするときに、OpenBLASをダウンロードしてきてビルドし、それをNumo::Linalgのバックグラウンドライブラリとして使用します。Juliaをビルドしてて思いついたものです。

$ gem install numo-openblas

OpenBLASをビルドするので、インストールはちょっと重いです。

require 'numo/openblas'

# 私はanyenvでrbenvをいれてRubyをインストールしているのですが、
# numo-openblasのディレクトリ下にlibopenblasがあり、
# それがバックグラウンドライブラリとして選択されます。
p Numo::Linalg::Loader.libs
# ["/Users/hoge/.anyenv/envs/rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/numo-openblas-0.3.1/vendor/lib/libopenblas.dylib"]

# ビルドされたOpenBLASのバージョンもわかります。
p Numo::OpenBLAS::OPENBLAS_VERSION
# " OpenBLAS 0.3.13 "

ちなみに、ベクトル・行列Gemとして、以前はNMatrixという選択肢もあったのですが、開発は止まっている様です。NMatrixと同じSciRubyのもとで、いまはnumrubyというのが動いています。

https://github.com/SciRuby/numruby

(2021/02/16追記)
Cudaに対応したNumo::NArrayとも言えるCumoがあります。NumPyに対するCuPyのような存在です。Numo::NArrayと互換性があり、切り替えも簡単です。

https://github.com/sonots/cumo

データフレーム

PythonでいうところのPandas、Rでいうところのdplyrですが、DaruとRoverがあります。DaruはSciRubyが開発しており、Rubyのデータフレームのデファクトスタンダードかもしれません。

https://github.com/SciRuby/daru

ただ、現在はあまり活発には開発されていません。また、サポートしているデータ形式にNMatrixはあるのですが、Numo::NArrayがありません。最近は多くの機械学習系のGemが、Numo::NArrayを利用しているので、取り回しがよくありません(DaruからArrayやMatrixに変換してNumo::NArrayにするなど)。これに対してRoverは、内部的にもNumo::NArrayを使用しており、最近の機械学習系のGemとも親和性が高いです。

https://github.com/ankane/rover

Apache Arrowは、Rubyのデータ処理ツールの開発を目指すRed Data Toolsのメンバーがコミッターとして参加しており、開発が活発です。

https://github.com/apache/arrow/tree/master/ruby/red-arrow

機械学習ライブラリ

PythonでいうところのScikit-learnですが、これはRumaleになります。Rumaleは、Scikit-learnと同様のインターフェースを意識しています。つまり、fitで訓練して、predictで予測するというものです。また、多くの機械学習アルゴリズムをサポートしています。

https://github.com/yoshoku/rumale

古典的な機械学習ライブラリといえば、LIBSVMとLIBLINEARですが、これをRumaleのインターフェースで使えるようにした、Rumale::SVMもあります。

https://github.com/yoshoku/rumale-svm

勾配ブースティングのXGBoostやLightGBMのbindingは、ankaneさんが開発しています。

https://github.com/ankane/xgboost

https://github.com/ankane/lightgbm

これらライブラリで、機械学習の一通りのことはできると思います。

深層学習

深層学習のほうが、古典的な機械学習ライブラリより、色々と開発されているかもしれません。

https://github.com/unagiootoro/ruby-dnn

https://github.com/red-data-tools/red-chainer

https://github.com/mrkn/mxnet.rb

https://github.com/ankane/tensorflow

https://github.com/ankane/torch.rb

torch.rbは、PyTorchのC++版APIといえるlibtorchをbindingしたものなのですが、libtorch自体がver. 1.5からstableなAPIとして提供されているので、安心して使えるかな〜といったところです。私は試してないですが、GPUも対応しています。また、ModelZoo的なものも使えるので、ちょっと遊ぶには良いかなと思います。

https://zenn.dev/yoshoku/articles/91ac1d0671ed04

グラフ作成

私がこのジャンルにうといのもあって、詳しくないのですが、chartyが有名だと思います。Numo::NArrayやDaruなど、様々なデータ形式に対応しています。

https://github.com/red-data-tools/charty

SciRubyであれば、Daru::Viewというのがあります。

https://github.com/SciRuby/daru-view

うといのも理由があって、長いことGnuplotでグラフを作ってまして、Numo::Gnuplotがあれば私としては十分だったりします。

https://github.com/ruby-numo/numo-gnuplot

近似最近傍探索

近似最近傍探索の古典的なものであるFLANNは、公式のリポジトリにRuby bindingがあります。ただデータの受け渡しにNMatrixを使います。

https://github.com/mariusmuja/flann/tree/master/src/ruby

最近のものですと、Yahoo! Japanが開発しているNGTや、Facebookが開発しているFaissのbindingがあります。

https://github.com/ankane/ngt
https://github.com/ankane/faiss

検索精度とインデックスの大きさのバランスの良さから、よくWebサービスで採用されているAnnoyのbindingもあります。

https://github.com/yoshoku/annoy.rb

torch.rbによるVGG-16 Networkを使った特徴抽出と組み合わせて、類似画像検索を作るというのをやってみました。

https://zenn.dev/yoshoku/articles/e04aeb3a555a02

画像処理

ImageMagickでは、RMagickとMiniMagickが定番です。

https://github.com/rmagick/rmagick

https://github.com/minimagick/minimagick

最近はlibvipsのbindingであるruby-vipsも人気みたいですね。

https://github.com/libvips/ruby-vips

OpenCVのbindingは複数あります。

https://github.com/ruby-opencv/ruby-opencv

https://github.com/D-Alex/ropencv

https://github.com/red-data-tools/red-opencv

私の開発しているMagroは、基本的には、pngとjpegがNumo::NArray形式で読み書きできる、というものです。機能としてもリサイズと畳み込みなどミニマルなものを意識してます。

https://github.com/yoshoku/magro

自然言語処理

割と色々なものが作られているのですが、NLTKやSpaCyのような統合的なものが無いように思います。そういったライブラリを作るのが今後の課題でしょうか。私も挑戦したい気持ちはあります。

https://github.com/arbox/nlp-with-ruby

日本語形態素解析では、MeCabをラップしたNattoがあります。

https://github.com/buruzaemon/natto

外部ライブラリなどを必要としない、Gemをインストールするだけで使える、PythonでいうところのJanomeのような辞書同梱型の形態素解析には、Suikaがあります。

https://github.com/yoshoku/suika

ただ、Suikaはまだ機能が少ないのと、ユーザー定義辞書も対応していません。辞書の読み込みが遅いので、まずはそこを何とかしたいのですが。

ノートブック

(2021/02/16追記)
IRubyを使うとJupyter NotebookでRubyが使えます。リポジトリのREADMEに丁寧にインストール方法が書かれています。

https://github.com/SciRuby/iruby

Try JupyterにもRubyのものがあります。RumaleのVersionは0.16.1なので、ちょっと前のものです。

https://jupyter.org/try

コミュニティ

SciRubyは、Rubyで機械学習やデータサイエンスに取り組んでいるコミュニティでは最も有名なんじゃないでしょうか。IRubyやDaruが有名です。

http://sciruby.com/

Red Data Toolsは、Ruby用のデータ処理ツールの開発を目指して活動されています。おそらくRubyでデータ処理ツールのコミュニティとしては、最も活発だと思います。

https://red-data-tools.github.io/ja/

Rubyプログラマーの交流の場でもあるruby-jpにもmachine-learning、datascience、nlpといったチャンネルがある様です。

https://ruby-jp.github.io/

おわりに

以上、勢いで書いた雑なまとめでした〜。 個人的な体験なのですが、ActiveRecordでデータを取ってきて、適当に加工して、Rumaleでサクッと分類器を作り、APIをたてるみたいなのが、すごいスムーズで便利でした。今後は、Railsとの親和性を高めるようなものがあると良いんだろうな〜と漠然と考えてます。

Discussion