この記事の目的
本記事は、Deep Learningの入門書「ゼロから作るDeep Learning」を参考に、Juliaを用いて同書の内容を実装してみる、という試みです。
※これはあくまで筆者の一つの試みと提案で、必ずしも内容が正解ではありませんのでご了承お願い致します。
また、より良いアドバイスや協力のご提案などありましたら、お気軽にお声がけ頂けますと幸いです。
今回取り組むこと
本記事は、参考書の3.4章「3層ニューラルネットワークの実装」にあたります。
特に、3.4.3の実装を確認したいと思います。
参考書のソースでは、init_network()関数の冒頭でnetwork変数を辞書型で宣言しています。Juliaでもこれと同じように、network変数を辞書型で宣言します。
さらに、networkの内容も併せて多次元配列で定義します。
network = Dict()
network["W1"] = [0.1 0.3 0.5; 0.2 0.4 0.6]
network["b1"] = [0.1 0.2 0.3]
network["W2"] = [0.1 0.4; 0.2 0.5; 0.3 0.6]
network["b2"] = [0.1 0.2]
network["W3"] = [0.1 0.3; 0.2 0.4]
network["b3"] = [0.1 0.2]
networkは以下のような行と列を持つ多次元配列となります。
行列 | 行と列の数 |
---|---|
network["W1"] | 2行3列 |
network["b1"] | 1行3列 |
network["W2"] | 3行2列 |
network["b2"] | 1行2列 |
network["W3"] | 2行2列 |
network["b3"] | 1行2列 |
Juliaでは、行列同士の掛け算や足し算、引き算はそのまま記述すれば良いです。
ただし、行数と列数が次の条件を満たしていることが必要です。
掛け算
条件:行列Aと行列Bをかけるとき、Aの列数とBの行数が同じであること。
例えば、l,m,nを整数とするとき、AとBのそれぞれの行数と列数が以下を満たすときです。
・Aはl行m列の行列
・Bはm行n列の行列
足し算、引き算
条件:二つの行列のそれぞれの行数と列数が等しいこと。
以下の計算を行う際のソースを作成します。
xを1行2列の行列、W1を2行3列の行列、b1を1行3列の行列とするとき、
a1 = x * W1 + b1
を求めるソースは、
x = [1.0 0.5]
W1 = [0.1 0.3 0.5; 0.2 0.4 0.6]
b1 = [0.1 0.2 0.3]
a1 = x * W1 + b1
上記の記載で行列の計算が行われます。
以降、参考書のソースに従うと、
関数init_network()を宣言し、辞書型の変数networkを取得する処理を作成します。
function init_network()
network = Dict()
network["W1"] = [0.1 0.3 0.5; 0.2 0.4 0.6]
network["b1"] = [0.1 0.2 0.3]
network["W2"] = [0.1 0.4; 0.2 0.5; 0.3 0.6]
network["b2"] = [0.1 0.2]
network["W3"] = [0.1 0.3; 0.2 0.4]
network["b3"] = [0.1 0.2]
return network
end
前回の記事で作成した[前回の記事]、シグモイド関数を引用します。
ソースは以下となります。
function sigmoid_function(x)
return map(i -> 1 / (1 + exp(-i)), x)
end
また、恒等関数を定義します。
参考書の通り、恒等関数は以下となります。
function identify_function(x)
return x
end
さらに、シグモイド関数及び恒等関数を用いて、ニューラルネットワークの各層の計算を行う以下のようなforward()関数を定義します。
function forward(network, x)
W1, W2, W3 = network["W1"], network["W2"], network["W3"]
b1, b2, b3 = network["b1"], network["b2"], network["b3"]
a1 = x * W1 + b1
z1 = sigmoid_function(a1)
a2 = z1 * W2 + b2
z2 = sigmoid_function(a2)
a3 = z2 * W3 + b3
y = identify_function(a3)
return y
end
これらの関数を用いて、以下の手順で行列の計算を行います。
手順(1) init_network()を実行し、行列network変数を取得する。
手順(2) 行列xを宣言する。
手順(3) 引数にnetworkとxを設定してforwar()関数を呼び出す。
forwar()関数の中でシグモイド関数や恒等関数を用いた行列の計算を行う。
手順(4) 解として得られる行列yを表示する。
全ソースは以下となります。
function init_network()
network = Dict()
network["W1"] = [0.1 0.3 0.5; 0.2 0.4 0.6]
network["b1"] = [0.1 0.2 0.3]
network["W2"] = [0.1 0.4; 0.2 0.5; 0.3 0.6]
network["b2"] = [0.1 0.2]
network["W3"] = [0.1 0.3; 0.2 0.4]
network["b3"] = [0.1 0.2]
return network
end
# シグモイド関数の定義
function sigmoid_function(x)
return map(i -> 1 / (1 + exp(-i)), x)
end
# 恒等関数の定義
function identify_function(x)
return x
end
function forward(network, x)
W1, W2, W3 = network["W1"], network["W2"], network["W3"]
b1, b2, b3 = network["b1"], network["b2"], network["b3"]
a1 = x * W1 + b1
z1 = sigmoid_function(a1)
a2 = z1 * W2 + b2
z2 = sigmoid_function(a2)
a3 = z2 * W3 + b3
y = identify_function(a3)
return y
end
network = init_network() # 手順(1)
x = [1.0 0.5] # 手順(2)
y = forward(network, x) # 手順(3)
println(y) # 手順(4)
参考書と同じ結果を得ました。
次は、ソフトマックス関数の実装を行ってみたいと思います。
もくじ
(1)論理回路
(2)活性化関数
(3)3層ニューラルネットワークの実装
(4)ソフトマックス関数
(5)MNIST手書き数字認識 その①画像表示
(5)MNIST手書き数字認識 その②推論
関連情報
Julia早引きノート[01]変数・定数の使い方
https://qiita.com/ttabata/items/a1ada2c0cba03672e105
Julia - 公式ページ
https://julialang.org/
Julia - 日本語公式ドキュメント
https://julia-doc-ja.readthedocs.io/ja/latest/index.html
初めてのJuliaとインストール (Windows & Linux)
https://qiita.com/ttlabo/items/b05bb43d06239f968035
出典
■参考書
「ゼロから作るDeep Learning ~ Pythonで学ぶディープラーニングの理論と実装」
斎藤康毅 著/オライリー・ジャパン
ご意見など
ご意見、間違い訂正などございましたらお寄せ下さい。