블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 


Data Preprocessing in ML Pipeline


본글은 구글 클라우드 블로그에 포스팅한 글을, 재 포스팅 허가를 받은 후 포스팅한 글입니다.

다른 좋은 글들도 많으니 아래 출처 링크를 참고해 주새요

출처 링크


머신러닝 파이프라인에서, 데이터는 모델 학습 및 서빙의 입력에 알맞게 가공되어야 한다. 이를 전처리라고 하는데, 이번 글에서는 전처리에 대한 개념과 이에 대한 구현 옵션등에 대해서 알아보도록 한다.

처리 단계별 데이터 분류

머신러닝에서 데이터 전처리는 모델 학습에 사용되는 데이터 형태로 데이터를 가공하는 과정을 이야기한다.

데이터 전처리는 여러 단계로 이루어지는데, 단계별로 처리된 데이터에 대해서 다음과 같이 명명한다. 

Raw data

초기에 수집된 원본 데이터로 분석이나, 머신러닝 학습 용도로 전혀 전처리가 되지 않은 데이터를 의미한다.

하둡과 같은 데이터 레이크에 저장된 데이터나, 기본적인 처리를 통해서 테이블 구조로 데이터 레이크에 저장된 데이터가 Raw 데이터에 해당한다.

Prepared data

Prepared data는 Data engineering 전처리에 의해서, 학습을 위한 데이터만 추출한 서브셋 데이터를 의미한다. 예를 들어 서울 20대 사용자의 구매 패턴을 머신러닝 모델로 만들고자 할때, 서울 20대 사용자 데이터만 추출한 경우 이 데이터를 Prepared data라고 한다. 단순하게 서브셋만을 추출하는 것이 아니라, 깨끗한 상태의 데이터로 정재된 데이터인데, 정재의 의미는 비어 있는 행이나 열을 삭제한 데이터를 의미한다. 

Engineered feature

이렇게 정제된 데이터는 머신러닝 학습과 서빙에 적절한 형태로 재가공 되어야 하는데 이를 Feature Engineering 이라고 한다. 예를 들어 숫자와 같은 값을 0~1 사이로 맵핑 시키거나 , 카테고리 밸류 예를 들어 남자/여자를 0,1과 같은 값으로 맵핑 시키고, 전체 데이터를 학습,평가용으로 7:3 분할하여 저장하는 것이 이에 해당 한다. 



<그림. 데이터 전처리 단계 및 단계별 생성된 데이터 >

데이터 전처리 기법

그러면, 이 데이터 전처리 과정에서 구체적으로 어떤 기법으로 데이터를 처리할까? 몇가지 대표적인 기법을 정리해보면 다음과 같다. 

  • Data cleansing : 데이터에서 값이 잘못되거나 타입이 맞지 않는 행이나 열을 제거하는 작업을 한다. 

  • Instance selection & partitioning : 데이터를 학습,평가,테스트용 데이터로 나누는 작업을 한다. 단순히 나누는 작업 뿐만 아니라, 데이터를 샘플링 할때, 그 분포를 맞추는 작업을 병행한다. 예를 들어 서울/대구/부산의 선거 투표 데이타가 있을때, 인구 비율이 9:2:3이라고 할때, 전체 인구를 랜덤하게 샘플링해서 데이타를 추출하는 것이 아니라, 서울/대구/부산의 인구 비율에 따라서 서울에서 9, 대구에서 2, 부산에서 3의 비율로 샘플링을 할 수 있다. 이를 stratified partitioning 이라고 한다. 또는 데이터 분포상에서 특정 카테고리의 데이터 비율이 적을때, 이 카테고리에 대해서 샘플의 비율을 높이는 minority classed oversampling 등의 기법을 이 과정에서 사용한다. 

  • Feature tuning : 머신러닝 피처의 품질을 높이기 위해서 0~1값으로 값을 normalization 시키거나, missing value를 제거 하거나, 아웃라이어등을 제거하는 등의 과정을 수행한다.

  • Representation transformation : 피처를 숫자로 맵핑 시키는 작업을 한다. 카레고리컬 피처를 one hot encoding 등을 통해서 숫자로 맵핑하거나, 텍스트를 embedding 을 통해서 숫자로 변환하는 작업등을 수행한다. 

  • Feature extraction : PCA와 같은 차원 감소 기법을 이용하여, 전체 피처의 수를 줄이는 작업을 수행하거나, 피처를 해시값으로 변환하여, 더 효율적인 피쳐를 사용하는 작업을 한다. . 

  • Feature selection : 여러개의 피처(컬럼)중에 머신러닝에 사용할 피처만을 선별한다. 

  • Feature construction : 기존의 피처를 기반으로 polynomial expansion 이나,  feature crossing 등의 기법을 이용하여 새로운 피처를 만들어낸다. 

데이터 전처리 단위

Instance level transformation & Full pass transformation

데이터 전처리를 할때 어떤 단위로 데이터를 전처리 할지에 대한 정의이다. 예를 들어 숫자 데이터의 값을 0~1 사이로 맵핑하고자 하면, 그 데이터의 최소/최대 값을 알아야 0~1사이로 맵핑할 수가 있는데, 최소/최대값을 추출하려면, 전체 데이터에 대한 스캔이 필요하다. 반대로 NULL 값을 0으로 변환하는 작업은 전체 데이터에 대한 스캔이 필요없고 개별 데이터만 변환하면 된다. 앞에 설명한 전체 데이터에 대한 스캔이 필요한 방식을 full pass transformation 이라고 하고, 전체 데이터를 볼 필요 없이 개별 데이터에 대해 변환하는 작업을 instance level transformation이라고 한다. 


Window aggregation

전체 데이터의 볼륨이 클 경우 이를 윈도우 단위로 잘라서 처리할 수 있는 방법이 있는데, 예를 들어 10분 단위로 데이터를 처리해서, 10분 단위로 최소/최대 값을 구하거나 또는 10분 단위로 어떤 값의 평균값을 대표값으로 사용하는 것들이 이에 해당한다. 

일반적으로 입력값은 (entity, timestamp, value) 형태가 되며, 전처리된 출력 값은 다음과 같이. (entity, time_index, aggregated_value_over_time_window) 엔터티(피쳐)에 대해서 윈도우별로 처리된 값을 저장하는 형태가 된다.  보통 이런 window aggregation 방식은 리얼 타임 스트리밍 데이터에서 시간 윈도우 단위로 데이터를 처리하는 경우에 많이 사용이 되며, Apache Beam과 같은 스트리밍 프레임워크를 이용하여 구현한다. 

구글 클라우드에서 데이터 전처리 방식

이러한 데이터 전처리는 다양한 컴포넌트를 이용해서 처리할 수 있는데, 어떤 방식이 있는지 살펴보기 전에 먼저 구글 클라우드 기반의 머신러닝 학습 파이프라인 아키텍처를 살펴보자.  아래는 일반적인 구글 클라우드 기반의 머신러닝 파이프라인 아키텍처이다. 


<그림. 구글 클라우드 플랫폼 기반의 일반적인 머신러닝 학습 파이프라인 아키텍처 >


  1. 원본 데이터는 빅쿼리에 저장된다. (테이블 형태의 데이터가 아닌 이미지나 텍스트등은 클라우드 스토리지(GCS)에 저장된다.)

  2. 저장된 원본 데이터는 Dataflow를 이용해서 머신러닝 학습에 알맞은 형태로 전처리 된다. 학습/평가/테스트 셋으로 나누는 것을 포함해서, 가능하면 텐서플로우 파일형태인 *.tfrecord 형태로 인코딩 된후에, GCS 에 저장된다. 

  3. 텐서플로우등으로 모델을 개발한 후에, trainer-package로 패키징을 하고, AI Platform 트레이닝에 이 모델을 업로드 한다. 업로드된 모델을 앞서 전처리된 데이터를 이용해서 학습이되고, 학습이 된 모델은 GCS에 저장된다. (텐서플로우에서 SavedModel로 저장한다.)

  4. GCS 에 저장된 모델은 AI Plaform 서빙 엔진에 배포되고 REST API를 이용하여 서빙된다.

  5. 클라이언트에서는 이 REST API를 이용하여 학습된 모델에 대한 서빙을 이용한다.

  6. 전체 워크플로우에 대한 파이프라인 관리는 Apache Airflow 매니지드 서비스인 Composer 를 이용한다. 또는 머신러닝에 특화된 파이프라인이기 때문에, AI Platform pipeline을 사용하는 것이 좋다.

Option A: 빅쿼리에서 데이터 전처리

일반적으로 빅쿼리를 이용한 전처리는 다음과 같은 시나리오에 유용하다.

  • Sampling : 데이터에서 랜덤하게 일부 데이터셋만 가지고 오는 용도

  • Filtering : 학습에 필요한 데이터만 WHERE 문을 이용해서 가지고 오는 용도

  • Partitioning : 데이터를 학습/평가/테스트 용도로 나누는 용도

주로 빅쿼리는 Dataflow로 데이터를 인입하기 전체 최초 전처리 용도로 사용이 되는데, 주의할점은 빅쿼리에 전처리 로직이 많을 경우 향후 서빙에서 재 구현이 필요할 수 있다. 무슨 이야기인가 하면, 서빙시에도 입력 데이터에 대한 동일한 전처리가 필요한데, 빅쿼리에서 SQL로 작성한 전처리 로직은 서빙시에는 사용할 수 없기 때문에, 자바나 파이썬으로 전처리 로직을 다시 구현해야 하는 이중작업이 될 수 있다. 물론 서빙이 빅쿼리에 있는 데이터를 사용하는 배치 서빙일 경우 문제가 없지만, 리얼타임으로 단건의 데이터에 대해서 서빙을 하는 경우에는 빅쿼리에서 서빙용 데이터를 전처리할 수 없다. 


그럼에도 불구하고 배치 서빙용인 경우 전처리를 빅쿼리를 이용할 경우 편리하고 특히 Dataflow 에 데이터를 입력하기전에 Full pass transformation 이 필요한 전체 통계 데이터 (예를 들어 평균,분산,최소/최대값)은 SQL을 통해서 쉽게 뽑아낼 수 있는 장점이 있다. 

Option B: Dataflow 에서 데이터 전처리

복잡한 데이터 변환 로직이 있는 경우등에 효율적으로 사용할 수 있는 방식인데, Instance level transformation 뿐만 아니라, full pass transformation, 그리고 window aggregation 타입 모두를 지원할 수 있다.

