Deep Learning Cluster with AWS for CPU

 

한국 지역 설정하기

sudo locale-gen ko_KR.UTF-8

tzselect

sudo apt-get install language-pack-ko

 

docker CE올리기

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository \
  "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) \
  stable"


sudo apt-get update
sudo apt-get install docker-ce

도커를 ubuntu계정에서 실행하게 변경(리붓해야지 반영됨)

sudo groupadd docker
sudo gpasswd -a ubuntu docker

 

우리 도커를 다운 받는다.

docker pull hoyai/hoyai_dev_docker:squashed

 

1번 서버는 nfs server를 올린다.

sudo apt-get install nfs-kernel-server

 

nfs 마운트 포인트를 만든다

sudo mkdir /var/nfs/hoya_src_root -p
sudo mkdir /var/nfs/hoya_model_root -p
sudo mkdir /var/nfs/hoya_str_root -p
sudo mkdir /var/nfs/hoyai_playground -p


sudo chown nobody:nogroup /var/nfs/hoya_src_root
sudo chown nobody:nogroup /var/nfs/hoya_model_root 
sudo chown nobody:nogroup /var/nfs/hoya_str_root

nfs conf

vi /etc/exports


/var/nfs/hoya_src_root   xx.xx.xx.xx(rw,sync,no_subtree_check)   xx.xx.xx.xx(rw,sync,no_subtree_check)
/var/nfs/hoya_model_root  xx.xx.xx.xx(rw,sync,no_subtree_check)   xx.xx.xx.xx(rw,sync,no_subtree_check)
/var/nfs/hoya_str_root   xx.xx.xx.xx(rw,sync,no_subtree_check)   xx.xx.xx.xx(rw,sync,no_subtree_check)

nfs reload 한다

service nfs-kernel-server reload

 

AWS에서 nfs용 Security group을 설정한다.

 

TCPPort (Service) Source 111 0.0.0.0/0  2049 0.0.0.0/0  32768 0.0.0.0/0  44182 0.0.0.0/0  54508 0.0.0.0/0

UDPPort (Service) Source 111 0.0.0.0/0  2049 0.0.0.0/0  32768 0.0.0.0/0  32770-32800 0.0.0.0/0

 

  • gpu에서 ap1번으로 붙는지 테스트 해봄

 

Hoya Docker cluster용(AP용) seciruty group 설정

Port (Service) Source Port (Service) Source 4369 0.0.0.0/0  25672 0.0.0.0/0  5672 0.0.0.0/0  2266 0.0.0.0/0  5432 0.0.0.0/0  8000 0.0.0.0/0  6006 0.0.0.0/0  8888 0.0.0.0/0  5901 0.0.0.0/0  5555 0.0.0.0/0

도커를 실행하면서, nfs 포인트로 올리고, 부팅시 자동으로 올라가게 하고, vnc확인하고, host도 확인하고,

도커를 재부팅시 자동으로 올라가게 설정 도커 이름은 hoyai_dev로 설정한다

docker run -itd --env="VNC_RESOLUTION=1920x1080" --env="DISPLAY" --env="QT_X11_NO_MITSHM=1" --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" --volume="/var/nfs/hoya_src_root:/hoya_src_root" --volume="/var/nfs/hoya_model_root:/hoya_model_root" --volume="/var/nfs/hoya_str_root:/hoya_str_root" --name hoyai_dev -p 4369:4369 -p 25672:25672 -p 5672:5672 -p 2266:2266 -p 5432:5432 -p 8000:8000 -p 6006:6006 -p 8888:8888 -p 5901:5901 -p 5555:5555 hoyai/hoyai_dev_docker:squashed

 

도커가 자동으로 올라가게 설정한다.

cd /etc/systemd/system/
 vi docker_hoyai.service
[Unit]
Description=hoyai container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a hoyai_dev
ExecStop=/usr/bin/docker stop -t 2 hoyai_dev

[Install]
WantedBy=default.target

도커 스타트업 스크립트

sudo systemctl enable docker_hoyai.service
   
   sudo systemctl start docker_hoyai.service

도커 서비스 삭제 스크립트

sudo systemctl disable docker_hoyai.service
  
  sudo systemctl stop docker_hoyai.service
sudo apt-get install nfs-common

 

도커 속에서 cluster 설정하기

