Julia入門~高速な動的型付け言語~【Fluxでの機械学習編】
IT技術
Fluxで機械学習編~Juliaに入門してみよう~
前回は、Julia と Jupyter Notebook を連携して、グラフ描画する方法を紹介しました。
今回は、Julia の機械学習フレームワーク「Flux」を紹介していきます!
※本記事で使用するのは、「Julia ver 1.5」です。
Fluxをインストールする
Flux は、Julia 向けに提供されている、機械学習フレームワーク。
Github の README を読むと、
Flux は100% Julia で書かれており、簡単に機械学習モデルを構築できる。
と、記載されています。
【Github:Flux】
https://github.com/FluxML/Flux.jl
ちなみに、今回は試しませんが、GPU コンピューティングもできるそうです。
機械学習フレームワークでは、なかなかの完成度と言えそうですね!
インストール
いつも通り、パッケージモードで追加します。
1(@v1.5) pkg> add Flux
これだけで OK です。
本記事では、執筆時点で最新の「v 0.11.0」を使用しています。
Fluxを使ってみる!
それでは早速、Jupyter Notebook を立ち上げて、実際に触ってみましょう!
1$ jupyter notebook
まずは、Flux を読み込みます。
そこそこ時間がかかりますが、気長に待ちましょう…
1using Flux
基本演算 (勾配演算)
Julia は、数学演算に特化しているため、「勾配計算」も Flux と組み合わせれば、簡単に計算ができます。
1f(x) = 3x^2 + 2x + 1
2df(x) = gradient(f, x)[1] # 一階微分 df/dx = 6x + 2
3d2f(x) = gradient(df, x)[1] # 二階微分 d²f/dx² = 6
4
5println(df(2)) # > 14
6println(d2f(2)) # > 6
もちろん、多変数関数の微分もできますし、一度にまとめて計算することもできます。
1f(x, y) = sum((x .- y).^2) # f(x,y) = ∑(x-y)²
2
3println(gradient(f, [2, 1], [2, 0])) # df(2, 1) & df(2, 0)
4
5# > ([0, 2], [0, -2])
ただ、機械学習でのパラメータ数は、「何百・何千・何万」という単位ですので、いちいち計算してられませんね…。
一方の Flux では、パラメータを一つにまとめることができるので、手間が省けるのです。
1x = [2, 1]
2y = [2, 0]
3
4gs = gradient(params(x, y)) do
5 f(x, y)
6end
7
8println(gs[x]) # > [0, 2]
9println(gs[y]) # > [0, -2]
単純なモデルで試してみる
それでは、少し機械学習寄りのコードも書いてみましょう!
線分回帰モデルを試す
ここでは、シンプルな「線形回帰モデル」を定義していきます。
1W = rand(2, 5) # 重み
2b = rand(2) # バイアス
3
4predict(x) = W*x .+ b
5
6function loss(x, y)
7 ŷ = predict(x)
8 sum((y .- ŷ).^2) # 二乗誤差 (Juliaでは最後の結果がreturnされる)
9end
10
11x, y = rand(5), rand(2) # 適当なデータ
12
13println("x = $(x)")
14println("y = $(y)")
15println("ŷ = $(predict(x))")
16println("loss = $(loss(x, y))")
1# 出力例
2x = [0.6147959006414276, 0.07791447535736151, 0.28634504031397356, 0.7806187614798725, 0.06985734225178786]
3y = [0.7047761745357362, 0.1583882051433998]
4ŷ = [1.6040926838038974, 1.2723395138879994]
5loss = 2.0496577020960767
上のコードを見ると、.+ や.- という表記が気になるかもしれません。
これは、加減演算子が関数として定義されているためで、配列データなどを繰り返し計算するために、ドット. をつけています。
今はまだ、ランダムで初期化された「重み」と「バイアス」なので、誤差がかなり大きいですね…。
勾配降下法を実装する
誤差が大きいので、勾配を計算して、「勾配降下法」を実装してみます。
1gs = gradient(() -> loss(x, y), params(W, b))
この勾配の計算は、以下のような書き方でも、同じ意味になります。
1gs = gradient(params(W, b)) do
2 loss(x, y)
3end
次は、勾配降下法で、一度だけ重みを更新してみましょう!
1W̄ = gs[W] # Wについて勾配を計算
2W .-= 0.1 .* W̄ # w ← w - η∇w
3
4println(loss(x, y))
1# 出力例
21.2596519626536098
しっかりと、誤差が小さくなっていますね!
コード量としては、かなり少ないのにもかかわらず、簡単に勾配計算ができてしまいました。
この線形回帰モデルのコードは、以下のとおり、たったこれだけです。
1using Flux
2
3W = rand(2, 5) # 重み
4b = rand(2) # バイアス
5
6predict(x) = W*x .+ b
7
8function loss(x, y)
9 ŷ = predict(x)
10 sum((y .- ŷ).^2) # 二乗誤差 (Juliaでは最後の結果がreturnされる)
11end
12
13x, y = rand(5), rand(2) # 適当なデータ
14
15# 勾配計算
16gs = gradient(() -> loss(x, y), params(W, b))
17
18# 勾配降下法
19W̄ = gs[W] # Wについて勾配を計算
20W .-= 0.1 .* W̄ # w ← w - η∇w
とてもコンパクトですね!
層を定義してみる
機械学習といえば、ニューラルネットワークで、多層にしたモデルが一般的です。
それを、Flux で単純に実装していきましょう!
1# 2層構造のシンプルな全結合ニューラルネットワーク
2# In(5) - fc(3) - fc(2)
3
4W1 = rand(3, 5)
5b1 = rand(3)
6layer1(x) = W1 * x .+ b1 # Layer1の出力
7
8W2 = rand(2, 3)
9b2 = rand(2)
10layer2(x) = W2 * x .+ b2 # Layer2の出力
11
12model(x) = layer2(σ.(layer1(x))) # モデルの定義 (σはシグモイド関数)
13
14println(model(rand(5))) # > 例: [1.857204783239992, 1.8739117950968038]
コード自体は、とてもシンプルで、実際に適切に動作します。
ただ、もし多層にしたくなったとき、少し面倒ですね…
これを回避するために、一つのアイデアとして、以下のように関数で全結合層を定義すると良いでしょう。
1# 2層構造のシンプルな全結合ニューラルネットワーク
2# In(5) - fc(3) - fc(2)
3
4function linear(in, out)
5 W = randn(out, in)
6 b = randn(out)
7 x -> W * x .+ b # xを引数とする無名関数を返す
8end
9
10linear1 = linear(5, 3)
11linear2 = linear(3, 2)
12
13model(x) = linear2(σ.(linear1(x)))
14
15println(model(rand(5)))
16
17println(linear1.W) # のようにパラメータもアクセス可能
かなりシンプルで、可読性に長けた形になりました!
ちなみFlux では、Dense() という名前で、すでに全結合層が用意されています。
層を積み上げてみる
それでは、Flux に用意されている便利な機能を存分に使って、ネットワークを構築してみます。
例えば、3層のニューラルネットワークであれば、以下のコードだけでOKです。
1model2 = Chain(
2 Dense(10, 5, σ),
3 Dense(5, 2),
4 softmax)
5
6println(model2(rand(10))) # > 例: Float32[0.7592539, 0.24074602]
Flux では、モデルを単なる関数として扱える点が、大きな特徴です。
PyTorch なんかもそうですが、「パラメータアクセスができる関数」といったところでしょうか。
さいごに
今回は、Juila の機械学習フレームワーク Flux について、簡単に紹介しました。
「何かしらデータセットを学習させて…」といったことはしませんでしたが、Flux の使い勝手の良さが、少なからず伝わったかと思います。
ちなみに、公式ドキュメントでは、他にも充実した実装サンプルが掲載されています。
もし、興味を持った方は、ぜひ試してみてくださいね!
【 Flux 公式サイト】
https://fluxml.ai/Flux.jl/stable/
さて、今回で「高速な動的型付け言語 Julia に入門する」シリーズは終わりになります。
今後また、応用編として、Julia の記事を書くかもしれません。
その時をお楽しみに!
こちらの記事もオススメ!
2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
2020.07.27IT・コンピューターの歴史特集IT・コンピューターの歴史をまとめていきたいと思います!弊社ブログにある記事のみで構成しているため、まだ「未完成状態」...
2020.07.28機械学習 特集知識編人工知能・機械学習でよく使われるワード徹底まとめ!機械学習の元祖「パーセプトロン」とは?【人工知能】ニューラルネ...
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
「好きを仕事にするエンジニア集団」の(株)ライトコードです! ライトコードは、福岡、東京、大阪の3拠点で事業展開するIT企業です。 現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。 いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。 システム開発依頼・お見積もり大歓迎! また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」「WEBディレクター」を積極採用中です! インターンや新卒採用も行っております。 以下よりご応募をお待ちしております! https://rightcode.co.jp/recruit