[Flux] MNIST Example

여기서 사용하는 Flux는 v0.10.1 이다.

Model-zoo의 MNIST 예제를 참고(https://github.com/FluxML/model-zoo/blob/master/vision/mnist/mlp.jl)

zoo의 mnist예제 mlp가 gpu모드에서 재대로 동작하지 않는데 주요 원인은 onecold function이 gpu모드에서 문제를 일으킨다.

위 예제에서 accuracy function에 onecold를 사용하고 train!에서 accuracy를 사용하기 때문에 문제가 된다.

따라서 아래와 같이 바꿔 준다

accuracy(x,y) = mean(onecold(m(x)) .== onecold(y)) ==> accuracy(x,y) = mean(onecold(m(x)|>cpu) .== onecold(y|>cpu))

또한 scalar연산을 할 때 GPU가 느려진다는 경고가 나오는데 아래 처럼 바꿔 두면 된다.
(Warning: Performing scalar operations on GPU arrays: This is very slow, consider disallowing these operations with allowscalar(false))

allowscalar(false) 를 설정 하는 경우 에러가 발생하기 때무에 아래 와 같이 변경 해준다.

Y = onehotbatch(labels,0:9) |> gpu ==> Y = cu.(onehotbatch(labels,0:9)) |> gpu

수정한 예제는 jyputer notebook(html버전) 여기를 눌러 주세요 –> 소스

참고 : 입력데이터의 배열이 (data,batch_size)이다 . 이 예에서 28×28 크기의 이미지 60,000개는 784길의 이미지 60,000개로 표현 하는데
tensorflow의 경우 (batch_size,data) 형태 죽 (60,000, 784)로 되는데 Flux 에서는 (data,batch_size) 형태로 (784, 60,000) 이다.

Flux 에서 y = W*x + b 형태 인데 W는 (32,784) 형태, 따라서 (32,784) (784,60,000) => (32, 60,000) 으로 직관적이다.
TensorFlow에서 W는 (784,32) 형태로 주어지고 y = Transpose(W)*x + b 형태를 취한다.

mnist.jl

using Flux
using Flux.Data.MNIST, Statistics
using Flux: onehotbatch, onecold, crossentropy
using Base.Iterators: repeated
using CuArrays
CuArrays.allowscalar(false)

# Classify MNIST digits with a simple multi-layer-perceptron
# imgs : [(28x28),(28x28),...,(28x28))]  60,000개의 데이터
# MNIST.images()는 MNIST.images(:train)과 동일하며 60,000개의 학습데이터를 가져온다.
imgs = MNIST.images()
# reshape.(imgs,:) : [(784,),(784,),...,(784,)]  60,000개의 데이터
# X : (784x60,000)
X = hcat(float.(reshape.(imgs,:))...)
# labels : (60,000,)
labels = MNIST.labels()
# label : 0 ~ 9
# Y : (10x60,000)
Y = onehotbatch(labels,0:9)
# Model
m = Chain(
  Dense(28^2,32,relu), # y1 = relu(W1*x + b1), y1 : (32x?), W1 : (32x784), b1 : (32,)
  Dense(32,10), # y2 = W2*y1 + b2, y2 : (10,?), W2: (10x32), b2:(10,)
  softmax
)
X = X |> gpu
Y = cu.(Y) |> gpu
m = m |> gpu
loss(x,y) = crossentropy(m(x),y)
accuracy(x,y) = mean(onecold(m(x)|>cpu) .== onecold(y|>cpu))

dataset = repeated((X,Y),200)

opt = ADAM()

Flux.train!(loss,params(m),dataset,opt)

println("Train loss:",loss(X,Y))

println("Train accuracy:", accuracy(X,Y))

# Test Accuracy
tX = hcat(float.(reshape.(MNIST.images(:test),:))...)
tY = onehotbatch(MNIST.labels(:test),0:9)

tX = tX |> gpu
tY = cu.(tY) |> gpu

println("Test loss:",loss(tX,tY))
println("Test accuracy:", accuracy(tX,tY))

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다