Dataflow는 Apache Beam 오픈소스 기반의 런타임이지만, 다양한 구현 방식을 지원하고 있다.

  • Apache Beam을 사용하는 방법 : 가장 일반적인 방식으로 Apache Beam Java/Python SDK 을 이용하여 데이터 변환 로직을 구현할 수 있다.  

  • Tensorflow Transformation 을 사용하는 방법 : 텐서플로우의 경우 Tensorflow Transformation (이하 TFT) 이라는 이름으로 데이터 변환 프레임워크를 제공한다. TFT는 Apache Beam 기반으로 동작하는데, 텐서플로우 코드를 기반으로 하기 때문에, 머신러닝 개발자 입장에서는 접근이 상대적으로 쉬운 장점이 있다. 

  • Dataflow SQL을 사용하는 방법 : 앞의 두 방식의 경우에는 Java나 Python 기반의 코딩이 필요한데, 이런 코딩 없이 Window aggregation이나, 기타 복잡한 로직을 구현하고자 할때 사용할 수 있는 방식이 Dataflow SQL이다.SQL을 사용하여 구현하지만, Dataflow의 함수등을 사용할 수 있는 장점이 있다. 

  • Dataflow Template + UDF를 사용 하는 방법 : 복잡한 변환이 아니라 단순한 맵핑이나 문자열 변환들을 어렵지 않게 구현하는 방식으로 Dataflow는 Pre-built in 된 Template을 제공한다. 이 템플릿 중에는 비즈니스 로직을 자바스크립트로 넣을 수 있는 UDF 라는 방식을 지원하는데, Apache Beam 형태로 구현할 필요 없이 단순한 변환 로직을 자바스크립트로 구현하여 GCS에 파일을 저장하고, 설정 정보에서 자바 스크립트 파일만 지정하면되기 때문에, 쉽게 사용할 수 있다. 


서빙시에도 다양한 아키텍처 구현이 가능한데, Pub/Sub 큐를 통해서 데이터를 실시간으로 인입한 데이터를 머신러닝 모델로 서빙한후에, Pub/Sub으로 내보내는 near realtime 서빙이 가능하고 또는 bigtable에 서빙 결과를 저장하여 마치 serving 결과에 대한 캐쉬식으로 사용하는 구조도 가능하다.




<그림. 스트림 데이터를 이용하여 서빙을 제공하는 아키텍처>

Option C: Tensorflow 모델 내에서 데이터 전처리

아니면 데이터 전처리를 Tensorflow 모델 코드내에서 하는 방식이 있다.

  • feature_column 를 이용하여 피처를 임베딩하거나, 버킷화 하는 방식이 있고

  • 아니면 데이터를 피딩하는  input functions(train_input_fn, eval_input_fn, and serving_input_fn) 안에 데이터 전처리 로직을 구현하는 방법이 있다. 

  • Custom estimator를 사용하는 경우에는 model_fn 자체에 데이터 전처리 로직을 넣을 수 있다. 

이렇게 텐서 플로우 코드단에 전처리 기능을 넣는 경우는 Instance level transformation은 가능하지만 다른 방식에 대해서는 불가능하다. 그렇지만 이미지 데이터를 학습전에 rotation하거나 flip 하는 argumentation 등은 텐서플로우 코드에서 하게 되면 동적으로 데이터를 학습 단계에 argumentation할 수 있기 때문에 효율이 좋은 장점이 있다. 

Option D: DataPrep을 이용한 데이터  전처리

구글 클라우드 플랫폼에서는 데이터의 특성을 분석하고 간단한 변환을 지원하기 위한 wrangling 도구로 DataPrep을 제공한다. Engineered feature 단계까지 데이터를 가공하는 것은 어려울 수 있겠지만, Raw data를 Prepared data 형태로 cleansing 하는 용도로는 충분히 사용할 수 있으며, 특히 시각화를 통한 데이터 분포나 아웃라이어 분석이나 단순 변환등에는 효과적으로 사용할 수 있다.


<그림 DataPrep 을 이용한 Wrangling 과정 예시> 

Option E: DataProc을 이용한 데이터 전처리

DataProc은 Hadoop/Spark 에 대한 구글 매니지드 서비스이다. Apache Beam을 사용하는 Dataflow와 같이 코딩을 기반으로 한다는 점은 같지만, 기존에 Hadoop/Spark 에코 시스템에 익숙한 사용자들의 경우에는 기존의 에코 시스템과 개발 코드를 재활용할 수 있다는 장점을 가지고 있다. 

데이터 전처리시 고려할점

그러면 이러한 기술을 이용해서 데이터를 전처리할때, 고려해야하는 점은 무엇이 있을까?

학습/서빙 데이터에 대한 스큐(skew)

모델을 학습하여, 서비스에 배포한후에, 향후 들어오는 데이터로 서빙을 하게 되는데, 이때 학습에서 사용한 데이터와 서빙시 사용한 데이터의 특성이 다를때 이를 training-serving skew 라고 한다. 

예를 들어 피처 A가 학습시에 범위가 1~255 였는데, 서빙시에 1~500 사이로 들어오게 되면 이 모델의 서빙 결과는 정확하지 못하게 된다.

(참고 : 이런 문제를 해결하기 위해서 데이터의 분포나, 수학적 통계값을 저장해 놓은 후에, 서빙전에 검증하는 방식을 사용할 수 있으며 이는 Tensorflow data validation으로 구현이 가능하다. )

Full pass transformation

Option C의 텐서플로우 모델내의 데이터 변환 로직은 Full pass transformation을 지원하지 않기 때문에, feature scaling이나, normalization 적용이 불가능하다. 이러한 전처리 기법은 최소/최대값등의 통계 데이터가 필요한데, 이러한 데이터는 모델 학습전에 계산되어야 하고, 계산된 데이터는 어디에든 저장되어 있어야 하며, 학습과/서빙 단계에 모두 일관되게 사용될 수 있어야 한다. 

성능 향상을 위한 Up front data loading 

Option C 텐서플로우 모델내에 데이터 변환 로직을 구현할때, 고려해야 하는 사항이다.

모델 코드 상에 데이터 전처리 로직이 있을 경우, 아래 그림과 같이 데이터 변환 작업이 끝나면, 그 데이터로 모델을 학습 시키는 구조가 된다. 


<그림. 데이터 전처리가 모델 학습전에 발생하여, 대기하는 현상>


이 경우에 데이터가 전처리되고 있는 동안에는 학습이 이루어지지 않기 때문에 자원이 낭비되는 문제가 발생하고, 모델의 학습 시간에 전처리 시간까지 포함되기 때문에 전체 학습시간이 상대적으로 오래걸린다. 


Option B의 데이터 플로우를 사용하는 것처럼 미리 여러 학습에 사용될 데이터를 전처리를 해놓거나 아니면 아래 그림과 같이 병렬적으로 데이터 플로우에서 데이터를 전처리하면서 모델은 학습에만 전념하도록 하면, 모델의 전체학습 시간을 줄일 수 있다. 


<그림. 병렬로 데이타 전처리를 해서 모델 학습을 최적화 하는 방식>

이를 up front data loading 이라고 하는데, 텐서플로우에서는 Prefetching, Interleave, Parallel mapping 등을 tf.data.DataSet에서 다양한 방식으로 이를 지원하고 있다. 


Tensorflow Transform

텐서플로우 프레임웍은 이러한 데이터 변환을 위해서 Tensorflow Transform (이하 TFT) 라는 프레임웍을 데이터 전처리 기능을 제공한다. 이 TFT를 구글 클라우드에서 실행하게 되면, Dataflow를 기반으로 실행할 수 있다. (Option B) 

tf.Transform 이라는 패키지로 제공된다. TFT는 instant level transformation 뿐만 아니라, full pass transformation, window aggregation 을 지원하는데, 특히 full pass transformation을 지원하기 위해서 데이터를 변환하기 전에 Analyze 라는 단계를 거치게 된다. 

아래 그림이 TFT가 작동하는 전반적인 구조를 기술한것인데,



Analyze 단계에서는 데이터의 통계적인 특성 (최소,최대,평균 값등)을 추출하고, Transform 단계에서는 이 값을 이용하여, 데이터 변환을 수행한다. 각 단계는 tft_beam.AnalyzeDataset , tft_beam.TransformDataset 로 실행될 수 있으며, 이 두 단계를 tft_beam.AnalyzeAndTransformDataset 로 합쳐서 한번에 실행하는 것도 가능하다. 


  • Analyze 단계 : Analyze 단계에서는 통계적인 값을 Full pass operation 을 통해서 계산해내는 것이외에도, transform_fn을 생성해내는 작업을 한다. transform_fn은 텐서플로우 그래프로, 데이터 변환에 대한 instance level operation 을 계산해낸 통계값을 사용해서 수행한다. 

  • Transform 단계 : 데이터 변환 단계에서는 transform fn을 인입 데이터에 적용하여, instance level로 데이터를 변환하는 작업을 수행한다. 


모델 학습시 데이터에 대한 전처리는 학습 데이터뿐만 아니라, 평가 (Eval) 데이터에도 동일하게 적용이 되어야 하는데, Analyze는 학습데이터에만 적용되서 데이터의 특성을 추출하고, 평가 데이터에는 별도로 Analyze를 수행하지 않고, 학습 데이터에서 추출된 데이터 특성을 그대로 사용한다

TFT pipeline export  

transform_fn으로 구성된 데이터 변환 파이프라인은 내부적으로 텐서 플로우 그래프로 변환이 되는데, 학습된 텐서플로우 모델을 export 하여 SavedModel로 저장할때, 이 transform_fn 그래프가  서빙용 데이터 입력함수인 serving_input_fn에 붙어서 같이 export 된다. 이 말은, 학습에서 사용한 데이터 전처리 로직인 transform_fn이 그대로 서빙단에도 같이 적용된다는 이야기이다. 물론 full-pass transformation에서 계산한 통계값도 상수형태로 저장하게 된다. 그래서 입력값에 대해서 학습과 서빙시 같은 변환 로직을 사용할 수 있게 된다.

데이터 전처리 옵션 정리

앞서 설명한 데이터 변환 전처리 옵션을 Instance level transformation, full pass level transformation, window aggregation 에 따라 정리해보면 다음과 같다. 


Disclaimer

본 글의 작성자는 Google 직원입니다. 그러나 본 글의 내용은 개인의 입장에서 작성된 글이며, Google의 입장을 대변하지 않으며, Google이 본 컨텐츠를 보장하지 않습니다.


References






Instance-level transformation

(stateless transformation)

Full pass during training

instance -level during serving

(stateful transformation)

Real-time (window) aggregations

during training and serving 

(streaming transformation)

배치 서빙

온라인 서빙

배치 서빙

온라인 서빙

배치 서빙

온라인 서빙

BigQuery (SQL)

OK

같은 데이터 변환 로직을 학습과 서빙 단계에 적용 가능

가능은 하지만 권장하지 않음


서빙시에는 BigQuery가 아니라 다른 방식으로 데이터 변환 로직을 구현해야 하기 때문에 결과적으로 학습/서빙 Skew를 유발할 수 있음

가능


BigQuery에서 수학적 통계값(최소/최대)를 계산하여, 이 값을 이용하면 가능하다.

그러나 계산된 값을 별도로 저장해서 학습/서빙시에 사용해야 하기 때문에 구현이 번거롭다.

N/A

가능은 하지만 권장하지 않음


BigQuery의 윈도우 함수등을 이용하여 구현은 가능하지만, 서빙시에는 BigQuery가 아닌 다른 툴로 구현을 해야 하기 때문에 학습/서빙 Skew가 발생할 수 있음

Dataflow (Apache Beam)

OK

서빙시 데이터가 Pub/sub을 통해서 데이터 블로우로 들어오면 가능하지만, 그렇지 않은 경우 학습/서빙 데이터간 Skew가 발생할 수 있음

가능


Dataflow에서 수학적 통계값(최소/최대)를 계산하여, 이 값을 이용하면 가능하다.

