こんにちは。
GMOアドマーケティングの石丸です。
以前こちらのブログで「OpenCVをRubyで動かす方法」について紹介させていただきました。
今回は「◯◯をRubyで動かすシリーズ」の第二弾として、Pythonで行列計算やベクトルを扱う際に使うNumPy をRubyで動かす方法を紹介します。
環境構築
RubyでNumPyを動かすために、まずは環境を整えます。
※RubyやPythonの環境構築については割愛しますが、Pythonの環境構築方法によってはPyCallが動かない場合があるのでご注意下さい。
今回はこのGemを使ってREADMEに記載の通りに環境構築を行います。
このGemはPyCallで動作するRuby用のNumPyラッパーです。
2019/09/18時点では、PyCallはRubyはバージョン2.3以上、Pythonは2.7以上をサポートしています。
今回はGemfileに gem 'numpy'
を追記して bundle install
しました。
PyCallもインストールされたことが確認できます。
1 2 3 4 5 6 7 8 |
$ bundle install --path vendor/bundle ---- 省略 ---- Fetching pycall 1.2.1 Installing pycall 1.2.1 with native extensions Fetching numpy 0.2.0 Installing numpy 0.2.0 Bundle complete! 1 Gemfile dependency, 3 gems now installed. Bundled gems are installed into `./vendor/bundle` |
余談ですが、PyCallの詳細やRubyでのデータサイエンス事情についてはPyCallの開発者が執筆された以下の記事をご覧ください。
Ruby-Pythonブリッジライブラリ「PyCall」を使ってRubyでデータ分析をしよう!
実際に使ってみる
動作確認として簡単なコードを動かしてみます。
PythonでNumPyを動かす場合は import numpy as np
のように書きますが、今回の環境では以下のように書きます。
1 2 3 4 5 6 7 8 9 10 |
require 'numpy' np = Numpy x = np.array([1, 2, 3]) p x p x.class # 実行結果 # => array([1, 2, 3]) # => <class 'numpy.ndarray'> |
特に違和感なく書けますね。
オブジェクトのクラスもNumPy用の配列 numpy.ndarray
になっていることが確認できます。
他にもいろいろ試してみます。
行列の基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
require 'numpy' np = Numpy # 行列の定義とサイズ確認 x = np.array([3, 4]) p x p x.shape y = np.array([[1, 3, 5], [2, 4, 6]]) p y p y.shape # 実行結果 # => array([3, 4]) # => (2,) # => array([[1, 3, 5], # [2, 4, 6]]) # => (2, 3) # 行列の計算 x = np.array([[1, 2], [3, 4]]) y = np.array([[5, 0], [7, 8]]) p x + y p x * y # 実行結果 # => array([[ 6, 2], # [10, 12]]) # => array([[ 5, 0], # [21, 32]]) # 乱数 p np.random.rand(2, 3) # 実行結果 # => array([[0.00542089, 0.35938922, 0.25116564], # [0.76220175, 0.95521454, 0.85678941]]) # 等差数列の作成 p np.arange(5) p np.arange(2, 16, 4) #初項2, 公差4, 終点16 # 実行結果 # => array([0, 1, 2, 3, 4]) # => array([ 2, 6, 10, 14]) # スカラーと行列の積 x = np.array([1, 2, 3]) p x p 10 * x # 実行結果 # => array([1, 2, 3]) # => array([10, 20, 30]) |
NumPyを使ったことがある場合はそのままの知識で書くことができますね。
せっかくPyCallの環境があるので、Matplotlibを使ってグラフも描画してみます。
1 2 3 4 5 6 7 8 9 10 11 12 |
require 'pycall/import' require 'numpy' include PyCall::Import pyimport 'matplotlib.pyplot', as: 'plt' np = Numpy x = np.arange(0, 7, 0.1) # 0.1刻みで0から10までの配列を作成 y = np.sin(x) # 正弦関数 plt.plot(x, y) # グラフの描画 plt.show() # グラフの表示 |
無事に描画されました。
Matplotlibも何も違和感なく書くことができました。
強いて言えばPythonを書いてる感覚と同じなので、生のPythonで書くこととの差別化が難しいところです。
Rubyで作られたプロジェクトとPyCallで作ったデータ処理系うまく連携させることで価値が見えてくるかもしれません。
さいごに
今回はNumPyのGem(≒PyCall)を使ってRubyでNumPyを動かす方法について紹介しました。
Rubyで機械学習を行うアプローチは他にもたくさんあるので、何か面白いものがあればこちらのブログで紹介させていただきます。
参考リンク
NumPy
mrkn/numpy.rb: Numpy wrapper for Ruby
mrkn/pycall.rb: Calling Python functions from the Ruby language
2016卒のWebエンジニア。
採用やマネジメントもやってます。