음...딥러닝쪽 게시글을 오래 전부터 안 올리고 있었는데, 사실 좀 귀찮았습니다(ㅋㅋㅋㅋㅋㅋ)

  뭐 정리는 해야할 거 같지만, 데이터만 쌓아두고 여러 모델 구축해서 돌리면서 재미있게 놀았죠. 최근에 Mathematica를 구매해서 내장 딥러닝 모듈을 통해 CIFAR-10을 학습하여 76%인가?(30분 학습했는데, 이정도면 대단한 거겠죠? ㅋㅋㅋ) 나오기도 했고, 방학 때는 소논문으로 날씨 예측을 주제로 삼아 새롭게 Keras를 공부하여 패턴 예측을 시도해보기도 하였습니다. 뭐, 나중에 간단하게 모델들 업로드하면서 글로 정리하기로 하고... 오늘은 제가 학수고대한 NCS가 어제 DHL로 도착해서 간단히 리뷰를 해보려고 합니다!


단촐하지만 위엄있는 USB 스틱!


  NCS(Neural Compute Stick)은 아마 인텔의 자회사?로 추정되는 Movidius에서 개발한 딥러닝 inference용(즉, 학습은 불가능합니다) 컴퓨팅 스틱으로 저전력으로 딥러닝을 할 수 있도록 만들어진 것입니다. 79달러이며 저는 Mouser에서 9만원 정도로 구매하였습니다. 다른 리셀러는 모르겠는데, Mouser는 60달러 이상 무료 배송이고 어차피 79달러에서 할인을 하진 않을테니 그냥 여기서 구매했습니다. 아마 여기가 가장 낫지 않을까 싶네요. 지금은 주문이 많이 밀려서 그런지 꽤 걸리는 거 같고, 제가 주문하고 오기까지 한 1달 정도(배송은 1주일도 안 걸렸을 거예요) 걸렸네요.

  Myriad 2를 기반으로 하며 성능은 대략 100Gflops 정도이며, 전력을 겨우 1W만 먹는다고 합니다(!) 그래서인지 Movidius에서 지금 RPI에서 돌아가도록 SDK 배포판을 만들어서 제공하고 있으며, Movidius에선 RPI3를 예시로 보여주지만 제가 가지고 있는 RPI B(1버전)에서도 잘 돌아가더라고요. 아쉽게도 현재 지원 중인 딥러닝 프레임워크는 Caffe 밖에 없습니다. 예제로 들어있는 AlexNet, GoogLeNet, Gender, SqueezeNet을 돌려보면 각각 283ms, 569ms, 237ms, 304ms 정도 걸립니다(Inference Time 기준). 이미지 크기가 크지만 않다면 대역폭 문제가 크게 작용하지 않아서 그런지, 제 컴퓨터에서 USB 3.0으로 할 때나, RPI에서 USB 2.0(정확히는 2.0보다 안 좋습니다. RPI는 젠더로 USB 대역폭을 제공해서...)으로 할 때나 걸리는 시간은 거의 같습니다. 생각보다 딜레이 시간이 커도 각 딜레이 시간에 맞게 카메라에서 frame을 받아서 inference하면 뭐 그래도 쓸만한 거 같네요(기본 제공 예제에 있습니다). 그리고 생각보다(?) 79달러라는 싼 가격 때문인지 많이 구매해서 쓸 수 있게(?) 여러 개의 USB 스틱을 사용할 수 있도록 지원하는 거 같네요.


  지금 고민 중인 RPI Zero W를 구매하게 된다면, 카메라도 같이 구매하고, Movidius랑 같이 엮어서 Multiple Object Detection을 해보려고 생각하고 있습니다. 잘만 응용하면 시각 장애인에게 음성으로 자신 앞에 어떤 물체가 있는지 알려줄 수 있기 때문에(실제품이 나온다고 들었긴 했는데, 한 번 제 손으로 만들어보고 싶네요 ㅎㅎ) 한 번 만들어볼 생각을 하고 있습니다. 크기도 작고, 전력도 작게 먹는데다가, 무려 RPI를 지원하기 때문에 응용할 곳은 무궁무진할 거 같네요. 나중에 TensorFlow랑 Keras만 지원되면 정말 좋을 거 같습니다 ㅎㅎ

