나만의 Tensorflow service 환경 만들기 Machine Learning for 정형 데이터

WRITTEN BY jeeHyunPaik 강사 소개

백지현

POSCOICT Manager [email protected] 목 차 나만의 tensotflow service 개발환경 만들기 첫번째, Tensorflow로 Web 서비스 하는 방법 두번째, Restful 을 위한 첫걸음 설정, nginx 설정 세번째, 비동기 처리를 위한 RabbitMQ와 Celery 첫번째, Tensorflow로 Web 서비스 하는 방법 Tensorflow로 서비스 하는 방법

AI Network를 만들었는데 어떻게 쓰지?

Tensorflow로 뉴로네트워크를 만들었는데 어떻게 다른 시스템과 연동하지? 훈련된 모델에게 여러 시스템이 Predict 을 요청할수 있을까?

여러 모델을 각각 훈련시킬수 있을까? Tensorflow로 서비스 하는 방법

TensorFlow Serving is a flexible, high-performance serving system for machine learning models, designed for production environments. TensorFlow Serving makes it easy to deploy new algorithms and experiments, while keeping the same server architecture and APIs.

Tensorflow Serving은 유연하고, 높은 성능을 보장하는 가동 환경에서 쓸수 있는 머신러닝 서비스 시스템

그러나 Tensorflow 밖에 안됨 Tensorflow로 서비스 하는 방법

https://www.djangoproject.com/

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.

- 정말 빠르고 - 웹 핸들링을 위한 모든게 준비되어 있으며 - 보안에 강력하며 - 스케일 가능하며 - 엄청나게 다목적인 프레임 워크 Tensorflow로 서비스 하는 방법

Neural Network를 서비스 하기 위해 기본 조건 - 훈련(Train) . 훈련할때 시간이 오래 걸리므로 여러 훈련 Task가 비동기적으로 실행가능

분산처리도 되면 좋음 - 예측(Predict) . Train과 상관없이 예측할 수 있어야함 . requests를 동시 처리 가능

여러 OpenSource 사용해서 종합해서 Service를 구축해보자

각각에 대해서는 뒤에서 설명 드리겠습니다. Tensorflow로 서비스 하는 방법 Docker-compose container 여럿을 사용하는 도커 애플리케이션을 정의하고 실행하는 도구

version: '3' services: web: nginx -> docker run --name some-nginx -d -p build: . 8080:80 some-content-nginx ports: - "5000:5000" volumes: posgres -> docker run --name some-app --link - .:/code some-postgres:postgres -d Docker Compose - logvolume01:/var/log 전환 application-that-uses-postgres links: - redis: <도커별로 실행하고, 실행 커맨드도 어려움> image: redis volumes: logvolume01: {}

Tensorflow로 서비스 하는 방법

Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a Compose file to configure your application’s services. Then, using a single command, you create and start all the services from your configuration. Tensorflow로 서비스 하는 방법

Docker-compose Image 종류 type name etc

was(Djnago) tf_edu_docker_skp:v1.2 modified

db postgres:latest official

httpd nginx:latest official

job tasker(Celery) tf_edu_docker_skp:v1.2 modified

message broker :latest official 두번째, Restful 을 위한 첫걸음 Django 설정, nginx 설정 Nginx, Django 설정 git clone

https://github.com/TensorMSA/skp_edu_docker.git

개발도커안의 Dockerfile 확인 Dockerfile

개발도커 내용 - Tensorflow 1.2.1 - python 3.5 - conda - nlp libraries(mecab, ngram) - jupyter Nginx, Django 설정 개발도커안의 폴더와 파일 내용 설명

Rest source 파일

환경설정 파일(주피터 암호설정)

Docker-compose 설정 파일

장고, 셀러리, 주피터 실행파일 Nginx, Django 설정 개발도커안의 pip 설치 파일을 확인

