빅데이타 & 머신러닝/머신러닝

얼굴 인식 모델을 만들어보자 #4 -클라우드를 이용하여 학습 시키기

Terry Cho 2017. 6. 22. 22:14

얼굴 인식 모델을 만들어보자 #4 클라우드를 이용하여 학습 시키기

(머신러닝 학습 및 예측 시스템의 운영환경화)


조대협 (http://bcho.tistory.com)

앞에서 모델을 만들고 학습도 다했다. 이제, 이 모델을 실제 운영 환경에서 운영할 수 있는 스케일로 포팅을 하고자 한다.


로컬 환경 대비 실제 운영 환경으로 확장할때 고려해야 하는 사항은


  • 대규모 학습 데이타를 저장할 수 있는 공간

  • 대규모 학습 데이타를 전처리하기 위한 병렬 처리 환경
    이 내용은 이미  http://bcho.tistory.com/1177에서 다루었다.

  • 대규모 학습 데이타를 빠르게 학습 시킬 수 있는 컴퓨팅 파워

  • 학습된 데이타를 이용한 대규모 예측 서비스를 할 수 있는 기능


위의 요건을 만족하면서 텐서플로우로 환경을 올리는 방법은 여러가지가 있지만, 클라우드를 선택하기로 한다.

이유는

  • 첫번째 모델 개발에 집중하고, 텐서플로우의 설치 및 운영 등에 신경쓰지 않도록 한다. 단순한 텐서플로우 설치뿐만 아니라 여러 장비를 동시에 이용하여 분산 학습을 하려면, 클러스터 구성 및 유지가 부담이 된다.

  • 클라우드 컴퓨팅 파워를 이용하여, 대규모 데이타에 대한 전처리를 수행하고 개개별 학습 속도를 높이는 것은 물론이고, 모델을 튜닝하여 동시에 여러 모델을 학습 시킬 수 있다.

  • 대용량 학습 데이타를 저장하기 위한 스토리지 인프라에 대한 구성 및 운영 비용을 절감한다.


즉 설정이나 운영은 클라우드에 맏겨 놓고, 클라우드의 무한한 자원과 컴퓨팅 파워를 이용하여 빠르게 모델을 학습하기 위함이다.

구글 클라우드


아무래도 일하는 성격상 구글 클라우드를 먼저 볼 수 밖에 없는데, 구글 클라우드에서는 텐서플로우의 매니지드 서비스인 CloudML을 제공한다.


CloudML은 별도의 설치나 환경 설정 없이 텐서플로우로 만든 모델을 학습 시키거나 학습된 결과로 예측을 하는 것이 가능하다. 주요 특징을 보면 다음과 같다.


  • 학습시에, 별도의 설정 없이 텐서플로우 클러스터 크기 조절이 가능하다. 싱글 머신에서 부터 GPU 머신 그리고 여러대의 클러스터 머신 사용이 가능하다

  • 하이퍼 패러미터 튜닝이 가능하다. DNN의 네트워크의 폭과 깊이도 하이퍼 패러미터로 지정할 수 있으며, CloudML은 이런 하이퍼패러미터의 최적값을 자동으로 찾아준다.

  • 예측 서비스에서는 Tensorflow Serv를 별도의 빌드할 필요 없이 미리 환경 설정이 다되어 있으며 (bazel 빌드의 끔직함을 겪어보신 분들은 이해하실듯) gRPC가 아닌 간단한 JSON 호출로 예측 (PREDICTION) 요청을 할 수 있다

  • 분당 과금이다. 이게 강력한 기능인데, 구글 클라우드는 기본적으로 분당 과금으로 CPU를 사용하던, GPU를 사용하던 정확히 사용한 만큼만 과금하기 때문에, 필요할때 필요한 만큼만 사용하면 된다. 일부 클라우드의 경우에는 시간당 과금을 사용하기 때문에, 8대의 GPU머신에서 1시간 5분을 학습하더라도 8대에 대해서 2시간 요금을 내야하기 때문에 상대적으로 비용 부담이 높다.

  • 가장 큰 메리트는 TPU (Tensorflow Processing Unit)을 지원한다는 것인데, 딥러닝 전용 GPU라고 생각하면 된다. 일반적인 CPU또는 GPU대비 15~30배 정도 빠른 성능을 제공한다.


    현재는 Close Alpha로 특정 사용자에게만 시범 서비스를 제공하고 있지만 곧 CloudML을 통해서 일반 사용자에게도 서비스가 제공될 예정이다.

CloudML을 이용하여 학습하기

코드 수정

CloudML에서 학습을 시키려면 약간의 코드를 수정해야 한다. 수정해야 하는 이유는 학습 데이타를 같이 올릴 수 없기 때문인데, 여기에는 두 가지 방법이 있다.


  • 학습 데이타를 GCS (Google Cloud Storage)에 올려놓은 후, 학습이 시작되기 전에 로컬 디렉토리로 복사해 오거나

  • 또는 학습 데이타를 바로 GCS로 부터 읽어오도록 할 수 있다.


첫번째 방법은 gsutil 이라는 GCS 명령어를 이용하여 학습 시작전에 GCS에서 학습 데이타를 카피해오면 되고,

두번째 방법은 학습 데이타의 파일명을 GCS 로 지정하면 된다.

예를 들어 텐서 플로우 코드에서 이미지 파일을 아래와 같이 로컬 경로에서 읽어왔다면

   image =  tf.image.decode_jpeg(tf.read_file(“/local/trainingdata/”+image_file),channels=FLAGS.image_color)


GCS에서 읽어오려면 GCS 경로로 바꿔 주면 된다. GCS 버킷명이 terrycho-training-data라고 하면

   image =  tf.image.decode_jpeg(tf.read_file(“gs://terrycho-training-data/trainingdata/”+image_file),channels=FLAGS.image_color)


첫번째 방법의 경우에는 데이타가 아주 많지 않고, 분산 학습이 아닌경우 매우 속도가 빠르다. 두번째 방법의 경우에는 데이타가 아주아주 많아서 분산 학습이 필요할때 사용한다. 아무래도 로컬 파일 억세스가 GCS 억세스 보다 빠르기 때문이다.


다음은 첫번째 방식으로 학습 데이타를 로컬에 복사해서 학습하는 방식의 코드이다.


https://github.com/bwcho75/facerecognition/blob/master/CloudML%20Version/face_recog_model/model_localfile.py

코드 내용은 앞서 만들 모델 코드와 다를것이 없고 단지 아래 부분과, 파일 경로 부분만 다르다

def gcs_copy(source, dest):

   print('Recursively copying from %s to %s' %

       (source, dest))

   subprocess.check_call(['gsutil', '-q', '-m', 'cp', '-R']

       + [source] + [dest]


gcs_copy 함수는 GCS의 source 경로에서 파일을 dest 경로로 복사해주는 명령이다.


def prepare_data():

   # load training and testing data index file into local

   gcs_copy( 'gs://'+DESTINATION_BUCKET+'/'+TRAINING_FILE,'.')

   gcs_copy( 'gs://'+DESTINATION_BUCKET+'/'+VALIDATION_FILE,'.')

   

   # loading training and testing images to local

   image_url = 'gs://'+DESTINATION_BUCKET+'/images/*'


   if not os.path.exists(FLAGS.local_image_dir):

        os.makedirs(FLAGS.local_image_dir)

   gcs_copy( image_url,FLAGS.local_image_dir)

   

prepare_data()    

main()


그리고 prepare_data를 이용해서, 학습과 테스트용 이미지 목록 파일을 복사하고, 이미지들도 로컬에 복사한다.

로컬에 데이타 복사가 끝나면 main()함수를 호출하여 모델을 정의하고 학습을 시작한다.



디렉토리 구조

코드를 수정하였으면, CloudML을 이용하여 학습을 하려면, 파일들을 패키징 해야 한다. 별 다를것은 없고


[작업 디렉토리]

  • __init__.py

  • {모델 파일명}.py


식으로 디렉토리를 구성하면 된다.

얼굴 학습 모델을 model_localfile.py라는 이름으로 저장하였다


명령어

이제 학습용 모델이 준비되었으면, 이 모델을 CloudML에 집어 넣으면 된다.

명령어가 다소 길기 때문에, 쉘 스크립트로 만들어놓거나 또는 파이썬 노트북에 노트 형식으로 만들어 놓으면 사용이 간편하다. 다음은 파이썬 노트북으로 만들어놓은 내용이다.


import google.auth

import os

import datetime


os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "/Users/terrycho/keys/terrycho-ml.json"

job_name = 'preparefacedata'+ datetime.datetime.now().strftime('%y%m%d%H%M%S')


리모트로 구글 클라우드의 CloudML을 호출하기 때문에, GOOGLE_APPLICATION_CREDIENTIALS에 서비스 어카운트 파일을 지정한다.

그리고 CloudML에 학습을 실행하면, 각 학습은 JOB으로 등록되는데, 손쉽게 JOB을 찾아서 모니터링 하거나 중지할 수 있도록, JOB ID를 현재 시간으로 생성한다.



print job_name

# Job name whatever you want

JOB_NAME=job_name

# the directory of folder that include your source and init file

PACKAGE_PATH='/Users/terrycho/anaconda/work/face_recog/face_recog_model'

# format: folder_name.source_file_name

MODULE_NAME='face_recog_model.model_localfile'

# bucket you created

STAGING_BUCKET='gs://terrycho-face-recog-stage'

# I recommand "europe-west1" region because there are not enough GPUs in US region for you.....

REGION='us-east1'

# Default is CPU computation. set BASIC_GPU to use Tesla K80 !

SCALE_TIER='BASIC_GPU'


# Submit job with these settings

!gcloud ml-engine jobs submit training $JOB_NAME \

--package-path=$PACKAGE_PATH \

--module-name=$MODULE_NAME \

--staging-bucket=$STAGING_BUCKET \

--region=$REGION \

--scale-tier=$SCALE_TIER \


다음은 cloudml 명령어를 실행하면 된다. 각 인자를 보면

  • JOB_NAME은 학습 JOB의 이름이다.

  • package-path는 __init__.py와 학습 모델 및 관련 파일들이 있는 디렉토리가 된다.

  • module-name은 package-path안에 있는 학습 실행 파일이다.

  • staging-bucket은 CloudML에서 학습 코드를 올리는 임시 Google Cloud Storage로, Google Cloud Storage 만든 후에, 그 버킷 경로를 지정하면 된다.

  • region은 CloudML을 사용한 리전을 선택한다.

  • 마지막으로 scale-tier는 학습 머신의 사이즈를 지정한다.

스케일 티어

설명

BASIC

싱글 머신. CPU

BASIC_GPU

싱글 머신 + K80 GPU

STANDARD_1

분산 머신

PREMIUM_1

대규모 분산 머신

CUSTOM

사용자가 클러스터 크기를 마음대로 설정


일반적인 모델은 BASIC_GPU를 사용하면 되고, 모델이 분산 학습이 가능하도록 개발되었으면 STANDARD_1 이나 PREMIUM_1을 사용하면 된다.


이렇게 명령을 수행하면 모델코드가 CloudML로 전송되고, 전송된 코드는 CloudML에서 실행된다.

학습 모니터링

학습이 시작되면 JOB을 구글 클라우드 콘솔의 CloudML 메뉴에서 모니터링을 할 수 있다.




다음은 CloudML에서의 JOB 목록이다.  (진짜 없어 보인다…)




실행중인 JOB에서 STOP 버튼을 누르면 실행중인 JOB을 정지시킬 수도 있고, View Logs 버튼을 누르면, 학습 JOB에서 나오는 로그를 볼 수 있다. ( 텐서플로우 코드내에서 print로 찍은 내용들도 모두 여기 나온다.)




여기까지 간단하게나마 CloudML을 이용하여 모델을 학습하는 방법을 알아보았다.

본인의 경우 연예인 인식 모델을 MAC PRO 15” i7 (NO GPU)에서 학습한 경우 7000 스텝가지 약 8시간이 소요되었는데, CloudML의 BASIC_GPU를 사용하였을때는 10,000 스탭에 약 1시간 15분 정도 (GCS를 사용하지 않고 직접 파일을 로컬에 복사해놓고 돌린 경우) 가 소요되었다. (빠르다)


여기서 사용된 전체 코드는 https://github.com/bwcho75/facerecognition/tree/master/CloudML%20Version 에 있다.


  • model_gcs.py 는 학습데이타를 GCS에서 부터 읽으면서 학습하는 버전이고

  • model_localfile.py는 학습데이타를 로컬 디스크에 복사해놓고 학습하는 버전이다.


다음 글에서는 학습된 모델을 배포하여 실제로 예측을 실행할 수 있는 API를 개발해보도록 하겠다.