hoyai/settings.py에서 DB를 AP1번을 보도록 설정

git에서 settings.py 추적 안하게 변경

git update-index --assume-unchanged hoyai/settings.py

 

각서버별로 장고가 뜨는지 확인

hosts파일을 만들어서 ap1, ap2, gpu1, gpu2에 배포

ssh를 활용해서 각각 서버에 붙는지 확인한다.

 

rabitmq cluster 연결을 위한 erlang cookie 맞추기

 

master에서 cooker를 보고, slave에 복사해준다

vi /var/lib/rabbitmq/.erlang.cookie

 

slave는 끄고

service rabbitmq-server stop

erlang cookie 복사하고

다시 스타트

service rabbitmq-server start

 

 

rabbitmq cluster를 확인한다.

rabbitmqctl cluster_status

 

hoya settings.py의 celery 설정 부분을 변경한다.

host는 master의 Docker id로 변경

CELERY_BROKER_URL = 'amqp://tensormsa:tensormsa@'+host+'//'

result_backend = 'db+postgresql://xxxxxxxxxxxxx'

 

entrypoint에 hosts파일 add하는것을 추가

echo "xxx.xxx.xxx" >> /etc/hosts

 

gpu1번을 ap1에 조인

rabbitmqctl stop_app

rabbitmqctl join_cluster --ram rabbit@16224139bcee


rabbitmqctl start_app

gpt2번을 ap1에 조인

rabbitmqctl stop_app

rabbitmqctl join_cluster --ram rabbit@16224139bcee

rabbitmqctl start_app

 

클러스터에서 빠지기

rabbitmqctl reset

 

 

 

 

 

 

 

client nfs 설치한다

sudo apt-get install nfs-common

 

부팅했을때 nfs가 자동으로 붙도록 설정

hoya_src_root, hoya_model_root, hoya_str_root 3개 디렉토리 설정

sudo mkdir /hoya_src_root -p
sudo mkdir /hoya_model_root -p
sudo mkdir /hoya_str_root -p

 

vi /etc/fstab
xx.xx.xx.xx:/var/nfs/hoya_src_root /hoya_src_root nfs hard 0 0
xx.xx.xx.xx:/var/nfs/hoya_model_root /hoya_model_root nfs hard 0 0
xx.xx.xx.xx:/var/nfs/hoya_str_root /hoya_str_root nfs hard 0 0

 

reboot 해서 df -h로 nfs가 잘 붙는지 확인한다

df -h

 

gpu Tensormsa Docker를 받는다

docker pull docker pull hoyai/hoyai_gpu_dev_docker:v1.0

 

gpu docker 를 실행한다.

nvidia-docker run -itd --env="VNC_RESOLUTION=1920x1080" --volume="/hoya_src_root:/hoya_src_root" --volume="/hoya_model_root:/hoya_model_root" --volume="/hoya_str_root:/hoya_str_root" --name hoyai_dev -p 4369:4369 -p 25672:25672 -p 5672:5672 -p 2266:2266 -p 5432:5432 -p 8000:8000 -p 6006:6006 -p 8888:8888 -p 5901:5901 -p 5555:5555 hoyai/hoyai_gpu_dev_docker:v1.0

docker 서비스를 올린다.

sudo gpasswd -a ubuntu docker

 

 

cd /etc/systemd/system/
 vi docker_hoyai.service

 

[Unit]
Description=hoyai container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/nvidia-docker start -a hoyai_dev
ExecStop=/usr/bin/nvidia-docker stop -t 2 hoyai_dev

[Install]
WantedBy=default.target

 

sudo systemctl enable docker_hoyai.service

sudo systemctl start docker_hoyai.service

 

sudo systemctl disable docker_hoyai.service

sudo systemctl stop docker_hoyai.service

 

AP1, GPU2, GPU2의 docker id와 IP를 찾는다.

[Env] Python3 – Konlpy

 – Env : Ubuntu, Conda3.5(Python 3.5) ,  Java1.8

1. install konlpy

pip install nltk-3.2.1
pip install konlpy-0.4.4

2. install open jdk

apt-get install openjdk-8-jdk

 3. install lib’s for compile

sudo apt-get install g++ python-dev

 4. install jpype with conda

conda install -c conda-forge jpype1

5. Mecab Install

