์ฌ์ ๋ฐํ ์๋ฃ: https://github.com/soumith/talks/blob/master/gtc2015/slides.pdf?raw=true
ํ ์น๋ Lua[JIT]์ ๊ธฐ๋ฐ์ ๋ ๊ณผํ ๊ณ์ฐ ํ๋ ์์ํฌ์ ๋๋ค. ํ ์น๋ ๊ฐ๋ ฅํ CPU์ ์ฟ ๋ค(CUDA) ์ฒ๋ฆฌ ๋ฅ๋ ฅ์ด ์์ต๋๋ค.
ํ ์น์ ๊ฐ์ :
http://torch.ch
https://github.com/torch/torch7/wiki/Cheatsheet
local
ํค์๋๊ฐ ์ฌ์ฉ๋์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ผ๋ก ์ ์ญ(global
)์{}
. ์ด๊ฒ์ ํด์ ํ
์ด๋ธ๊ณผ ๋ฐฐ์ด์ ์ด์ค์ ์ญํ ์ ํจ.foo:bar()
๋ foo.bar(foo)
์ ๊ฐ์.a = 'hello'
print(a)
b = {}
b[1] = a
print(b)
b[2] = 30
for i=1,#b do -- '#'๋ ๋ฃจ์์์ ์์์ ๊ฐ์๋ฅผ ๋ฆฌํดํ๋ ์ฐ์ฐ์์.
print(b[i])
end
a = torch.Tensor(5,3) -- 5x3 ํ๋ ฌ ์์ฑ, ์ด๊ธฐํ๋์ง ์์.
a = torch.rand(5,3)
print(a)
b=torch.rand(3,4)
-- ํ๋ ฌ-ํ๋ ฌ ๊ณฑ: ๋ฌธ๋ฒ 1
a*b
-- ํ๋ ฌ-ํ๋ ฌ ๊ณฑ: ๋ฌธ๋ฒ 2
torch.mm(a,b)
-- ํ๋ ฌ-ํ๋ ฌ ๊ณฑ: ๋ฌธ๋ฒ 3
c=torch.Tensor(5,4)
c:mm(a,b) -- a*b ๊ฒฐ๊ณผ๋ฅผ c์ ์ ์ฅ
ํ ์๋ค์ :cuda ํจ์๋ฅผ ์ฌ์ฉํ์ฌ GPU๋ก ์ฎ๊ฒจ์ง ์ ์์ต๋๋ค.
require 'cutorch';
a = a:cuda()
b = b:cuda()
c = c:cuda()
c:mm(a,b) -- GPU์์ ๊ณ์ฐ๋จ
function addTensors(a,b)
return a -- a๋ก ๊ณ ์
end
a = torch.ones(5,2)
b = torch.Tensor(3,4):fill(4)
print(addTensors(a,b))
ํ ์น์์ ์ ๊ฒฝ๋ง์ nn
ํจํค์ง๋ฅผ ์ฌ์ฉํ์ฌ ๋ง๋ค ์ ์์ต๋๋ค.
require 'nn';
๋ชจ๋
์ ์ ๊ฒฝ๋ง์ ๊ตฌ์ถํ๊ธฐ ์ํ ์์(building block)์
๋๋ค. ๊ฐ ๋ชจ๋์ ๊ทธ ์์ฒด๋ก ์ ๊ฒฝ๋ง์
๋๋ค. ๋ณต์กํ ์ ๊ฒฝ๋ง์ ๋ง๋ค๊ธฐ ์ํด, ๊ฐ ๋ชจ๋์ ๋ค๋ฅธ ์ ๊ฒฝ๋ง๊ณผ ์ปจํ
์ด๋
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฐํฉ๋ ์ ์์ต๋๋ค.
์ด๋ฅผํ ๋ฉด, ์ซ์ ์์๋ค์ ๋ถ๋ฅํ๋ ์ด ๋คํธ์ํฌ๋ฅผ ๋ณด์ญ์์ค:
์ด๊ฒ์ ๋จ์ํ ํผ๋ํฌ์๋ ๋ง์ ๋๋ค. ์ด ๋คํธ์ํฌ๋ ํ ์ ๋ ฅ์ ๋ฐ์, ๊ทธ๊ฒ์ ์ฌ๋ฌ ์ธต์ ๊ฑธ์ณ ์ ํํ๊ณ , ๋ง์ง๋ง์ ์ถ๋ ฅ์ ๋ด๋ณด๋ ๋๋ค.
์ด๋ฐ ๋คํธ์ํฌ์ ์ปจํ
์ด๋๋ nn.Sequential
์
๋๋ค.
net = nn.Sequential()
net:add(nn.SpatialConvolution(1, 6, 5, 5)) -- 1 ์
๋ ฅ ์์ ์ฑ๋, 6 ์ถ๋ ฅ ์ฑ๋, 5x5 ์ปจ๋ณผ๋ฃจ์
์ปค๋
net:add(nn.SpatialMaxPooling(2,2,2,2)) -- 2x2 ์๋์ฐ๋ค์ ํตํด ๋ณด๋ ๋งฅ์ค ํ๋ง(max-pooling) ์ฐ์ฐ ๊ทธ๋ฆฌ๊ณ ๊ทธ ๊ฐ ์๋์ฐ์์ ์ต๋๊ฐ์ ์ฐพ์.
net:add(nn.SpatialConvolution(6, 16, 5, 5))
net:add(nn.SpatialMaxPooling(2,2,2,2))
net:add(nn.View(16*5*5)) -- 16x5x5์ 3 ์ฐจ์ ํ
์๋ฅผ 16*5*5์ 1 ์ฐจ์ ํ
์๋ก ๋ณํ
net:add(nn.Linear(16*5*5, 120)) -- ์์ ์ฐ๊ฒฐ๋(fully connected) ์ธต (์
๋ ฅ๊ณผ ๊ฐ์ค์น๋ค ์ฌ์ด์ ํ๋ ฌ ๊ณฑ)
net:add(nn.Linear(120, 84))
net:add(nn.Linear(84, 10)) -- 10 ์ ์ถ๋ ฅ ์ธต์ ๋
ธ๋ ์.
net:add(nn.LogSoftMax()) -- ๊ทธ ์ถ๋ ฅ์ ๋ก๊ทธ ํ๋ฅ ๋ก ๋ณํ. ๋ถ๋ฅ ๋ฌธ์ ๋ค์ ์ ์ฉํจ.
print('Lenet5\n' .. net:__tostring());
์๋ ๊ทธ๋ฆผ์ nn ์ปจํ ์ด๋์ ๋ค๋ฅธ ์๋ฅผ ๋ณด์ฌ์ค๋๋ค.
๋ชจ๋ ํ ์น์ ์ ๊ฒฝ๋ง ๋ชจ๋์ ์๋ ๋ฏธ๋ถ ๊ธฐ๋ฅ์ ๊ฐ์ง๋๋ค. :forward(input)
ํจ์๋ ํ ์ฃผ์ด์ง ์
๋ ฅ์์ ํ ์ ๊ฒฝ๋ง ์ถ๋ ฅ์ ๊ณ์ฐํฉ๋๋ค. :backward(input, gradient)
ํจ์๋ ์ฐ์ ๋ฒ์น(chain rule)์ผ๋ก ๊ทธ ๋ง์ ์๋ ๊ฐ ๋ด๋ฐ์ ์ญ์ ํ ๋ฏธ๋ถ๊ฐ์ ๊ณ์ฐํฉ๋๋ค.
input = torch.rand(1,32,32) -- ํ ๋๋ค ํ
์๋ฅผ ๋คํธ์ํฌ ์
๋ ฅ์ผ๋ก ์ ๋ฌ
output = net:forward(input)
print(output)
net:zeroGradParameters() -- ๋คํธ์ํฌ์ ๊ธฐ์ธ๊ธฐ(gradient) ๋ฒํผ๋ค์ 0์ผ๋ก ์ด๊ธฐํ (๋์ค์ ๋ค์ ๋์ด)
gradInput = net:backward(input, torch.rand(10))
print(#gradInput)
ํ ๋ชจ๋ธ์ด ๋ฌด์ธ๊ฐ๋ฅผ ํ๋๋ก ๊ฐ๋ฅด์น๊ณ ์ถ๋ค๋ฉด, ๊ทธ ๋ชจ๋ธ์๊ฒ ์ด๋ป๊ฒ ํ๋ ๊ฒ์ด ์ํ๋ ๊ฒ์ธ์ง ํผ๋๋ฐฑ์ ์ฃผ์ด์ผ ํฉ๋๋ค. ๊ทธ ๋ชจ๋ธ ์ฑ๋ฅ์ ์ธก์ ํ๋ ๊ฐ๊ด์ ์์น๋ฅผ ๊ณ์ฐํ๋ ํจ์๋ฅผ __์์ค ํจ์__๋ผ ๋ถ๋ฆ ๋๋ค.
์ ํ์ ์ธ ์์ค ํจ์๋ ๋ชจ๋ธ ์ถ๋ ฅ๊ณผ ์ ๋ต์ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ๊ทธ ๋ชจ๋ธ์ ์ฑ๋ฅ์ ์ ๋ํํ๋ ๊ฐ์ ๊ณ์ฐํฉ๋๋ค.
๋ชจ๋ธ์ ๋ ์ ์ ์์ค์ ๊ฐ๋๋ก ์์ ์ ๊ณ ์ณ๋๊ฐ๋๋ค.
ํ ์น์์, ์์ค ํจ์๋ ์ ๊ฒฝ๋ง ๋ชจ๋์ฒ๋ผ ๊ตฌํ๋๊ณ ์๋ ๋ฏธ๋ถ ๊ธฐ๋ฅ์ ๊ฐ์ง๋๋ค. ์์ค ํจ์์๋ ๋ ํจ์๊ฐ ์์ต๋๋ค. forward(input, target)
์ backward(input, target)
๊ฐ ๊ทธ๊ฒ์
๋๋ค.
์ด๋ฅผํ ๋ฉด,
criterion = nn.ClassNLLCriterion() -- ๋ค๋ถ๋ฅ ๋ถ๋ฅ๋ฅผ ์ํ negative log-likelihood criterion
criterion:forward(output, 3) -- ์ ๋ต์ด ๋ถ๋ฅ ๋๋ฒ 3์ด๋ผ๊ณ ํฉ์๋ค.
gradients = criterion:backward(output, 3)
gradInput = net:backward(input, gradients)
ํ ์ ๊ฒฝ๋ง ์ธต์ ํ์ตํ ์ ์๋ ๋งค๊ฐ๋ณ์๋ค์ ๊ฐ์ง ์ ์๋๊ฐ ์๋๊ฐ.
ํ ์ปจ๋ณผ๋ฃจ์ ์ธต์ ๊ทธ๊ฒ์ ์ปจ๋ณผ๋ฃจ์ ์ปค๋๋ค์ ํ์ตํฉ๋๋ค. ๋ชฉ์ ์ ์ ๋ ฅ ๋ฐ์ดํฐ์ ์ ์ํ์ฌ ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ๊ฐ ํ๋ฆฌ๊ฒ ํ๋ ๊ฒ์ ๋๋ค. ๋งฅ์คํ๋ง ์ธต์๋ ํ์ตํ ์ ์๋ ๋งค๊ฐ๋ณ์๋ค์ด ์์ต๋๋ค. ๋งฅ์คํ๋ง ์ธต์ ๋จ์ง ๊ทธ๊ฒ์ ๋ก์ปฌ ์๋์ฐ๋ค์์ ์ต๋๊ฐ์ ์ฐพ๋ ์ญํ ๋ง ํฉ๋๋ค.
ํ ์น์์ ํ์ตํ ์ ์๋ ๊ฐ์ค์น(weight)๋ค์ ๊ฐ๋ ํ ์ธต์ ๋ณดํต .weight (๊ทธ๋ฆฌ๊ณ ์ ํ์ ์ผ๋ก, .bias) ํ๋๋ฅผ ๊ฐ์ง ๊ฒ์ ๋๋ค.
m = nn.SpatialConvolution(1,3,2,2) -- ์ ๊ฐ์ 2x2 ์ปค๋๋ค ํ์ต
print(m.weight) -- ์ด๊ธฐ์, ๊ฐ์ค์น๋ค์ ๋๋คํ๊ฒ ์ด๊ธฐํ๋จ
print(m.bias) -- ํ ์ปจ๋ณผ๋ฃจ์
์ธต์์ ์ด ์ฐ์ฐ์: output = convolution(input,weight) + bias
ํ๋์ ํ์ต ๊ฐ๋ฅ ์ธต์๋ ๋ ๊ฐ์ ๋๋ค๋ฅธ ๋ค๋ฅธ ์ค์ํ ํ๋๊ฐ ์์ต๋๋ค. gradWeight์ gradBias๊ฐ ๊ทธ๊ฒ์ ๋๋ค. gradWeight๋ ๊ทธ ์ธต์ ๊ฐ ๊ฐ์ค์น์ ๋ํ ๋ฏธ๋ถ๊ฐ๋ค์ ๋์ ํฉ๋๋ค. gradBias๋ ๊ทธ ์ธต์ ๊ฐ bias์ ๋ํ ๋ฏธ๋ถ๊ฐ๋ค์ ๋์ ํฉ๋๋ค.
๋ง์ฝ ์ถ๊ณ์ ๊ฒฝ์ฌ ๊ฐํ(Stochastic Gradient Descent, SGD)๊ฐ ์ฌ์ฉ๋๋ค๋ฉด ๋คํธ์ํฌ๋ ๋ณดํต ์ 1๋ก ๊ฐฑ์ ๋ฉ๋๋ค:
weight = weight + learningRate * gradWeight [์ 1]
์ด ์์ ์๊ฐ์ด ์ง๋จ์๋ฐ๋ผ ๋คํธ์ํฌ ๊ฐ์ค์น๋ค์ ์ถ๋ ฅ ์์ค์ด ๊ฐ์ํ๋๋ก ์กฐ์ ํฉ๋๋ค.
์ด์ ๋น ์ง ํ ์กฐ๊ฐ์ ๋ํด ๋ ผ์ํ ์๊ฐ์ ๋๋ค. ๋๊ฐ ์ ๊ฒฝ๋ง์ ๊ฐ ์ธต์ ๋ฐฉ๋ฌธํ๊ณ ์ 1์ ๋ฐ๋ผ ๊ฐ์ค์น๋ค์ ๊ฐฑ์ ํ ๊น์?
์ฌ๋ฌ ๋ต์ด ์์ง๋ง, ์ฐ๋ฆฌ๋ ๊ฐ์ฅ ๋จ์ํ ๋ต์ ์ฌ์ฉํ๊ฒ ์ต๋๋ค. ์ฆ, ๋จ์ํ ์ ๊ฒฝ๋ง ๋ชจ๋์ ํ์ฌ๋ SGD ํ๋ จ๊ธฐ(trainer)๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค: nn.StochasticGradient.
SGD ํ๋ จ๊ธฐ๋ :train(dataset) ํจ์๋ฅผ ๊ฐ์ง๋๋ค. ๊ทธ ํจ์๋ ๋จ์ํ ๋ฐ์ดํฐ์ธํธ(dataset)๋ฅผ ์ ๋ ฅ๋ฐ์ ๊ทธ ๋ฐ์ดํฐ์ธํธ ์์ ๋ค๋ฅธ ์ํ๋ค์ ๋คํธ์ํฌ์ ๋ณด์ฌ์ค์ผ๋ก์จ ๋คํธ์ํฌ๋ฅผ ํ๋ จํฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก, ์์, ๋ฌธ์, ์ค๋์ค ๋๋ ๋น๋์ค ๋ฐ์ดํฐ๋ฅผ ๋ค๋ค์ผ ํ ๋, ๊ทธ ๋ฐ์ดํฐ๋ฅผ torch.Tensor ๋๋ ๋ฃจ์ ํ ์ด๋ธ๋ก ์ ์ฌํ๊ธฐ ์ํด ๋ค์ ํ์ค ํจ์๋ค์ด ์ฌ์ฉ๋ ์ ์์ต๋๋ค: image.load ๋๋ audio.load.
์ฐ๋ฆฌ์ ๋คํธ์ํฌ๋ฅผ ํ๋ จํ๊ธฐ ์ํด ๊ฐ๋จํ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํด๋ด ์๋ค.
์ฐ๋ฆฌ๋ CIFAR-10 ๋ฐ์ดํฐ์ธํธ๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. CIFAR-10์ 10๊ฐ์ ๋ถ๋ฅ(class)๋ฅผ ๊ฐ์ง๋๋ค: 'airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'.
CIFAR-10 ์์์ ํฌ๊ธฐ๋ 3x32x32์ ๋๋ค. ์ฆ, 32x32 ํฝ์ ํฌ๊ธฐ์ 3 ์ฑ๋ ์ปฌ๋ฌ ์์๋ค์ ๋๋ค.
CIFAR-10์๋ ์ด 5๋ง ๊ฐ ํ๋ จ ์์๊ณผ 1๋ง ๊ฐ ์ํ ์์์ด ์์ต๋๋ค.
์ด์ ์ฐ๋ฆฌ์ ์ฒซ ํ ์น ์ ๊ฒฝ๋ง์ ํ๋ จํ๊ธฐ ์ํ ๋ค์ฏ ๋จ๊ณ๋ฅผ ๋จ๊ฒจ๋๊ณ ์์ต๋๋ค
1. ๋ฐ์ดํฐ ๋ก๋ ๋ฐ ์ ๊ทํ
์ค๋, ์๊ฐ ์ ์ฝ์ ์ํด, ์ฐ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ 4์ฐจ์ ํ ์น ByteTensor๋ก ๋ฏธ๋ฆฌ ์ค๋นํ์์ต๋๋ค. ํ๋ จ ๋ฐ์ดํฐ ํฌ๊ธฐ๋ 10000x3x32x32์ด๊ณ ์ํ ๋ฐ์ดํฐ์ ํฌ๊ธฐ๋ 10000x3x32x32์ ๋๋ค. ๊ทธ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ์ฌ ์กฐ์ฌํด๋ด ์๋ค.
os.execute('wget -c https://s3.amazonaws.com/torch7/data/cifar10torchsmall.zip')
os.execute('unzip cifar10torchsmall.zip')
trainset = torch.load('cifar10-train.t7')
testset = torch.load('cifar10-test.t7')
classes = {'airplane', 'automobile', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck'}
print(trainset)
print(#trainset.data)
์ฌ๋ฏธ๋ฅผ ์ํด, ์์ ํ๋๋ฅผ ๋์๋ด ์๋ค:
itorch.image(trainset.data[100]) -- ๋ฐ์ดํฐ์ธํธ ์์ 100๋ฒ ์งธ ์์์ ๋์คํ๋ ์ด
print(classes[trainset.label[100]])
์ด์ , ๋ฐ์ดํฐ์ธํธ๊ฐ __nn.StochasticGradient__์ ์ฌ์ฉ๋ ์ ์๋๋ก ์ค๋นํ๊ธฐ ์ํด, ๋ฌธ์์ ๋ฐ๋ผ ๋ช ๊ฐ์ง ํ ์ผ์ด ์์ต๋๋ค.
์ด ๋์ ๋ค์ ๋ช ๋ น์ด๋ก ์ํ๋ ์ ์์ต๋๋ค.
-- ์ง๊ธ์ setmetatable์ ๋ฌด์ํ์ญ์์ค, ์ด ํํ ๋ฆฌ์ผ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ ํน์ฑ์ด๊ธฐ ๋๋ฌธ์
๋๋ค. setmetatable์ ์ธ๋ฑ์ค ์ฐ์ฐ์๋ฅผ ์
ํ
ํฉ๋๋ค.
setmetatable(trainset,
{__index = function(t, i)
return {t.data[i], t.label[i]}
end}
);
trainset.data = trainset.data:double() -- ๋ฐ์ดํฐ๋ฅผ ByteTensor์์ DoubleTensor๋ก ๋ณํํฉ๋๋ค.
function trainset:size()
return self.data:size(1)
end
print(trainset:size()) -- ๋จ์ง ํ
์คํธ ๋ชฉ์
print(trainset[33]) -- 33๋ฒ ์ํ ๋ก๋.
itorch.image(trainset[33][1])
(์ผ๋ฐ์ ์ธ ๋ฐ์ดํฐ ๊ณผํ ๋๋ ๊ธฐ๊ณ ํ์ต์) ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ์์ ๊ฐ์ฅ ์ค์ํ ๊ฒ ์ค ํ๋๋ ๊ทธ ๋ฐ์ดํฐ๊ฐ ํ๊ท ์ด 0์ด๊ณ ํ์ค ํธ์ฐจ๊ฐ 1์ด ๋๋๋ก ๋ง๋๋ ๊ฒ์ ๋๋ค.
๊ทธ ์ผ์ ์ด ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ๋ง์ง๋ง ๋จ๊ณ๋ก ํด๋ด ์๋ค.
๊ทธ๊ฒ์ ํ๊ธฐ ์ํด, ํ ์ ์ธ๋ฑ์ฑ ์ฐ์ฐ์๋ฅผ ์๊ฐํฉ๋๋ค. ํ ์ ์ธ๋ฑ์ฑ ์ฐ์ฐ์๋ ๋ค์ ์์ฒ๋ผ ์ฌ์ฉ๋ฉ๋๋ค:
redChannel = trainset.data[{ {}, {1}, {}, {} }] -- ์ด๊ฒ์ {๋ชจ๋ ์์๋ค, ์ฒซ ๋ฒ์งธ ์ฑ๋, ๋ชจ๋ ์์ง ํฝ์
๋ค, ๋ชจ๋ ์ํ ํฝ์
๋ค}์ ์ ํํฉ๋๋ค.
print(#redChannel)
์ด ์ธ๋ฑ์ฑ ์ฐ์ฐ์์์, ์ฒ์์ ___[{ }]___๋ก ์์ํฉ๋๋ค. ์ด ์ฐ์ฐ์๋ ํ ์ฐจ์ ์์ ๋ชจ๋ ์์(element)๋ค์ ๋ฆฌํดํฉ๋๋ค. ๋ฐ๋ฉด, ___{i}___ ์ฐ์ฐ์๋ ํ ์ฐจ์์์ ํน์ ํ ___i___ ๋ฒ์งธ ์์๋ฅผ ๋ฆฌํดํฉ๋๋ค. ___{i1, i2}___ ์ฐ์ฐ์๋ ___i1___ ๋ฒ์งธ์์ ___i2___ ๋ฒ์งธ ์์๋ค์ ๋ฆฌํดํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ___{3,5}___๋ 3, 4, 5๋ฒ์งธ ์์๋ค์ ๋ฆฌํดํฉ๋๋ค.
์ฐ์ต: ๋ฐ์ดํฐ์ 150 ๋ฒ์งธ์์ 300๋ฒ์งธ ์์๋ค์ ์ ํํด๋ณด์ธ์.
-- ์ฌ๊ธฐ์ ์ฝ๋๋ฅผ ์ ๊ณ ์คํํด ๋ณด์ธ์.
๋ค์ ํ๊ท ์ฐจ๊ฐ(subtraction)๊ณผ ํ์ค ํธ์ฐจ ๊ธฐ๋ฐ ์ค์ผ์ผ๋ง์ผ๋ก ๋์๊ฐ์, ๊ทธ ์ฐ์ฐ์ ์์์ ๋ฐฐ์ด ์ธ๋ฑ์ค ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ฉด ์ฝ์ต๋๋ค:
mean = {} -- ํ๊ท ์ ์ ์ฅํ๊ธฐ ์ํ ๊ณต๊ฐ, ํ
์คํธ์ธํธ๋ฅผ ์ ๊ทํํ๊ธฐ ์ํด ์ฌ์ฉ๋ ์์
stdv = {} -- ํ์ค ํธ์ฐจ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ์ฌ์ฉ๋ ์์
for i=1,3 do -- ๊ฐ ์์ ์ฑ๋์ ๋ํด
mean[i] = trainset.data[{ {}, {i}, {}, {} }]:mean() -- ํ๊ท ์ถ์
print('Channel ' .. i .. ', Mean: ' .. mean[i])
trainset.data[{ {}, {i}, {}, {} }]:add(-mean[i]) -- ํ๊ท ๋นผ๊ธฐ
stdv[i] = trainset.data[{ {}, {i}, {}, {} }]:std() -- ํ์ค ํธ์ฐจ ์ถ์
print('Channel ' .. i .. ', Standard Deviation: ' .. stdv[i])
trainset.data[{ {}, {i}, {}, {} }]:div(stdv[i]) -- ํ์ค ํธ์ฐจ ์ค์ผ์ผ๋ง
end
์ด์ ์ฐ๋ฆฌ์ ํ๋ จ ๋ฐ์ดํฐ๊ฐ ์ ๊ทํ๋์ด ์ฌ์ฉ๋ ์ค๋น๊ฐ ๋์์ต๋๋ค.
__ 2. ์ ๊ฒฝ๋ง ์ ์__
์ฐ์ต: ์ ์ ๊ฒฝ๋ง(Neural Networks) ์น์ ์์ ๊ธฐ์กด 1 ์ฑ๋ ์ ๊ฒฝ๋ง ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ 3 ์ฑ๋ ์์๋ค์ ๋ง๋๋ก ์์ ํด๋ณด์ญ์์ค. ํํธ: ์ฒซ ๋ฒ์งธ ์ธต์์ ์ซ์ 1๋ง 3์ผ๋ก ๋ฐ๊พธ๋ฉด ๋ฉ๋๋ค.
์ ๋ต:
net = nn.Sequential()
net:add(nn.SpatialConvolution(3, 6, 5, 5)) -- 3 ์
๋ ฅ ์์ ์ฑ๋, 6 ์ถ๋ ฅ ์ฑ๋, 5x5 ์ปจ๋ณผ๋ฃจ์
์ปค๋
net:add(nn.SpatialMaxPooling(2,2,2,2)) -- 2x2 ์๋์ฐ๋ค์ ํตํด ๋ณด๋ฉด์ ์ต๋๊ฐ์ ์ฐพ๋ ๋งฅ์คํ๋ง ์ฐ์ฐ
net:add(nn.SpatialConvolution(6, 16, 5, 5))
net:add(nn.SpatialMaxPooling(2,2,2,2))
net:add(nn.View(16*5*5)) -- 16x5x5 3 ์ฐจ์ ํ
์๋ฅผ 16*5*5 1์ฐจ์ ํ
์๋ก ๋ณํ
net:add(nn.Linear(16*5*5, 120)) -- ์์ ์ฐ๊ฒฐ ์ธต(fully connected layer) (์
๋ ฅ๊ณผ ๊ฐ์ค์น๋ค ์ฌ์ด์ ํ๋ ฌ ๊ณฑ)
net:add(nn.Linear(120, 84))
net:add(nn.Linear(84, 10)) -- 10์ ๋คํธ์ํฌ ์ถ๋ ฅ์ ๊ฐ์
net:add(nn.LogSoftMax()) -- ์ถ๋ ฅ์ ๋ก๊ทธ ํ๋ฅ ๋ก ๋ณํ. ๋ถ๋ฅ ๋ฌธ์ ์ ์ ์ฉํจ.
3. ์์ค ํจ์ ์ ์
๋ก๊ทธ-์ฐ๋(log-likelihood)๋ฅผ ์ฌ์ฉํด๋ด ์๋ค. ์ด๊ฒ์ ๋๋ถ๋ถ์ ๋ถ๋ฅ ๋ฌธ์ ์ ์ ํฉํฉ๋๋ค.
criterion = nn.ClassNLLCriterion()
4. ์ ๊ฒฝ๋ง ํ๋ จ
์ฌ๊ธฐ์๋ถํฐ ์ฌ๋ฏธ์์ด์ง๊ธฐ ์์ํฉ๋๋ค. ์ฐ์ nn.StochasticGradient ๊ฐ์ฒด๋ฅผ ์ ์ํฉ์๋ค. ๊ทธ ๋ค์ ์ฐ๋ฆฌ ๋ฐ์ดํฐ์ธํธ๋ฅผ ๊ทธ ๊ฐ์ฒด์ ___:train___ ํจ์์ ๋ฃ์ ๊ฒ์ ๋๋ค.
trainer = nn.StochasticGradient(net, criterion)
trainer.learningRate = 0.001
trainer.maxIteration = 5 -- ํ๋ จ์ ์ํด 5 ์ํฌํฌ(epoch)๋ง ๋ฐ๋ณต.
trainer:train(trainset)
5. ๋คํธ์ํฌ ์ํ, ์ ํ๋ ์ถ๋ ฅ
์ฐ๋ฆฌ๋ ํ๋ จ ๋ฐ์ดํฐ์ธํธ์ ๋ํด 2 pass๋ค์ ์ํ ๋คํธ์ํฌ๋ฅผ ํ๋ จํ์์ต๋๋ค. (์ญ์ ์ฃผ: pass๊ฐ ๋ฌด์จ ๋ป์ผ๊น์?) ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ๊ทธ ๋คํธ์ํฌ๊ฐ ์ ๋๋ก ํ์ต๋์๋์ง ํ์ธํ ํ์๊ฐ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ ํ์ธ์ ๋คํธ์ํฌ ์ถ๋ ฅ์ผ๋ก ๋์ค๋ ๋ถ๋ฅ ๋ ์ด๋ธ๊ณผ ์ ๋ต๊ณผ ๋น๊ตํจ์ผ๋ก์จ ํฉ๋๋ค. ๋ง์ฝ ๋คํธ์ํฌ ์์ธก์ด ์ ํํ๋ฉด, ์ฐ๋ฆฌ๋ ๊ทธ ์ํ์ ๋ฐ๋ฅธ ์์ธก ๋ชฉ๋ก์ ์ถ๊ฐํฉ๋๋ค.
์ข์ต๋๋ค, ์ฒซ ๋จ๊ณ์ ๋๋ค. ์ต์ํด์ง๊ธฐ ์ํด ์ํ ์งํฉ์ ํ ์์์ ๋์๋ด ์๋ค.
print(classes[testset.label[100]])
itorch.image(testset.data[100])
ํ๋ จ ๋ฐ์ดํฐ์ ํ๊ท ๊ณผ ํ์ค ํธ์ฐจ๋ฅผ ๊ณ์ฐํด ๋์์ผ๋ฏ๋ก, ํ๋ จ ๋ฐ์ดํฐ์ ํ๊ท ๊ณผ ํ์ค ํธ์ฐจ๋ก ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ๊ทํ ํด๋ด ์๋ค.
testset.data = testset.data:double() -- Byte tensor๋ฅผ Double tensor๋ก ๋ณํ
for i=1,3 do -- ๊ฐ ์์ ์ฑ๋์ ๋ํด
testset.data[{ {}, {i}, {}, {} }]:add(-mean[i]) -- ํ๊ท ๋นผ๊ธฐ
testset.data[{ {}, {i}, {}, {} }]:div(stdv[i]) -- ํ์ค ํธ์ฐจ ์ค์ผ์ผ๋ง
end
-- ์ฌ๋ฏธ๋ฅผ ์ํด, 100๋ฒ์งธ ์์ ์ ํ๊ท ๊ณผ ํ์ค ํธ์ฐจ ์ถ๋ ฅ
horse = testset.data[100]
print(horse:mean(), horse:std())
์ข์ต๋๋ค, ์ด์ ์ ๊ฒฝ๋ง์ด ์ ์์ ๋ค์ ์ด๋ป๊ฒ ์๊ฐํ๋์ง ๋ด ์๋ค:
print(classes[testset.label[100]])
itorch.image(testset.data[100])
predicted = net:forward(testset.data[100])
-- ๋คํธ์ํฌ ์ถ๋ ฅ์ ๋ก๊ทธ ํ๋ฅ ๋ค ์
๋๋ค. ๊ทธ๊ฒ๋ค์ ํ๋ฅ ๋ค๋ก ๋ฐ๊พธ๊ธฐ ์ํด exp(x)๋ฅผ ์ทจํฉ๋๋ค.
print(predicted:exp())
์ด์ ๋คํธ์ํฌ ์์ธก์ ๋ณผ ์ ์์ต๋๋ค. ๋คํธ์ํฌ๋ ์ฃผ์ด์ง ํ ์์์ ๋ํด ํ๋ฅ ๋ค์ ๊ฐ ๋ถ๋ฅ์ ํ ๋นํ์์ต๋๋ค. ๋ ๋ช ํํ๊ฒ ๋ณด๊ธฐ ์ํด, ๊ฐ ํ๋ฅ ์ ๋ถ๋ฅ ์ด๋ฆ์ผ๋ก ํ๊น ํด ๋ด ์๋ค:
for i=1,predicted:size(1) do
print(classes[i], predicted[i])
end
์, ์ข์ต๋๋ค. ํ ์์ ๊ฐ ์ฒ๋ฆฌ๋์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ํ ์งํฉ์์ ์ ์ฒด์ ์ผ๋ก๋ ์ผ๋ง๋ ๋ง์ ์์ ๊ฐ ์ ๋ต์ผ๊น์?
correct = 0
for i=1,10000 do
local groundtruth = testset.label[i]
local prediction = net:forward(testset.data[i])
local confidences, indices = torch.sort(prediction, true) -- ์ค์ ํ๊ท ๋ค, ๋ด๋ฆผ ์ฐจ์์ผ๋ก ์ ๋ ฌ
if groundtruth == indices[1] then
correct = correct + 1
end
end
print(correct, 100*correct/10000 .. ' % ')
๋คํธ์ํฌ๊ฐ ๋ฌด์ธ๊ฐ ๋ฐฐ์ด ๊ฒ ๊ฐ์ต๋๋ค.
ํ , ์ ๋ถ๋ฅ๋ ๋ถ๋ฅ๋ ๋ฌด์์ด๊ณ , ๊ทธ๋ ์ง ๋ชปํ ๋ถ๋ฅ๋ ๋ฌด์์ผ๊น์:
class_performance = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
for i=1,10000 do
local groundtruth = testset.label[i]
local prediction = net:forward(testset.data[i])
local confidences, indices = torch.sort(prediction, true) -- ์ค์ ํ๊ท ๋ค, ๋ด๋ฆผ ์ฐจ์์ผ๋ก ์ ๋ ฌ
if groundtruth == indices[1] then
class_performance[groundtruth] = class_performance[groundtruth] + 1
end
end
for i=1,#classes do
print(classes[i], 100*class_performance[i]/1000 .. ' %')
end
์ข์ต๋๋ค, ๋ค์์ ๋ฌด์์ผ๊น์? ์ด๋ป๊ฒ ์ด ์ ๊ฒฝ๋ง์ GPU์์ ์ด์ฉํ ์ ์์๊น์?
require 'cunn'
์ฌ์ฉ๋ฒ์ ๊ฐ๋จํฉ๋๋ค. ์ ๊ฒฝ๋ง์ ๊ฐ์ ธ์์, ๊ทธ๊ฒ์ GPU๋ก ์ ์กํ๋ฉด ๋ฉ๋๋ค:
net = net:cuda()
๋ํ, ํ๋ณ ํจ์(criterion)๋ฅผ GPU๋ก ์ ์กํฉ๋๋ค:
criterion = criterion:cuda()
์ด์ ๋ฐ์ดํฐ ์ ๋๋ค:
trainset.data = trainset.data:cuda()
์ข์ต๋๋ค, GPU์์ ํ๋ จํด ๋ด ์๋ค. :) #๋๋ฌด ์ฝ์ต๋๋ค
trainer = nn.StochasticGradient(net, criterion)
trainer.learningRate = 0.001
trainer.maxIteration = 5 -- ํ๋ จ์ ์ํด 5 ์ํฌํฌ(epoch)๋ง ๋ฐ๋ณตํฉ๋๋ค.
trainer:train(trainset)
์ CPU์ ๋นํด ๋ง์ด ๊ฐ์๋์ง ์์์๊น์? ๋คํธ์ํฌ ํฌ๊ธฐ๊ฐ ๋๋ฌด ์์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ฐ์ต ๋คํธ์ํฌ ํฌ๊ธฐ๋ฅผ ํค์๋ณด์ญ์์ค (nn.SpatialConvolution(...) ์ธ์ 1๊ณผ 2). ๊ทธ๋ฆฌ๊ณ ์ด๋ค ๊ฐ์์ด ์์๋์ง ๋ณด์ญ์์ค.
์ฐ๋ฆฌ๊ฐ ์ฑ์ทจํ ๊ฒ: