2017년 5월 24일 수요일

Docker 기반 우분투, 텐서플로우, PyTorch 설치, 개발 및 관련 명령 정리

노트북에서 윈도우와 우분투 듀얼 부팅을 사용하다 보면, 오피스 작업하다가 재부팅해야 하는 등 불편할 때가 많다. 이럴 경우, 윈도우에서 도커를 설치하고, 그 위에 우분투 이미지를 설치해 사용하는 방법이 좋은 대안이 될 수 있다.

이 글은 도커에 대해 간략히 살펴보고, 도커 컨테이너에 우분투, 텐서플로우, PyTorch(파이 토치)를 설치해 본다.

이 내용은 다음 링크를 참고하였다.
1. 개념
도커는 2013년 3월 Pycon 컨퍼런스(산타클라라)에서 dotCloud 창업자인 Solomon Hykes가 리눅스 컨테이너의 미래라는 세션을 발표하면서 처음 알려졌다. 이후 도커는 급성장해 2015년 4월 1,100억원 투자유치를 받았으며, 마이크로소프트가 2016년 6월 4 billion dollar에 도커를 인수하려 했다.

도커는 컨테이너 기반 오픈소스 가상화 플랫폼이다. 실행 중인 컨테이너에 접속해 명령을 실행하고, apt-get 으로 패키지를 설치할 수 있다. 여러 프로세스를 백그라운드로 실행할 수 있다.

이미지는 컨테이너 실행에 필요한 파일과 설정값을 포함하고 있다. 컨테이너는 이미지를 실행한 상태이다. 예를 들어, 우분투 이미지는 우분투 실행을 위한 모든 파일을 가지고 있다. 

도커는 레이어 구조로 설치 패키지를 관리하기 때문에, 이미 빌드된 레이어를 재활용해, 도커 빌드 속도를 크게 개선할 수 있다. 아울러, 빌드된 레이어를 재활용해, 빌드될 이미지를 조합할 수 있다.
도커 레이어 구조

도커 이미지는 Docker hub에 등록되거나 Docker Registry 저장소를 만들어 관리할 수 있다. 현재 공개된 도커 이미지는 50만개 이상이며, 도커 기반 오픈소스 프로젝트는 10만개가 넘는다.

이미지는 url 방식으로 관리하고, 태그를 붙일 수 있다. 도커는 이미지를 만들기 위해 Dockerfile 이란 DSL(domain specific language)를 이용해 이미지 생성과정을 기술한다.

도커 명령어는 직관적이며, http기반의 REST API도 지원해 확장성이 좋다.

도커는 가상머신에 비해 사용이 쉽고 성능이 좋으나 한계가 있다. 운영체제의 라이브러리 및 시스템을 재활용하므로, 이에 의존되어 동작된다. 만약, 운영체제의 드라이버 설정에 GPU가 설치안되어 있다면, 도커 이미지도 이와 관련된 라이브러리를 사용하지 못할 것이다. 이는 성능은 느리나 운영체제 독립적인 가상머신과는 크게 다른 점이다.

2. 도커 설치
도커를 설치하는 방법은 간단하다. 아래 링크를 클릭해 적당한 버전을 설치하면 된다. 맥, 윈도우, 리눅스 버전 등이 제공된다. 
만약, 윈도우 10 버전에서 하이퍼-V(Hyper-V) 가상머신을 사용해 도커를 실행하려면, 윈도우 10 프로페셔널 이상 운영체제가 설치되어야 함에 주의한다. 하위 버전에서는 오라클 VirtualBox가 설치된다(성능이 하이퍼-V보다 낮다고 알려져 있다). 
설치 후에 Docker Quickstart Terminal, Kitematic, Oracle VM VirtualBox(혹은 Hyper-V)가 설치된 것을 확인할 수 있다.

참고 - 2019년 4월 도커 버전과 Kitematic 버전이 서로 문제를 일으켜서, 도커 이미지 다운로드 안되는 현상있음. 이 경우, https://github.com/docker/kitematic/releases 에서 Kitematic 0.17.3 버전을 다운로드 받아 실행해 볼것.