그러나 계산된 값을 별도로 저장해서 학습/서빙시에 사용해야 하기 때문에 구현이 번거롭다.

OK


동일한 Apache Beam 기반의 데이터 변환 로직이 학습을 서빙시 적용이 가능함

Dataflow (Apache Beam + TFT)

권장함


학습과 서빙의 Skew를 방지할 수 있고, 학습/서빙전 데이터를 미리 준비할 수 있음

권장함


데이터 변환 로직과, 모델 학습시에 계산된 통계 결과 텐서플로우 그래프 형태로 저장되서, 서빙 모델을 export할시에 같이 저장됨

Tensorflow
(input_fn & serving_input_fn)

가능은 하지만 권장하지 않음


학습과 서빙 효율성을 생각하면, 학습전에 데이터를 변환하는게 좋음

가능은 하지만 권장하지 않음


학습과 서빙 효율성을 생각하면, 학습전에 데이터를 변환하는게 좋음

불가능

불가능


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

Wide and deep network 모델 활용하기

빅데이타/머신러닝 | 2017. 7. 20. 17:12 | Posted by 조대협


Wide & deep model 알아보기

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

Wide & deep model

이글에 설명된 예제는 https://www.tensorflow.org/tutorials/wide_and_deep  문서에 있는 코드를 활용하였습니다. 음식 검색 키워드와 검색 결과를 학습 시킨 후에 이 결과를 기반으로 사용자에게 음식을 추천해주는 서비스가 있다고 하자.

Monetization and Wide model (기억과 와이드 모델)

로지스틱 회귀 모델을 이용하여 추천 알고리즘을 작성하여 학습을 시킨 경우, 학습 데이타를 기반으로 상세화된 예측 결과를 리턴해준다. 예를 들어 검색 키워드 (프라이드 치킨)으로 검색한 사용자가 (치킨과 와플)을 주문한 기록이 많았다면, 이 모델은 (프라이드 치킨)으로 검색한 사용자는 항상 (치킨과 와플)을 추천해주게 된다.  즉 예전에 기억된 값 (Memorization된 값)을 통해서 예측을 하는데, 이러한 모델을 와이드 모델이라고 한다.



<그림 와이드 모델 >

그러나 (프라이드 치킨)으로 검색한 사용자에게 같은 패스트 푸드 종류인 햄버거나 프렌치프라이등을 추천해도 잘 구매가 되지만 와이드 모델은 기존에 기억된 결과로만 추천을 하기 때문에 이러한 결과를 얻기가 어렵다.


Generalization and Deep model (일반화와 딥모델)

뉴럴네트워크 모델의 경우 프라이드 치킨을 햄버거, 프랜치 프라이등을 일반화 시켜서 패스트 푸드로 분류하여 프라이드 치킨으로 검색을 해도 이와 같은 종류의 햄버거를 추천해도 사용자가 택할 가능성이 높다.


<그림 딥 모델>


이러한 모델을 딥모델이라고 하는데, 딥 모델의 경우 문제점이, 너무 일반화가(under fitting)  되서 엉뚱한 결과가 나올 수 있다는 것인데, 예를 들어서 따뜻한 아메리카노를 검색했는데, 커피라는 일반화 범주에서 아이스 라떼를 추천해줄 수 있다는 것이다. 즉 커피라는 일반화 범주에서 라떼는 맞는 추천일 수 있지만, 따뜻한 음료를 원하는 사람에게 차가운 음료를 추천하는 지나친 일반화가 발생할 수 있다.


