윈도우에서 텐서플로우 사용하기

며칠 동안 설치라는 미명하에
눈을 빨갛게 하고 애들한테 화를 내며 알아낸 것을 적어보려 한다.
일이 안 되면 애들한테 굉장히 예민해지는 직업병이 있다.

텐서플로우는 리눅스와 매킨토시에서만 동작한다.
마이크로소프트도 자신만의 머신러닝 도구를 갖고 있고 오픈까지 했기 때문일까?
사용자가 가장 많은
프로그래머가 아닌 사람들에게까지 저변을 확대하고 있는 시점에서
윈도우를 지원하지 않는다는 것은 정말 이상한 일이다.
다만 도커(docker)를 사용해 보니
어느 정도는 이것 때문에 윈도우 버전을 제공하지 않았구나, 라는 느낌을 받을 수 있었다.


도커는 리눅스 운영체제를 윈도우나 맥에서 사용할 수 있게 해주는 프로그램이라고 생각하면 된다.
다시 말해, 텐서플로우가 동작하는 리눅스 운영체제를
가상 머신(virtual machine)처럼 윈도우 위에서 대신 동작시켜 주는 엔진으로,
윈도우에서 직접 텐서플로우를 다룰 수는 없다.
일반적으로 가상 머신은 느리고, 도커는 엄청 빠르다고 한다. 
이번에 처음 써본 느낌은 "최고 중의 최고"라고 생각한다. 사용법도 무지 쉽다.

순서대로 따라가 보자. 
화면을 일일이 캡쳐하는 식의 이미지는 넣지 않겠다. 그리 어렵지 않으니까.

1. 도커 설치
가장 먼저 할 일은 도커를 설치하는 것이다. 
개인적으로는 이게 제일 어려웠는데, 두 가지 방법이 있다.
도커 툴박스(Docker Toolbox)와 도커포윈도우(Docker for Windows).

구글링을 하면 도커 툴박스를 설치하는 것으로 시작하는 문서가 대부분이다.
그러나, 도커 툴박스는 윈도우 10 이전의 버전에서만 사용하는 것이 좋다.
도커 홈페이지의 글을 읽어보면
2016년 7월 현재, 무료로 설치할 수 있는 버전인 윈도우 10 Pro같은 최신 버전은
도커포윈도우를 설치하면 성능에 유리하다고 한다. 네이티브(native) 코드를 직접 사용하기 때문에.
참, 운영체제는 반드시 64비트여야 한다.

  도커 툴박스 https://www.docker.com/products/docker-toolbox
  도커포윈도우 https://docs.docker.com/docker-for-windows

주의할 점이 또 있다.
도커 툴박스는 오라클에서 배포하는 VirtualBox라는 가상 머신 프로그램을 설치하는데,
도커포윈도우는 최신 버전의 Hyper-V 프로그램을 사용하고, 당연히 Hyper-V가 더 낫다.
도커 제작사에서 그렇게 얘기하니까. 
그런데, 구글링을 하면 VirtualBox에 대한 얘기를 많이 하기 때문에
도커 설치 후 잘 동작하지 않으면 VirtualBox 설치를 안 했기 때문으로 착각할 수 있다.

두 가지 모두, 설치는 기본 옵션만 사용한다.
그 어떤 것도 바꾸지 말고 계속해서 엔터키만 눌러서 진행한다.
나는 두 대의 컴퓨터에 각각 설치해 봤다.
그런데, 두 개 모두 설치하니까 VirtualBox와 Hyper-V 충돌이 발생했다. 한 가지만 사용하자.

사용법은 두 가지가 같다.
도커 툴박스는 Docker Quickstart Terminal이라는 전용 콘솔을 사용하고,
도커포윈도우는 윈도우에 기본 제공되는 콘솔을 사용한다.
콘솔의 모양이 살짝 다르지만, 이후 진행 과정에서 입력하는 내용은 완전히 똑같다.
입력 문구나 에러가 발생했을 때의 메시지까지 모두 똑같다.