3. 실행
도커 버전을 확인하기 위해, Docker Quickstart Terminal을 실행해 다음과 같은 명령을 내려 본다. 
$ docker version
도커는 서버와 클라이언트로 분리되어 있고, 명령을 입력하면, 클라이언트가 서버로 명령을 전송하고 결과를 받아 터미널에 출력해 준다. 
도커 클라이언트 서버 구조
Kitematic 를 실행해 보면, 도커 가상머신에서 올릴 수 있는 수많은 이미지를 검색할 수 있다(2019년 4월 현재 도커 최신 버전과 Kitematic 버전이 서로 문제를 일으켜서, 다운로드가 안됨. 이 경우, https://github.com/docker/kitematic/releases 에서 Kitematic 0.17.3 버전을 다운로드 받아 실행해 볼것). 검색한 이미지는 도커 위에서 생성해 사용할 수 있다. 

4. 우분투 이미지 생성 및 실행하기 
우분투 이미지를 올려보자. 터미널을 실행하고, 아래 명령을 실행해 본다. 
$ docker run ubuntu:16.04

만약, 이미지가 로컬에 없다면, 다운로드(pull 명령) 후 컨테이너를 생성(create 명령)하고, 시작(start)한다. 우분투 이미지에 명령은 전달하지 않았기 때문에 이미지는 시작하자 마자 종료된다. 

이제, /bin/bash 명령어를 이용해, 컨테이너를 실행한다.
$ docker run --rm -it ubuntu:16.04 /bin/bash


도커의 각 명령은 docker 명령해 뒤에 아래 명령을 추가하면 실행된다. 각 명령의 의미는 다음과 같다. 
옵션설명
-ddetached mode 흔히 말하는 백그라운드 모드
-p호스트와 컨테이너의 포트를 연결 (포워딩)
-v호스트와 컨테이너의 디렉토리를 연결 (마운트)
-e컨테이너 내에서 사용할 환경변수 설정
–name컨테이너 이름 설정
–rm프로세스 종료시 컨테이너 자동 제거
-it-i와 -t를 동시에 사용한 것으로 터미널 입력을 위한 옵션
–link컨테이너 연결 [컨테이너명:별칭]
exit 를 실행해 bash 쉘을 종료하면, 우분투 이미지 컨테이너도 자동 종료된다. 

5. 텐서플로우 이미지 실행
이제 구글의 머신러닝 플랫폼인 텐서플로우 이미지를 실행해 보자. 다음 명령어를 도커 입력하면, 이미지를 다운로드 받은 후 실행된다. 
$ docker run -d -p 8888:8888 -p 6006:6006 teamlab/pydata-tensorflow:0.1


이미지가 실행된 후, 웹브라우저에서 jupyter를 접속해, 파이썬 코드를 입력해 본다. 제대로 실행되면, 성공한 것이다.

6. PyTorch 이미지 실행
PyTorch는 텐서플로우와 비슷한 머신러닝 플랫폼이다.

다음 명령을 입력해, PyTorch 이미지를 컨테이너에서 실행해 본다. 참고로 이미지는 DockerHub의 StepanKuzmin의 pytorch-notebook을 사용한다.
$ docker run -it --rm -p 8888:8888 stepankuzmin/pytorch-notebook

7. 간단한 도커 우분투, Ngnix 서버 이미지 만들기
이 장은 도커 이미지 개념을 이해하기 쉽도록, 간단하게 도커 우분투, node.js 서버 이미지 만드는 방법을 설명한다. 도커가 설치되었다는 가정하에 다음 명령을 입력한다(우분투 기준). 참고로, NVIDIA GPU 도커 이미지는 현재 우분투에서 밖에 지원되지 않는다.
mkdir -p nginx-image
cd nginx-image/
touch Dockerfile
gedit Dockerfile

다음과 같이 우분투 20.04 버전을 기반으로 NGNIX 서버를 설치하고, 환경을 설정하는 명령을 Dockerfile에 입력한 후 저장한다.
# Download base image ubuntu 20.04
FROM ubuntu:20.04

# LABEL about the custom image
LABEL maintainer="admin@sysadminjournal.com"
LABEL version="0.1"
LABEL description="This is custom Docker Image for \
the PHP-FPM and Nginx Services."

# Disable Prompt During Packages Installation
ARG DEBIAN_FRONTEND=noninteractive

# Update Ubuntu Software repository
RUN apt update

# Install nginx, php-fpm and supervisord from ubuntu repository
RUN apt install -y nginx php-fpm supervisor && \
    rm -rf /var/lib/apt/lists/* && \
    apt clean
 
# Define the ENV variable
ENV nginx_vhost /etc/nginx/sites-available/default
ENV php_conf /etc/php/7.4/fpm/php.ini
ENV nginx_conf /etc/nginx/nginx.conf
ENV supervisor_conf /etc/supervisor/supervisord.conf

# Enable PHP-fpm on nginx virtualhost configuration
COPY default ${nginx_vhost}
RUN sed -i -e 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' ${php_conf} && \
    echo "\ndaemon off;" >> ${nginx_conf}
 
# Copy supervisor configuration
COPY supervisord.conf ${supervisor_conf}

RUN mkdir -p /run/php && \
    chown -R www-data:www-data /var/www/html && \
    chown -R www-data:www-data /run/php
 
# Volume configuration
VOLUME ["/etc/nginx/sites-enabled", "/etc/nginx/certs", "/etc/nginx/conf.d", "/var/log/nginx", "/var/www/html"]

# Copy start.sh script and define default command for the container
COPY start.sh /start.sh
CMD ["./start.sh"]

# Expose Port for the Application
EXPOSE 80 443

이제 앞서 추가 설정해야 할 Nginx 웹서버 설정 파일을 다음과 같이 수정한다. 
gedit default

server {
    listen 80 default_server;
    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;
    server_name _;
    location / {
        try_files $uri $uri/ =404;
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    }
}

다음과 같이 supervisrod.conf 파일을 생성한다. 
[unix_http_server]
file=/dev/shm/supervisor.sock   ; (the path to the socket file)

[supervisord]
logfile=/var/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB        ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10           ; (num of main logfile rotation backups;default 10)
loglevel=info                ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false               ; (start in foreground if true;default false)
minfds=1024                  ; (min. avail startup file descriptors;default 1024)
minprocs=200                 ; (min. avail process descriptors;default 200)
user=root             ;

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///dev/shm/supervisor.sock ; use a unix:// URL  for a unix socket

[include]
files = /etc/supervisor/conf.d/*.conf

[program:php-fpm7.4]
command=/usr/sbin/php-fpm7.4 -F
numprocs=1
autostart=true
autorestart=true

[program:nginx]
command=/usr/sbin/nginx
numprocs=1
autostart=true
autorestart=true

다음과 같이 start.sh 파일을 생성한다.
#!/bin/sh
/usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf

다음과 같이 실행권한으로 변경한다.
chmod +x start.sh

다음 명령을 실행해 앞서 생성한 도커 파일들 의존성을 확인한다. 
tree .

다음과 같이 도커를 빌드한다.
docker build -t nginx-image .

빌드 후 이미지 리스트를 확인한다.
docker image ls

다음과 같이 index.html 파일을 생성한다. 
echo '<h1>Nginx and PHP-FPM 7.4 inside Docker Container with Ubuntu 20.04 Base Image</h1>' > /webroot/index.html

웹 루트 폴더를 생성한다. 그리고, 다음과 같이 도커 이미지를 통해 웹서버를 실행한다.
mkdir -p /webroot
docker run -d -v /webroot:/var/www/html -p 8080:80 --name test-container nginx-image

크롬으로 로컬호스트 8080 포트를 입력하면, 설정된 도커 nginx 서버가 실행될 것이다. 

도커 이미지 내부 파일 저장하기
도커 이미지 실행 후 데이터베이스같은 파일을 저장하고, 종료하면, 파일도 함께 사라진다. 하지만, 도커 마운트를 이용하면, 도커를 실행하는 호스트 파일 시스템에 도커에서 생성된 파일들을 영구 보관할 수 있다.

도커는 이를 위해 볼륨(volume), 바인드 마운트(bind mount) 두 가지 방법을 제공한다.

볼륨은 다음과 같은 명령으로 생성한다. 이를 통해 다중 도커 이미지 간 폴더 파일들을 함께 공유할 수 있다.
docker volume create

예를 들어 다음과 같이 볼륨을 생성하고, 도커를 실행하면, myvol이 도커 /app와 연결된다.
docker volume create my-vol
docker run -d --name devtest --mount source=myvol, target=/app nginx:latest

볼륨 저장 위치는 다음 명령으로 알 수 있다.
docker inspect my-vol

바인드 마운트는 호스트 파일 시스템의 중요 시스템 변경이 가능하다. 바인드를 위해서, 다음 $(pwd)부분을 현재 바인드할 폴더명령 입력한다. 다음 예는 ngnix 서버를 실행하며, 영구 저장할 파일이 보관될 곳으로 $(pwd)와 /app를 서로 바인딩하는 예이다.
docker run -d -it --name devtest --mount type=bind, source="$(pwd)"/target, target=/app nginx:latest

이를 통해, 도커 이미지를 종료하더라도 이미지에서 생성, 수정한 파일을 영구 보관할 수 있다. 다음 링크는 mysql database file을 마운트를 통해 영구 보관하는 방법을 보여준다.
NVIDIA GPU 도커 사용하기

지금까지 도커 개발 방법을 간단히 살펴보았다. 도커는 운영체계 라이브러리에 의존하므로, 윈도우에서는 아직 NVIDIA GPU 도커가 동작하지 않는다. 즉, GPU 모드 딥러닝 프레임웍을 사용할 수가 없다. 여기서는 NVIDIA GPU 우분투 도커 버전을 간략히 설명한다.
이 도커는 아래 구조로 동작한다.
NVIDIA GPU 도커 이미지는 우분투 16.04, 18.04, 20.04에서 동작한다.

다음 명령을 통해 NVIDIA GPU 도커를 설치한다.
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker

# Add the package repositories
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
zypper ar https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo

sudo zypper install -y nvidia-docker2  # accept the overwrite of /etc/docker/daemon.json
sudo systemctl restart docker

다음과 같이 사용한다.
#### Test nvidia-smi with the latest official CUDA image
docker run --gpus all nvidia/cuda:10.0-base nvidia-smi

# Start a GPU enabled container on two GPUs
docker run --gpus 2 nvidia/cuda:10.0-base nvidia-smi

# Starting a GPU enabled container on specific GPUs
docker run --gpus '"device=1,2"' nvidia/cuda:10.0-base nvidia-smi
docker run --gpus '"device=UUID-ABCDEF,1"' nvidia/cuda:10.0-base nvidia-smi

# Specifying a capability (graphics, compute, ...) for my container
# Note this is rarely if ever used this way
docker run --gpus all,capabilities=utility nvidia/cuda:10.0-base nvidia-smi

도커 명령어
이 장에서는 도커 명령을 간단히 요약해 본다.

1. 컨테이너 목록 확인하기
$ docker ps -a

2. 컨테이너 중지하기
$ docker stop ${container ID}

3. 컨테이너 제거하기
$ docker rm ${container ID#1} ${container ID#2}

4. 이미지 목록 확인하기
$ docker images

5. 이미지 다운로드 하기
$ docker pull

6. 이미지 삭제하기
$ docker rmi ${image ID}

7. 컨테이너 로그 보기
$ docker logs --tail 10 ${container ID}

8. 실시간 컨테이너 로그 보기
$ docker logs -f ${container ID}

9. 실행중인 컨테이너에 명령 실행하기
$ docker exec [option] container command [arg ...]
run은 새로 컨테이너를 만들어 실행하고, exec는 실행 중인 컨테이너에 명령을 실행하는 차이이다.
다음은 MySQL 컨테이너의 /bin/bash 쉘을 실행하는 예이다.
$ docker exec -it mysql /bin/bash

10. 도커 컨테이너 업데이트
도커에서 컨테이너를 업데이트할 때 컨테이너에 생성된 파일은 모두 삭제될 수 있다. 그러므로, 유지해야 할 데이터가 있는 경우, 컨테이너 내부가 아닌 외부 스토리지에 저장해야 한다.

11. 도커 컴포즈
도커 컴포즈 툴을 이용해, 도커 명령을 하나의 설정으로 간편하게 처리할 수 있다. 자세한 내용은 다음 링크를 참고한다.
기타 도커에서 생성된 데이터를 보관하려면 호스트 드라이버와 연결해 데이터를 저장하거나, 도커 볼륨을 생성해 그 위에 도커를 생성해 사용해야 한다. 그냥 도커를 실행한 후 종료하면 그 동안 작업된 데이터는 삭제된다는 것을 주의해야 한다. 관련 내용은 아래를 참고한다.

도커 이미지 완전 삭제 방법
도커 이미지를 완전히 삭제하기 위해서는 이미지를 사용하는 컨테이너를 모두 제거한 후 삭제해야 한다. 아래와 같이 명령을 실행한다. 지금 실행된 이미지들을 리스트한 후, 해당 이미지를 삭제해보자. 명령어에 있는 숫자들은 삭제할 IMAGE ID 이다. 

sudo docker images

sudo docker rm -f $(sudo docker ps -a --filter ancestor=8b9d78381e5d)

sudo docker stop $(sudo docker ps -a --filter ancestor=8b9d78381e5d)

sudo docker rmi 8b9d78381e5d

마무리

2017년 5월 23일 화요일

텐서플로우 MNIST 딥러닝 및 텐서보드 그래프 가시화

이 글은 TensorFlow를 설치하면, 사용할 수 있는 필기체 이미지인 MNIST 를 훈련해 보고, Tensorboard(텐서보드)로 훈련된 모델을 가시화해본다. 참고로, 이 글에서 사용하는 Tensorflow 버전은 1.1이다.

TensorFlow 설치는 앞에 을 참고한다. 이 글은 아래  TensorFlow Tutorial 문서를 참고하였다.
MNIST는 손글씨로 쓴 0에서 9사이 숫자 이미지이다. 이 이미지는 20 x 20 픽셀 정규화된 흑백 이미지이다. 이를 안티알리아싱(ansialiasing)처리된 28 x 28 그레이(gray) 이미지가 포함되어 있다. mnist.train(훈련), mnist.test(테스트) 데이터가 포함되어 있고, 각 데이터 원소는 이미지(xs), 레이블(ys)로 구성되어 있다. 이미지는 mnist.train.image로 참조가 가능하다.

그레이 이미지 행렬이 28 x 28 이미로, 784차원 벡터라 볼 수 있다. 다음 그림과 같이, 각 펙셀의 그레이값은 0 ~ 1.0 사이값으로 표현된다.
그레이 이미지는 다음 그림과 같이 55000개가 있다.
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
이에 대응하는 라벨 벡터도 55000개 있으며, 구조는 10개 라벨에 대한 참값을 가지는 1차원 벡터로 구성된다. 예를 들어, 숫자 2에 대응하는 라벨 벡터는 [0, 0, 1, ..., 0] 이다.

이 이미지를 텍스트 라벨로 분류할 수 있도록 TensorFlow로 훈련시켜본다. 훈련방법은 softmax를 이용한 신경망 모델, CNN(convolutional neural network) 모델 두가지 방법이다.

1. softmax 함수 신경망 기반 MNIST 훈련
MNIST 훈련을 위해, 다음과 같이 신경망을 구성하고, MNIST 데이터를 훈련해 본다. 학습 모델의 텐서 구조는 다음과 같다.
A simple MNIST model 구조

활성함수 φ는 다음과 같은 softmax 함수를 이용한다. 
   y = softmax(v)

신경망 계산 및 softmax 함수 동작 방식

TensorFlow에서 다음 코드를 입력한다.

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.nn.softmax(tf.matmul(x, W) + b)
y_ = tf.placeholder(tf.float32, [None, 10])

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

sess = tf.InteractiveSession()
tf.global_variables_initializer().run()

for _ in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

이 코드의 실행결과는 다음과 같다. 대략 92% 정확도를 가진 훈련모델을 얻을 수 있다.

2. CNN 기반 MNIST 훈련
92% 정확도도 나쁘지는 않지만, 99.2% 수준으로 훈련모델을 개선할 수 있는 더 좋은 방법이 있다. CNN(convolutional neural network) 딥러닝을 이용해 다음과 같이 개선한다.
코드는 다음과 같다.

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

x_image = tf.reshape(x, [-1,28,28,1])

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2

cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
sess.run(tf.global_variables_initializer())
for i in range(20000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:
    train_accuracy = accuracy.eval(feed_dict={
        x:batch[0], y_: batch[1], keep_prob: 1.0})
    print("step %d, training accuracy %g"%(i, train_accuracy))
  train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print("test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

실행 결과는 다음과 같다. 98% 이상의 정확도를 얻을 수 있다.

3. Fully Connected Feed
MNIST는 머신러닝의 전통적인 문제를 보여준다. 이 챕터에서는 tensorflow sample에 포함되어 있는 fully conntected feed 예제를 실행해 본다. 아나콘다를 설치한 경우, 이 예제는 [아나콘다 설치 폴더]\envs\tensorflow\Lib\site-packages\tensorflow\examples\tutorials에 포함되어 있다.

python fully_connected_feed.py

그럼, 다음과 같은 결과를 얻을 수 있다.

4. TensorBoard 활용 그래프 가시화
텐서보드(TensorBoard)를 이용하면, 텐서플로우 학습모델링 그래프를 시각적으로 확인할 수 있다. 텐서보드를 이용하려면, 텐서보드 그래프 가시화에 필요한 로그 데이터를 저장할 폴더를 지정해야 한다. 다음과 같이 아나콘다에서 텐서보드 logdir를 지정한다. 

tensorboard --logdir=[Tensorboard log directory] 
예) tensorboard --logdir=d:\program\anaconda3\envs\tensorflow\tensorboard_log

여기에서는 앞의 fully_connected_feed.py 에서 실행된 logdir 폴더에 저장된 데이터를 다음과 같이 텐서보드로 확인해 보겠다. 

tensorboard --logdir=/tmp/tensorflow/mnist/logs/fully_connected_feed


실행 후에 다음과 같이, http://localhost:6006/에서 학습된 결과들을 확인할 수 있다. 
텐서보드의 그래프를 살펴보면, 학습모델을 어떻게 구성했는 지 직관적으로 파악 수 있다.
fully_connected_feed 텐서플로우 그래프
텐서보드의 임베딩 벡터 가시화
텐서보드의 임베딩 벡터 가중치 T-SINE 가시화 영상(iteration)

5. 마무리
지금까지 텐서플로우를 이용해, MNIST를 딥러닝해보고, 학습모델링된 그래프를 가시화해 보는 텐서보드를 살펴보았다. 앞으로, 텐서플로우와 같은 머신러닝 플랫폼을 이용해, 많은 문제들이 지능화되리라 생각한다.


기타 레퍼런스

2017년 5월 22일 월요일

텐서 플로우 및 케라스 최신버전 설치 방법 (Windows 10)과 개념

이 글은 텐서플로우(Tensorflow) 1.1, 케라스(keras)를 윈도우 10 환경에서 설치하는 순서를 정리한다. 기타, 쥬피터 노트북에 사용되는 NumPy 같은 파이썬 라이브러리와 케라스 설치도 함께 다루겠다.

참고로, 현재(2018.2.8) 시점에서는 1.5버전이 릴리즈되어 있다. 1.5버전 설치는 아래 순서는 동일하다. 다만, CUDA 설치 버전을 9.0으로 (9.1 최신버전이 아닌) 설치해야, 텐서플로우 1.5버전과 호환되는 CUDA라이브러리가 설치되는 것만 조심하면 된다.

텐서플로우 1.0 버전은 다음과 같은 성능 개선이 있었다.
  • 계산 속도 개선
  • tf.layers, tf.metrics, tf.losses 모듈 추가
  • 고급 신경망 네트워크 라이브러리인 Keras 라이브러리 호환
  • Python API를 NumPy와 유사하게 변경
  • 텐서플로우 도메인 컴파일러 XLS 개선
  • 텐서플로우 디버거(tfdbg)
  • 객체 인식 용 Android 데모 추가
  • Pyton 3 도커 이미지 추가
참고로, 우분투+NVIDIA+CUDA+텐서플로우 조합에 실패하였다면(우분투 16.04는 NVIDIA 드라이버 충돌 문제가 있다.ㅎ 테크트리 잘못타면 무한 로긴, 무한 blink screen 반복. NVIDIA의 OpenGL 라이브러리와 우분투 충돌문제 등 다양한 설이 있음), 윈도우 10 환경의 텐서플로우는 괜찬은 대안이 될 수 있다. 
참고로, 무한 로긴 및 반복 현상이 발생한다면, 로긴 화면에서 콘솔모드로 전환(ctrl+alt+F1 키)한 후 다음처럼 NVIDIA 그래픽 드라이버를 복구할 수 있다.

sudo apt-get purge nvidia-*
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt-get update
sudo apt-get install nvidia-375


1. 개념
텐서플로우는 구글에서 발표한 오픈소스 기반 머신러닝 플랫폼이다. 텐서플로는 데이터 플로 그래프(data flow graph)를 사용해 수치연산을 한다. 그래프 노드는 수학 연산, 그래프 에지(edge)는 다차원 배열(tensor)를 정의한다. 그래프는 데이터와 알고리즘이 포함되어 있다. 그래프를 이용하면, 링크 간의 종속성을 이용해, GPU를 이용한 병렬처리를 할 수 있다. 머신러닝 딥러닝 내용은 다음 링크를 참고한다.
텐서플로우를 이용해 개발된 알고리즘은 텐서보드(tensorboard)를 이용해, 실행 상태를 가시화할 수 있다. 텐서플로 서빙(tensorflow serving)을 이용하면, 텐서플로에서 훈련된 모델을 이용해, 서비스를 운영할 수 있다.

우분투 환경에서는 텐서플로우 설치는 PIP를 이용해 다음처럼 상대적으로 간단하다.
$ sudo apt-get install python-pip python-dev python-virtualenv
$ virtualenv --system-site-packages ~/tensorflow
$ source ~/tensorflow/bin/activate
(tensorflow)$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/llinux/cpu/tensorflow-0.9.0-cp27-none-linux_x86_64.whl

윈도우 10환경에서는 다음 3가지 방법으로 텐서플로우를 설치할 수 있다. 
1. Docker for Windows 기반 텐서플로우 이미지 설치
2. Anaconda(아나콘다) 기반 텐서플로우 설치
3. 가상머신(VM, Hyper-V)에서 텐서플로우 설치

이 중에 상대적으로 설치가 간편한 아나콘다 기반 텐서플로우 설치를 한다. 컴퓨터는 NVIDIA GPU가 있다고 가정한다. 설치 방법은 다음과 같다. 

2. CUDA 8.0 설치
CUDA(Compute Unified Device Architecture)는 NVIDIA에서 개발한 GPU기반 병렬 계산 개발 플랫폼이다. 
아래 링크에서 CUDA 8.0 local 버전을 다운로드 받아 디폴트값으로 설치한다.

3. CuDNN 설치
CuDNN(CUDA® Deep Neural Network library)은 CUDA기반 딥러닝 라이브러리이다.
아래 링크에서 앞의 CUDA 8.0과 호환되는 CuDNN 버전을 다운로드 받고, 압축파일을 CUDA 폴더 아래에 덮어 써 준다. 참고로, 다운로드 받기 전에 회원가입 절차가 있다.

4. Python 3.5 설치
아나콘다 설치전에 Python 3.5를 설치해야 한다. 아래 링크에서 Windows x86-64 executable installer 설치파일을 다운로드해 설치한다.

5. 아나콘다 4.2 설치
아나콘다(https://www.continuum.io)는 Python언어 기반 수치 및 통계해석 패키지이다.
아래 링크에서 아나콘다 Anaconda3-4.2.0-Windows-x86_64.exe 파일을 다운로드해 설치한다.

6. 텐서플로우 설치
텐서플로우(https://www.tensorflow.org)는 구글에서 공개한 머신러닝 플랫폼이다.
텐서플로우를 설치하기 위해, 아나콘다 콘솔 메뉴(Anaconda Prompt)를 실행한다.
콘솔에서 아래 명령어를 차례대로 실행한다.
1) pip 업그레이드
python -m pip install --upgrade pip

2) Conda 환경 생성
conda create -n tensorflow python=3.5

3) TensorFlow 설치
activate tensorflow
pip install tensorflow-gpu

설치가 제대로 되면 다음 명령어로 설치된 버전을 확인할 수 있다.
pip freeze

IPython은 대화형 파이썬 노트북이다. 파이썬 입력 및 실행 결과를 대화형으로 손쉽게 확인할 수 있다. IPython 을 실행해 다음과 같이 'import tensorflow as tf' 를 입력한다. 아래와 같이 에러가 없다면 성공이다.

7. 텐서플로우 테스트
텐서플로우가 제대로 설치되었는 지 확인하기 위해, 다음과 같이 실행해 본다. 에러가 없다면, 정상적으로 설치된 것이다. 

python
>>> import tensorflow as tf
>>> print('TensorFlow version: {0}'.format(tf.__version__))
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))

다음과 같이 출력되면 성공이다. 

8. 쥬피터 노트북 설치
쥬피터 노트북을 설치해 본다. 쥬피터 노트북은 IPython을 구동해, 입력된 파이썬 명령의 결과를 브라우저에 전달해 준다. 명령을 입력하고 실행결과를 확인하기 좋다.

아나콘다 콘솔에서 'conda install jupyter notebook' 명령을 입력해 설치한다. 

설치한 후 다음과 같이 jupyter notebook password 명령으로 쥬피터 노트북 암호를 설정한다. 

다음과 같이 jupyter notebook 을 실행한다. 

브라우저가 자동으로 실행되며, localhost:8888로 접속해, 다음과 같이 쥬피터 노트북을 구동한다. 

New 메뉴의 Python 메뉴를 클릭해 새로운 노트북을 생성한다. 그리고, import tensorflow as tf 명령을 입력한 후 Shift+Enter 를 입력해 실행한다. 에러가 없으면 성공한 것이다.

9. 파이썬 기타 라이브러리
개발을 위해 필수적인 파이썬 라이브러리를 미리 설치해 놓는 것이 좋다. 아나콘다 콘솔에서 차트, 표, 이미지 처리, 그래픽 가시화와 관련된 아래 패키지를 설치한다.
pip install numpy matplotlib pandas pillow graphviz

다만, scipy 는 윈도우10에서 pip install scipy 시 문제가 있을 수 있다. 이 경우, scipy 설치를 위해서 직접 다운로드하는 방법이 있다. 자세한 내용은 여기(How to get SciPy working in Windows, 2017.2)를 참고한다.
설치 후, 테스트를 위해, 쥬피터 노트북에서 New-Python 메뉴로 노트북을 만들고, 다음 코드를 실행해 본다.

import matplotlib
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 3*np.pi, 500)
plt.plot(x, np.sin(x**2))
plt.title('A simple chirp')
plt.show()

실행 결과가 다음과 같다면 성공한 것이다.

10. 케라스
만약, 시간이 좀 더 있다면, 아나콘다 명령창에서 tensorflow와 함께 쓰이는 keras(케라스)도 아래와 같이 설치하여, 공부해 보자.

1. CPU 버전 설치
conda install -c anaconda keras

2. GPU 버전 설치
conda install -c anaconda keras-gpu

케라스 소스와 예제는 다음 링크를 참고한다.
케라스를 설치한 후, 다음과 같이 LSTM 예제를 실행시켜 본다. 이상이 없으면 제대로 설치된 것이다. 

from keras.models import Sequential from keras.layers import LSTM, Dense import numpy as np data_dim = 16 timesteps = 8 num_classes = 10 # expected input data shape: (batch_size, timesteps, data_dim) model = Sequential() model.add(LSTM(32, return_sequences=True, input_shape=(timesteps, data_dim))) # returns a sequence of vectors of dimension 32 model.add(LSTM(32, return_sequences=True)) # returns a sequence of vectors of dimension 32 model.add(LSTM(32)) # return a single vector of dimension 32 model.add(Dense(10, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy']) # Generate dummy training data x_train = np.random.random((1000, timesteps, data_dim)) y_train = np.random.random((1000, num_classes)) # Generate dummy validation data x_val = np.random.random((100, timesteps, data_dim)) y_val = np.random.random((100, num_classes)) model.fit(x_train, y_train, batch_size=64, epochs=5, validation_data=(x_val, y_val))

케라스 실행 결과
11.PyTorch 설치
PyTorch(파이토치) 설치 방법은 다음과 같이 매우 간단하다.

conda install pytorch torchvision -c pytorch


부록: 텐서플로우 함수 요약
수학 연산. add, sub, mul, div, abs, mod, neg
배열. concat, slice, split, constant, rank, shape, shuffle
행렬. diag, transpose, matmul, matrix_determinant, matrix_inverse
신경망. softmax, sigmoid, ReLU, Convlution2D, MaxPool
세션. save, restore
큐잉/동기화. enqueue, dequeue, MutexAcquire, MutexRelease
흐름제어. merge, switch, enter, leave, NextIteration

레퍼런스
이 글은 아래 사이트를 참고하였다. 
2. Jaejun Yoo, TensorFlow 설치
8. 윈도우(Windows) 환경에서 Docker를 이용해서 텐서플로우(TensorFlow) 설치하기
9. 윈도우 GPU tensorflow 설치 및 그래픽카드별 성능 비교
10. 병렬처리 – First Contact with TensorFlow
11. Deep Learning을 위해 어떤 GPU를 써야 할까?
12. 윈도우즈에 아나콘다, 텐서플로우 설치하기
13. GPU vs CPU benchmark (Adobe)
14. DIY GPU 서버 : 딥 러닝용 PC 직접 만들기
15. Ubuntu 17.04 Upgrade 및 WSL 잡담
16. 우분투 16.04에서 CUDA 성공적으로 설치하기(무한로긴 현상 발생하는 경우 있음)
17. Ubuntu 16.04 -17.04 NVIDIA drivers install is EASY
18. VI 에디터 사용방법
19. NVIDIA 그래픽 카드 설치 방법(상세)
20. CUDA Toolkit 9.0 Download
21. Tensorflow getting started 1.5
22. cuDNN Download
23. Installing Tensorflow on Ubuntu
24. How to benchmark your GPU on Linux


P.S. How to install tensorflow and keras on Ubuntu 16.04
GPU = GTX 1070 (note book)

1. install NVIDIA driver and CUDA 9.0
refer to No.16

2. if there is login loop, restore NVIDIA driver
sudo apt-get purge nvidia-*
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt-get update
sudo apt-get install nvidia-384

3. install cuDNN for CUDA 9.0
4. install pip and tensorflow
5. install pyton library
6. install keras