https://bitbucket.org/eunjeon/mecab-ko-dic/downloads-dic/downloads

install mecab with konlpy

sudo apt-get install curl
bash <(curl -s https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh)

install gcc for c compile

conda install libgcc

install mecab dic

wget https://bitbucket.org/eunjeon/mecab-ko-dic/downloads/mecab-ko-dic-2.0.1-20150920.tar.gz
tar xzvf mecab-ko-dic-2.0.1-20150920.tar.gz
cd mecab-ko-dic-2.0.1-20150920
./configure 
make
sudo make install 

sudo ldconfig
ldconfig -p | grep /usr/local/lib

 

 

 

Tensorflow Examples (Jupyter Notebook)

Bellow lists will be linked to github which includes jupyter files.
Personally I believe  Blog is not a effective tool to explain Tensorflow codes, so I decide to just post links to my github.

[chap01] Explain basic concept of tensorflow, graph, variable types, session use

[chap02] Data handling numpy, tensorflow shape methods, storage connections

[chap03] Basic Models explain concept of “machine learning (Data driven)”

[chap04] Basic Neural Networks (DNN, CNN, RNN)

[chap05] Working on .. make custom Reinforcement (with out gym)

[chap06] Working on .. Word 2 Vec based examples

[chap07] Working on .. scikit learn samples

[chap08] Working on .. making custom scikit learn app with estimator

[chap09] Working on .. Tensorboard usages

[chap10] Working on .. Customize AI Painter open source

Plan to make some NLP (ChatBot or understand Context) stuffs ..

chap02_data_handling
chap03_basic_models
chap04_basic_neural_networks
chap05_basic_reinforcement
chap06_rnn_with_word2vec
chap07_basic_scikit_learn
chap08_scikit_custom
chap09_tensorboard
chap10_nueral_style

Pycharm – Watch limit size increase

For an intelligent IDE, it is essential to be in the know about any external changes in files it is working with – e.g. changes made by VCS, or build tools, or code generators etc. For that reason, IntelliJ platform spins background process to monitor such changes. The method it uses is platform-specific, and on Linux, it is the Inotify facility.

Inotify requires a “watch handle” to be set for each directory in the project. Unfortunately, the default limit of watch handles may not be enough for reasonably sized projects, and reaching the limit will force IntelliJ platform to fall back to recursive scans of directory trees.

To prevent this situation it is recommended to increase the watches limit (to, say, 512K):

1. Add the following line to either /etc/sysctl.conf file or a new *.conf file (e.g. idea.conf) under /etc/sysctl.d/ directory:

fs.inotify.max_user_watches = 524288

2. Then run this command to apply the change:

sudo sysctl -p --system

And don’t forget to restart your IDE.

Note: the watches limit is per-account setting. If there are other programs running under the same account which also uses Inotify the limit should be raised high enough to suit needs of all of them.

Docker – uwsgi – nginx – Django

 1. Assume
– Docker is already installed [Link]
– Django & it’s project is ready [Link]
– Postgres or MySQL is ready [Link]
– Python3
– CentOS 7

  2. Install Packages

yum install uwsgi
yum install nginx

 3. Create Uwsgi conf file
– Location : doesn’t matter , where you want..
– Name : whatever you want (*.ini)

[uwsgi]
project = firstsite
base = /home/user

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

master = true
processes = 5

socket = %(base)/%(project)/%(project).sock
chmod-socket = 664
vacuum = true

 4. Run Uwsgi

uwsgi ./<*.ini file> --emperor <Django Project Home> &

 5. Edit Nginx conf file
– Location : /etc/nginx/nginx.conf

server {
    listen <port>;
    server_name <servername>;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/dev/<project>/<project>/static;
    }

    location / {
        include         uwsgi_params;
        uwsgi_pass      unix:/home/dev/<project>/<project>.sock;
    }
}

 6. Run Nginx

/usr/sbin/nginx

 7. Test

http://<ip>:<port>

 

Apache – Django

A. Install packages

[python 2.7]

yum install httpd
yum install httpd-devel
yum install python-pip
pip install django
yum install mod_wsgi # case of python 2.7

[python 3.X]

yum install pcre-devel
wget http://mirrors.koehn.com/apache//httpd/httpd-2.4.23.tar.gz
tar xvzf httpd-2.4.23.tar.gz 
configure
make install