원래 제 목표가 자비스 만드는 거라(ㄹㅇ) 딥 러닝쪽 공부를 이제서야 시작하게 되었습니다. 원래 여름방학 때부터 하려고 했는데, 그놈의 귀차니즘이.....

이번엔 목표가 제대로 생겨서(고2때 카이스트 입학) 동기부여가 잘 되서, 좀 방향이 잡히더라고요. 여튼 뭐 그래서 제가 공부한 것들 좀 올려보려고 합니다.


일단 앞으로 딥 러닝 공부는 Tensorflow로 할 생각입니다. 제가 Python을 상당히 싫어하지만, 또 써보니 괜찮은 언어이기도 하고 무엇보다 제가 공부하고 있는 곳(http://hunkim.github.io/ml/)을 기준으로 추가적으로 제가 더 찾아보고 그러는 거라서, Tensorflow가 적합한 거 같네요.


- 1. Linear Regression은 무엇인고?


선형 회귀라고도 하며, 두 변수에 대한 선형 관계를 나타낸 것이라고 할 수 있을 듯 합니다.


- 2. Linear Regression을 한 번 해보자!


예를 들어 게임을 하는데 게임을 하는 시간과 그에 따라 얻는 경험치에 대한 표가 있다고 합시다.


 시간(y)

경험치(x)

2

35

60 

70 

100 


그리고 앞으로 게임에서 매일 일정 레벨에 도달하려고 할 때 얼마 만큼의 경험치를 얻기 위해 하루에 몇 시간 정도 게임을 하는 것이 적합한 지에 대해 알고 싶어한다고 합시다. 일반적으로 자연 현상에서는 대부분이 선형 관계이므로 1차 함수꼴(y = ax + b)로 두 변수에 대한 관계를 나타낼 수 있습니다. 따라서 일단 그 관계를 함수로 나타내기 위해서 저 데이터들을 그래프에 나타내봅시다.


이렇게 나옵니다. 이때 저 네 점에 대해 가장 가깝게 지나는 1차 함수를 구해야 합니다. 그래서 나온 것이 최소제곱법입니다. y = ax + b라는 식과 xi, yi 라는 데이터가 있을 때, 최소제곱법의 값은 cost(a, b)라고 하면, 아래와 같은 식이 나옵니다.

이때, 구하고자 하는 가장 최적의 y = ax + b를 만들려면 이때의 cost값이 가장 작아야합니다. TensorFlow에서는 이러한 cost값을 줄여주기 위한 알고리즘으로 GradientDescentOptimizer가 있습니다.  실제로 cost를 줄이는 알고리즘을 구현하고자 하면 조금 까다롭긴 하지만 크게 어렵지는 않습니다.


먼저 y = ax + b에서 우리는 cost를 줄이기 위해 a, b를 변수로 두고 이를 조정해야합니다. 위의 cost(a, b)식을 전개하면 다음과 같이 나옵니다.


휴... 전개가 좀 힘드네요. 여튼 잘 보시면 이 식은 간단하게 z = ax2 + by2 + cxy + d(a, b, c, d는 상수)의 함수꼴로 나타낼 수 있습니다. 일단 cost 함수를 위의 예시대로 데이터를 넣어서 전개해봅시다.

그리고 이 식대로 그래프를 한 번 그려봅시다. (식이 조금 복잡한 관계로, 다른 그래프들과 달리 https://academo.org/demos/3d-surface-plotter/를 사용했습니다.)



?! 아닛, 3D 포물면을 보는 기분이군요(WolframAlpha에서도 같은 함수를 돌렸는데 포물면인가 뭐시기라고 나온 거 같네요) 근데 사실 정확히 포물면은 아니고, 저기에 마우스 대서 값을 보면 최솟값인 부분이 한 군데로 수렴하는 거 같습니다. 뭐 여튼, 이때 cost의 최솟값 부분을 찾아야 하니 이 함수를 미분해서 0인 부분을 찾으면 됩니다! (아마 고등학교 과정의 미적분 수준으로는 힘들 거 같고, 편미분으로 할 수 있지 않을까 싶네요) 편미분으로 하는 과정은 다음 글에 한 번 써보도록 노력을 해보겠습니다. 


일단 본래 목적은 TensorFlow에서 GradientDescentOptimizer를 통해 cost를 줄여, 최종적인 1차 함수꼴을 얻는게 목적이니 이제 TensorFlow를 사용해봅시다. 소스 코드는 다음과 같습니다.

import tensorflow as tf import matplotlib.pyplot as plt x_data = [35, 60, 70, 100] y_data = [2, 4, 5, 9] W = tf.Variable(tf.random_uniform([1], -2.0, 2.0)) b = tf.Variable(tf.random_uniform([1], -2.0, 2.0)) y = W * x_data + b loss = tf.reduce_mean(tf.square(y - y_data)) optimizer = tf.train.GradientDescentOptimizer(0.0002) train = optimizer.minimize(loss) init = tf.initialize_all_variables() sess = tf.Session() sess.run(init) for step in xrange(300001): sess.run(train) if step % 60000 == 0: print(step, sess.run(W), sess.run(b)) print(step, sess.run(loss)) # Graph plt.plot(x_data, y_data, "go") plt.plot(x_data, sess.run(W) * x_data + sess.run(b)) plt.axis([0, 110, 0, 10]) plt.show()

문제는 GradientDescentOptimizer의 특성인지, learning_rate를 0.0002정도로 세팅해야지, 이 이상으로 세팅하면 값이 수렴하지 않고 오히려 INF로 넘어가서 아예 함수를 못 만들게 되는 현상이 일어납니다... learning_rate를 아주 작게 세팅하니 그만큼 수렴 속도도 무진장 느리고요... 원인 파악은 못 했으나 GradientDescentOptimizer 대신 TensorFlow의 다른 Optimizer를 시험삼아 써봤더니 아주 아주 조금 부정확하지만 빨리 수렴하더라고요 흠... 연구가 많이 필요해보입니다. 아마 다음 글에서 편미분하고 알고리즘 직접 작성하면서 알게될 수 있을지도 모르겠다는 생각이 드네요.


그리고 제가 GPU 세팅된 TensorFlow 버전을 사용하는데도 다 돌리는데 1분 넘게 걸리니 웬만하면 step을 1천 정도로 잡아주시는게 간단히 보는데 좋을 거 같습니다. 굳이 좋게 하실려면 GradientDescentOptimizer 대신 AdamOptimizer(0.5)를 돌려주시면 깔끔하게 나올 겁니다. (저건 또 왜인지 모르겠지만 무진장 좋긴 한데, 로그를 보시면 값이 수렴하지 않고 마지막까지 조금씩 바뀌기도 하더군요)


그래프의 변화도 첨부하고 싶었는데, 좀 노잼이여서(... 겁나 느리게 수렴합니다) 그냥 마지막 그래프만 보여드리겠습니다.


Linear Regression은 뭐 이정도면 얼추 끝난 거 같습니다. 다음 글에서는 위에서 말한 편미분을 통한 cost 줄이기 알고리즘을 직접 설계해서 돌려보도록 하겠습니다. 그 다음엔 다중 Linear Regression? 뭐 이런 걸 할 거 같네요. (위에 언급한 머신러닝 강의 순서대로 공부하고 글을 쓸 예정입니다)

+ Recent posts

티스토리 툴바