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


Archive»


 
 

Wide and deep network 모델 활용하기

빅데이타/머신러닝 | 2017.07.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.04.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.03.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)에 넣는 방법

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



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


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


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

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


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

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


언더 피팅


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



오버 피팅

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


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

오버피팅의 해결

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

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

  • 피쳐의 수를 줄이거나

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



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




수포자를 위한 딥러닝


#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 )이 검수해주셨습니다. 감사합니다.


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


머신 러닝을 다시 시작해서 보다 보니 어떤 언어로 개발을 해야 하는지 의문이 들어서 페이스북 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



Numpy Install

빅데이타/머신러닝 | 2015.02.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

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

2015년 개발 트랜드-조대협

IT 이야기/트렌드 | 2015.01.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 기술의 약진으로, 금년에 중국발 오픈소스나 기술들이 인터넷으로 조금씩 공개되지 않을까 기대해봅니다.