Julia
Keras
TensorFlow
PyCall.jl

Juliaで機械学習:PyCall.jlを使ってTensorFlowのKerasを使ってみる

Juliaでの機械学習パッケージは色々あるが、今回はPyCall.jlを使って、Pythonの機械学習フレームワークTensorFlowと使ってみよう。そして、TensorFlowの高レベルAPIであるKerasを使うことで、Juliaからもお気楽に機械学習ができることをみてみる。

Juliaを使うことで、Python特有のforループをなるべく使わない、とか、numpyでの配列の作り方、などにとらわれる必要がなくなり、Juliaで作った配列をTensorFlowに投げ込むことができるようになる。

この記事の一番最後に、全体のコードを載せておいた。


機械学習フレームワークとこれまでの記事

Juliaでの機械学習フレームワークはいくつかあり、

Flux.jl:

「Juliaで機械学習:深層学習フレームワークFlux.jlを使ってみる その1:基本編」

https://qiita.com/cometscome_phys/items/e99d6177325e78ebb228

「Juliaで機械学習:深層学習フレームワークFlux.jlを使ってみる その2:線形回帰編」

https://qiita.com/cometscome_phys/items/f58174c0dad7ecb811ed

「Juliaで機械学習:深層学習フレームワークFlux.jlを使ってみる その3:ニューラルネットとバッチ正規化編」

https://qiita.com/cometscome_phys/items/1b7ad193dc1db9b184db



Knet.jl:

「Juliaで機械学習:深層学習フレームワークKnet.jlを使ってみる」

https://qiita.com/cometscome_phys/items/f09e801bc5b3f57f6350

そして、

TensorFlow.jl:

「JuliaでTensorFlow その1」

https://qiita.com/cometscome_phys/items/358bc4a1feaec1c7fa14

「JuliaでTensorFlow その2: 線形回帰をやってみる」

https://qiita.com/cometscome_phys/items/244cfed8ab309156735c

「JuliaでTensorFlow その3: 過学習について」

https://qiita.com/cometscome_phys/items/638dca2c980ab0f98a9e

「JuliaでTensorFlow その4: 線形基底関数を用いた回帰」

https://qiita.com/cometscome_phys/items/92dba9f82cd58d877ec5

「JuliaでTensorFlow その5: ニューラルネットワークの導入と深層学習」

https://qiita.com/cometscome_phys/items/45017aa9741c5fdc7eb9

という記事をすでに書いている。

今回は、Juliaの機械学習フレームワークではなく、Pythonの機械学習フレームワークをJuliaから使ってみることとする。TensorFlow以外の有名なフレームワークとしては、PyTorchがあり、

「PyCall.jlでPyTorch使ってDeep Learningする」

https://qiita.com/yatra9/items/0a1a9a5ba19e9efe08c0

を参考にさせていただいた。


バージョン

Julia 1.1.0

TensorFlow 1.12.0

を用いる。コードはMac OS 10.14.3の上で実行した。


TensorFlowのインストール

まず、TensorFlowが入っていない方のために、TensorFlowのインストールから述べる。色々なインストール方法があると思うが、ここではAnacondaを用いることとする。

まず、

https://www.anaconda.com

から自分のOSに合ったAnacondaを入れる。

インストールが終わったら、

conda create -n keras

として、新しいcondaの環境を作る。

そして、

conda activate keras

でアクティベートする。

そして、Pythonを3.6に指定して(2019年2月8日現在、TensorFlowはPython 3.7をサポートしていないため)、

conda install python=3.6 tensorflow

として、TensorFlowをインストールする。

インストールが終わったら、

which python

でpythonの入っているpathを見ておく。例えば、Macであれば、

/anaconda3/envs/keras/bin/python

などが表示される。


PyCallのインストール

次に、Juliaを起動して、PyCallのインストールを行う。

まず、先ほど調べたpathをJulia上で

ENV["PYTHON"]="/anaconda3/envs/keras/bin/python"

としてセットする。次に、]を押してパッケージモードにしてから、

add PyCall

をする。もしすでにPyCallが入っている場合には、

build PyCall

で入れ直しができる。これが終わったら、delキーなどを押してパッケージモードを終了する。


PyCallを用いたTensorFlowによる機械学習


バージョンの確認

まず、インストールしたPythonのバージョンを確認しておこう。

using PyCall

PyCall.pyversion

でPythonのバージョンを表示できる。

v"3.6.8"

などが出れば、ちゃんとPython 3.6系が入っていることになる。

TensorFlowとKerasのバージョンを確認しておく。

そのためには、

const tensorflow = pyimport("tensorflow")

としてから、

println( tensorflow[:__version__])

とすればTensorFlowのバージョンが表示される。Pythonではtensorflow.versionとなっていたが、PyCallではa.bを使う代わりに、a[:b]を使う。a.b.cであれば、a[:b][:c]となる。Kerasのバージョンは

println( tensorflow[:keras][:__version__])

で調べることができる。


バージョン

TensorFlow 1.12.0

Keras 2.1.6-tf


Kerasを用いた機械学習

それでは、実際の機械学習をやってみよう。

以後はJupyter notebookでやってもjulia test.jlなどで実行してもよい。