requirement.txt django==1.10.5 - django : was uwsgi==2.0.14 psycopg2==2.7.2 - psycopg2 : posgres library django_jenkins==0.110.0 django-rest-swagger==2.1.1 - django rest : restful for django djangorestframework==3.5.3 - celery : Task queue celery==4.0.2 django-celery==3.2.1 - gunicorn : Web Server gateway nltk==3.2.1 konlpy==0.4.4 - 각종 Machine learning library gensim==1.0.1 - 각종 NLP Library keras==2.0.2 flower==0.9.1 neo4j-driver==1.2.1 opencv-python==3.2.0.7 django-cors-headers==2.0.2 hanja==0.11.0 ngram==3.3.2 gunicorn==19.6.0 Nginx, Django 설정 0. 기존에 설정 되어 있는 파일과 폴더를 백업한다. 바꾼다.

mv code code_bk mkdir code mv docker-compose.yml docker-compose.yml_bk 1. docker-compose 를 생성 vi docker-compose.yml version: '3' docker-compose 를 BackGround로 올림 services: db: image: postgres:latest env_file: .env docker-compose up -d web: image: hoyai/tf_edu_docker_skp:v1.2 env_file: .env volumes: - ./code:/code - ./code/static:/static ports: - "8888:8888" < 실행결과 > - "8989:8989" - "5555:5555" ** 혹씨 다른 컨테이너가 올라가 있으면 port 충돌로 - "8000:8000" 에러가 발생할수 있음. Docker ps 로 확인후 depends_on: Container를 Stop 하자 - db Nginx, Django 설정 2. django project를 만든다. 꼭 docker-compose.yml이 있는 곳에서 실행. project 이름은 tfrest로 설정한다.

docker-compose exec web django-admin.py startproject tfrest .

3. DB접속을 위한 ./code/tfrest/setting.py 수정

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'postgres', 'USER': 'postgres', 'HOST': 'db', 'PORT': 5432, } } ALLOWED_HOSTS = ['*'] 4.. Django Postgres migation 수행 docker-compose.yml이 있는 곳에서 실행해야함

docker-compose exec web python manage.py makemigrations 이게 실행안되면 2번을 다른 위치에서 실행했을 docker-compose run web python manage.py migrate 가능성이 있음 code 디렉토리 지우고 2번부터 다시 실행 Nginx, Django 설정 4. Docker 안으로 들어가서 테스트 해보기

docker ps docker exec -it bash python /code/tfrest/manage.py runserver 0.0.0.0:8000

http://xxx.xx.xx.xxx:8000으로 확인한다.

Django runserver는 테스트용 서버이므로 ngnix로 교체 예정 Nginx, Django 설정 5. docker-compose 에 시작 스크립트 넣기

docker-compose down vi docker-compose.yml

command에 시작 스크립트 추가

docker-compose up -d web: image: hoyai/tf_edu_docker_skp:v1.2 env_file: .env http://xxx.xx.xx.xxx:8888으로 jupyter를 확인한다. volumes: - ./code:/code - ./code/static:/static ports: - "8888:8888" - "8989:8989" - "5555:5555" - "8000:8000" command: bash -c "(/run_django.sh &) && /run_jupyter.sh" depends_on: - db Nginx, Django 설정 6. Django Restful 설정 api app을 생성한다(꼭 docker-compose.yml이 있는 곳에서 실행)

docker-compose exec web python manage.py startapp api

api django app이 생성된다. settings.py django rest 설정 추가.

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', ] Nginx, Django 설정 7. restful Service를 위한 Tensorflow logic 파일 복사 Tensorflow와 rest api 코드를 복사한다

cd code/api/ cp ../../code_bk/api/tf* .

tf_service_exam.py → restful post, get, put, delete tf_service_celery.py → restful post, get, put, delete tf_service_logic.py → tensorflow logic tf_service_celery_logic_task.py → celery tensorflow logic

https://github.com/TensorMSA/skp_edu_docker/tree/master/code/api

code/api__init__.py 수정