2. 콘솔 창 열기
도커 툴박스를 설치했다면, 새로 설치된 프로그램에서 Docker 그룹을 찾는다.
그 안에 보면 Docker Quickstart Terminal 메뉴가 있다. 이걸 클릭하면 된다.

도커 툴박스를 사용하는 설치 방법을 보여주는 문서를 참고할 수도 있다.
http://www.netinstructions.com/how-to-install-and-run-tensorflow-on-a-windows-pc/

도커포윈도우라면, 윈도우 기본 콘솔을 열어야 한다.
화면 왼쪽 아래 있는 창문처럼 생긴 윈도우 버튼을 누른다.
'명령 프롬프트' 메뉴가 있으면 누르고 없으면 검색 버튼을 누르고 입력 창에 cmd라고 입력한다.

윈도우 10 화면이다. 이 부분에 cmd라고 입력한다.

아무 것도 없는 검정 화면이 콘솔이다. 왼쪽에 있는 >를 프롬프트(prompt)라고 부른다.
자기 컴퓨터 이름으로 나타나기 때문에 서로 다를 수 있다.

보통 도커 사용법을 검색하면
이 시점에서 가상으로 뭔가를 만들라고 하는데, 전혀 그럴 필요 없다.
도커를 사용하는 목적이 가상 파일 배포에 있는 것이 아니라 
다른 사람들이 만들어 놓은 가상 파일을 가져다 이용하는 데 있기 때문에
이 시점에선 할 게 없다. 뒤에서 명령어 복사해서 붙여넣을 거니까.

3. 텐서플로우 공식 설치 페이지로 이동
구글에서 제공하는 공식 페이지가 있다.
https://www.tensorflow.org/versions/master/get_started/os_setup.html

 
구글링해서 들어가면 예전 문서가 많아서 0.9 버전같은 이전 버전으로 연결될 수도 있다.
이럴 경우 왼쪽에 보면 버전을 선택할 수 있도록 되어 있는데,
여기서 master를 선택하면 언제나 최신 버전이 된다. 현재 버전은0.10.

4. Docker install로 이동
Pip, Virtualenv, Anaconda, Docker, From sources와 같은 방법으로 설치할 수 있다.
우리는 이 중에서 도커를 사용해서 설치하려 하고 있다.

페이지 중간쯤에 보면 Docker installation 항목이 나온다.
대충 읽어보면, 구글에서는 도커 이미지를 4가지 종류로 제공한다고 말하고 있다.
cpu binary, cpu binary + source, gpu binary, gpu binary + source.

여기 있는 4가지 중의 하나를 고른다. 
나는 노트북에서 돌릴 거라서 첫 번째에 있는 cpy binary 버전을 사용했다.

  docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow
  nvidia-docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow:latest-gpu

위의 그림 바로 아래에 위와 같은 도커 명령이 있다.
명령 오른쪽 끝에 있는 것이 이미지 이름이다. 다른 버전을 고르고 싶다면, 해당 이미지 이름을 사용하면 된다.
이들 버전은 모두 IPython Notebook이라는 웹 기반의 파이썬 인터페이스와 연동되어 있다.
그래서, 명령 중간에 -p 8888:8888처럼 웹 브라우져에서 접근할 수 있는 포트 번호를 쓰게 되어 있다.
앞뒤가 똑같은 포트번호~~. 번호는 아무 거나 줘도 되지만, 같은 것을 주는 것이 좋다.
8888과 6006을 가장 많이 사용한다 아래 명령어는 gpu 버전에 사용한다.

5. 도커 명령 입력
도커 툴박스 전용 콘솔 혹은 기본 콘솔 창에 위의 내용을 붙여 넣고 엔터를 누른다.
첫 번째 나오는 메시지에 "뭐가 없어서 할 수 없다"처럼 뜨는데, 무시하면 된다.
컴퓨터에 없기 때문에 서버로부터 가져오겠다, 정도의 문구다.
다운로드 받고, 압축도 풀고 하면서 많은 것을 한다.
시간은 10분 정도 걸리는 것 같다.