download site : https://github.com/GrahamDumpleton/mod_wsgi/releases

wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.5.7.tar.gz
tar xvzf 4.5.7.tar.gz
cd /<extract path>
./configure --with-apxs=/usr/local/apache2/bin/apxs
make install

B. Create Django Project

django-admin startproject django_demo

 C. Set mod_wsgi configuration

[python 2.7 – yum install httpd]

PATH : /etc/httpd/conf/

[python 3.x – manual install]

PATH : /usr/local/apache2

vi /etc/httpd/conf/httpd.conf

Listen <port>
IncludeOptional conf.d/*.conf
LoadModule wsgi_module modules/mod_wsgi.so

vi /etc/httpd/conf.d/django.conf

<VirtualHost *:80>

        WSGIScriptAlias / /opt/django_demo/django_demo/wsgi.py

        <Directory /opt/django_demo/django_demo>
        <Files wsgi.py>
                Require all granted
        </Files>
        </Directory>
</VirtualHost>

 D. Django wsgi.py

import os, sys


path = os.path.abspath(__file__+'/../..')

if path not in sys.path:

    sys.path.append(path)


from django.core.wsgi import get_wsgi_application


os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_demo.settings")


application = get_wsgi_application()
chmod 777 /<path>/wsgi.py

E. Restart Apache

sudo service httpd.service restart

[manual start]

/usr/sbin/httpd

F. give permission

cat /etc/passwd | awk -F: '{print $1}' | grep apache

sudo visudo


----------------------------
apache  ALL=(ALL)       ALL

G. Log

/var/log/httpd

 

Django reset migration

If you want to remove all database migration settings and start from zero base
you can use “migrate –fake”.
Follow the bellow process will helps you to reset your jango database env.

[delete migration file]

go to your app folder then you will see folder name “migration” delete all the contents inside that folder except __init__.py

[make new migrations]

python manage.py makemigrations

[reset migration]

python manage.py migrate --fake <app-name> zero

[migrate new data base]

python manage.py migrate

 

 

DJango – templates & static

가. 시작하기

장고에서 뷰를 개발하려고 하면 통상적으로 필요한 것이  html, js, css, img 정도가 될 것이다. 그럼 장고에서는 이러한 파일들을 어떻게 관리하고 개발하는지 세팅 부분까지만 정리하고자 한다

나. template 정의하기

[setting.py]

DIRS 부분에 templates 폴더의 위치를 지정해 준다.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'tfmsaview/templates/')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
[urls.py]

아래 부분을 추가해 template 에 접근 할 수 있도록 한다

  url(r'^view/index/$', ui_view.UI_Service.as_view()),

[예제 전체]

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^nn/cnn/service/$', rest_view.CNN_Service.as_view()),
    url(r'^nn/cnn/config/$', rest_view.CNN_Config.as_view()),
    url(r'^nn/cnn/data/$', rest_view.CNN_Data.as_view()),
    url(r'^nn/cnn/stastics/$', rest_view.CNN_Stastics.as_view()),
    url(r'^view/index/$', ui_view.UI_Service.as_view()),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
[폴더 및 파일 생성]

실제 폴더를 만들고 static 으로 사용할 파일을 넣어 준다. template 도 아까 정의한 것처럼 폴더를 생성하고 html 을 넣어 준다.

%ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2016-09-11-12-16-50

[html sample code]

template 안에서 static (js, css, img) 를 불러서 사용하려면 아래와 같은 패턴으로 사용하면 된다.

{% load staticfiles %}
{% static 'img/a.png' %}

아래는 전체 예제 코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% load staticfiles %}
<img src="{% static 'img/a.png' %}" alt="My image"/>
</body>
</html>

 다. STATIC 정의하기

기본적으로 3가지 정의는 필요하다. root 는 실제 서비스시 서버에서 이미지를 제공할 경로가 된다. url 은 urls.py 에서 정의하게 되는데 웹에서 접속시 접속 경로가 된다. dirs 는 사용자가 이미지를 올리고자 하는 위치가 된다. 뒤에서 커맨드를 실행하면 dirs 에 있는 파일이 root 로 자동으로 옮겨지는 것을 볼 수가 있다.

[settings.py]
STATIC_ROOT = os.path.join(BASE_DIR , 'tfmsaview/')
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "tfmsaview/static"),
]
 [urls.py]

아래부분을 추가해 준다. 이는 직접적으로 url 을 통해 이미지 등에 접근 할 수 있도록 도와준다

+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^nn/cnn/service/$', rest_view.CNN_Service.as_view()),
    url(r'^nn/cnn/config/$', rest_view.CNN_Config.as_view()),
    url(r'^nn/cnn/data/$', rest_view.CNN_Data.as_view()),
    url(r'^nn/cnn/stastics/$', rest_view.CNN_Stastics.as_view()),
    url(r'^view/index/$', ui_view.UI_Service.as_view()),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
[파일 생성]

settings.py 에 정의한 것 처럼 파일(js, css, img ) 등을 넣는다

%ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2016-09-11-12-16-50

[스태틱 파일들을 모아준다]

(/home/kim/anaconda2/) root@kim:~/PycharmProjects/TensorMSA# python manage.py collectstatic --noinput -i admin

 라. 테스트

다이렉트로 이미지에 접속도 잘 되었고, template 을 통한 이미지도 잘 접속 되었다.

%ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2016-09-11-12-26-34 %ec%8a%a4%ed%81%ac%eb%a6%b0%ec%83%b7-2016-09-11-12-26-46

 

TensorFlow – 기본문법 (6) – CNN Load & Predict

niektemme/tensorflow-mnist-predict

위 의 github 를 참조하였으며, 로컬에서 파일 로드, 배열 변환, 모델 로드 및 실행까지 간단하게 코드가 잘 정리되어 있습니다.  여기까지는 기본 구조를 파악하기 위함이었으니 기존예제들을 분석하는 위주로 진행하였지만, 다음부터는 가변적인 데이터 구조와 가변적인 모델을 감안한 개발을 시작하고자 합니다.

가. 로컬 이미지 로드 및 배열로 변환

def imageprepare(argv):
    """
    로컬에서 이미지를 받아서 Tensorflow 처리 가능한 형태로 변환하는 역할을 수행합니다.
    """
    im = Image.open(argv).convert('L')
    width = float(im.size[0])
    height = float(im.size[1])
    newImage = Image.new('L', (28, 28), (255))  # 우리가 테스트할 네트워크는 28/28 이미지이다

    # 입력된 28/28이 아닌 이미지를 28/28로 변환하기 위해 가로 세로 중 어느쪽이 큰지 확인
    if width > height:
        # 폭이 더 큰 경우 처리 로직
        nheight = int(round((20.0 / width * height), 0))  # resize height according to ratio width

        # 20/20 이미지로 변환하고
        img = im.resize((20, nheight), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
        wtop = int(round(((28 - nheight) / 2), 0))  #
        newImage.paste(img, (4, wtop))  # 리사이즈된 이미지를 흰색 바탕의 캔버스에 붙여 넣는다
    else:
        # 높이가 더 큰경우에 처리 로직
        nwidth = int(round((20.0 / height * width), 0))
        if (nwidth == 0):
            nwidth = 1
            # resize and sharpen
        img = im.resize((nwidth, 20), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
        wleft = int(round(((28 - nwidth) / 2), 0))
        newImage.paste(img, (wleft, 4))

    # newImage.save("sample.png")

    tv = list(newImage.getdata())  # 픽셀 데이터로 변환

    # 255의 RGB 0 흰색, 1 검은색의 이진수로 노멀라이제이션 작업을 수행
    tva = [(255 - x) * 1.0 / 255.0 for x in tv]
    return tva

나. 훈련시 사용한 모델을 동일하게 재 정의 합니다.

x = tf.placeholder(tf.float32, [None, 784])
    W = tf.Variable(tf.zeros([784, 10]))
    b = tf.Variable(tf.zeros([10]))

    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.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

다. 모델 복구 및 실행

init_op = tf.initialize_all_variables()
 saver = tf.train.Saver()

 """
 모델을 saver 를 사용하여 복구합니다.
 sess.run(init_op)
 saver.restore(sess, "model2.ckpt")
 """
 with tf.Session() as sess:
     sess.run(init_op)
     saver.restore(sess, "model2.ckpt")
     prediction = tf.argmax(y_conv, 1)
     return prediction.eval(feed_dict={x: [imvalue], keep_prob: 1.0}, session=sess)

전체 코드 링크