from .tf_service_exam import TfExamService from .tf_service_celery import TfServiceCelry Nginx, Django 설정 Rest - 웹의 창시자(HTTP)중 한사람인 Roy Fielding의 2000년 논문에 의해서 소개 - 현재의 웹이 본래 설계의 우수성을 많이 활용하지 못하고 판단했기 때문에 웹의 장점을 최대한 활용할수 있는 아키텍처를 설계 - Representational safe transfer(Rest) - Uniform, Stateless, Cacheable, Self-descriptiveness, Client-Server, 계층형구조 특징

restful api - uri는 정보의 자원을 표현해야 한다(동사보다는 명사 사용) - 자원에 대한 행위는 http method로 표현한다.

POST POST를 통해 해당 URI를 요청하면 리소스를 생성합니다.

GET GET를 통해 해당 리소스를 조회합니다. 리소스를 조회하고 해당 도큐먼트에 대한 자세한 정보를 가져온다.

PUT PUT를 통해 해당 리소스를 수정합니다.

DELETE DELETE를 통해 리소스를 삭제합니다. Nginx, Django 설정 Tensorflow Code 설명 - Tensorflow는 변수와 연산자로 이뤄진 Graph 형태로 표현됨 - Session은 graph를 실행하기 위한 객체

session에 넣고 실행

restful 에서 구현할 메소드

tf.add(a,b) : a 와 b를 더함 tf.reduce_sum(100- ) : [0,~100] 리스트의 reduce_sum연산 Nginx, Django 설정 8. url pattern 설정 project root에 위치

vi /tfrest/urls.py

from django.conf.urls import url from django.contrib import admin from api import TfExamService as tf_service from django.views.decorators.csrf import csrf_exempt from api import TfServiceCelry as tf_service_celery

urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/test/type/example1/operator/(?P.*)/values/(?P.*)/', csrf_exempt(tf_service.as_view())), url(r'^api/test/type/celeryexam1/operator/fib/values/(?P.*)/', csrf_exempt(tf_service_celery.as_view())), ] Nginx, Django 설정 9. nginx와 django 연동 nginx 설정 파일 확인. 이미 git에 반영 시켜 놓았음

/config/nginx/tfrest.conf

upstream web { ip_hash; server web:8000; } # portal - 포트 : 8000번 server { - 장고 static 연동 location /static/ { autoindex on; alias /static/; } location / { proxy_pass http://web/; * * Static을 연결 안시키면 나중에 화면이 깨짐 } listen 8000; 각종 js files를 ngnix에서 access하게 설정해야함 server_name localhost; } Nginx, Django 설정 10. Django static 설정을 위한 Settings.py 수정

# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.10/howto/static-files/ STATIC_ROOT = os.path.join(BASE_DIR , 'static') STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, "api/static"), ]

11. Collect static 실행

code 디렉토리에서 실행 mkdir -p ./api/static (?) 물어보면 yes docker-compose run web python manage.py collectstatic Nginx, Django 설정 12. Docker-compose 에 nginx(웹서버)를 추가

nginx: image: nginx:latest ports: - "8000:8000" volumes: - ./code:/code - ./config/nginx:/etc/nginx/conf.d - ./code/static:/static depends_on: - web env_file: .env

web command: bash -c "(gunicorn tfrest.wsgi -b 0.0.0.0:8000 &)&&(flower -A tfrest &)&&/run_jupyter.sh;" 8000 ports 삭제 Nginx, Django 설정 13. docker-compose down & up

docker-compose down docker-compose up -d

http://xxx.xx.xx.xxx:8000:admin으로 접속 Django 설정 14. postgres migration 과 admin 설정

docker-compose exec web python manage.py makemigrations docker-compose exec web python manage.py migrate docker-compose exec web python manage.py createsuperuser

15. admin password 입력

admin

[email protected]

암호입력 2번 Django 설정 16. docker-compose stop, start admin 으로 접속 잘됨