설치가 끝나면, 자동으로 해당 이미지 환경으로 들어간다.
정확하게 설명하면, 설치한 리눅스 환경으로 들어간다.
커서 왼쪽에 있는 프롬프트 모양이 $나 #으로 바뀌었고, 이제부터 리눅스 명령어를 사용해야 한다.
리눅스 운영체제를 도커의 도움으로 돌리고 있으니까.

그런데, 여기서 IPython Notebook으로 자동 진입하기 때문에
실제로는 몇몇 색상이 나타나긴 하지만, 커서 같은 것은 없다.
출력된 도움말을 보면 ctrl+c를 누르면 종료한다고 되어 있다.
종료하면 리눅스를 탈출해서 이전의 콘솔 환경으로 돌아간다. 그 전에 웹 브라우저를 띄워보자.
그리고, localhost:8888이라고 주소창에 입력하자. 그러면, 아래와 같은 그림을 볼 수 있다.
IPython Notebook이 동작 중이라서 프롬프트는 보이지 않는다.



6. 리눅스 서버 재진입
ctrl+c를 누르고 빠져 나오자.
IPython Notebook은 따로 공부가 필요하다. 구글링해서 필요한 만큼만 공부하도록 하자. 

  docker run -it gcr.io/tensorflow/tensorflow bash

포트 번호 없이 입력하면 리눅스 bash 환경으로 들어갈 수 있다.
오른쪽 끝에 있는 bash를 쉘(shell)이라고 부른다. 윈도우 콘솔과 같은 개념이다.

파이썬을 모르면 할 수 있는게 없다. python 또는 python3이라고 입력하고 엔터를 누른다.
놀랍게도 우리가 설치한 리눅스 서버는 버전2와 3을 모두 설치해 놓았다.
아쉬운 점은 텐서플로우는 버전 2에만 연결되어 있고, 버전 3에서는 사용할 수 없다.

7. 텐서플로우 예제 테스트
bash 환경에서 python이라고 입력했다고 가정하자. python3에서는 동작하지 않으니까.
python을 입력했다면 >>>가 나와 있는 파이썬 인터프리터로 진입한 상태이다.
여기서 입력하는 모든 것을 파이썬이 해석한다.
빠져나올 때는 exit()라고 둥근 괄호까지 입력해야 한다.

Run a TensorFlow demo model 항목에 보면 코드가 한 줄 나와 있다. 아래 코드를 복사해서 붙여 넣자.

 $ python -c 'import os; import inspect; import tensorflow; 
              print(os.path.dirname(inspect.getfile(tensorflow)))'

나는 두 줄로 썼지만, 타이핑하지 말고 꼭 복사해서 붙여 넣자.
텐서플로우가 설치된 경로를 화면에 출력한다.
Run a TensorFlow demo model 항목에 나와 있는 것처럼 경로가 표시된다.

 /usr/local/lib/python2.7/dist-packages/tensorflow
 
/usr/local/lib/python2.7/site-packages/tensorflow

8. mnist 모델 구동
구글에서 코딩해 놓은 mnist 모델이 있다. 이걸 돌려보자.
명령어는 아래와 같은 데, 같은 곳에 숨어 있어서 잘 보이지 않는다.
일단 python 콘솔에서 빠져 나온다. 이 명령은 파이썬 외부에서 파이썬 코드를 실행시킨다.

  python -m tensorflow.models.image.mnist.convolutional

2대의 데스크탑에서 돌려봤는데, 한 번은 55분, 한 번은 1시간 30분 걸렸다.
python이라고 했으니까, 버전 2를 사용하고 있음을 알겠다.

8,500회 반복하고, 100번에 한 번씩 결과를 출력한다.
최종 성능은 99를 넘는 훌륭한 모델이다. 입력 명령에 있는 것처럼 convolutional 모델을 사용하고 있다.
김성훈 교수님께서 말씀하시던 99%가 이걸 보고 말씀하신 것 같다.

