LoginSignup
25
24

More than 1 year has passed since last update.

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

Last updated at Posted at 2019-02-08

Juliaでの機械学習パッケージは色々あるが、今回はPyCall.jlを使って、Pythonの機械学習フレームワークTensorFlowと使ってみよう。そして、TensorFlowの高レベルAPIであるKerasを使うことで、Juliaからもお気楽に機械学習ができることをみてみる。
Juliaを使うことで、Python特有のforループをなるべく使わない、とか、numpyでの配列の作り方、などにとらわれる必要がなくなり、Juliaで作った配列をTensorFlowに投げ込むことができるようになる。

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

[2019年9月2日追記]以下の記事ではPythonのA.Bを表現するためにA[:B]を使っているが、最新のPyCall.jlでは、A.BをJuliaでも使うことができる。
[2021年5月27日追記]Julia 1.6での動作確認をしたコードを追記。

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

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")

追記

Julia 1.6で動作確認したコードは以下。

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")

確認環境は

  • Julia 1.6.0
  • Python 3.8.9
  • Tensorflow 2.5.0
julia> println( tensorflow.__version__)
2.5.0

なお、MacOSでpyenvで入れたPythonの場合は
https://qiita.com/kjunichi/items/7453814cb902158f9836
をする必要があるようだ。

25
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
24