저는 현재 3개의 모니터를 동시에 쓰고 있습니다. 한 개는 가로로 두고, 나머지 두 개는 세로로 둬서 코딩하는데 쓰는데, 모니터 세 대가 종류가 다 달라서 크기도 가지각색이고 그럽니다. 뭐 아무튼 이 환경에서 Ubuntu 16.04.1과 Windows 10을 멀티부팅해서 쓰는데, 윈도에서는 각 모니터마다 배경화면을 달리 정할 수 있지만, Ubuntu에서는 기본적으로는 불가능합니다. 좀 당황해서 처음에는 검색하면서 여러가지 다 시도해봤는데 다 안돼서 좌절했는데, 오늘 다시 해보니까 되더라고요(음?) 이 방법을 소개해보려고 합니다.


참고한 곳은 여기입니다. (http://askubuntu.com/questions/390367/using-different-wallpapers-on-multiple-monitors-gnome-2-compiz) 처음에 여기 방법을 시도하다가 잘못해서 성공 못 해서 다른 곳도 찾아봤는데, 진짜 이거 말고는 답이 없어보입니다.


일단 먼저 배경화면으로 설정할 사진들을 여럿 준비하시고, nitrogen과 gnome-tweak-tool이라는 프로그램을 깝니다.


sudo apt install nitrogen gnome-tweak-tool


여기서 일단 gnome-tweak-tool을 실행합니다. 아마 gnome 환경에 대한 세세한 설정을 할 수 있게 해주는 프로그램인 거 같네요. 여기서 Desktop을 들어가시고 Icons on Desktop을 OFF로 둡니다. 이거 안 하면 배경화면을 암만 바꿔도 설정된 게 보이지 않더군요. 그리고 이거 끄면, 바탕화면에 어떠한 아이콘을 둘 수 없다는 것을 염두하셔야 합니다. (Windows의 바탕화면 아이콘 표기 안 하기랑 같은 기능 같네요)


다음으로 nitrogen을 실행합니다.


실행한 후에 Preferences에서 바탕화면 사진들이 들어있는 경로 폴더를 추가해줍니다.

이후 OK를 누르시면 그 폴더에 있는 사진들이 뜹니다.  (쿨럭, 제가 바로 아이유 팬입니다!)


그 사진들 중에서 하나 선택하시고 Automatic이 있는 곳을 통해 사진 설정(꽉 채우기, 바둑판식 채우기 등)을 하시고 어디 모니터에 하실지 선택하신 후 Apply해주시면 배경화면이 설정됩니다! 저는 아래와 같이 세팅해뒀습니다~~~


아 그리고, 이 nitrogen으로 설정된 배경화면은 세팅한 이후로 재부팅하면 사라지기 때문에 Launcher에 있는 Search your computer을 클릭하신 후 Startup Applications을 클릭하시고 여기서 다음 명령어를 시작 프로그램에 추가해주시면 됩니다.


nitrogen --restore


참고로 재시작한 이후에 로그인 하시고 한 10초 정도? 기다리셔야지 바뀐 배경화면들이 다시 적용되어서 보입니다. 아마 시작 프로그램의 딜레이 때문 아닐까 싶네요.

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

이번엔 목표가 제대로 생겨서(고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? 뭐 이런 걸 할 거 같네요. (위에 언급한 머신러닝 강의 순서대로 공부하고 글을 쓸 예정입니다)

제가 IDC에 서버를 두고 앱 서버를 돌리는데, 이번에 남는 서버가 한 대 생겨서(문제는 램 드라이버 문제 때문에 CentOS 6.4부터 안 올라감 ㅁㅊ) 거기에 GPU 하나 끼워서 제 연구서버로 써볼까 생각을 해봤습니다. 서버가 1U짜리이기 때문에 서버 케이스 안에 GPU를 넣는 건 좀 오바고, riser(PCIE 연장선)을 이용해서 좁디 좁은 케이스 밖에 GPU를 두려고 생각을 해봤습니다. 찾아보니까 PCIE riser가 있긴 있는데, 대부분 비트코인 같은 사이버코인 마이닝용으로 나온 PCIE x16 to x1 밖에 없더군요(;;) 나름 서버 내부에 x16 레인이 있기 때문에 써보고 싶었는데 x1과 x16의 GPGPU 상의 성능이 크게 차이가 나지 않는다는 소리가 들어서 한 번 테스트해봤습니다.


만저 제 컴퓨터 사양은 다음과 같습니다.

CPU: Intel i7-5820K

RAM: DDR4 16GB

GPU: GTX970

HDD: SATA2 Seagate 320GB (08년도쯤에 생산된 것으로 추정됩니다 ㄷㄷ)

PSU: SuperFlower SF-600R14SE Silver Green FX


OS: Ubuntu 16.04.1

Kernel: Linux 4.4.0-34-generic

Software: neural-style, Torch7, CUDA 7.5, cuDNN(버전은 기억이 안 나네요)


참고로 테스트시에는 모니터 3개를 켜뒀고(DVI x 2, DP x 1) 크롬 켜두고, 터미널 창 세 개 켜뒀습니다. 한 터미널은 공백 상태(log 저장용이라 걍 켜둔 셈), 한 터미널에서는 neural-style이 돌아가고 있었고, 나머지 한 터미널에서는 아래의 명령어로 GPU를 모니터링했습니다.


watch -n 1 nvidia-smi


* 테스트는 riser를 끼운 상태(x1)에서 오후 12시쯤에 테스트했고, riser를 안 끼운 상태(x16)에서는 오후 8시쯤에 테스트했습니다. nvidia-smi를 확인해보니 GPU에 쓰로틀링이 걸리던데, 일단 아래 두 테스트할 때 riser 끼운 상태에서는 GPU 사용률이 95%에서 맴돌았고 riser를 안 끼운 상태에서는 97~100%를 맴돌았습니다. 제 방은 에어컨따위 틀지 않고 오직 선풍기만 틀어서 방안 온도는 크게 변하지 않았을 것으로 추정되어 테스트에 큰 영향은 없을 것이라 생각이 됩니다.


비교를 위해 사용한 riser는 아래 링크에 있는 riser입니다. 사실 이더리움 마이닝 테스트용으로 한 개 샀던 것인데, 딱히 마이닝할 일도 없고 이번에 성능 비교해서 잘 나오면 IDC에 박으려고 생각했던 것입니다. (무려 그 일주일 전에 알리에서 샀던 이어폰보다 먼저 오시는 riser 클라스 ㄷㄷ)

http://www.aliexpress.com/item/PCIe-PCI-E-PCI-Express-Riser-Card-1x-to-16x-USB-3-0-Data-Cable-SATA/32548726067.html?spm=2114.13010608.0.50.CpdraB



라이저를 끼우고 그래픽카드를 외부로 뺀 상황입니다.


그리고 테스트를 돌렸습니다. 테스트는 위에 써둔 것처럼 Torch7 기반의 neural-style을 GPU로 돌려봤습니다. 명령어는 아래와 같습니다.


time th neural_style.lua -style_image examples/inputs/picasso_selfport1907.jpg -content_image examples/inputs/brad_pitt.jpg -gpu 0


총 3회를 테스트하였으며 맨 밑의 더보기를 통해 그 로그들을 확인하실 수 있습니다. 참고로 이상하게 컴퓨터를 부팅한 이후 바로 torch를 돌리면 준비 때문인지 약간 딜레이가 있어서 두 테스트 다 처음에 1회 간단히 돌린 이후에 테스트를 돌렸습니다. (즉, 간단히 돌린 이 1회를 제외한 그 다음 테스트부터 아래 표에 반영되어 있습니다.)


테스트 결과는 다음과 같습니다. time 명령어를 통해 real 시간을 측정하였습니다.



흠... 생각보다 정말 듣던대로 x16과 x1에서의 성능차이는 크지 않았습니다. x16 riser가 구해지지 않으면, 지금 가지고 있는 이걸 IDC에 있는 서버에 끼워서 연구용 서버로 사용해야할 거 같네요. 굿굿


ps. 차트 이쁘게 넣어보겠다고 찾아보다가, Google Chart 모듈을 찾아서 넣어봤습니다. 정작 글 쓰면서 차트 모듈 사용해서 차트 작성한게 1시간 반정도 먹는 듯... ㅠㅠ


neural-style w/ riser


neural-style w/o riser


'Artificial Intelligence' 카테고리의 다른 글

PCIE x16 VS PCIE x1에서의 GPU 성능 비교  (0) 2016.08.10

+ Recent posts