17. docker-compose down 후 up admin 으로 접속 에러 두번째, Postgres을 위한 Docker Volumn Docker volume Docker Volume - Docker 데이터 볼륨은 데이터를 컨테이너가 아닌 호스트에 저장하는 방식 - 데이터볼륨은 컨테이너끼리 데이터를 공유하는데 주로 사용

- A data volume is a specially-designated directory within one or more containers that bypasses the Union File System. Data volumes provide several useful features for persistent or shared data: - Volumes are initialized when a container is created. If the container’s parent image contains data at the specified mount point, that existing data is copied into the new volume upon volume initialization. (Note that this does not apply when mounting a host directory.) - Data volumes can be shared and reused among containers. - Changes to a data volume are made directly. - Changes to a data volume will not be included when you update an image. - Data volumes persist even if the container itself is deleted. Postgrs & Docker volume 설정 18. docker volume 만들기

docker volume create --name=pg_data

docker volume 기타 명령어 docker volume ls

docker volume inspect

docker volume rm Postgres & Docker volume 설정 19. Data volume을 Postgres에서 바라 보도록 설정

db: image: postgres:latest env_file: .env volumes: - pg_data:/var/lib/postgresql/data/

volumes: pg_data: external: true

20. Docker-compose restart 후 확인 docker-compose down docker-compose up -d docker-compose exec web python manage.py makemigrations DB Data docker-compose exec web python manage.py migrate Container가 docker-compose exec web python manage.py createsuperuser 지워져도 유지가능 docker-compose down docker-compose up -d Postgres & Docker volume 설정 21. Rest api를 확인 predict는 get method로 처리

curl -X GET http://xx.xx.xx.xx:8000/api/test/type/example1/operator/add/values/1,2/

train은 post method로 처리

curl -X POST http://xx.xx.xx.xx:8000/api/test/type/example1/operator/add/values/300/ Postgres & Docker volume 설정 22. Train이 오래 걸리는 경우

curl -X POST http://xx.xx.xx.xx:8000/api/test/type/example1/operator/add/values/100000000/

post가 끝날때 까지 기다려야함…... 세번째, 비동기 처리를 위한 RabbitMQ와 Celery Celery Celery - Celery는 Python으로 작성된 비동기 작업 큐(Asynchronous task queue/job queue) RabbitMq - RabbitMQ는 표준 AMQP (Advanced Message Queueing Protocol)메세지 브로커 소프트웨어(message broker software) 오픈소스 - RabbitMQ는 erlang언어로 만들어졌을 뿐만 아니라, clustering과 failover를 위한 OTP framework로 구성 - RabbitMQ는 다양한 언어로된 RabbitMQ client를 지원 - 대용량 데이터를 처리하기 위한 배치 작업이나, 채팅 서비스, 비동기 데이터를 처리할때 사용

https://docs.google.com/presentation/d/ 185sirdtEzVm59oGAivd7vILeffn6ZeXA22 b6PXS1vM4/edit#slide=id.i61 Celery Rabbit MQ Flow

https://docs.google.com/presentation/d/185sirdtEzVm59oGAivd7 vILeffn6ZeXA22b6PXS1vM4/edit#slide=id.i61 Celery 설정 23. 개발도커에는 celery 관련 library가 설치 되어 있음 requirement.txt

djangorestframework==3.5.3 celery==4.0.2 django-celery==3.2.1

24. rabbitmq를 docker-composer에 올리기 docker-composer down docker-compose.yml

rabbit: hostname: rabbit image: rabbitmq:latest environment: - RABBITMQ_DEFAULT_USER=admin - RABBITMQ_DEFAULT_PASS=mypass depends_on: - web ports: - "5672:5672" # we forward this port because it's useful for debugging - "15672:15672" # here, we can access rabbitmq management plugin Celery 설정 25. RabbitMq 가동 docker-composer up -d & docker-compose ps Celery 설정

26. django에서 rabbit을 바라 볼수 있도록 settings.py 수정

