Caffe Example : 2.Training LeNet on MNIST with Caffe (Kor) - ys7yoo/BrainCaffe GitHub Wiki
Training LeNet on MNIST with Caffe)
Caffe๋ฅผ ์ด์ฉํ MNIST์์ LeNet ํ๋ จ์ํค๊ธฐ (์ด๋ฒ ์ ๋ฌธ์๋ ๋น์ ์ด Caffe๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ์ปดํ์ผํ๋ค๋ ๊ฐ์ ํ์ ์งํํ๋ค. ๊ทธ๋ ์ง ์๋ค๋ฉด, ์ค์น ํ์ด์ง๋ฅผ ์ฐธ๊ณ ํ๋ผ. ์ด๋ฒ ์ ๋ฌธ์์์๋ ์ฐ๋ฆฌ๋ ๋น์ ์ Caffe๊ฐ ์ค์น๋ ๋๋ ํ ๋ฆฌ๊ฐ CAFFE_ROOT์ ์๋ค๊ณ ๊ฐ์ ํ๋ค.
1. ๋ฐ์ดํฐ ์ธํธ ์ค๋น (Prepare Datasets)
๋จผ์ MNIST ์น์ฌ์ดํธ๋ก๋ถํฐ ๋ฐ์ดํฐ ํํ๋ฅผ ๋ค์ด๋ฐ๊ณ ๋ณํํด์ผํ ํ์๊ฐ ์๋ค. ์ด๋ฅผ ์ํด, ๊ฐ๋จํ ๋ค์๊ณผ ๊ฐ์ ๋ช ๋ น๋ฌธ์ ์คํํ ์ ์๋ค. :
cd $CAFFE_ROOT
./data/mnist/get_mnist.sh
./examples/mnist/create_mnist.sh
๋ง์ฝ wget์ด๋ gunzip์ด ์ค์น๋์ง ์์๋ค๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด, ์ด๊ฒ๋ค์ ๊ฐ๊ฐ ์ค์นํด์ผ์ฃผ์ด์ผ๋ง ํ๋ค. ์์ ๋ช ๋ น์ด๋ฅผ ์คํํํ์๋ ๋ ๊ฐ์ ๋ฐ์ดํฐ ์ธํธ, mnist_train_lmdb์ mnist_test_lmdb๊ฐ ์์ ๊ฒ์ด๋ค.
2. LeNet : MNIST ๋ถ๋ฅํ ๋ชจ๋ธ (LeNet: the MNIST Classification Model)
์ค์ ๋ก ํธ๋ ์ด๋ ํ๋ก๊ทธ๋จ์ ์คํํ๊ธฐ์ ์, ๋ฌด์์ด ๋ฐ์ํ ๊ฒ์ธ์ง ์ค๋ช ํด๋ณด์. ์ฐ๋ฆฌ๋ LeNet ๋คํธ์ํฌ๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ฉฐ ์ด๋ ์ซ์ ๋ถ๋ฅํ ์ ๋ฌด์ ๋ํด ์ ์๋ํ๋ ๊ฒ์ผ๋ก ์๋ ค์ ธ์๋ค. ์ฐ๋ฆฌ๋ ๋ด๋ฐ์ ๋ํ ์ ๋ฅํ ์ ํ ๋จ์ (Rectified Linear Unit : (ReLU))๋ก ์๊ทธ๋ชจ์ด๋ ํ์ฑํ๋ฅผ ๋์ฒดํ๋ฉด์ ๊ธฐ์กด์ LeNet ์ํ์ผ๋ก๋ถํฐ ์กฐ๊ธ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ๊ฒ์ด๋ค.
LeNet์ ๊ตฌ์ฑ์ ImageNet์์ ๊ฒ๋ค๊ณผ ๊ฐ์ ๋ ํฐ ๋ชจ๋ธ๋ค์์ ์ฌ์ ํ ์ฌ์ฉ๋๊ณ ์๋ CNN์ ์ ์(ํต์ฌ์์)๋ฅผ ํฌํจํ๊ณ ์๋ค. ์ผ๋ฐ์ ์ผ๋ก, Pooling ๊ณ์ธต์ ์ํ convolution ๊ณ์ธต๊ณผ ๋ค๋ฅธ Pooling๊ณ์ธต์ ์ํ convolution ๊ณ์ธต, ๊ธฐ์กด์ ๋ค์ค๊ณ์ธต ์ธ์ง(conventional multilayer perceptrons)์ ์ ์ฌํ ์ด ๋๊ณผ ๋ชจ๋ ์ฐ๊ฒฐ๋ ๊ณ์ธต์ผ๋ก ๊ตฌ์ฑ๋์ด ์๋ค. ์ฐ๋ฆฌ๋ $CAFFE_ROOT/examples/mnist/lenet_train_test.prototxt์ ๊ณ์ธต๋ค์ ์ ์ํด์๋ค.
3.MNIST ๋คํธ์ํฌ ์ ์ (Define the MNIST Network)
์ด ๋จ์์์๋ MNIST ์์ผ๋ก ์ด ์ซ์ ๋ถ๋ฅํ๋ฅผ ์ํ LeNet ๋ชจ๋ธ์ ๋ช
์ํ๋ lenet_train_test.prototxt ๋ชจ๋ธ ์ ์๋ฅผ ์ค๋ช
ํ๋ค. ๋น์ ์ด Google Protobuf์ ์น๊ทผํ๊ณ Caffe์ ์ํด ์ฌ์ฉ๋๋ protobuf ์ ์๋ฅผ ์ฝ์๋ค๊ณ ๊ฐ์ ํ ๊ฒ์ด๋ฉฐ ์ด๋ $CAFFE_ROOT/src/caffe/proto/caffe.proto์์ ์ฐพ์๋ณผ ์ ์๋ค.
ํนํ, protobuf๋ฅผ caffe::NetParameter (ํน์ ํ์ด์ฌ์์, caffe.proto.caffe_pb2.NetParameter)๋ก ์์ฑํ ๊ฒ์ด๋ค. ๋ค์๊ณผ ๊ฐ์ด ์ฃผ์ด์ง ๋คํธ์ํฌ ์ด๋ฆ์ผ๋ก ์์ํ ๊ฒ์ด๋ค.
name: "LeNet"
๋ฐ์ดํฐ ๊ณ์ธต ์์ฑํ๊ธฐ (Writing the Data Layer)
ํ์ฌ, ๋ฐ๋ชจ์ ์ฐ๋ฆฌ๊ฐ ์ด๊ธฐ์ ๋ง๋ lmdb๋ก๋ถํฐ์ MNIST ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ๊ฒ์ด๋ค. ์ด๊ฒ์ ๋ฐ์ดํฐ ๊ณ์ธต์ ์ํด ์ ์๋๋ค :
layer {
name: "mnist"
type: "Data"
transform_param {
scale: 0.00390625
}
data_param {
source: "mnist_train_lmdb"
backend: LMDB
batch_size: 64
}
top: "data"
top: "label"
}
ํนํ, ์ด๊ณ์ธต์ ์ด๋ฆ์ด mnist์ด๊ณ , ํ์ ์ data์ด๋ฉฐ, ์ฃผ์ด์ง lmdb ์์ค๋ก ๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด๋ค์ธ๋ค. ์ผํ ์ฒ๋ฆฌ๋ ํฌ๊ธฐ๋ก 64๋ฅผ ์ฌ์ฉํ๋ฉฐ ๋ฐ์๋ค์ด๋ ํฝ์ ์ ์กฐ์ ํ ๊ฒ์ด๋ฉฐ ๋ฐ๋ผ์ ์ด๋ [0,1)๋ฒ์๋ฅผ ๊ฐ์ง๋ค. ๊ทผ๋ฐ ์ 0.00390625์ผ๊น? ์ด๋ 1์ 256์ผ๋ก ๋๋๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ต์ข ์ ์ผ๋ก, ์ด๋ ๋๊ฐ์ blobs, ํ๋๋ data blobs, ๋ค๋ฅธ ํ๋๋ label blob๋ฅผ ์์ฑํ๋ค.
์ปจ๋ณผ๋ฃจ์ ๊ณ์ธต ์์ฑํ๊ธฐ (Writing the Convolution Layer)
์ฒซ ์ปจ๋ณผ๋ฃจ์ ๊ณ์ธต์ ์ ์ํด๋ณด์ :
layer {
name: "conv1"
type: "Convolution"
param { lr_mult: 1 }
param { lr_mult: 2 }
convolution_param {
num_output: 20
kernel_size: 5
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
bottom: "data"
top: "conv1"
}
์ด ๊ณ์ธต์ data blob(๋ฐ์ดํฐ ๊ณ์ธต์ ์ํด ์์ฑ๋ ๊ฒ์ด๋ค)๋ฅผ ๋ฐ๊ณ , conv1 ๊ณ์ธต์ ์์ฐํ๋ค. ์ปจ๋ณผ๋ฃจ์
์ ์ปค๋ ํฌ๊ธฐ 5๋ฅผ ๊ฐ์ง๊ณ stride 1๋ก ์ํ๋๋ 20๊ฐ์ ์ฑ๋ ์ถ๋ ฅ๋ค์ ์์ฐํ๋ค.
ํํฐ๋ ๊ฐ์ค์น์ ํธํฅ์ ๊ฐ์ ์์์ ์ผ๋ก ์ด๊ธฐํํ๋ ๊ฒ์ ํ๋ฝํ๋ค. ๊ฐ์ค์น ํ๋ฌ(filler)์ ๋ํ์ฌ, ์ฐ๋ฆฌ๋ ์
๋ญ๊ณผ ์ถ๋ ฅ ๋ด๋ฐ๋ค์ ์์ ๊ธฐ๋ฐํ ์ด๊ธฐํ์ ํฌ๊ธฐ๋ฅผ ์๋์ ์ผ๋ก ๊ฒฐ์ ํ๋ xavier ์๊ณ ๋ฆฌ์ฆ ์ฌ์ฉํ ๊ฒ์ด๋ค. ํธํฅ ํ๋ฌ(filler)์ ๋ํ์ฌ, ์ฐ๋ฆฌ๋ ๊ฐ๋จํ 0๊ฐ์ผ๋ก ์ฑ์ฐ๋ ๋ํดํธ๋ก ์์๋ก์จ ์ด๊ธฐํํ ๊ฒ์ด๋ค.
lr_mults๋ ๊ณ์ธต์ ํ์ต๊ฐ๋ฅํ ํ๋ผ๋ฏธํฐ๋ฅผ ์ํ์ฌ ํ์ต์จ์ ์กฐ์ ํ๋ ์ฅ์น์ด๋ค. ์ด ๊ฒฝ์ฐ์์ , ์ฐ๋ฆฌ๋ ์๋์๊ฐ๋์ ํด๊ฒฐ์ฌ์ ์ํด ์ฃผ์ด์ง๋ ํ์ต์จ๊ณผ ๋น์ทํ๊ฒ ๊ฐ๋ ๊ฐ์ค์น ํ์ต์จ์ ์ค์ ํ๊ณ , ์ฃผ์ด์ง๋ ๊ฒ๋ณด๋ค ๋๋ฐฐ ํฐ ํธํฅ ํ์ต์จ(์ด๋ ๋ณดํต ๋ ๋์ ์๋ ด์จ์ ๋ณด์ธ๋ค)์ ์ค์ ํ ๊ฒ์ด๋ค.
Pooling ๊ณ์ธต ์์ฑํ๊ธฐ (Writing the Pooling Layer)
ํด, Pooling ๊ณ์ธต์ ์ค์ ๋ก ์ ์ํ๊ธฐ ๋งค์ฐ ์ฝ๋ค :
layer {
name: "pool1"
type: "Pooling"
pooling_param {
kernel_size: 2
stride: 2
pool: MAX
}
bottom: "conv1"
top: "pool1"
}
์ด๋ ์ฐ๋ฆฌ๊ฐ pool ์ปค๋ ์ฌ์ด์ฆ2 ๊ทธ๋ฆฌ๊ณ stride of 2๋ก max pooling์ ์ํํ ๊ฒ์์ ๋งํ๋ค (๋ฐ๋ผ์ ์ฃผ์์ pooling ์ง์ญ ์ฌ์ด์ ์ค๋ณต์ด ์๋ค). ๊ฐ๋จํ, ๋๋ฒ์งธ ์ปจ๋ณผ๋ฃจ์ ๊ณผ pooling ๊ณ์ธต์ ์์ฑํ ์ ์๋ค. ์์ธํ ์ฌํญ์ $CAFFE_ROOT/examples/mnist/lenet_train_test.prototxt๋ฅผ ํ์ธํ๋ผ.
์ ์ฒด์ ์ผ๋ก ์ฐ๊ฒฐ๋ ๊ณ์ธต ์์ฑํ๊ธฐ (Writing the Fully Connected Layer)
์ ์ฒด์ ์ผ๋ก ์ฐ๊ฒฐ๋ ๊ณ์ธต์ ์์ฑํ๋ ๊ฒ ๋ํ ๊ฐ๋จํ๋ค:
layer {
name: "ip1"
type: "InnerProduct"
param { lr_mult: 1 }
param { lr_mult: 2 }
inner_product_param {
num_output: 500
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
bottom: "pool2"
top: "ip1"
}
์ด๊ฒ์ด (๋ด๋ถ์์ฐ(InnerProduct)๊ณ์ธต์ผ๋ก์จ Caffe์ ์๋ ค์ง)500๊ฐ์ ์ถ๋ ฅ์ ์ง๋ ์ ์ฒด์ ์ผ๋ก ์ฐ๊ฒฐ๋ ๊ณ์ธต์ ์ ์ํ ๊ฒ์ด๋ค. ๋ชจ๋ ๋ค๋ฅธ ๋ผ์ธ๋ค์ ์น๊ทผํด๋ณด์ผ๊ฑฐ์ผ, ๋ง์ง?
ReLU ๊ณ์ธต ์์ฑํ๊ธฐ (Writing the ReLU Layer)
ReLU ๊ณ์ธต ๋ํ ๊ฐ๋จํ๋ค:
layer {
name: "relu1"
type: "ReLU"
bottom: "ip1"
top: "ip1"
}
ReLU๋ element-wise operation์ด๊ธฐ ๋๋ฌธ์, ๋ช๋ช์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ฝํ๊ธฐ ์ํ์ฌ ์ ์๋ฆฌ์์ ์๋ํ ์ ์๋ค. ์ด๊ฒ์ bottom๊ณผ top blob์ ๊ฐ์ ์ด๋ฆ์ ์ค์ผ๋ก์จ ๊ฐ๋จํ ๋ฌ์ฑ๋๋ค. ๋น์ฐํ, ๋ค๋ฅธ ๊ณ์ธต ํ์
์ ์์ฌ ๋ณต์ ๋ blob๋ฅผ ์ฌ์ฉํ์ง๋ง์์ผํ๋ค.
ReLU ๊ณ์ธต ์ ์ ํ์, ์ฐ๋ฆฌ๋ ๋ค๋ฅธ ๋ด๋ถ์์ฐ๊ณ์ธต์ ์์ฑํ ๊ฒ์ด๋ค :
layer {
name: "ip2"
type: "InnerProduct"
param { lr_mult: 1 }
param { lr_mult: 2 }
inner_product_param {
num_output: 10
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
}
}
bottom: "ip1"
top: "ip2"
}
์์ค ๊ณ์ธต ์์ฑํ๊ธฐ (Writing the Loss Layer)
๋ง์นจ๋ด, ์์ค ๊ณ์ธต์ ์์ฑํ ๊ฒ์ด๋ค!
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
}
softmax_loss ๊ณ์ธต์ ์ํํธ๋งฅ์ค์ ๋คํญ์์ ๋ก์ง์คํฑ ์์ค(์๊ฐ์ ์ ์ฝํ๊ณ , ์์ ์์ ์ฑ์ ํฅ์์ํจ๋ค) ๋ชจ๋๋ฅผ ์ํํ๋ค. ๋ฐ์ดํฐ ๊ณ์ธต์์ ์ ๊ณตํ ๋ ๊ฐ์ blob๋ฅผ ์ทจํ๋ฉฐ ์ฒ์ ๊ฒ์ ์์ธกํ ๊ฒ ๊ทธ๋ฆฌ๊ณ ๋๋ฒ์งธ ๊ฒ์ ๋ผ๋ฒจํ ๊ฒ์ด๋ค (๊ธฐ์ต๋๋?). ์ด๋ ํ ์ถ๋ ฅ๋ ์์ฐํ์ง ์์ผ๋ฉฐ, ์ด๊ฒ์ด ํ๋ ๋ชจ๋ ๊ฒ์ ์์ค ํจ์ ๊ฐ์ ๊ณ์ฐํ ๊ฒ์ด๋ฉฐ, backpropagation์ด ์์๋๋ฉด ๋ณด๊ณ ํ๋ฉฐ, ip2์ ๋ํ์ฌ ๊ทธ๋๋์ธํธ๋ฅผ ์ด๊ธฐํํ๋ค. ์ด๊ฒ์ด ๋ชจ๋ ๋ง๋ฒ์ ์์์ด๋ค.
์ถ๊ฐ ํ๊ธฐ : ๊ณ์ธต ๊ท์น ์์ฑํ๊ธฐ (Additional Notes: Writing Layer Rules)
๊ณ์ธต ์ ์๋ ์๋์ ๊ฒ๊ณผ ๊ฐ์ด ๋คํธ์ํฌ ์ ์์ ํฌํจํ ๋์ ํ ์ง ์ํ ์ง์ ๋ํ์ฌ ๊ท์น์ ํฌํจํ ์ ์๋ค:
layer {
// ...layer definition...
include: { phase: TRAIN }
}
์ด๊ฒ์ด ๊ท์น์ด๋ฉฐ, ์ด๋ ํ์ฌ ๋คํธ์ํฌ์ ์ํ์ ๊ธฐ๋ฐํ์ฌ ๋คํธ์ํฌ์ ๊ณ์ธต์ด ํฌํจ๋ ๊ฒ์ ํต์ ํ๋ค. ๊ณ์ธต ๊ท์น๊ณผ ๋ชจ๋ธ ๊ฐ์์ ๋ํ์ฌ ๋ ๋ง์ ์ ๋ณด๊ฐ ํ์ํ๋ค๋ฉด $CAFFE_ROOT/src/caffe/proto/caffe.proto๋ฅผ ์ฐธ๊ณ ํ ์ ์๋ค.
์์ ์์์, ์ด ๊ณ์ธต์ ์ค์ง TRAIN ๋จ๊ณ์์ ํฌํจ๋ ๊ฒ์ด๋ค. ๋ง์ฝ TRAIN์ TEST๋ก ๋ฐ๊พธ๋ฉด, ์ด ๊ณ์ธต์ ์ค์ง ํ
์คํธ ๋จ๊ณ์์๋ง ์ฌ์ฉ๋ ๊ฒ์ด๋ค. ์๋์ ์ผ๋ก, ์ฆ ๊ณ์ธต ๊ท์น์์ด, ๊ณ์ธต์ ํญ์ ๋คํธ์ํฌ์ ํฌํจ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก, lenet_train_test.prototxt๋ (๊ฐ๊ธฐ ๋ค๋ฅธ ์ผํ ์ฒ๋ฆฌ๋์ ๊ฐ์ง๋ฉด์) ํ๋๋ ํ๋ จ๋จ๊ณ์์, ํ๋๋ ์คํ ๋จ๊ณ์์ ์ ์๋ ๋๊ฐ์ ๋ฐ์ดํฐ ๊ณ์ธต์ ๊ฐ์ง๋ค. ๋ํ lenet_solver.prototxt์์ ์ ์๋ ๊ฒ์ ๋ฐ๋ผ, ๋งค 100๋ฒ์ ๋ฐ๋ณตํ์ฌ ๋ชจ๋ธ ์ ํ๋๋ฅผ ๋ณด๊ณ ํ๋๊ฒ์ ์ํ TEST ๋จ๊ณ์์๋ง ํฌํจ๋๋ ์ ํ๋ ๊ณ์ธต(Accuracy layer)๊ฐ ์กด์ฌํ๋ค.
4. MNIST ํด๊ฒฐ์ฌ ์ ์ํ๊ธฐ (Define the MNIST Solver)
prototxt์์ ๊ฐ๊ฐ์ ๋ผ์ธ ์ค๋ช ํ๋ ์ฝ๋ฉํธ๋ฅผ ํ์ธํ๋ผ. ######$CAFFE_ROOT/examples/mnist/lenet_solver.prototxt:
# ๋ง ํ๋กํ ์ฝ ๋ฒํผ ์ ์
net: "examples/mnist/lenet_train_test.prototxt"
# test_iter๋ ์ผ๋ง๋ ์ ๋ฐฉํฅ๊ณผ์ ์ test๋จ๊ณ์์ ์ํํด์ผํ๋ ๋ช
์ํ๋ค.
# MNIST์ ๊ฒฝ์ฐ์์, ์ ์ฒด ์คํ์ฉ 10000๊ฐ์ ์ด๋ฏธ์ง์ ๋ํ์ฌ
# ์ฐ๋ฆฌ๋ ์คํ ์ผํ ์ฒ๋ฆฌ๋์ 100์ผ๋ก, 100๋ฒ์ ์คํ ๋ฐ๋ณต์๋ฅผ ๊ฐ์ง๋ค.
test_iter: 100
# ์คํ์ ๋งค 500๋ฒ ํ๋ จ ๋ฐ๋ณต๋ง๋ค ํ๋ฒ ์คํํ๋ค.
test_interval: 500
# ๊ธฐ๋ณธ ํ์ต์จ, ๋คํธ์ํฌ์ ๋ชจ๋ฉํ
๊ณผ ๊ฐ์ค์น ๊ฐ์
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005
# ํ์ต์จ ์ ์ฑ
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# ๋งค 100ํ๋ง๋ค ๋ณด์ฌ์ค๋ค.
display: 100
# ์ต๋ ๋ฐ๋ณต ํ์
max_iter: 10000
# ์ค๋
์ท ์ฌ์ด์ฌ์ด์ ๊ฒฐ๊ณผ
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
# ํด๊ฒฐ์ฌ ๋ชจ๋ : CPU or GPU
solver_mode: GPU
5. ๋ชจ๋ธ์ ํ๋ จ์ํค๊ธฐ์ ์คํํ๊ธฐ (Training and Testing the Model)
๋ชจ๋ธ์ ํ๋ จ์ํค๋ ๊ฒ์ ๋คํธ์ํฌ ์ ์ protobuf์ ํด๊ฒฐ์ฌ protobuf ํ์ผ๋ค์ ์์ฑํ ํ์๋ ๊ฐ๋จํ๋ค. ๊ฐ๋จํ train_lenet.sh ์ด๋ ๋ค์๊ณผ ๊ฐ์ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ผ:
cd $CAFFE_ROOT
./examples/mnist/train_lenet.sh
train_lenet.sh๋ ๊ฐ๋จํ ์คํฌ๋ฆฝํธ์ง๋ง, ์ฌ๊ธฐ ๋น ๋ฅธ ์ค๋ช
์ด ์๋ค : ์ธ๊ธํ ๊ฒ์ ๋ฐ๋ผ ํ์ต์ ์ํ ํต์ฌ ๋๊ตฌ๋ trainํ๋๊ณผ ํด๊ฒฐ์ฌ protobuf ํ
์คํธ ํ์ผ๋ฅผ ๊ฐ์ง caffe์ด๋ค.
์ด ์ฝ๋๋ฅผ ์คํํ ๋, ๋ค์๊ณผ ๊ฐ์ด ๋ ๋ผ๋ค๋๋ ์๋ง์ ๋ฉ์ธ์ง๋ฅผ ๋ณผ ๊ฒ์ด๋ค:
I1203 net.cpp:66] Creating Layer conv1
I1203 net.cpp:76] conv1 <- data
I1203 net.cpp:101] conv1 -> conv1
I1203 net.cpp:116] Top shape: 20 24 24
I1203 net.cpp:127] conv1 needs backward computation.
์ด๋ฌํ ๋ฉ์ธ์ง๋ ๊ฐ๊ฐ์ ๊ณ์ธต, ์ด์ ๋ํ ์ฐ๊ฒฐ๋ค๊ณผ ์ถ๋ ฅํํ์ ๋ํ์ฌ ์์ธํ ์ฌํญ์ ๋งํด์ฃผ๋ฉฐ, ์ด๋ ๋๋ฒ๊น ์ ์์ด ๋์์ด ๋ ์ง ๋ชจ๋ฅธ๋ค. ์ด๊ธฐํํ์๋, ํ์ต์ด ์์๋ ๊ฒ์ด๋ค:
I1203 net.cpp:142] Network initialization done.
I1203 solver.cpp:36] Solver scaffolding done.
I1203 solver.cpp:44] Solving LeNet
ํด๊ฒฐ์ฌ ์ค์ ์ ๊ธฐ๋ฐํ์ฌ, ๋งค 100ํ ๋ฐ๋ณต๋ง๋ค ์์คํจ์๋ฅผ ํ๋ จํ ๊ฒ์ ์ถ๋ ฅํ ๊ฒ์ด๊ณ , ๋งค 500ํ ๋ฐ๋ณต๋ง๋ค ๋คํธ์ํฌ๋ฅผ ํ ์คํธํ ๊ฒ์ด๋ค. ๋น์ ์ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์ธ์ง๋ฅผ ๋ณผ ๊ฒ์ด๋ค:
I1203 solver.cpp:204] Iteration 100, lr = 0.00992565
I1203 solver.cpp:66] Iteration 100, loss = 0.26044
...
I1203 solver.cpp:84] Testing net
I1203 solver.cpp:111] Test score #0: 0.9785
I1203 solver.cpp:111] Test score #1: 0.0606671
๊ฐ๊ฐ์ ๋ฐ๋ณต ํ๋ จ์ ๋ํ์ฌ, lr์ ์ด ๋ฐ๋ณต์ ํ์ต์จ์ด๊ณ , loss๋ ํ๋ จํ๋ ํจ์์ด๋ค. ํ
์คํธ ๋จ๊ณ์ ์ถ๋ ฅ์ ๋ํ์ฌ, score 0๋ ์ ํ๋, score 1์ ํ
์คํ
์์ค ํจ์์ด๋ค.
๊ทธ๋ฆฌ๊ณ ๋ช๋ถ ํ๋ฉด ๋๋๋ค!
I1203 solver.cpp:84] Testing net
I1203 solver.cpp:111] Test score #0: 0.9897
I1203 solver.cpp:111] Test score #1: 0.0324599
I1203 solver.cpp:126] Snapshotting to lenet_iter_10000
I1203 solver.cpp:133] Snapshotting solver state to lenet_iter_10000.solverstate
I1203 solver.cpp:78] Optimization Done.
์ด์ง์ protobuf ํ์ผ๋ก ์ ์ฅ๋ ์ต์ข ํจ์๋ ๋ค์๊ณผ ๊ฐ์ ๊ณณ์ ์ ์ฅ๋๋ค.
lenet_iter_10000
๋ง์ฝ ์ค์ธ๊ณ์์ ์์ฉ๋๋ ๋ฐ์ดํฐ ์ธํธ๋ก ํ๋ จ๋ ๊ฒ์ด๋ผ๋ฉด, ๋น์ ์ ์์ฉ์์ ํ๋ จ๋ ๋ชจ๋ธ๋ก์จ ๋ฐฐ์น๋ ์ ์๋ค.
์... GPU ํ๋ จ์ ์ด๋?(Umโฆ How about GPU training?)
์ด๋ฏธ ํ๋ค! ๋ชจ๋ ํ๋ จ๋ค์ GPU ์์์ ์ํ๋์ด์ง๋ค. ์ฌ์ค ๋ง์ฝ CPU์์์ ํ๋ จ์ํค๊ณ ์ถ๋ค๋ฉด, ๊ฐ๋จํ lenet_solver.prototxt์ ํ ์ค์ ๋ฐ๊พธ๋ฉด ๋๋ค:
# solver mode: CPU or GPU
solver_mode: CPU
๊ทธ๋ฆฌ๊ณ ํ๋ จ์ด CPU๋ฅผ ์ฌ์ฉํด์ ์ด๋ฃจ์ด์ง ๊ฒ์ด๋ค. ๊ฐ๋จํ์ง ์๋? ์ปค๋ฎค๋์ผ์ด์ ์ค๋ฒํค๋ ๋๋ถ์, MNIST๋ ์์ ๋ฐ์ดํฐ ์ธํธ๋ผ GPU๋ก ํ๋ จ์ํค๋๊ฒ์ด ์ฌ์ค ์๊ฐํ ๊ฐ์น๊ฐ ์์ง๋ ์๋ค. ๋ ๋ณต์กํ ๋ชจ๋ธ๋กํ๋ ๋ ํฐ ๋ฐ์ดํฐ์ธํธ์ ๋ํ์ฌ, ์๋ฅผ๋ค๋ฉด ImageNet๊ฐ์, ์ฐ์ฐ ์๋์ ์ฐจ์ด์ ์ ์์ฃผ ์๋นํ ๊ฒ์ด๋ค.
๊ณ ์ ๋จ๊ณ์์ ์ด๋ป๊ฒ ํ์ต์จ์ ์ค์ผ ์ ์๋์? (How to reduce the learning rate at fixed steps?)
lenet_multistep_solver.prototxt์ ๋ณด์๋ผ.