그래서 이런 문제를 해결하기 위해서 와이드 모델과 딥모델을 합친 “Wide & deep model”이라는 것을 구글이 개발하였고 이를 구글 플레이 스토어에 적용한 결과, 큰 효과를 얻었다고 한다. (https://arxiv.org/abs/1606.07792)


<그림 와이드 앤 딥모델 >


모델 사용 방법

이 모델이 텐서플로우에서 tf.contrib.learn 패키지에 라이브러리 형태로 공개가 되었다.

Classification 용은 tf.contrib.learn.DNNLinearCombinedClassifier

Regression 용은 tf.contrib.learn.DNNLinearCombinedRegressor

를 사용하면 된다.


이 라이브러리들은 텐서플로우의 Esimator API (https://www.tensorflow.org/extend/estimators)인데, 복잡한 알고리즘을 구현할 필요 없이 불러다 쓸 수 있는 하이레벨 API 이면서 학습에서 중요한 다음 두가지를 도와준다.

  • 분산러닝
    멀티 GPU나 멀티 머신에서 분산학습을 하려면 직접 텐서플로우 코드를 써서 작업 분산 및 취합 작업을 해줘야 하는데, Estimator API를 사용할 경우 Experiment API 를 통해서 Google CloudML 인프라 상에서 이런 작업을 자동으로 해준다.

  • 모델 EXPORT
    그리고 학습된 모델은 운영환경에서 예측용으로 사용할때, 모델을 Export 하여 Tensorflow Serving 과 같은 예측 엔진에 배포해야 하는데, 모델을 Export 하려면, 예측에 사용할 텐서플로우 그래프를 다시 그려주고 변수 값을 채워넣는 것에 대한 코드를 작성해야 하는데 (자세한 설명은 http://bcho.tistory.com/1183 문서 참조), 이 역시도 자동화를 해준다.


자 이제 머신러닝 모델은  있으니 여기에 데이타 즉 적절한 피쳐만 제대로 넣어서 학습을 시키면 되는데, 와이드 모델과 딥모델 각각 학습 하기 좋은 피쳐가 따로 있다.

와이드 모델 학습용 피쳐

와이드 모델에는 카테고리(분류)와 같은 비연속성을 가지는 데이타가 학습에 적절하다. 카테고리성 컬럼의 경우에는 다음과 같이 크게 두 가지가 있다.

Sparse based column

성별, 눈동자의 색깔과 같이 비연속성을 지니는 값으로 학습에 사용하려면 이를 벡터화를 해야 한다.

예를 들어 남자 = [1,0] 여자는 = [0,1] 식으로 또는 검정눈 = [1,0,0], 갈색눈 = [0,1,0], 푸른눈 = [0,0,1] 식으로 벡터화할 수 있다.

이때는 다음과 같이 sparse_column_with_keys라는 메서드를 써주면 위와 같은 방식으로 인코딩을 해준다.

gender = tf.contrib.layers.sparse_column_with_keys(column_name="gender", keys=["Female", "Male"])

만약에 나이와 같이 연속형 데이타라도 이를 10대,20대,30대와 같이 구간으로 나눠서 비연속성 분류 데이타로 바꾸고자 할 경우에는 다음과 같이 bucketized_column을 사용하면 된다.

age_buckets = tf.contrib.layers.bucketized_column(age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])

Crossed column

다음은 crossed column 이라는 피쳐인데, 예를 들어 교육 수준과, 직업이라는 피쳐가 있다고 하자. 이를 각각의 독립된 변수로 취급할 수 도 있지만, 교육수준과 직업에 상관 관계가 있다고 할때 이를 관계를 묶어서 피쳐로 사용할 수 있다. 예를 들어 대졸 사원의 연봉, 컴퓨터 프로그래머의 연봉과 같이 독립된 특징으로 보는것이 아니라 대졸 컴퓨터 프로그래머, 대학원졸 컴퓨터 프로그래머와 같은 상관 관계를 기반으로 피쳐를 사용할 수 있는데 이를 Crossed column이라고 한다. Cross column은 다음과 같이 crossed_colmn이라는 메서드를 이용해서 정의할 수 있다.

tf.contrib.layers.crossed_column([education, occupation], hash_bucket_size=int(1e4))

딥 모델 학습용 피쳐

딥 모델용 학습데이타는 연속성을 가지는 데이타가 적절하다.

Continuous column

Continuous column은 일반적인 연속형 데이타 변수이고 간단하게 real_valued_column 메서드를 정해서 다음과 같이 정의가 가능하다.

age = tf.contrib.layers.real_valued_column("age")

Embedding column

문장의 단어들을 학습 시키기 위해서 각 단어를 벡터로 표현하고자 할때 , 예를 들어 boy = [1,0,0,0..], girl=[0,1,0,...] 으로 단어 하나를 하나의 숫자로 1:1 맵핑을 시킬 수 있다. 그러나 이 경우 이 단어가 다른 단어와 어떤 상관 관계를 갖는지 표현이 불가능하다. 예를 들어 남자:소년=여자:?? 라는 관계식을 줬을때, 위의 방식으로는 단어간의 관계를 유추할 수 없기 때문에, ?? 를 찾아낼 수 없다. 즉 컴퓨터가 “단어가 다른 단어와 어떤 차이점과 공통점”을 가지는지 이해할 수가 없다는 단점이 존재한다.

이런 문제를 해결하기 위해서 단어를 다차원 공간에서 벡터로 표현하여 각 단어간의 관계를 표현할 수 있는 방법을 만들었다.

이와 같은 원리로 어떤 비연속된 카테고리 피쳐들을 숫자로 맵핑할때, 위의 boy,girl 과 같은 방식 (on_hot_encoding) 으로 의미없이 1:1 맵핑을 하는 것이 아니라, 각 카테고리들이 어떠한 연관 관계를 가질때 이 연관성을 표현하여 벡터값으로 변환하는 방법을 임베딩 (embedding)이라고 한다.


그래서 카테고리내의 값들이 서로 연관성을 가질때는 임베딩을 이용하여 벡터 값으로 변경을 한 후, 이 값을 딥모델에 넣어서 학습하면 좋은 결과를 얻을 수 있다. 카테고리화된 값을 임베딩하기 위해서는 아래와 같이 embedding_column이라는 메서드를 사용하면 된다.


tf.contrib.layers.embedding_column(education, dimension=8)

피쳐를 모델에 넣는 방법

위와 같은 방법으로 분리되고 변경된 피쳐는, Wide & deep model에서 각각 와이드 모델과, 딥모델로 주입되서 학습되게 된다.

아래와 같이 피쳐를 와이드 컬럼과 딥 컬럼으로 구별한 후에, 리스트에 넣는다.

wide_columns = [
 gender, native_country, education, occupation, workclass, relationship, age_buckets,
 tf.contrib.layers.crossed_column([education, occupation], hash_bucket_size=int(1e4)),
 tf.contrib.layers.crossed_column([native_country, occupation], hash_bucket_size=int(1e4)),
 tf.contrib.layers.crossed_column([age_buckets, education, occupation], hash_bucket_size=int(1e6))

deep_columns = [
 tf.contrib.layers.embedding_column(workclass, dimension=8),
 tf.contrib.layers.embedding_column(education, dimension=8),
 tf.contrib.layers.embedding_column(gender, dimension=8),
 tf.contrib.layers.embedding_column(relationship, dimension=8),
 tf.contrib.layers.embedding_column(native_country, dimension=8),
 tf.contrib.layers.embedding_column(occupation, dimension=8),
 age, education_num, capital_gain, capital_loss, hours_per_week]

다음 딥모델용 피쳐 리스트와 와이드 모델용 피쳐 리스트를 DNNLinearCombinedClassifier 에 각각 변수로 넣으면 된다. 이때 딥 모델은 뉴럴네트워크이기 때문에, 네트워크의 크기를 정해줘야 하는데 아래 코드에서는 각각 크기가 100인 히든 레이어와 50인 레이어 두개를 넣어서 구성하도록 하였다.

m = tf.contrib.learn.DNNLinearCombinedClassifier(
   model_dir=model_dir,
   linear_feature_columns=wide_columns,
   dnn_feature_columns=deep_columns,
   dnn_hidden_units=[100, 50])



지금 까지 아주 간단하게 나마 Wide & deep model에 대한 이론 적인 설명과 이에 대한 구현체인 DNNLinearCombinedRegressortf.contrib.learn.DNNLinearCombinedClassifier 에 대해서 알아보았다.  이 정도 개념만 있으면 실제 Wide & deep model 튜토리얼을 이해할 수 있으니, 다음은 직접 튜토리얼을 참고하기 바란다. https://www.tensorflow.org/tutorials/wide_and_deep


Reference


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

머신러닝 모델 개발 삽질기

빅데이타/머신러닝 | 2017. 4. 24. 14:27 | Posted by 조대협

머신러닝 모델 개발 삽질 경험기


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


딥러닝을 공부하고 CNN 모델을 기반으로 무언가를 만들어보겠다는 생각에, 해외 유명 연예인 얼굴 사진을 가져다가 분류하는 얼굴 인식 모델을 만들어 보기로 하였다.

아직도 진행중이지만, 많은 시행 착오를 겪었는데 같은 시행 착오를 겪지 않고 경험을 공유하기 위해서 겪었던 시행 착오들을 정리해 본다.

학습 데이타 확보 및 분류

먼저 학습용 데이타를 수집 하는 것이 가장 문제 였다. 인터넷에서 사진을 모아서 학습 데이타로 사용해도 되겠지만, 아무래도 저작권 및 초상권 문제가 있고, 일일이 사진을 하나씩 받아서 수집하거나 또는 별도의 수집기를 만드는 것도 부담이 되었다.

그래서 찾은 것이 pubfig라는 셀럽 얼굴 데이타인데 http://www.cs.columbia.edu/CAVE/databases/pubfig/

상용 목적이 아니라 연구용 목적이면 사용이 가능하다. 이 데이타는 파일 URL, 셀럽 이름 형태로 라벨링이 되어 있기 때문에, 학습에 적합하리라고 생각하고, 이 파일을 기반으로 데이타를 수집하였다.


여기서 생긴 문제는, 이 데이타가 오래된 데이타라서 존재하지 않는 파일이 다수 있었고, 이 경우 파일을 저장하고 있는 사이트에서, 404 Not found와 같은 이미지를 리턴하였기 때문에, 이를 필터링해야 하였고, 같은 사진이 중복되서 오는 문제등이 있었기 때문에,상당량을 일일이 필터링을 해야 했다.


그리고, 사진상에, 여러 얼굴이 있는 이미지가 많았기 때문에, VISION API로 얼굴을 인식해서 얼굴 사진만 잘라낼 요량이었기 때문에, 독사진만을 일일이 보고 골라내야 했다. 나중에 생각해보니 VISION API로 얼굴이 한명만 인식이 되는 사진만 필터링을 했으면 됐을텐데. 불필요한 작업이 많았다.

라벨을 문자열로 쓴 문제

학습 데이타에 대한 라벨을 생성할때, 괜히 가독성을 높힌다고 라벨을 문자열로 해서 각 사람의 이름을 사용하였다.

CNN에서 마지막은 Softmax는 matrix이기 때문에, 라벨 문자열을 나중에 list.indexOf를 이용하여 배열로 변경할 예정이었는데, 파이썬에서는 쉽게 될지 몰라고, 텐서플로우 코드에서는 이 과정이 쉽지 않았다.

그래서..

결국은 라벨 데이타를 문자열이 아니라, 0~44의 int 값으로 재 생성한후에,


   batch_label_on_hot=tf.one_hot(tf.to_int64(batch_label),

       FLAGS.num_classes, on_value=1.0, off_value=0.0)


tf.one_hot 함수를 이용하여, 1*45 행렬로 바뀌어서 사용하였다.

학습용 및 검증용 데이타를 초기에 분류하지 않았던 문제

학습데이타를 준비할때, 학습 데이타를 학습용과 검증용으로 따로 분류를 해놨어야 하는데, 이 작업을 안해서, 결국 모델을 만들다가 다시 학습 데이타를 7:3 비율로 학습 데이타와 검증용 데이타로 분류하는 작업을 진행하였다.

학습 데이타의 분포가 골고르지 못했던 문제

사진을 모으는 과정에서 필터링 되서 버려지는 데이타가 많았고, 원본 데이타 역시 사람별로 사진 수가 고르지 못했기 때문에, 결과적으로 모여진 학습 데이타의 분포가 사람별로 고르지 못했다.

학습데이타가 많은 셀럽은 200~250장, 적은 사람은 50장으로 편차가 컸다.


이로 인해서 첫번째 모델의 학습이 끝난 후에, 모델을 검증해보니, 학습 데이타를 많이 준 사람으로 대부분 분류를 해냈다. 47개의 클래스 약 6000장의 사진으로 5시간 학습 시킨 결과, 예측을 검증하는 과정에서 90%이상을 모두 브래드피트로 인식해내는 문제가 생겼다. (내 맥북이 브레드피트를 좋아하는가??)


그래서 결과적으로 학습데이타와 검증 데이타를 클래스별로 분포를 같게 하기 위해서, 클래스당 약 50 장의 샘플 사진으로 맞춰서 예측 결과가 편중되는 현상을 해결하려고 하였다.

학습 순서가 클래스별로 된 문제

클래스별 학습 데이타의 양을 균일하게 맞췄음에도 불구하고, 모델의 학습 결과가 특정 클래스들로 편향되는 현상이 발생하였다.

이는 학습을 시킬때, 골고루 학습을 시켜야 하는데, 학습 데이타를 순서대로 학습을 시켰기 때문에 발생한 문제이다. 즉 풀어서 말하자면, “브래드 피트"를 20번 학습 시키고, “안젤리나 졸리"를 20분 학습 시키고, “브루스 윌리스”를 20번 학습 시켜서 모델이 첫 학습데이타 쪽으로 편향되는 현상이 발생한것인데, 이를 해결하려면 학습 데이타를 랜덤으로 만들어서 학습시켜야 한다.

예를 들어 “브래드 피트”,”안젤리나 졸리",”브루스 윌리스",”안젤리나 졸리",”브루스 윌리스", ”안젤리나 졸리",“브래드 피트” …. 이런식으로 말이다.

즉 코드 상에서 배치 데이타를 읽어올때 셔플 처리를 하면되는데 이를 위해서 데이타를 읽는 부분을 다음과 같이 변경 하였다.


def get_input_queue(csv_file_name,num_epochs = None):

   train_images = []

   train_labels = []

   for line in open(csv_file_name,'r'):

       cols = re.split(',|\n',line)

       train_images.append(cols[0])

       # 3rd column is label and needs to be converted to int type

       train_labels.append(int(cols[2]) )

                           

   input_queue = tf.train.slice_input_producer([train_images,train_labels],

                                              num_epochs = num_epochs,shuffle = True)

   

   return input_queue


get_input_queue 함수에, csv_file_name을 인자로 주면, 이 파일을 한줄 단위로 읽어서, 첫번째는 파일명, 세번째는 라벨로 읽은 후에, 각각 train_images와  train_lables에 각각 string과 int 형으로 저장한다

그 다음이 배열을 가지고 tf.train.slice_input_producer를 사용하면 배열에서 데이타를 읽어 드리는 input queue 를 생성하는데, 이때 인자로 shuffle = True로 주면 데이타를 리턴 할때 순차적으로 리턴하지 않고 셔플된 형태로 랜덤하게 리턴한다.


def read_data(input_queue):

   image_file = input_queue[0]

   label = input_queue[1]

   

   image =  tf.image.decode_jpeg(tf.read_file(image_file),channels=FLAGS.image_color)

   

   return image,label,image_file


다음으로, 이 큐를 이용하여 이미지 파일명과, 라벨을 읽어서 이미지 파일 데이타(텐서)와 라벨로 읽는 코드를 read_data라는 함수로 구현하였다. 입력값은 input_queue인데, input queue에서 데이타를 읽으면 첫번째는 이미지 파일명, 두번째는 라벨이 되는데, 첫번째 파일명을 tf.image.decode_jpeg함수를 이용하여 텐서로 읽은후, 읽은 이미지 데이타와 라벨을 리턴하였다.


def read_data_batch(csv_file_name,batch_size=FLAGS.batch_size):

   input_queue = get_input_queue(csv_file_name)

   image,label,file_name= read_data(input_queue)

   image = tf.reshape(image,[FLAGS.image_size,FLAGS.image_size,FLAGS.image_color])

   

   batch_image,batch_label,batch_file = tf.train.batch([image,label,file_name],batch_size=batch_size)

                                                      #,enqueue_many=True)

   batch_file = tf.reshape(batch_file,[batch_size,1])


   batch_label_on_hot=tf.one_hot(tf.to_int64(batch_label),

       FLAGS.num_classes, on_value=1.0, off_value=0.0)

   return batch_image,batch_label_on_hot,batch_file


마지막으로, 배치로 데이타를 읽는 함수 부분에서 앞에 정의한 get_input_queue와 read_data 함수를 이용하여 데이타를 shuffle 된 상태로 읽은 후에, tf.train.batch를 이용하여 일정한 개수 (배치) 형태로 리턴하도록 하였다.


그 결과 예측 결과가 한쪽으로 편향되는 현상을 없앨 수 는 있었다.

샘플 데이타의 부족

데이타 편향 현상은 잡았지만, 클래스의 수(45)에 대비하여, 샘플데이타의 수(클래스당 50개)로 부족하여, 학습을 계속 진행해도 cross entropy 함수는 4~7 사이에서 왔다갔다 하면서 더 이상 0으로 수렴하지 않았고 정확도되 0~35% 사이를 왔다갔다 하면서 수렴을 하지 않았다.


그래서, 학습 이미지의 색이나, 방향등을 변경하는 방법으로 데이타를 뻥튀기 하려고 하는데, 이 부분은 아직 작업중.

그외에 자잘한 삽질

모 그외에도 엄청 여러가지 삽질을 하고 있다. 그래도 모델 하나 제대로 만들어봐야 겠다는 생각에 끝까지 우격다짐으로 진행하고 있지만, 학습을 돌다가 스크린 세이버나, 절전 모드로 들어가서 학습이 중단된 사례. 모델을 개발하다가 중간에 텐서 플로우 버전이 올라가서 코드를 수정한 일. 맥에서 개발하다가 윈도우 머신에 GPU로 바꿨더니, 파이썬 2.7이 아니라 파이썬 3.5만 지원을 해서, 2.7 코드를 모두 다시 고친일등.


머신러닝이 과학이나 수학보다 노가다라는데, 몸소 느끼는 중.


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

구글의 IOT 솔루션

클라우드 컴퓨팅 & NoSQL/M2M & IOT | 2017. 3. 10. 10:31 | Posted by 조대협


구글의 IOT 솔루션


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


오늘 샌프란시스코 구글 NEXT 행사에서 IOT 솔루션에 대한 소개가 있었는데, 내용이 괜찮아서 정리를 해놓는다.



구글의 특징은 안드로이드 플랫폼, 클라우드 , 분석 플랫폼, 개발자 에코 시스템  등 End to End 에 걸쳐서 상당히 다양한 포트폴리오를 가지고 있다는 것이 장점인데 이를 잘 녹여낸 아키텍쳐 구성이다.

디바이스 OS

IOT는 라즈베리파이와 같은 임베디드 디바이스를 사용하는 것이 일반적인데, 이런 임베디드 시스템 운용에 어려운 점중의 하나가 보안이다.

장비에 따라서 보안적인 문제가 없는지 체크를 해야 하고, 주기적으로 기능 및 보안에 대한 업데이트를 해줘야 하는데, 구글의 Android IOT (https://developer.android.com/things/index.html) 플랫폼은 이를 다 자동으로 해준다.


더구나, 기존의 모바일 안드로이드 플랫폼을 기반으로 하기 때문에, 안드로이드 개발자 풀을 그대로 사용할 수 있다는 장점이 있다.

이미 Android IOT 플랫폼은 인텔,라즈베리파이등 여러 디바이스 업체와 협업을 하면서 Certi 작업을 하고 있기 때문에 잘 알려진 플랫폼이라면 보안 테스트나 별도의 기능 테스트 없이 바로 사용이 가능하다.


백앤드

IOT의 백앤드는 구글 클라우드 플랫폼을 이용한다.

  • 디바이스로 부터 수집된 데이타는 Pub/Sub 큐에 저장된후

  • DataFlow 프레임웍을 통해서 배치나 실시간 스트리밍 분석이 되고

  • 분석된 데이타는 빅테이블이나 빅쿼리에 저장된다. 분석이나 리포팅을 위해서는 빅쿼리, 타임 시리즈 데이타나 고속의 데이타 접근을 위해서는 빅테이블이 사용된다.

  • 이렇게 저장된 데이타들은 구글의 머신러닝 프레임웍 텐서플로우의 클라우드 런타임인 CloudML을 사용해서 분석 및 예측 모델을 만들게 된다.



머신러닝을 등에 탑재한  디바이스

구글이 재미있는 점은 텐서플로우라는 머신러닝 프레임웍을 가지고 있다는 것인데, 애초부터 텐서플로우의 디자인은 서버 뿐만 아니라, 클라이언트 그리고 IOT 디바이스에서 동작하게 디자인이 되었다. 그래서 학습된 모델을 디바이스로 전송하여, 디바이스에서 머신러닝을 이용한 예측이 가능하다.

예를 들어 방범용 카메라를 만들었을때, 방문자의 사진을 클라우드로 저장하는 시나리오가 있다고 하자.

그런데 매번 전송을 하면 배터리나 네트워크 패킷 요금이 문제가 될 수 있기 때문에, 텐서 플로우 기반의 얼굴 인식 모델을 탑재하여 등록되지 않은 사용자만 사진을 찍어서 클라우드로 전송하게 하는 등의 시나리오 구현이 가능하다.


파이어 베이스 연동

동영상을 보다가 놀란점 중의 하나는 파이어 베이스가 Android IOT에 연동이 된다.

아래 그림은 온도를 측정해서 팬의 속도를 조정하는 시나리오인데, 우측 하단에 보면 파이어베이스가 위치해 있다.



센서로 부터 온도를 측정한 다음, 디바이스 컨트롤러로 온도 조정 명령을 내리는 것을 파이어베이스 메시징 서비스를 이용하도록 되어 있다.


결론

Android IOT 서비스 하나만 IOT 서비스로 내놓은 것이 아니라 구글 클라우드 플랫폼, 텐서플로우에 파이어베이스까지 구글의 기존의 노하우들을 묶어서 포트폴리오를 만들어 내었고, 더구나 이러한 기술들이 개발자 에코 시스템이 이미 형성이 되어 있는 시스템인 점에서, IOT 개발에 있어서 누구나 쉽게 IOT 서비스를 개발할 수 있게 한다는데, 큰 의미가 있다고 본다.


'클라우드 컴퓨팅 & NoSQL > M2M & IOT' 카테고리의 다른 글

구글의 IOT 솔루션  (0) 2017.03.10
TI의 IOT 개발용 센서 키트  (0) 2016.03.17
MQTT 서버 간단 공부 노트  (2) 2014.02.13
본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

텐서플로우 - 파일에서 학습데이타를 읽어보자#1


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


텐서플로우를 학습하면서 실제 모델을 만들어보려고 하니 생각보다 데이타 처리에 대한 부분에서 많은 노하우가 필요하다는 것을 알게되었다. MNIST와 같은 예제는 데이타가 다 이쁘게 정리되어서 학습 하기 좋은 형태로 되어 있지만, 실제로 내 모델을 만들고 학습을 하기 위해서는 데이타에 대한 정재와 분류 작업등이 많이 필요하다.


이번글에서는 학습에 필요한 데이타를 파일에서 읽을때 필요한 큐에 대한 개념에 대해서 알아보도록 한다.


피딩 (Feeding) 개념 복습


텐서플로우에서 모델을 학습 시킬때, 학습 데이타를 모델에 적용하는 방법은 일반적으로 피딩 (feeding)이라는 방법을 사용한다. 메모리상의 어떤 변수 리스트 형태로 값을 저장한 후에, 모델을 세션에서 실행할 때, 리스트에서 값을 하나씩 읽어서 모델에 집어 넣는 방식이다.



위의 그림을 보면, y=W*x라는 모델에서 학습 데이타 x는 [1,2,3,4,5]로, 첫번째 학습에는 1, 두번째 학습에는 2를 적용하는 식으로 피딩이 된다.

그런데, 이렇게 피딩을 하려면, 학습 데이타 [1,2,3,4,5]가 메모리에 모두 적재되어야 하는데, 실제로 모델을 만들어서 학습을할때는 데이타의 양이 많기 때문에 메모리에 모두 적재하고 학습을 할 수 가 없고, 파일에서 읽어드리면서 학습을 해야 한다.


텐서플로우 큐에 대해서

이러한 문제를 해결하기 위해서는 파일에서 데이타를 읽어가면서, 읽은 데이타를 순차적으로 모델에 피딩하면 되는데, 이때 큐를 사용한다.


파일에서 데이타를 읽는 방법에 앞서서 큐를 설명하면, 큐에 데이타를 넣는 것(Enqueue) 은 Queue Runner 라는 것이 한다.

이 Queue Runner가 큐에 어떤 데이타를 어떻게 넣을지를 정의 하는 것이 Enqueue_operation인데, 데이타를 읽어서 실제로 어떻게 Queue에 Enqueue 하는지를 정의한다.


이 Queue Runner는 멀티 쓰레드로 작동하는데, Queue Runner 안의 쓰레드들을 관리해주기 위해서 별도로 Coordinator라는 것을 사용한다.


이 개념을 정리해서 도식화 해주면 다음과 같다.


=


Queue Runner 는 여러개의 쓰레드 (T)를 가지고 있고, 이 쓰레드들은 Coordinator들에 의해서 관리된다. Queue Runner 가 Queue에 데이타를 넣을때는 Enqueue_op이라는 operation에 의해 정의된 데로 데이타를 Queue에 집어 넣는다.


위의 개념을 코드로 구현해보자


import tensorflow as tf


QUEUE_LENGTH = 20

q = tf.FIFOQueue(QUEUE_LENGTH,"float")

enq_ops = q.enqueue_many(([1.0,2.0,3.0,4.0],) )

qr = tf.train.QueueRunner(q,[enq_ops,enq_ops,enq_ops])


sess = tf.Session()

# Create a coordinator, launch the queue runner threads.

coord = tf.train.Coordinator()

threads = qr.create_threads(sess, coord=coord, start=True)


for step in xrange(20):

   print(sess.run(q.dequeue()))


coord.request_stop()

coord.join(threads)


sess.close()


Queue 생성

tf.FIFOQUEUE를 이용해서 큐를 생성한다.

q = tf.FIFOQueue(QUEUE_LENGTH,"float")

첫번째 인자는 큐의 길이를 정하고, 두번째는 dtype으로 큐에 들어갈 데이타형을 지정한다.

Queue Runner 생성

다음은 Queue Runner를 만들기 위해서 enqueue_operation 과, QueueRunner를 생성한다.

enq_ops = q.enqueue_many(([1.0,2.0,3.0,4.0],) )

qr = tf.train.QueueRunner(q,[enq_ops,enq_ops,enq_ops])

enqueue operation인 enq_ops는 위와 같이 한번에 [1.0,2.0,3.0,4.0] 을 큐에 넣는 operation으로 지정한다.

그리고 Queue Runner를 정의하는데, 앞에 만든 큐에 데이타를 넣을것이기 때문에 인자로 큐 ‘q’를 넘기고 list 형태로 enq_ops를 3개를 넘긴다. 3개를 넘기는 이유는 Queue Runner가 멀티쓰레드 기반이기 때문에 각 쓰레드에서 Enqueue시 사용할 Operation을 넘기는 것으로, 3개를 넘긴것은 3개의 쓰레드에 Enqueue 함수를 각각 지정한 것이다.

만약 동일한 enqueue operation을 여러개의 쓰레드로 넘길 경우 위 코드처럼 일일이 enqueue operation을 쓸 필요 없이

qr = tf.train.QueueRunner(q,[enq_ops]*NUM_OF_THREAD)

[enq_ops] 에 쓰레드 수 (NUM_OF_THREAD)를 곱해주면 된다.

Coordinator 생성

이제 Queue Runner에서 사용할 쓰레드들을 관리할 Coordinator를 생성하자

coord = tf.train.Coordinator()

Queue Runner용 쓰레드 생성

Queue Runner와 쓰레드를 관리할 Coordinator 가 생성되었으면, Queue Runner에서 사용할 쓰레드들을 생성하자

threads = qr.create_threads(sess, coord=coord, start=True)

생성시에는 세션과, Coordinator를 지정하고, start=True로 해준다.

start=True로 설정하지 않으면, 쓰레드가 생성은 되었지만, 동작을 하지 않기 때문에, 큐에 메세지를 넣지 않는다.

큐 사용

이제 큐에서 데이타를 꺼내와 보자. 아래코드는 큐에서 20번 데이타를 꺼내와서 출력하는 코드이다.

for step in xrange(20):

   print(sess.run(q.dequeue()))


큐가 비워지면, QueueRunner를 이용하여 계속해서 데이타를 채워 넣는다. 즉 큐가 비기전에 계속해서 [1.0,2.0,3.0,4.0] 데이타가 큐에 계속 쌓인다.

쓰레드 정지

큐 사용이 끝났으면 Queue Runner의 쓰레드들을 모두 정지 시켜야 한다.

coord.request_stop()

을 이용하면 모든 쓰레드들을 정지 시킨다.

coord.join(threads)

는 다음 코드를 진행하기전에, Queue Runner의 모든 쓰레드들이 정지될때 까지 기다리는 코드이다.

멀티 쓰레드

Queue Runner가 멀티 쓰레드라고 하는데, 그렇다면 쓰레드들이 어떻게 데이타를 큐에 넣고 enqueue 연산은 어떻게 동작할까?

그래서, 간단한 테스트를 해봤다. 3개의 쓰레드를 만든 후에, 각 쓰레드에 따른 enqueue operation을 다르게 지정해봤다.

import tensorflow as tf


QUEUE_LENGTH = 20

q = tf.FIFOQueue(QUEUE_LENGTH,"float")

enq_ops1 = q.enqueue_many(([1.0,2.0,3.0],) )

enq_ops2 = q.enqueue_many(([4.0,5.0,6.0],) )

enq_ops3 = q.enqueue_many(([6.0,7.0,8.0],) )

qr = tf.train.QueueRunner(q,[enq_ops1,enq_ops2,enq_ops3])


sess = tf.Session()

# Create a coordinator, launch the queue runner threads.

coord = tf.train.Coordinator()

threads = qr.create_threads(sess, coord=coord, start=True)


for step in xrange(20):

   print(sess.run(q.dequeue()))


coord.request_stop()

coord.join(threads)


sess.close()


실행을 했더니, 다음과 같은 결과를 얻었다.


첫번째 실행 결과

1.0

2.0

3.0

4.0

5.0

6.0

6.0

7.0

8.0



두번째 실행결과

1.0

2.0

3.0

1.0

2.0

3.0

4.0

5.0

6.0


결과에서 보는것과 같이 Queue Runner의 3개의 쓰레드중 하나가 무작위로 (순서에 상관없이) 실행되서 데이타가 들어가는 것을 볼 수 있었다.


파일에서 데이타 읽기


자 그러면 이 큐를 이용해서, 파일 목록을 읽고, 파일을 열어서 학습 데이타를 추출해서 학습 파이프라인에 데이타를 넣어주면 된다.

텐서 플로우에서는 파일에서 데이타를 읽는 처리를 위해서 앞에서 설명한 큐 뿐만 아니라 Reader와 Decoder와 같은 부가적인 기능을 제공한다.


  1. 파일 목록을 읽는다.

  2. 읽은 파일목록을 filename queue에 저장한다.

  3. Reader 가 finename queue 에서 파일명을 하나씩 읽어온다.

  4. Decoder에서 해당 파일을 열어서 데이타를 읽어들인다.

  5. 필요하면 읽어드린 데이타를 텐서플로우 모델에 맞게 정재한다. (이미지를 리사이즈 하거나, 칼라 사진을 흑백으로 바꾸거나 하는 등의 작업)

  6. 텐서 플로우에 맞게 정재된 학습 데이타를 학습 데이타 큐인 Example Queue에 저장한다.

  7. 모델에서 Example Queue로 부터 학습 데이타를 읽어서 학습을 한다.


먼저 파일 목록을 읽는 부분은 파일 목록을 읽어서 각 파일명을  큐에 넣은 부분을 살펴보자.

다음 예제코드는 파일명 목록을 받은 후에, filename queue에 파일명을 넣은후에, 파일명을 하나씩 꺼내는 예제이다.

import tensorflow as tf


filename_queue = tf.train.string_input_producer(["1","2","3"],shuffle=False)


with tf.Session() as sess:

   

   coord = tf.train.Coordinator()

   threads = tf.train.start_queue_runners(coord=coord,sess=sess)

   

   for step in xrange(10):

       print(sess.run(filename_queue.dequeue()) )


   coord.request_stop()

   coord.join(threads)


코드를 보면 큐 생성이나, enqueue operation 처리들이 다소 다른것을 볼 수 있는데, 이는 텐서플로우에서는  학습용 파일 목록을 편리하게 처리 하기 위해서 조금 더 추상화된 함수들을 제공하기 때문이다.


filename_queue = tf.train.string_input_producer(["1","2","3"],shuffle=False)


train.xx_input_producer() 함수는 입력 받은 큐를 만드는 역할을 한다.

위의 명령을 수행하면, filename queue 가 FIFO (First In First Out)형태로 생긴다.


큐가 생기기는 하지만, 실제로 큐에 파일명이 들어가지는 않는다. (아직 Queue Runner와 쓰레드들을 생성하지 않았기 때문에)

다음으로 쓰레드를 관리하기 위한 Coordinator 를 생성한다.

   coord = tf.train.Coordinator()

Coordinator 가 생성이 되었으면 Queue Runner와 Queue Runner에서 사용할 Thread들을 생성해주는데,  start_queue_runner 라는 함수로, 이 기능들을 모두 구현해놨다.

   threads = tf.train.start_queue_runners(coord=coord,sess=sess)

이 함수는 Queue Runner와, 쓰레드 생성 및 시작 뿐 만 아니라 Queue Runner 쓰레드가 사용하는 enqueue operation 까지 파일형태에 맞춰서 자동으로 생성 및 지정해준다.






Queue, Queue Runner, Coordinator와 Queue Runner가 사용할 쓰레드들이 생성되고 시작되었기 때문에,Queue Runner는 filename queue에 파일명을 enqueue 하기 시작한다.

파일명 Shuffling

위의 예제를 실행하면 파일명이 다음과 같이 1,2,3 이 순차적으로 반복되서 나오는 것을 볼 수 있다.

실행 결과

1

2

3

1

2

3

1

2

3

1


만약에 파일명을 랜덤하게 섞어서 나오게 하려면 어떻게해야 할까? (매번 학습시 학습데이타가 일정 패턴으로 몰려서 편향되지 않고, 랜덤하게 나와서 학습 효과를 높이고자 할때)

filename_queue = tf.train.string_input_producer(["1","2","3"],shuffle=False)

큐를 만들때, 다음과 같이 셔플 옵션을 True로 주면 된다.

filename_queue = tf.train.string_input_producer(["1","2","3"],shuffle=True)

실행 결과

2

1

3

2

3

1

2

3

1

1

지금까지 파일명을 지정해서 이 파일명들을 filename queue에 넣는 방법에 대해서 알아보았다.

다음은 이 file name queue에서 파일을 순차적으로 꺼내서

  • 파일을 읽어드리고

  • 각 파일을 파싱해서 학습 데이타를 만들고

  • 학습 데이타용 큐 (example queue)에 넣는 방법

에 대해서 설명하도록 한다.



본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. 2017.03.07 23:31  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  2. asht 2017.04.13 14:39  댓글주소  수정/삭제  댓글쓰기

    좋은 글 감사합니다. 정독하면서 공부중입니다!
    아직 잘 모르는 부분이 많아서요.. 한가지 질문을 드리고 싶은데
    enq_ops = q.enqueue_many(([1.0,2.0,3.0,4.0],) )
    enqueue_many 안에 데이터를 튜플로 넣는지,
    [1.0, 2.0, 3.0, 4.0] 뒤에 컴마를 적지 않고 하나의 리스트만 넣으면 왜 작동이 안되는지 궁금합니다.

  3. mnm 2017.09.06 21:29  댓글주소  수정/삭제  댓글쓰기

    큰 도움이 되었습니다. 감사드립니다.

  4. yell 2019.07.16 15:03  댓글주소  수정/삭제  댓글쓰기

    coordinator와 thread 개념 찾다가 이 블로그에 들어왔는데, 덕분에 queue와 thread, coordinator의 개념을 쉼게 이해할 수 있었습니다. 감사드려요. 저번에도 tensorflow정보 찾다가 이 블로그 들어와서 좋은 정보를 얻은 적이 있었어요ㅋㅋ 이렇게 명쾌하고 친절하게 설명하기 힘드셨을텐데 진짜 대단하세요. 항상 공부하시고 지식을 널리 알려주시는 점 존경스럽습니다!

머신러닝의 과학습 / 오버피팅의 개념


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


머신 러닝을 공부하다보면 자주 나오는 용어 중에 하나가 오버피팅 (Overfitting)이다.

과학습이라고도 하는데, 그렇다면 오버 피팅은 무엇일까?


머신 러닝을 보면 결과적으로 입력 받은 데이타를 놓고, 데이타를 분류 (Classification) 하거나 또는 데이타에 인접한 그래프를 그리는 (Regression) , “선을 그리는 작업이다.”

그러면 선을 얼마나 잘 그리느냐가 머신 러닝 모델의 정확도와 연관이 되는데, 다음과 같이 붉은 선의 샘플 데이타를 받아서, 파란선을 만들어내는 모델을 만들었다면 잘 만들어진 모델이다. (기대하는)


언더 피팅


만약에 학습 데이타가 모자라거나 학습이 제대로 되지 않아서, 트레이닝 데이타에 가깝게 가지 못한 경우에는 다음과 같이 그래프가 트레이닝 데이타에서 많이 떨어진것을 볼 수 있는데, 이를 언더 피팅 (under fitting)이라고 한다.



오버 피팅

오버 피팅은 반대의 경우로, 다음 그림과 같이 트레이닝 데이타에 그래프가 너무 정확히 맞아 들어갈때 발생한다.


샘플 데이타에 너무 정확하게 학습이 되었기 때문에, 샘플데이타를 가지고 판단을 하면 100%에 가까운 정확도를 보이지만 다른 데이타를 넣게 되면, 정확도가 급격하게 떨어지는 문제이ㅏㄷ.

오버피팅의 해결

이런 오버피팅 문제를 해결하는 방법으로는 여러가지가 있는데 대표적인 방법으로는

  • 충분히 많은 학습 데이타를 넣거나

  • 피쳐의 수를 줄이거나

  • Regularization (정규화)를 이용하는 방법이 있다.



그림 출처 : 출처 : https://kousikk.wordpress.com/2014/11/20/problem-of-overfitting-in-machine-learning/




본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. 김홍회 2017.06.16 06:02  댓글주소  수정/삭제  댓글쓰기

    피쳐의 수를 줄이거나 => "여기에 PCA등을 통해"를 앞에 넣어주면 좋을거 같아요.

수포자를 위한 딥러닝


#2 - 선형회귀분석을 통한 머신러닝의 기본 개념 이해


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


Linear Regression을 통한 머신 러닝의 개념 이해

거리에 따른 택시 요금 문제

머신러닝이란 무엇일까? 개념 이해를 돕기 위해서 선형 회귀 (Linear Regression)이라는 머신러닝 모델을 보자. 먼저 선형 회귀 (Linear regression)이 무엇인지 부터 이해를 해야 하는데, 쉽게 설명하자면 결과값 (output value)이 있고 그 결과값을 결정할 것이라고 추정되는 입력값 (input value)과 결과 값의 연관관계를 찾는 것이고 이를 선형 관계를 통해 찾는 방법이 선형 회귀 (Linear regression)이다.

예를 들어서 설명해보자, 택시 요금을 예로 들어보자,택시 요금은 물론 막히냐 마냐에 따라 편차가 있지만, 대부분 거리에 비례해서 요금이 부과된다. 그래서 결과값 (요금)과 입력값 (거리)의 관계를 찾아야 한다.


거리별 요금을 그래프로 나타내보면 대략 다음과 같은 분포를 띄게 된다

원본 데이타의 거리를 x_data 그리고, 그 거리에서 측정된 택시 요금을 y_origin 이라고 하자.



가설 (Hypothesis) 정의

거리와 요금이 서로 비례하기 때문에, 거리(x_data)와 요금(y_data)간의 상관 관계는 다음과 같이 일차 방정식과 형태의 그래프를 그리게 된다고 가정하자. W (Weight)는 그래프의 각도, b는 bias를 뜻한다

y_data = Wx_data + b

이 일차 방정식 형태로 대충 1차원 그래프를 그려보자 같은 형태로 아래와 같이 그래프를 그려봤다.


그래프를 그려보니 그래프의 각이 안맞는것 같다. 그래프의 각도와 높이를 보정해보자


그래프를 보정했지만 또 안 맞는 것 같다. 그렇다면 최적의 그래프의 각도 W와, 높이 B는 어떻게 찾아야 하는 것일까?

코스트(비용) 함수

우리가 구하고자 하는 그래프는 실제 값에서 그래프의 값까지 차이가 가장 작은 값을 구하고자 하는 것이다. 아래 그림을 보자, 아래와 같이 y_data=Wx_data +b와 같은 그래프를 그렸다고 하자.


원래 값에서 우리가 예측한 값의 차이는 

(원래값과 계산된 값의 차이) = 측정값 - 그래프의 값

인데, 차이를 d라고 하자. 그리고 그래프에 의해서 계산된 값은 y_data라고 하면 택시 거리 x_data 에서 원래 측정된 값을 y_orgin라고 해서 수식으로 나타내면,

d = y_data - y_origin

이 된다. 이때 측정값은 여러개가 있기 때문에 n이라고 하면  n번째 측정한 택시비와 산식에 의해서 예측된 값의 차이는 dn이 된다.


dn = y_data_n - y_origin_n


즉 우리가 구하고자 하는 값은 dn의 합이 최소가 되는 W와 b의 값을 구하고자 하는 것이다.

다르게 설명하면 실제 측정한값과, 예측한 값의 차이가 최소가 되는 W와 b를 구하고자 하는 것이다.

dn은 위의 그래프에서 처럼 그래프 위에도 있을 수 있지만 (이경우 dn은 양수), 그래프 아래에도 있을 수 있기 때문에, (이경우 dn은 음수). 합을 구하면, 예측 선에서의 실측값 까지의 거리의 합이 되지 않기 때문에, dn에 대한 절대값을 사용한다고 하자.

그리고 n이 측정에 따라 여러개가 될 수 있기 때문에, 평균을 사용하자.


( ABS(d1)+ABS(d2)+ABS(d3)+.....+ABS(dn)) ) / n


즉 우리가 구하고자 하는 W와 b는 위의 함수의 값이 최소가 되는 값을 구하면 된다.

이렇게 측정된 값에서 연산된 값간의 차이를 연산하는 함수를 비용 함수 또는 영어로 코스트 함수 (Cost function이라고 한다.


사람이 일일이 계산할 수 없이니 컴퓨터를 이용해서 W=0.1,0.2,0.3,.... b=0.1,0.2,0.3,..... 식으로 넣어보고 이 코스트 함수가 가장 최소화되는 W와 b의 값을 찾을 수 있다.

옵티마이져 (Optimizer)

코스트 함수의 최소값을 찾는 알고리즘을 옵티마이져(Optimizer)라고 하는데, 상황에 따라 여러 종류의 옵티마이져를 사용할 수 있다. 여기서는 경사 하강법 (Gradient Descent) 라는 옵티마이져에 대해서 소개하도록 하겠다.


경사 하강법

그러면 W와 b를 구할때 W와 b를 어떤식으로 증가 또는 감소 시켜서 코스트 함수의 최소값을 가장 효율적으로 찾아낼 수 있을까? 위에서 언급한것 처럼 W를 0.0에서 부터 ). 0.1씩 증가시켜나가고 b도 같이 0.0에서 부터 1씩 증가 시켜 나갈까? 무한한 컴퓨팅 자원을 이용하면 되기는 하겠지만, 이렇게 무식하게 계산하지는 않는다.

코스트 함수를 최적화 시킬 수 있는 여러가지 방법이 있지만, Linear regression의 경우에는 경사 하강법 (그레이언트 디센트 : Gradient descent)라는 방식을 사용한다. 경사하강법에 대해서는 자세하게 알필요는 없고 ”대략 이런 개념을 사용하는 구나” 하는 정도만 알면 된다.


경사 하강법을 사용하기 위해서는 위의 코스트 함수를,측정값과 예측값의 절대값의 평균이 아니라 평균 제곱 오차라는 함수를 사용한다.

이 함수는 형식으로 정의되는데, 평균 제곱 오차 함수 (Mean square error function)이라고 한다.


Cost =  Sum( (y_data_n - y_origin_n) ^ 2) / n


풀어서 설명하면, n 번째의 원래데이타(y_origin_n)와 예측 데이타(y_data_n)의 차이를 제곱(^2)해서, 이 값을 n으로 나눈 평균 값이다.

즉 이 Cost가 최소가 되는 W와 b값을 구하면 된다.

편의상 W하나만을 가지고 설명해보자. 위의 그래프를 W와 b에 대한 상관 그래프로 그려보면 다음과 같은 함수 형태가 된다.


이 그래프에서 W에 대한 적정값에 대한 예측을 시작하는 점을 위의 그림에서 파란 점이라고 하면, 경사 하강법은 현재 W의 위치에 대해서, 경사가 아래로 되어 있는 부분으로 점을 움직이는 방법이다. 어느 방향으로 W를 움직이면 Cost 값이 작아지는지는 현재 W위치에서 비용 함수를 미분하면 된다. (고등학교 수학이 기억이 나지 않을 수 있겠지만 미분의 개념은 그래프에서 그 점에 대한 기울기를 구하는 것이다. )


이렇게, 경사를 따라서 아래로 내려가다 보면 Cost 함수가 최소화가 되는 W 값을 찾을 수 있다. 이렇게 경사를 따라서 하강 (내려가면서) 최소값을 찾는다고 하여 경사 하강법이라고 한다.  


학습

코스트 함수가 정의 되었으면 실제 데이타 x_data_n과 y_data_n을 넣어서 경사하강법에 의해서 코스트 함수가 최소가 되는 W와 b를 구한다. 이 작업은 W값을 변화시키면서 반복적으로 x_data_n로 계산을 하여, 실제 측정 데이타와 가설에 의해서 예측된 결과값에 대한 차이를 찾아내고 최적의 W와 b값을 찾아낸다.

예측

학습 과정에 의해서 최적의 W와 b를 찾았으면 이제, 이 값들을 이용해서 예측 해보자

학습에 의해서 찾아낸 W가 1600, b가 2000이라고 하면, 앞의 가설에서 정의한 함수는 Wx*b였기 때문에, 예측 함수는 


y = Wx +b

거리에 따른 택시비 = W*(거리) + b

거리에 따른 택시비 = 1600 * (거리) + 2000

이 되고, 이를 학습된 모델 이라고 한다.


이제 예측을 수행해보자, 거리가 10km일 때 택시비는 얼마일까? 공식에 따라

택시비 = 1600 * 10km + 2000

으로, 18000원이 된다.

머신 러닝의 순서

지금까지 택시 거리와 택시비에 대한 문제를 가지고 머신 러닝에 대한 기본 원리를 살펴보았다.

이를 요약해서 머신 러닝이란 것이 어떤 개념을 가지고 있는지 다시 정리해보자.


기본 개념은 데이타를 기반으로해서 어떤 가설 (공식)을 만들어 낸 다음, 그 가설에서 나온 값이 실제 측정값과의 차이(코스트 함수)가 최소한의 값을 가지도록 변수에 대한 값을 컴퓨터를 이용해서 찾은 후, 이 찾아진 값을 가지고 학습된 모델을 정의해서 예측을 수행 하는 것이다.  


학습 단계

즉 모델을 만들기 위해서, 실제 데이타를 수집하고, 이 수집된 데이타에서 어떤 특징(피쳐)를 가지고 예측을 할것인지 피쳐들을 정의한 다음에, 이 피쳐를 기반으로 예측을 한 가설을 정의하고, 이 가설을 기반으로 학습을 시킨다.


예측 단계

학습이 끝나면 모델 (함수)가 주어지고, 예측은 단순하게, 모델에 값을 넣으면, 학습된 모델에 의해서 결과값을 리턴해준다.


지금까지 Linear regression 분석을 통한 머신러닝의 원리에 대해서 간략하게 알아보았다. 다음 다음장에서는 이 모델을 어떻게 프로그래밍 언어를 이용하여 학습을 시키고 운영을 하는지에 대해서 알아보도록 하겠다.



Thanx to 

이글은 딥러닝 전문가 김홍회 박사님(Ayden Kim - https://www.facebook.com/Ayden.Kim )이 검수해주셨습니다. 감사합니다.


본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. 2016.10.04 20:19  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  2. 나그네 2016.10.06 10:51  댓글주소  수정/삭제  댓글쓰기

    아무래도... 수학이 빠져버리니 gradient descent가 학습에서 어떻게 이용되는지에 대한 내용을 이해하기 힘드네요..
    암튼 수식 오류 찾아내서 알려 드립니다.
    Sum( ABS(d1+d2+d3+.....+dn) ) / n
    이 수식인데요. 절대값은 각 dn에 대해 따로 적용해야겠죠 그리고 이미 모든 dn들을 더했으니 Sum 기호는 필요 없을거 같습니다.
    또는 이렇게 바꿀수 있겠네요.
    (1/n)Sum_n[Abs(dn)]

  3. lopiter 2016.10.07 08:35  댓글주소  수정/삭제  댓글쓰기

    텐서플로우 책을보다가 어려운 부분이 많았는데 , 글을 읽고나니 조금은 더 잘이해가 되는것 같습나다.
    감사합니다.

  4. 피돌 2016.12.14 09:59  댓글주소  수정/삭제  댓글쓰기

    감사합니다. 수학을 모르지만 아직까지는 이해하기 쉽게 설명해주셨습니다.

머신 러닝 프레임웍에 대한 간단 정리


머신 러닝을 다시 시작해서 보다 보니 어떤 언어로 개발을 해야 하는지 의문이 들어서 페이스북 Server Side architecture 그룹에 올렸더니, 좋은 정보가 많이 들어왔다.

Matalab이나 R과 같은 언어는 수학 라이브러리가 풍부해서, 주로 모델을 만들어서 시뮬레이션 하는데 많이 사용되고

Python이 수학 라이브러리가 풍부해서 그런지 ML 부분에서 많이 사용되는데, Production 까지 올라가는 경우는 잘 못본거 같고, 주로 Python으로 모델을 프로토타이핑 하는 수준으로 사용되는 것으로 보인다. 아직까지 자세히는 보지 못했지만, 자바의 Spark이나 Mahout과 같은 분산 환경 지원성이 약하고, 언어의 특성상 다른 언어보다 성능이 떨어져서, 실제 Production은 다른 언어, 주로 자바를 많이 사용하는 듯 하다.


Python으로 ML을 하려면, numpy,matplot등 다양한 패키지를 설치해야 하는데, 이 경우 방화벽과 프록시가 있는 환경에서는 설치가 쉽지 않다. (몇시간을 무지 삽질했던 경험이.. Proxy를 설정해도 패키지 인스톨이 잘안되서)

Python의 경우 이런 주요 수학 라이브러리를 패키징해놓은 인스톨 패키징이 있는데

대표적으로 Continum의 아나콘다 http://continuum.io/downloads

http://www.scipy.org/ 등이 있다.

그리고 Python에서 많이 사용되는 ML 프레임웍으로는 http://scikit-learn.org/ 등이 있다.


각 언어별로 ML 지원 라이브러리와 사용 용도를 정리해놓은 글이 있다. https://github.com/josephmisiti/awesome-machine-learning


알고리즘을 직접 작성하는 경우가 대부분이겠지만, 왠만해서는 기존 알고리즘 보다 잘 만들기가 어렵기 때문에 기존 알고리즘을 잘 활용하거나 데이타 샘플링을 잘하거나 또는 구현 인프라를 최적화 하는 방안을 고려해볼 수 있겠고, 여러 알고리즘을 중첩 적용하여 조합 함으로써 좋은 결과를 이끌어내는 방법을 고려해볼 수 있겠다.
아울러 근래에는 클라우드에 ML 라이브러리를 제공하고 있기 때문에, Azure ML이나 IBM Watson등을 고려해볼 수 있다.

SSAG에서 관련된 몇가지 중요한 댓글 메모

하용호 참고로 애초에 분산환경을 활용하도록 만들어진 MLLib등을 제외하면, 자바든 C든 R이든 속도는 대동소이 합니다. 대부분 매트릭스 연산에 그쪽으로 최적화된 LAPACK이나 BLAS, 돈 좀 쓰면 MKL등의 라이브러를 가져다가 쓰게 되어 있어서요. 뭐랄까 다들 같은 육수집에서 육수 받아서 쓴다랄까. 파이썬 쓰세요 파이썬 ㅎㅎㅎ 으하핫

민경국 mvn clean package -DskipTests 가 문제없이 돌아가는 방화벽 상황이라면 제플린으로 스프크와 스파크ML 을 보시는 건 어떨지요?
mvn 명령 한방으로 제플린 + 스파크가 설치되니 학습하기 좋은것 같습니다.
...더 보기

서민구 R이 싫으면 파이썬이 좋은데 설치가 잘 안된다니 안타깝네요. Pandas, numpy, scipy, scikitlearn, nltk 정도만 있어도 좋은데요. 언어가 파이썬이라 개발자들이 쉽게 배우구요. 통계분석 라이브러리는 문서화가 미비하지만 scikitlearn 의 문서는 대단히 훌륭합니다.

KwangHo Yoon 몇년전에는 직접 구현하는 걸 선호했는데.. 지금은 python이나 R이 라이브러리가 너무 좋아서 저도 파이썬을 사용하고 있습니다. PredictionIO나 h2o를 사용하시면 hbase나 spark등의관리를 편하게 해주어서..대용량의 데이터를 처리할 때에도 머신 러닝에 더 집중하여 개발할 수 있습니다.h2o에도 위에서 말씀하신 제플린과 비슷한 h2o flow가 있는데..인터렉티브한 화면으로 예측 결과까지 제공합니다 https://www.youtube.com/watch?v=wzeuFfbW7WE



본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. newbornking87@gmail.com 2017.04.09 21:26  댓글주소  수정/삭제  댓글쓰기

    왓챠 라는 추천 시스템같은 경우 어떤 프레임 워크를 사용할까요?
    왓챠는 영화 추천 시스템 사이트 입니다. 이런종류의 추천 시스템은 전체적인 설계를 어떻게 하는지 궁금합니다

Numpy Install

빅데이타/머신러닝 | 2015. 2. 10. 01:31 | Posted by 조대협

NumPy 설치 하기


파이썬으로 머신 러닝을 구현하기 위해서는 수학 라이브러리인 numpy가 필요하다

설치는 

http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy 에서 *.whl 파일을 다운로드 받은후

pip install numpy-1.9.2rc1+mkl-cp27-none-win_amd64.whl (64 비트 기준)

으로 설치 하면 된다.



설치후 확인을 위해서는 위와 같이 from numpy import * 를 한후에, random.rand(4,4)가 제대로 실행되는지 확인하자


참고

머신러닝이나 빅데이타 분석을 위해서는 NumPy 뿐만 아니라 matplot등 다양한 수학 모듈을 깔아야 하는데, 방화벽등이 있거나 하면 깔기가 매우 까다롭다. (의존성 관계도 복잡하고). 그래서 수학용 모듈을 모아 놓은 파이썬 인스톨패키지가 있다. http://www.scipy.org/install.html

처음부터 이걸로 까는게 시간을 절약할 수 있는 방법일듯

본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. 감사합니다 2016.12.21 01:51  댓글주소  수정/삭제  댓글쓰기

    블로그 잘 보고 있습니다 유용한 정보 감사합니다

2015년 개발 트랜드-조대협

IT 이야기/트렌드 | 2015. 1. 12. 10:09 | Posted by 조대협

2015년 개발 트랜드


조대협입니다. 2015년 개발 트렌드에 대해서 간략하게 정리해봅니다. 여러 기술들을 보고 정리한 개인적인 생각이며, 앞으로 저도 집중하려고 하는 분야이기도 합니다.


애자일 및 협업 문화

애자일 과 수평 조직 기반의 개발 문화에 대한 현상은 올해에도 쭈욱 지속될 듯 합니다. 기존의 워터폴이나 경직된 조직 문화와 방법론으로는 현대의 빠른 서비스 개발을 따라갈 수 가 없져

애자일은 워낙 오래전 부터 언급되고 나온거라서 별도로 언급을 하지 않겠습니다만, 왜 이 부분을 2015년의 트랜드로 잡았느냐 하면, 국내 기업의 경우 애자일 프로세스만을 도입하는 것이 아니라, 조직의 구조나 문화 자체를 애자일 사상으로 옮겨가는 경우가 많이 보이기 때문입니다. 기존에 무늬만 애자일이었다면, 작년부터 올해까지는 애자일 문화를 적용하기 위한 직급을 없애고 직책(ROLE) 기반으로 일하기 위한 변화, 수평적 조직 구조, 그리고 스크럼 마스터와 프러덕트 오너등이 조직내에 점점 더 확실하게 자리 잡아 가는 것 같습니다.


MSA 아키텍쳐

작년 중반 부터 떠오르기 시작하더니 국내에도 많은 시스템들이 MSA 사상으로 구현되가고 있는 것들이 보입니다. 이제 시작 단계들로 보이는데, MSA를 적용을 하고 있는 조직들은 MSA가 가지고 있는 전통적인 문제들, 분산 트렌젝션에 대한 처리, 여러개의 API를 모아서 새로운 기능을 만들어내는 aggregation 개념들에서 많은 고민들을 하고 있는 것이 보입니다.

그리고 MSA를 개발하기 위한 개발환경을 셋팅하는데 많은 고민들을 하는데, MSA의 특성상 서버 컴포넌트가 많이 분산이 되고 폴리그랏(다양한 언어로 개발)현상이 조금씩 가속화 됨에 따라서, 이러한 복잡한 개발환경을 어떻게 개발자에게 전달할것인가가 새로운 키워드가 될 듯 합니다.

이에 대한 대안으로는 Docker등이 빠르게 떠오르고 있고, 사내/사외 개발용 클라우드를 구축 하는 움직임이 생기지 않을까 조심스럽게 점쳐 봅니다.

MSA를 적용함에 있어서 앞단에 api gateway (또는 proxy)역할을 하는 것들이 중요해지고 있는데, 현재는 대부분 직접 개발해서 사용하는 경우가 많습니다. 그 만큼 거기에 사용할 제대로된 제품이나 오픈소스가 없다는 것인데, (오픈소스는 현재 WSO2 api gateway, 상용 CA Layer7, 클라우드 기반 서비스 apigee) 아마 금년에는 이러한 needs 때문에 다양한 오픈소스가 나오지 않을까 조심스럽게 기대해봅니다. 2013년까지만 해도 API gateway 오픈 소스 제품들은 손에 꼽을 정도였는데, 작년말에 한번 만들어 볼까 하는 마음으로 살펴보니, 벌써 몇개의 오픈소스들이 시작되고 있더군요

그리고 MSA에 맞춰서, SpringBoot도 같이 올라가면서, 자바 진영의 개발 주류가 되지 않을까 생각해봅니다.


데이타 스트리밍 프로세스

빅데이타 영역은 하둡을 중심으로 어느정도 정리가 되었으나, 근래에 들어서 실시간 데이타 분석에 대한 니즈(needs)가 올라오면서 실시간 스트리밍 처리가 작년말부터 다시 주목 받는것 같습니다. 람다 아키텍쳐나 데이타레이크 아키텍쳐가 다시 언급되는 것도 같은 선상이라고 보는데, 금년에는 Storm,Spark 중심의 실시간 데이타 처리 기술이 다시금 부각되지 않을까 합니다.


머신 러닝의 보편화

머신 러닝은 수학 통계적인 지식이 있어야 접근할 수 있는 분야였지만, 근래에는 Apache Mahout등의 프레임웍으로, 주로 사용되는 머신 러닝 알고리즘 들은 대부분 프레임웍화 되어 있어서 접근이 매우 쉽습니다. 약간의 지식만으로도 머신러닝을 사용할 수 있다는 겁니다.

여기에, Microsoft Azure ML 서비스와, IBM의 왓슨 서비스들은 클라우드 기반으로 머신 러닝 알고리즘을 서비스하는데, 사용이 매우 쉬워서, 일반 개발자들도 쉽게 머신 러닝 알고리즘을 구현 및 운영 환경에 적용이 가능합니다.

다른 빅데이타 분석들도 이런 흐름을 따라가지 않을까 싶은데 제가 보는 관점에서는 ML쪽이 선두가 되서 서비스화되는 현상이 작년말 부터 시작되고, 금년에는 초기 활성화 단계에 들지 않을까 합니다.


폴리 그랏

작년에도 그랬지만, 금년에도 여러가지 프로그래밍 언어를 사용하는 폴리그랏 현상은 더욱 더 가속되지 않을까 합니다. Node.js등은 계속해서 약진할거 같고, Ruby,Groovy와 같은 기존의 스크립트 언어 뿐만 아니라 Google Go, MS가 이번에 Linux까지 자사의 프로그래밍 언어를 지원하겠다고 한 이마당에, 금년에 프로그래밍 언어의 흐름은 지켜볼만 합니다.


기타

자바스크립트의 약진, 자바스크립트 기반의 Pure 웹 클라이언트, 클라우드의 적용 가속화

이런것들은 워낙 뻔한 이야기이니 별도로 언급하지 않겠다. 다만 마지막으로 지켜볼것은 중국 IT 기술의 약진으로, 금년에 중국발 오픈소스나 기술들이 인터넷으로 조금씩 공개되지 않을까 기대해봅니다.


 

본인은 구글 클라우드의 직원이며, 이 블로그에 있는 모든 글은 회사와 관계 없는 개인의 의견임을 알립니다.

댓글을 달아 주세요

  1. heon 2015.01.21 17:16  댓글주소  수정/삭제  댓글쓰기

    잘 보고 갑니다 ~

  2. 영준이 2015.10.04 05:29 신고  댓글주소  수정/삭제  댓글쓰기

    우와 정말 잘 보고갑니다!