Understanding Deep LearningのノートブックをJuliaで確認する。
4.1 Composing networks
1層のニューラルネットワークで何が起こっているかはJuliaでDeep Learningを理解する: 3.1 Shallow neural networks Iで確認した。層を増やすと実際のところ何が起きるのだろうか?
以下のような2層のニューラルネットワークを考える。
(画像はudlbookより引用)
function shallow(x, activation_fn, phi, theta)
pre = theta * [1; x]
act = activation_fn.(pre)
w_act = phi' .* [1; act]
sum(w_act, dims=1)
end
ReLU(z) = ifelse(z < 0, zero(z), z)
n1_theta = [
0.0 -1.0
0 1.0
-0.67 1.0
]
n1_phi = [
1.0 -2.0 -3.0 9.3
]
n2_theta = [
-0.6 -1.0
0.2 1.0
-0.5 1.0
]
n2_phi = [
0.5 -1.0 -1.5 2.0
]
それぞれのネットワークがどのような関数か確認する。
using CairoMakie
x = -1:0.001:1
net1_out = first.(shallow.(x, ReLU, n1_phi |> Ref, n1_theta |> Ref))
net2_out = first.(shallow.(x, ReLU, n2_phi |> Ref, n2_theta |> Ref))
fig = Figure()
ax1 = Axis(fig[1, 1])
lines!(ax1, x, net1_out, label="n1")
lines!(ax1, x, net2_out, label="n2")
fig[1, 2] = Legend(fig, ax1)
net1_out
をネットワーク2の入力とすると
net12_out = first.(shallow.(net1_out, ReLU, n2_phi |> Ref, n2_theta |> Ref))
fig = Figure()
ax1 = Axis(fig[1, 1])
lines!(ax1, x, net1_out, label="n1")
lines!(ax1, x, net12_out, label="n12")
vlines!(ax1, [0, 0.67], color=:red, linestyle=:dot)
fig[1, 2] = Legend(fig, ax1)
これが層を増やすことにより起こることである。2層目の関数を1層目で作った領域数分、1層目の値に沿って繰り返している。
1層目で3分割し、2層目で4分割しているので、3x4=12分割されている。
1層のみで隠れユニットを6個にした時、分割数は7なので、効率よく分割できている。
1層のみの場合は、それぞれの領域で異なる線形関係にできるが、2層の場合は形が図のように制限されることになる。
制限がある分、表現力に劣るわけだが、この制限は正則化という形で精度に貢献することになる。
なぜニューラルネットワークを深くしたいかが何となく理解できたと思う。