Current section

Files

Jump to
deeppipe2 lib deeppipe.ex
Raw

lib/deeppipe.ex

defmodule Deeppipe do
alias Cumatrix, as: CM
@moduledoc """
main module of DeepPipe2.
functions for Deep-Learning.
"""
@doc """
for debug
forcely stop
"""
def stop() do
raise("stop")
end
@doc """
for debug
invoke garbage collection forcely.
"""
def gbc() do
:erlang.garbage_collect()
end
# for dropout. push mask-tensor to input data as tuple.
# e.g. [after-data,{befor-data,mask-tensor}|befors]
# backward with dropout require mask-tensor.
defp push(x, y, []) do
[x, y]
end
defp push(x, y, [z | zs]) do
[x, {z, y} | zs]
end
@doc """
forward
return all middle data
```
1st arg is input data matrix
2nd arg is network list
3rd arg is generated middle layer result
```
"""
def forward(_, [], res) do
res
end
def forward(x, [{:weight, w, _, _, dr, _} | rest], res) do
# IO.puts("FD weight")
if dr == 0.0 do
x1 = CM.mult(x, w)
forward(x1, rest, [x1 | res])
else
mw = CM.dropout(w, dr)
x1 = CM.mult(x, CM.emult(w, mw))
forward(x1, rest, push(x1, mw, res))
end
end
def forward(x, [{:bias, b, _, _, dr, _} | rest], res) do
# IO.puts("FD bias")
if dr == 0.0 do
x1 = CM.add(x, b)
forward(x1, rest, [x1 | res])
else
mw = CM.dropout(b, dr)
x1 = CM.add(x, CM.emult(b, mw))
forward(x1, rest, push(x1, mw, res))
end
end
def forward(x, [{:function, name} | rest], res) do
# IO.puts("FD function")
x1 = CM.activate(x, name)
forward(x1, rest, [x1 | res])
end
def forward(x, [{:filter, w, {st_h, st_w}, pad, _, _, dr, _} | rest], res) do
# IO.puts("FD filter")
if dr == 0.0 do
x1 = CM.convolute(x, w, st_h, st_w, pad)
forward(x1, rest, [x1 | res])
else
mw = CM.dropout(w, dr)
x1 = CM.convolute(x, CM.emult(w, mw), st_h, st_w, pad)
forward(x1, rest, push(x1, mw, res))
end
end
def forward(x, [{:pooling, st_h, st_w} | rest], [_ | res]) do
# IO.puts("FD pooling")
{x1, x2} = CM.pooling(x, st_h, st_w)
forward(x1, rest, [x1, x2 | res])
end
def forward(x, [{:full} | rest], res) do
# IO.puts("FD full")
x1 = CM.full(x)
forward(x1, rest, [x1 | res])
end
def forward(x, [{:analizer, n} | rest], res) do
# IO.puts("FD analizer")
CM.analizer(x, n)
forward(x, rest, res)
end
def forward(x, [{:visualizer, n, c} | rest], res) do
# IO.puts("FD visualizer")
CM.visualizer(x, n, c)
forward(x, rest, res)
end
@doc """
gradient with backpropagation
```
1st arg is input data matrix
2nd arg is network list
3rd arg is train matrix
```
"""
def gradient(x, network, t) do
[x1 | x2] = forward(x, network, [x])
loss = CM.sub(x1, t)
network1 = Enum.reverse(network)
result = backward(loss, network1, x2, [])
result
end
# backward
# calculate grad with gackpropagation
# 1st arg is loss matrix
# 2nd arg is network list
# 3rd arg is generated new network with calulated gradient
# var l is loss matrix
# var u is input data matrix or tesnro at each layer
defp backward(_, [], _, res) do
res
end
defp backward(l, [{:weight, w, ir, lr, dr, v} | rest], [u | us], res) do
# IO.puts("BK weight")
if dr == 0.0 do
{n, _} = CM.size(l)
w1 = CM.mult(CM.transpose(u), l) |> CM.mult(1 / n)
l1 = CM.mult(l, CM.transpose(w))
backward(l1, rest, us, [{:weight, w1, ir, lr, 0.0, v} | res])
else
{n, _} = CM.size(l)
{u1, mw} = u
w1 = CM.mult(CM.transpose(u1), l) |> CM.mult(1 / n) |> CM.emult(mw)
l1 = CM.mult(l, CM.transpose(CM.emult(w, mw)))
backward(l1, rest, us, [{:weight, w1, ir, lr, dr, v} | res])
end
end
defp backward(l, [{:bias, _, ir, lr, dr, v} | rest], [u | us], res) do
# IO.puts("BK bias")
if dr == 0.0 do
b1 = CM.average(l)
backward(l, rest, us, [{:bias, b1, ir, lr, 0.0, v} | res])
else
{_, mw} = u
b1 = CM.average(l) |> CM.emult(mw)
backward(l, rest, us, [{:bias, b1, ir, lr, dr, v} | res])
end
end
defp backward(l, [{:function, :softmax} | rest], [_ | us], res) do
# IO.puts("BK softmax")
backward(l, rest, us, [{:function, :softmax} | res])
end
defp backward(l, [{:function, name} | rest], [u | us], res) do
# IO.puts("BK function")
l1 = CM.diff(l, u, name)
backward(l1, rest, us, [{:function, name} | res])
end
defp backward(l, [{:filter, w, {st_h, st_w}, pad, ir, lr, dr, v} | rest], [u | us], res) do
# IO.puts("BK filter")
if dr == 0.0 do
w1 = CM.gradfilter(u, w, l, st_h, st_w, pad)
l1 = CM.deconvolute(l, w, st_h, st_w, pad)
backward(l1, rest, us, [{:filter, w1, {st_h, st_w}, pad, ir, lr, 0.0, v} | res])
else
{u1, mw} = u
w1 = CM.gradfilter(u1, w, l, st_h, st_w, pad) |> CM.emult(mw)
l1 = CM.deconvolute(l, CM.emult(w, mw), st_h, st_w, pad)
backward(l1, rest, us, [{:filter, w1, {st_h, st_w}, pad, ir, lr, dr, v} | res])
end
end
defp backward(l, [{:pooling, st_h, st_w} | rest], [u | us], res) do
# IO.puts("BK pooling")
l1 = CM.unpooling(u, l, st_h, st_w)
backward(l1, rest, us, [{:pooling, st_h, st_w} | res])
end
defp backward(l, [{:full} | rest], [u | us], res) do
# IO.puts("BK full")
{_, c, h, w} = CM.size(u)
l1 = CM.unfull(l, c, h, w)
backward(l1, rest, us, [{:full} | res])
end
defp backward(l, [{:analizer, n} | rest], us, res) do
# IO.puts("BK analizer")
CM.analizer(l, -n)
backward(l, rest, us, [{:analizer, n} | res])
end
defp backward(l, [{:visualizer, n, c} | rest], us, res) do
# IO.puts("BK visualizer")
backward(l, rest, us, [{:visualizer, n, c} | res])
end
@doc """
learning(network1,network2)
learning/2
1st arg is old network list
2nd arg is network with gradient
generate new network with leared weight and bias
update method is sgd
"""
# --------sgd----------
def learning([], _) do
[]
end
def learning([{:weight, w, ir, lr, dr, v} | rest], [{:weight, w1, _, _, _, _} | rest1]) do
# IO.puts("LN weight")
w2 = CM.sgd(w, w1, lr)
[{:weight, w2, ir, lr, dr, v} | learning(rest, rest1)]
end
def learning([{:bias, w, ir, lr, dr, v} | rest], [{:bias, w1, _, _, _, _} | rest1]) do
# IO.puts("LN bias")
w2 = CM.sgd(w, w1, lr)
[{:bias, w2, ir, lr, dr, v} | learning(rest, rest1)]
end
def learning([{:filter, w, {st_h, st_w}, pad, ir, lr, dr, v} | rest], [
{:filter, w1, _, _, _, _, _, _} | rest1
]) do
# IO.puts("LN filter")
w2 = CM.sgd(w, w1, lr)
# w2 |> CM.to_list() |> IO.inspect()
[{:filter, w2, {st_h, st_w}, pad, ir, lr, dr, v} | learning(rest, rest1)]
end
def learning([network | rest], [_ | rest1]) do
# IO.puts("LN else")
# IO.inspect(network)
[network | learning(rest, rest1)]
end
@doc """
learning(network1,network2,update_method)
learning/3
update method is :momentam, :adagrad, :sgd
"""
def learning(network1, network2, :sgd) do
learning(network1, network2)
end
# --------momentum-------------
def learning([], _, :momentum) do
[]
end
def learning(
[{:weight, w, ir, lr, dr, v} | rest],
[{:weight, w1, _, _, _, _} | rest1],
:momentum
) do
# IO.puts("LMom weight")
{v1, w2} = CM.momentum(w, v, w1, lr)
[{:weight, w2, ir, lr, dr, v1} | learning(rest, rest1, :momentum)]
end
def learning([{:bias, w, ir, lr, dr, v} | rest], [{:bias, w1, _, _, _} | rest1], :momentum) do
# IO.puts("LMom bias")
{v1, w2} = CM.momentum(w, v, w1, lr)
[{:bias, w2, ir, lr, dr, v1} | learning(rest, rest1, :momentum)]
end
def learning(
[{:filter, w, {st_h, st_w}, pad, ir, lr, dr, v} | rest],
[{:filter, w1, _, _, _, _, _, _} | rest1],
:momentum
) do
# IO.puts("LMom filter")
{v1, w2} = CM.momentum(w, v, w1, lr)
[{:filter, w2, {st_h, st_w}, pad, ir, lr, dr, v1} | learning(rest, rest1, :momentum)]
end
def learning([network | rest], [_ | rest1], :momentum) do
# IO.puts("LMom else")
[network | learning(rest, rest1, :momentum)]
end
# --------AdaGrad--------------
def learning([], _, :adagrad) do
[]
end
def learning(
[{:weight, w, ir, lr, dr, h} | rest],
[{:weight, w1, _, _, _, _} | rest1],
:adagrad
) do
{h1, w2} = CM.adagrad(w, h, w1, lr)
[{:weight, w2, ir, lr, dr, h1} | learning(rest, rest1, :adagrad)]
end
def learning([{:bias, w, ir, lr, dr, h} | rest], [{:bias, w1, _, _, _, _} | rest1], :adagrad) do
{h1, w2} = CM.adagrad(w, h, w1, lr)
[{:bias, w2, ir, lr, dr, h1} | learning(rest, rest1, :adagrad)]
end
def learning(
[{:filter, w, {st_h, st_w}, pad, ir, lr, dr, h} | rest],
[{:filter, w1, _, _, _, _, _, _} | rest1],
:adagrad
) do
{h1, w2} = CM.adagrad(w, h, w1, lr)
[{:filter, w2, {st_h, st_w}, pad, ir, lr, dr, h1} | learning(rest, rest1, :adagrad)]
end
def learning([network | rest], [_ | rest1], :adagrad) do
[network | learning(rest, rest1, :adagrad)]
end
defp repeat(size,mini) do
if rem(size,mini) == 0 do
div(size,mini)
else
div(size,mini)+1
end
end
@doc """
```
1st arg network
2nd arg train image list
3rd arg train onehot list
4th arg test image list
5th arg test label list
6th arg loss function (;cross or :square)
7th arg learning method
8th arg minibatch size
9th arg epochs
```
automaticaly save network to temp.ex
"""
def train(network, tr_imag, tr_onehot, ts_imag, ts_label, loss_func, method, m, e) do
IO.puts("preparing data")
train_image = tr_imag |> CM.new() |> CM.standardize()
train_onehot = tr_onehot |> CM.new()
n = repeat(length(tr_onehot), m)
{time, network1} =
:timer.tc(fn ->
train1(
network,
train_image,
train_onehot,
ts_imag,
ts_label,
loss_func,
method,
m,
n,
e,
1
)
end)
save("temp.ex", network1)
IO.puts("time: #{time / 1_000_000} second")
:ok
end
defp train1(network, _, _, _, _, _, _, _, _, 0, _) do
network
end
defp train1(
network,
train_image,
train_onehot,
ts_imag,
ts_label,
loss_func,
method,
m,
n,
epoch,
count
) do
IO.puts("\nepoch #{count}")
network1 = train2(network, train_image, train_onehot, loss_func, method, m, n, n)
{train_image1, train_onehot1} = CM.random_select(train_image, train_onehot, m)
[y | _] = forward(train_image1, network1, [])
loss = CM.loss(y, train_onehot1, loss_func)
IO.puts("random loss = #{loss}")
rate = accuracy(ts_imag, network1, ts_label, m)
IO.puts("accuracy rate = #{rate * 100}%")
train1(
network1,
train_image,
train_onehot,
ts_imag,
ts_label,
loss_func,
method,
m,
n,
epoch - 1,
count + 1
)
end
defp train2(network, _, _, _, _, _, 0, _) do
newline()
network
end
defp train2(network, train_image, train_onehot, loss_func, method, m, n, all) do
{train_image1, train_onehot1} = CM.random_select(train_image, train_onehot, m)
network1 = gradient(train_image1, network, train_onehot1)
network2 = learning(network, network1, method)
rate = (all - n) / all
progress(rate)
train2(network2, train_image, train_onehot, loss_func, method, m, n - 1, all)
end
@doc """
retrain
load network from file and restart learning
"""
def retrain(file, tr_imag, tr_onehot, ts_imag, ts_label, loss_func, method, m, e) do
IO.puts("preparing data")
network = load(file)
train_image = tr_imag |> CM.new() |> CM.standardize()
train_onehot = tr_onehot |> CM.new()
n = div(length(tr_onehot), m)
{time, network1} =
:timer.tc(fn ->
train1(
network,
train_image,
train_onehot,
ts_imag,
ts_label,
loss_func,
method,
m,
n,
e,
1
)
end)
save("temp.ex", network1)
IO.puts("time: #{time / 1_000_000} second")
:ok
end
@doc """
for pre-test
```
1st arg network
2nd arg train image list
3rd arg train onehot list
4th arg test image list
5th arg test label list
6th arg loss function (;cross or :square)
7th arg learning method
8th arg minibatch size
9th arg repeat number
```
automaticaly save network to temp.ex
"""
def try(network, tr_imag, tr_onehot, ts_imag, ts_label, loss_func, method, m, n) do
IO.puts("preparing data")
train_image = tr_imag |> CM.new() |> CM.standardize()
train_onehot = tr_onehot |> CM.new()
{time, network1} =
:timer.tc(fn ->
try1(network, train_image, train_onehot, loss_func, method, m, n)
end)
correct = accuracy(ts_imag, network1, ts_label, m)
IO.puts("learning end")
IO.write("accuracy rate = ")
IO.puts(correct)
IO.inspect("time: #{time / 1_000_000} second")
IO.inspect("-------------")
:ok
end
defp try1(network, train_image, train_onehot, loss_func, method, m, n) do
IO.puts("learning start")
IO.puts("count down: loss:")
network1 = try2(train_image, network, train_onehot, loss_func, method, m, n)
save("temp.ex", network1)
network1
end
defp try2(_, network, _, _, _, _, 0) do
network
end
defp try2(image, network, train, loss_func, method, m, n) do
{image1, train1} = CM.random_select(image, train, m)
network1 = gradient(image1, network, train1)
network2 = learning(network, network1, method)
[y | _] = forward(image1, network2, [])
loss = CM.loss(y, train1, loss_func)
IO.write(n)
IO.write(" ")
IO.puts(loss)
try2(image, network2, train, loss_func, method, m, n - 1)
end
@doc """
retry
load network from file and restart learning
"""
def retry(file, tr_imag, tr_onehot, ts_imag, ts_label, loss_func, method, m, n) do
IO.puts("preparing data")
network = load(file)
train_image = tr_imag |> CM.new() |> CM.standardize()
train_onehot = tr_onehot |> CM.new()
{time, network1} =
:timer.tc(fn ->
try1(network, train_image, train_onehot, loss_func, method, m, n)
end)
correct = accuracy(ts_imag, network1, ts_label, m)
IO.puts("learning end")
IO.write("accuracy rate = ")
IO.puts(correct)
IO.inspect("time: #{time / 1_000_000} second")
IO.inspect("-------------")
:ok
end
@doc """
train for batch. not show accuracy, not show execute time
```
1st arg network
2nd arg train image list
3rd arg train onehot list
4th arg loss function (;cross or :square)
5th arg learning method
6th arg minibatch size
7th arg repeat number
```
automaticaly save network to temp.ex
"""
def batch_train(network, tr_imag, tr_onehot, loss_func, method, m, n) do
IO.puts("batch process")
train_image = tr_imag |> CM.new() |> CM.standardize()
train_onehot = tr_onehot |> CM.new()
batch_train1(network, train_image, train_onehot, loss_func, method, m, n)
end
defp batch_train1(network, train_image, train_onehot, loss_func, method, m, n) do
IO.puts("learning start")
IO.puts("count down: loss:")
network1 = batch_train2(train_image, network, train_onehot, loss_func, method, m, n)
save("temp.ex", network1)
network1
end
defp batch_train2(_, network, _, _, _, _, 0) do
network
end
defp batch_train2(image, network, train, loss_func, method, m, n) do
{image1, train1} = CM.random_select(image, train, m)
network1 = gradient(image1, network, train1)
network2 = learning(network, network1, method)
[y | _] = forward(image1, network2, [])
loss = CM.loss(y, train1, loss_func)
IO.write(n)
IO.write(" ")
IO.puts(loss)
try2(image, network2, train, loss_func, method, m, n - 1)
end
@doc """
calculate accuracy
1st arg list of image
2nd arg network
3rd arg list of label
4th arg mini batch size
"""
def accuracy(image, network, label, m) do
accuracy1(image, network, label, m, length(label), 0)
end
defp accuracy1([], _, [], _, total, correct) do
correct / total
end
defp accuracy1(image, network, label, m, total, correct) do
n = min(length(label), m)
image1 = Enum.take(image, n) |> CM.new()
label1 = Enum.take(label, n)
[y | _] = forward(image1, network, [])
n1 = CM.correct(y, label1)
accuracy1(Enum.drop(image, n), network, Enum.drop(label, n), m, total, correct + n1)
end
@doc """
select random data from image data and train data
size of m. range from 0 to n
and generate tuple of two matrix
"""
def random_select(image, train, m, n) do
random_select1(image, train, [], [], m, n)
end
defp random_select1(_, _, res1, res2, 0, _) do
mt1 = CM.new(res1)
mt2 = CM.new(res2)
{mt1, mt2}
end
defp random_select1(image, train, res1, res2, m, n) do
i = :rand.uniform(n - 1)
image1 = Enum.at(image, i)
train1 = Enum.at(train, i)
random_select1(image, train, [image1 | res1], [train1 | res2], m - 1, n)
end
@doc """
translate from number to onehot-list
iex(1)> Deeppipe.to_onehot(1,9)
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
"""
def to_onehot(x, n) do
to_onehot1(x, n, [])
end
defp to_onehot1(_, -1, res) do
res
end
defp to_onehot1(x, x, res) do
to_onehot1(x, x - 1, [1.0 | res])
end
defp to_onehot1(x, c, res) do
to_onehot1(x, c - 1, [0.0 | res])
end
@doc """
normalize dataset element
normalize(x,bias,div)
```
x + bias / div
e.g. bias = -127, div = 255
0~255 => -0.5~0.5
```
"""
def normalize(x, bias, div) do
Enum.map(x, fn z -> (z + bias) / div end)
end
@doc """
save network to file
"""
def save(file, network) do
network1 = save1(network)
File.write(file, inspect(network1, limit: :infinity))
end
defp save1([]) do
[]
end
defp save1([{:weight, w, ir, lr, dr, v} | rest]) do
[{:weight, CM.to_list(w), ir, lr, dr, CM.to_list(v)} | save1(rest)]
end
defp save1([{:bias, w, ir, lr, dr, v} | rest]) do
[{:bias, CM.to_list(w), ir, lr, dr, CM.to_list(v)} | save1(rest)]
end
defp save1([{:filter, w, {st_h, st_w}, pad, ir, lr, dr, v} | rest]) do
[{:filter, CM.to_list(w), {st_h, st_w}, pad, ir, lr, dr, CM.to_list(v)} | save1(rest)]
end
defp save1([{:function, name} | rest]) do
[{:function, name} | save1(rest)]
end
defp save1([network | rest]) do
[network | save1(rest)]
end
@doc """
load network from file
"""
def load(file) do
Code.eval_file(file) |> elem(0) |> load1
end
defp load1([]) do
[]
end
defp load1([{:weight, w, ir, lr, dr, v} | rest]) do
[{:weight, CM.new(w), ir, lr, dr, CM.new(v)} | load1(rest)]
end
defp load1([{:bias, w, ir, lr, dr, v} | rest]) do
[{:bias, CM.new(w), ir, lr, dr, CM.new(v)} | load1(rest)]
end
defp load1([{:filter, w, {st_h, st_w}, pad, ir, lr, dr, v} | rest]) do
[{:filter, CM.new(w), {st_h, st_w}, pad, ir, lr, dr, CM.new(v)} | load1(rest)]
end
defp load1([{:function, name} | rest]) do
[{:function, name} | load1(rest)]
end
defp load1([network | rest]) do
[network | load1(rest)]
end
@doc """
display network
"""
def print(x) do
cond do
is_number(x) || is_atom(x) ->
:io.write(x)
CM.is_matrix(x) ->
CM.print(x)
CM.is_tensor(x) ->
x |> CM.to_list() |> IO.inspect()
true ->
print1(x)
IO.puts("")
end
end
defp print1([]) do
true
end
defp print1([x | xs]) do
print2(x)
print1(xs)
end
defp print2({:weight, w, _, _, _, _}) do
IO.puts("weight")
CM.print(w)
end
defp print2({:bias, w, _, _, _, _}) do
IO.puts("bias")
CM.print(w)
end
defp print2({:function, name}) do
:io.write(name)
end
defp print2({:filter, w, _, _, _, _, _, _}) do
IO.puts("filter")
CM.print(w)
end
defp print2(x) do
if CM.is_matrix(x) do
CM.print(x)
else
:io.write(x)
IO.puts("")
end
end
@doc """
display newline
"""
def newline() do
IO.puts("")
end
def progress(r) do
size = 50
done = round(size * r)
yet = size - done
done_str = String.duplicate("#", done)
yet_str = String.duplicate(" ", yet)
IO.write("\r[")
IO.write(done_str)
IO.write(yet_str)
IO.write("](#{round(r * 100)}%)")
end
@doc """
download(x)
```
case x
:mnist download and decompress MNIST dataset
:fashon download and decompress Fashion-MNIST dataset
:cifar10 download and decompress CIFAR10 dataset
:iris download iris dataset
```
"""
def download(:mnist) do
Application.ensure_all_started(:inets)
base_url = 'http://yann.lecun.com/exdb/mnist/'
{:ok, resp} =
:httpc.request(:get, {base_url ++ 'train-images-idx3-ubyte.gz', []}, [],
body_format: :binary
)
{{_, 200, 'OK'}, _headers, body} = resp
Mix.shell().cmd("mkdir mnist")
File.write!("mnist/train-images-idx3-ubyte.gz", body)
{:ok, resp} =
:httpc.request(:get, {base_url ++ 'train-labels-idx1-ubyte.gz', []}, [],
body_format: :binary
)
{{_, 200, 'OK'}, _headers, body} = resp
File.write!("mnist/train-labels-idx1-ubyte.gz", body)
{:ok, resp} =
:httpc.request(:get, {base_url ++ 't10k-images-idx3-ubyte.gz', []}, [], body_format: :binary)
{{_, 200, 'OK'}, _headers, body} = resp
File.write!("mnist/t10k-images-idx3-ubyte.gz", body)
{:ok, resp} =
:httpc.request(:get, {base_url ++ 't10k-labels-idx1-ubyte.gz', []}, [], body_format: :binary)
{{_, 200, 'OK'}, _headers, body} = resp
File.write!("mnist/t10k-labels-idx1-ubyte.gz", body)
Mix.shell().cmd("gzip -d mnist/train-images-idx3-ubyte.gz")
Mix.shell().cmd("gzip -d mnist/train-labels-idx1-ubyte.gz")
Mix.shell().cmd("gzip -d mnist/t10k-images-idx3-ubyte.gz")
Mix.shell().cmd("gzip -d mnist/t10k-labels-idx1-ubyte.gz")
:ok
end
def download(:fashion) do
Application.ensure_all_started(:inets)
base_url = 'http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/'
{:ok, resp} =
:httpc.request(:get, {base_url ++ 'train-images-idx3-ubyte.gz', []}, [],
body_format: :binary
)
{{_, 200, 'OK'}, _headers, body} = resp
Mix.shell().cmd("mkdir fashion")
File.write!("fashion/train-images-idx3-ubyte.gz", body)
{:ok, resp} =
:httpc.request(:get, {base_url ++ 'train-labels-idx1-ubyte.gz', []}, [],
body_format: :binary
)
{{_, 200, 'OK'}, _headers, body} = resp
File.write!("fashion/train-labels-idx1-ubyte.gz", body)
{:ok, resp} =
:httpc.request(:get, {base_url ++ 't10k-images-idx3-ubyte.gz', []}, [], body_format: :binary)
{{_, 200, 'OK'}, _headers, body} = resp
File.write!("fashion/t10k-images-idx3-ubyte.gz", body)
{:ok, resp} =
:httpc.request(:get, {base_url ++ 't10k-labels-idx1-ubyte.gz', []}, [], body_format: :binary)
{{_, 200, 'OK'}, _headers, body} = resp
File.write!("fashion/t10k-labels-idx1-ubyte.gz", body)
Mix.shell().cmd("gzip -d fashion/train-images-idx3-ubyte.gz")
Mix.shell().cmd("gzip -d fashion/train-labels-idx1-ubyte.gz")
Mix.shell().cmd("gzip -d fashion/t10k-images-idx3-ubyte.gz")
Mix.shell().cmd("gzip -d fashion/t10k-labels-idx1-ubyte.gz")
:ok
end
def download(:iris) do
Application.ensure_all_started(:inets)
base_url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/'
{:ok, resp} = :httpc.request(:get, {base_url ++ 'iris.data', []}, [], body_format: :binary)
{{_, 200, 'OK'}, _headers, body} = resp
Mix.shell().cmd("mkdir iris")
File.write!("iris/iris.data", body)
:ok
end
def download(:cifar10) do
IO.puts("wait few minutes")
Application.ensure_all_started(:inets)
base_url = 'https://www.cs.toronto.edu/~kriz/'
{:ok, resp} =
:httpc.request(:get, {base_url ++ 'cifar-10-binary.tar.gz', []}, [], body_format: :binary)
{{_, 200, 'OK'}, _headers, body} = resp
File.write!("cifar-10-binary.tar.gz", body)
Mix.shell().cmd("tar xzvf cifar-10-binary.tar.gz")
Mix.shell().cmd("rm *.tar.gz")
:ok
end
@doc """
numerical_gradient(ts,network,train)
numerical gradient for debug
1st arg input tensor
2nd arg network
3rd arg train matrix
"""
def numerical_gradient(x, network, t) do
numerical_gradient1(x, network, t, [], [])
end
defp numerical_gradient1(_, [], _, _, res) do
Enum.reverse(res)
end
defp numerical_gradient1(x, [{:bias, w, ir, lr, dr, v} | rest], t, before, res) do
# IO.puts("ngrad bias")
w1 = numerical_gradient_bias(x, w, t, before, {:bias, w, ir, lr, dr, v}, rest)
numerical_gradient1(x, rest, t, [{:bias, w, ir, lr, dr, v} | before], [
{:bias, w1, ir, lr, dr, v} | res
])
end
defp numerical_gradient1(x, [{:weight, w, ir, lr, dr, v} | rest], t, before, res) do
# IO.puts("ngrad wight")
w1 = numerical_gradient_matrix(x, w, t, before, {:weight, w, ir, lr, dr, v}, rest)
numerical_gradient1(x, rest, t, [{:weight, w1, ir, lr, dr, v} | before], [
{:weight, w1, ir, lr, dr, v} | res
])
end
defp numerical_gradient1(
x,
[{:filter, w, {st_h, st_w}, pad, ir, lr, dr, v} | rest],
t,
before,
res
) do
# IO.puts("ngrad filter")
w1 =
numerical_gradient_filter(
x,
w,
t,
before,
{:filter, w, {st_h, st_w}, pad, ir, lr, dr, v},
rest
)
numerical_gradient1(x, rest, t, [{:filter, w, {st_h, st_w}, pad, ir, lr, dr, v} | before], [
{:filter, w1, {st_h, st_w}, pad, ir, lr, dr, v} | res
])
end
defp numerical_gradient1(x, [{:analizer, n} | rest], t, before, res) do
# IO.puts("FD analizer")
CM.analizer(x, n)
numerical_gradient1(x, rest, t, [{:analizer, n} | before], [
{:analizer, n} | res
])
end
defp numerical_gradient1(x, [y | rest], t, before, res) do
# IO.puts("ngrad else")
numerical_gradient1(x, rest, t, [y | before], [y | res])
end
# calc numerical gradient of bias
defp numerical_gradient_bias(x, w, t, before, now, rest) do
{_, c} = Cumatrix.size(w)
for r1 <- 1..1 do
for c1 <- 1..c do
numerical_gradient_bias1(x, t, r1, c1, before, now, rest)
end
end
|> CM.new()
end
defp numerical_gradient_bias1(x, t, r, c, before, {:bias, w, ir, lr, dr, v}, rest) do
delta = 0.0001
w1 = CM.add_diff(w, r, c, delta)
network0 = Enum.reverse(before) ++ [{:bias, w, ir, lr, dr, v}] ++ rest
network1 = Enum.reverse(before) ++ [{:bias, w1, ir, lr, dr, v}] ++ rest
[y0 | _] = forward(x, network0, [])
[y1 | _] = forward(x, network1, [])
(CM.loss(y1, t, :cross) - CM.loss(y0, t, :cross)) / delta
end
# calc numerical gradient of matrix
defp numerical_gradient_matrix(x, w, t, before, now, rest) do
{r, c} = Cumatrix.size(w)
for r1 <- 1..r do
for c1 <- 1..c do
numerical_gradient_matrix1(x, t, r1, c1, before, now, rest)
end
end
|> CM.new()
end
defp numerical_gradient_matrix1(x, t, r, c, before, {:weight, w, ir, lr, dr, v}, rest) do
delta = 0.0001
w1 = CM.add_diff(w, r, c, delta)
network0 = Enum.reverse(before) ++ [{:weight, w, ir, lr, dr, v}] ++ rest
network1 = Enum.reverse(before) ++ [{:weight, w1, ir, lr, dr, v}] ++ rest
[y0 | _] = forward(x, network0, [])
[y1 | _] = forward(x, network1, [])
(CM.loss(y1, t, :cross) - CM.loss(y0, t, :cross)) / delta
end
# calc numerical gradient of filter
defp numerical_gradient_filter(x, w, t, before, now, rest) do
{n, c, h, w} = Cumatrix.size(w)
for n1 <- 1..n do
for c1 <- 1..c do
for h1 <- 1..h do
for w1 <- 1..w do
numerical_gradient_filter1(x, t, n1, c1, h1, w1, before, now, rest)
end
end
end
end
|> CM.new()
end
defp numerical_gradient_filter1(
x,
t,
n,
c,
h,
w,
before,
{:filter, m, {st_h, st_w}, pad, ir, lr, dr, v},
rest
) do
delta = 0.0001
m1 = CM.add_diff(m, n, c, h, w, delta)
network0 = Enum.reverse(before) ++ [{:filter, m, {st_h, st_w}, pad, ir, lr, dr, v}] ++ rest
network1 = Enum.reverse(before) ++ [{:filter, m1, {st_h, st_w}, pad, ir, lr, dr, v}] ++ rest
[y0 | _] = forward(x, network0, [])
[y1 | _] = forward(x, network1, [])
(CM.loss(y1, t, :cross) - CM.loss(y0, t, :cross)) / delta
end
end