vi tfrest/settings.py

BROKER_URL = 'amqp://admin:mypass@rabbit//' CELERY_ACCEPT_CONTENT = ['json'] CELERY_RESULT_BACKEND = 'db+sqlite:///results.sqlite' CELERY_TASK_SERIALIZER = 'json' CELERY_HIJACK_ROOT_LOGGER = False

27. celery 설정 파일을 만듬 from __future__ import absolute_import, unicode_literals import os from celery import Celery import logging from django.conf import settings vi tfrest/celery.py os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tfrest.settings')

app = Celery('tfrest') app.config_from_object('django.conf:settings') app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

CELERYD_HIJACK_ROOT_LOGGER = False Celery 설정

28. django Project에서 Celery 사용할수 있게 __init__.py 변경

vi tfrest/__init__.py

from __future__ import absolute_import, unicode_literals from .celery import app as celery_app

__all__ = ['celery_app'] Celery 설정

29. celery shared job을 설정(@shared_task) - celery task로 실행할 method에 @shared_task를 붙임 - rest에서 호출할때는 delay로 호출

from api.tf_service_celery_logic_task import train rom __future__ import absolute_import, unicode_literals import logging from celery import shared_task from .tf_service_logic import TfExamBackendService as tebs class TfServiceCelry(APIView): def post(self, request,values): @shared_task try : def train(num): logging.info("celery test start") print("train delay started") result = train.delay(int(values)) try: result_data = {"status": "200", "result": str(result)} tf_class = tebs() return Response(json.dumps(result_data)) tf_result = tf_class.tf_logic_train_reduce_sum(num) except Exception as e: except Exception as e: logging.error(str(e)) print(str(e)) raise tf_result = str(e) return tf_result Celery 설정

30. celery demon startup script - celery 서버는 ngnix 대신 celery를 실행해야 함 run_celery.sh #!/bin/bash

celery -A tfrest worker -l info

31. Docker-compose에 Celery 추가 run_celery.sh

celery: image: hoyai/tf_edu_docker_skp:v1.2 volumes: - ./code:/code command: bash -c "/run_celery.sh;" depends_on: - rabbit Celery 설정

32. docker-compose down & up docker-compose up -d Celery 설정

33. docker network 확인 docker network ls docker network inspect Celery 설정

33. Celery로 task 실행

curl -X POST http://xx.xx.xx.xx:8000/api/test/type/celeryexam1/operator/fib/values/100000000/

uri패턴을 모르면 urls.py 참조해서 호출

url(r'^api/test/type/celeryexam1/operator/fib/values/(?P.*)/', csrf_exempt(tf_service_celery.as_view())),

34. Celery 결과 확인 Celery 설정

35. Celery 작업 결과를 확인할수 있는 celery flower 설치 - 이미 개발 도커에 설치 되어 있음 requirement.txt

celery==4.0.2 flower==0.9.1

36. Django web에서 flower 같이 실행되게 Docker-compose 설정

docker-compose.yml

web: command: bash -c "(gunicorn tfrest.wsgi -b 0.0.0.0:8000 &)&&(flower -A tfrest &)&&/run_jupyter.sh;" Celery 설정

37. celery flower 접속 - http://xx.xx.xx.xx:5555

- post 호출

curl -X POST http://xx.xx.xx.xx:8000/api/test/type/celeryexam1/operator/fib/values/10/ Celery 설정

38. 여러개의 task가 순차적으로 실행되는것을 확인

작업결과 확인가능 Celery 설정

39. Docker-compose는 scale up 가능

docker-compose scale celery=5

scale 명령으로 celery를 순간 5개를 실행함 Celery 설정 - flower에서도 worker 가 순간 5개로 할당됨

- post 마구 실행

curl -X POST http://xx.xx.xx.xx:8000/api/test/type/celeryexam1/operator/fib/values/10/ 나만의 Tensorflow service 개발 환경 만들기 끝