9. mnist 실행 결과
두 번의 실행 결과에서 cpu가 좋지 않은 컴퓨터의 성능이 더 좋았다.
컴퓨터에 설치된 지저분한 것들이 좋은 컴퓨터에 많았던 것은 사실이다.
두 번째로는 성능 좋은 쪽에서는 도커 툴박스에서 실행했다.
느낌이 뭐라 그럴까.., 얘가 동작하고 있나.. 하는 느낌이 들 정도로 기분이 묘했다.
일단은 구글에서 얘기한 것처럼 도커포윈도우가 좋은 성능을 낸다고 보는 게 맞는 것 같다.

하나 더.
도커 허브에서 우분투 이미지를 가져다가 파이썬3과 텐서플로우까지 직접 설치했다.
성능 안 좋은 컴퓨터 얘기다.
그런데, 여기서 돌렸던 mnist 모델은 성능이 40% 가량 좋게 나왔다.
이게 뭐야? 구글이 텐서플로우 이미지에다 무슨 짓을 한건가?
다시 테스트를 해보겠지만, 정말 정말 놀라운 결과였다.

64비트 Windows 10 Pro. 인텔 코어 i5-2500 3.3Ghz. 메모리 8G
1시 32분에 실행해서 2시 57분에 종료(1시간 25분 소요)
최종 에러율 0.8%(정확도 99.2%)

Step 0 (epoch 0.00), 6.5 ms
Minibatch loss: 12.053, learning rate: 0.010000
Minibatch error: 90.6%
Validation error: 84.6%
Step 100 (epoch 0.12), 584.6 ms
Minibatch loss: 3.283, learning rate: 0.010000
Minibatch error: 6.2%
Validation error: 6.8%
... 중략
Step 8400 (epoch 9.77), 585.5 ms
Minibatch loss: 1.600, learning rate: 0.006302
Minibatch error: 0.0%
Validation error: 0.7%
Step 8500 (epoch 9.89), 586.3 ms
Minibatch loss: 1.594, learning rate: 0.006302
Minibatch error: 0.0%
Validation error: 0.8%
Test error: 0.8%

64비트 Windows 10 Pro. 인텔 코어 i3-2112 3.3Ghz. 메모리 8G
11시 27분에 실행해서 12시 22분에 종료(55분 소요)
최종 에러율 0.8%(정확도 99.2%)

Step 0 (epoch 0.00), 7.5 ms
Minibatch loss: 12.054, learning rate: 0.010000
Minibatch error: 90.6%
Validation error: 84.6%
Step 100 (epoch 0.12), 369.5 ms
Minibatch loss: 3.289, learning rate: 0.010000
Minibatch error: 6.2%
Validation error: 7.0%
... 중략
Step 8400 (epoch 9.77), 371.0 ms
Minibatch loss: 1.595, learning rate: 0.006302
Minibatch error: 0.0%
Validation error: 0.8%
Step 8500 (epoch 9.89), 370.5 ms
Minibatch loss: 1.617, learning rate: 0.006302
Minibatch error: 1.6%
Validation error: 0.8%
Test error: 0.8%

64비트 Windows 10 Pro. 인텔 코어 i5-6500 3.2Ghz. 메모리 8G
8시 54분에 실행해서 9시 37분에 종료(43분 소요)
최종 에러율 0.8%(정확도 99.2%)

Step 8500 (epoch 9.89), 285.4 ms
Minibatch loss: 1.617, learning rate: 0.006302
Minibatch error: 1.6%
Validation error: 0.8%
Test error: 0.8%

머신러닝 제대로 돌려보려고 구매한 조립 컴퓨터.
GPU 버전을 설치해야 하지만, 막 조립을 끝내고 mnist만 돌려봄.
CPU가 많이 차이나는데, 시간은 그에 비해 차이가 나지 않는 것 같다는 생각이 듬.