PythonのKerasについては、

「TensorFlowの高レベルAPIの使用方法:Kerasの使い方」

https://qiita.com/cometscome_phys/items/d9553fe7c92e09fc14a9

「TensorFlowの高レベルAPIを使ったBatch Normalizationの実装:Keras版」

https://qiita.com/cometscome_phys/items/47467f1f0e3ab0a695cb

「TensorFlowの高レベルAPIの使用方法:Dataset APIを使ってみる with Keras」

https://qiita.com/cometscome_phys/items/d36af6fcead172847231

の記事を書いているので、参考にすることができる。

この記事では、一番最初の記事でやっていることをJuliaで実行することを目的とする。


再現する関数

再現する関数は、これまでずっと使ってきた、

a0 = 3.0

a1 = 2.0
b0 = 1.0

n = 10
x0 = range(-2, 2, length=n)
y0 = zeros(n,1)
y0[:,1] = a0*x0.+a1*x0.^2 .+ b0 .+ 3*cos.(20*x0)

nm = 300
xmany = range(-2, 2, length=nm)
ymany = zeros(nm,1)
ymany[:,1] = a0*xmany.+a1*xmany.^2 .+ b0 .+ 3*cos.(20*xmany)

using Plots
plot(xmany,ymany)
savefig("test.png")

としよう。グラフは、

test.png

となる。

これまでの記事と同じように多項式でのフィッティングを行うため、

function make_phi(x0,k)

n = length(x0)
phi = zeros(n,k)
for i=1:n
for j=1:k
phi[i,j] = x0[i]^(j-1)
end
end
return phi
end

という関数を作り、

k = 6

phi = make_phi(x0,k)
phimany = make_phi(xmany,k)

としてインプットデータを作っておこう。


モデルの構築

モデルの構築は

using PyCall

const tensorflow = pyimport("tensorflow")
const keras =tensorflow[:keras]
const layers =keras[:layers]
const optimizers =keras[:optimizers]

function build_model(d_input,d_middle)
inputs = keras[:Input](shape=(d_input,))
x = layers[:Dense](d_middle, activation="relu")(inputs)
y = layers[:Dense](1)(x)
adam = optimizers[:Adam]()
model = keras[:Model](inputs=inputs, outputs=y)
model[:compile](optimizer=adam,
loss="mean_squared_error")

return model
end

でできる。ここで、PyCallで呼び出すものをあらかじめconstで定義しておいた。

また、build_modela.bの代わりにa[:b]を使っている以外はPythonのコードと変わらない。一つだけ異なるのは、activation="relu"はPythonではactivation='relu'となっていたことだけである。Juliaではそのまま使うとエラーとなった。

この関数を使ってKerasのモデルを作るには、

d_input = k

d_middle = 10
model = build_model(d_input,d_middle)

とすればよい。


学習

学習を行うには、

history = model[:fit](phimany, ymany, epochs=2000,batch_size=20,validation_data=(phi, y0))

とすればよい。

結果は、

ytest = model[:predict](phimany)

plot(xmany,ytest)
plot!(xmany,ymany)
savefig("testkeras.png")
testloss = history[:history]["val_loss"]

plot(testloss)
savefig("testloss.png")

でプロットしてみる。

グラフは

testkeras.png

となり、lossは

testloss.png

となる。


全体コード

最後に全体コードを載せておく。


keras.jl

a0 = 3.0

a1 = 2.0
b0 = 1.0

n = 10
x0 = range(-2, 2, length=n)
y0 = zeros(n,1)
y0[:,1] = a0*x0.+a1*x0.^2 .+ b0 .+ 3*cos.(20*x0)

nm = 300
xmany = range(-2, 2, length=nm)
ymany = zeros(nm,1)
ymany[:,1] = a0*xmany.+a1*xmany.^2 .+ b0 .+ 3*cos.(20*xmany)

using Plots
plot(xmany,ymany)
savefig("test.png")

function make_phi(x0,k)
n = length(x0)
phi = zeros(n,k)
for i=1:n
for j=1:k
phi[i,j] = x0[i]^(j-1)
end
end
return phi
end

k = 6
phi = make_phi(x0,k)
phimany = make_phi(xmany,k)

using PyCall
const tensorflow = pyimport("tensorflow")
const keras =tensorflow[:keras]
const layers =keras[:layers]
const optimizers =keras[:optimizers]

function build_model(d_input,d_middle)
inputs = keras[:Input](shape=(d_input,))
x = layers[:Dense](d_middle, activation="relu")(inputs)
y = layers[:Dense](1)(x)
adam = optimizers[:Adam]()
model = keras[:Model](inputs=inputs, outputs=y)
model[:compile](optimizer=adam,
loss="mean_squared_error")

return model
end

d_input = k
d_middle = 10
model = build_model(d_input,d_middle)

history = model[:fit](phimany, ymany, epochs=2000,batch_size=20,validation_data=(phi, y0))
ytest = model[:predict](phimany)
plot(xmany,ytest)
plot!(xmany,ymany)
savefig("testkeras.png")
testloss = history[:history]["val_loss"]

plot(testloss)
savefig("testloss.png")