はじめに
これまで何度か紹介してきたPyCallですが、バージョンが1.0になって大幅にライブラリが変更されたので、新しいバージョンにあわせた使い方を紹介してみます。
mrkn/pycall.rb: Calling Python functions from the Ruby language
インストール
以下のコマンドでインストールができます。
gem install pycall
ちなみに、以下のライブラリも入れておくと便利です。
gem install numpy
gem install pandas
Anacondaを使っている場合
私はMacにAnaconda3-4.3.1をインストールしており、この環境では以下の環境設定をしないとエラーが出たので補足します。
export PYTHONPATH=/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6/:/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6/site-packages/:/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6/lib-dynload/
export PYTHONHOME=$PYTHONPATH
※「xxx」は各自のユーザー名に置き換えて下さい。
ちなみに、anacondaというブランチで修正版が公開されているので、あわせてご参照下さい。
基本
PyCallを呼び出して、RubyにPythonのライブラリを設定します。
以下は、Pythonのsysを呼び出して、パスを表示するサンプルです。
require 'pycall'
sys = PyCall.import_module('sys')
p sys.path
私の環境では以下のように表示されます。
['/Users/xxx/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/pycall-1.0.2/lib/pycall/python', '/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python36.zip', '/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6', '/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6/lib-dynload', '/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6/site-packages', '/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6/site-packages/Sphinx-1.5.1-py3.6.egg', '/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6/site-packages/aeosa', '/Users/xxx/.pyenv/versions/anaconda3-4.3.1/lib/python3.6/site-packages/dlib-19.6.0-py3.6-macosx-10.7-x86_64.egg']
基本的には、以下の使い方になるようです。
ライブラリ名 = PyCall.import_module('ライブラリ名')
ライブラリ名.メソッド
Numpy
Numpyは専用にgemが作ってあり、もっと使いやすくなっています。
require 'numpy'
np = Numpy
x = np.asarray([1,2,3,4,5])
p x.sum()
上記のコードを実行すると「15」が返ってくるはずです。
Pandas
Pandasにも同様に専用のgemがあります。
ここでは、以下のCSVファイルを読み込む例を紹介します。
a,b,c
0,1,2
3,4,5
6,7,8
以下のコードを実行します。
require 'pandas'
pd = Pandas
x = pd.read_csv('sample.csv')
p x.shape
結果、「(3, 3)」と表示されまるはずです。
Matplotlib
可視化ライブラリを使用して、とても単純なグラフを描画してみます。
require 'pycall'
plt = PyCall.import_module('matplotlib.pyplot')
plt.plot([1,3,2,4])
plt.savefig("test.png")
実行すると「test.png」という画像ファイルが生成され、以下のようなグラフが描画されます。
機械学習
毎度のことではありますが、中国電力さんが公開されている電力使用量の過去データを学習し、電力使用量を予測する機械学習のサンプルを以下に示します。
ここでは、サンプルを単純にするため、2016年度のデータのみを使って学習しています。
まずは、以下のURLより2016年度のデータをダウンロードします。
http://www.energia.co.jp/jukyuu/download.html
次に以下のサンプルを実行して下さい。
# ライブラリ読込
require 'pycall'
require 'pandas'
require 'time'
pd = Pandas
# ファイル読込
filename = "juyo-2016.csv"
df_kw = pd.read_csv(filename, encoding: "SHIFT-JIS", skiprows: 2)
df_kw["KW"] = df_kw.pop("実績(万kW)")
# データ加工
year = []
month = []
day = []
wday = []
hour = []
PyCall.len(df_kw).times do |i|
dt = DateTime.parse(df_kw.DATE.iloc[i] + " " + df_kw.TIME.iloc[i])
year << dt.year
month << dt.month
day << dt.day
wday << dt.wday
hour << dt.hour
end
df_kw["YEAR"] = year
df_kw["MONTH"] = month
df_kw["DAY"] = day
df_kw["WEEK"] = wday
df_kw["HOUR"] = hour
# 学習データの取得
cols = ["KW","YEAR","MONTH","WEEK","HOUR"]
df = df_kw[cols]
y = df.pop("KW").as_matrix().astype("int").flatten()
x = df.as_matrix().astype("float")
# クロスバリデーション
cv = PyCall.import_module('sklearn.model_selection')
x_train, x_test, y_train, y_test = cv.train_test_split(x, y, test_size: 0.1, random_state: 42)
# 正規化
preprocessing = PyCall.import_module('sklearn.preprocessing')
scaler = preprocessing.StandardScaler.new()
scaler.fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)
# 学習
ensemble = PyCall.import_module('sklearn.ensemble')
model = ensemble.RandomForestRegressor.new(random_state: 42)
model.fit(x_train, y_train)
puts model.score(x_test,y_test)
実行すると「0.77093639126251379」と表示され、約77%の精度で予測できることがわかります。
さいごに
これからもっとサンプルができたら都度追加していきます。
補足
iRuby Notebookを使うともっと色々なことができます。興味のある方は以下のURLをご参照頂き、iRubyをインストールしてご利用下さい。