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


Archive»


 
 


글은 제가 텐서플로우와 딥러닝을 공부하면서 블로그에 메모해놨던 내용을 모아놓은 글입니다.

혼자 공부하면서 어려웠던 점도 있었기 때문에, 저처럼 텐서플로우와 딥러닝을 공부하시는 분들께 도움이 되고자 자료를 공개합니다.

텐서플로우 초기버전부터 작성하였기 때문에, 다소 코드가 안맞는 부분이 있을 있으니 양해 부탁드리며, 글은 개인이 스터디용으로 자유롭게 사용하실 있으며, 단체나 기타 상용 목적으로 사용은 금지 됩니다.


머신러닝 이북-수포자를 위한 머신러닝.pdf.zip


혹시 이 교재로 공부하시다가 잘못된 부분을 수정하셨으면 다른분들을 위해서 친절하게 댓글을 달아주시면 감사하겠습니다.


그리고 오프라인 스터디 그룹을 진행하시는 분들을 위해서 지원을 해드립니다.

  • 발표용 프리젠테이션 파일
  • 실습 자료
  • 온라인 실습용 https://google.qwiklabs.com/catalog 토큰
스터디 지원을 위해서는 
1. https://www.facebook.com/groups/googlecloudkorea/ 구글 클라우드 사용자 그룹에 가입 하신후
2. https://www.meetup.com/GDG-Cloud-Korea 에 가입하신 후에, 스터디 모임을 매주 진행하실때 마다 밋업을 여시면 됩니다.
그후에, 저한테 페이스북으로 연락 주시면 https://www.facebook.com/terry.cho.7 제가 자료와 함께 실습 토큰 (무료 크레딧)을 제공해 드립니다.



Classification & Clustering 모델 평가


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


클러스터링과 분류 모델에 대한 성능 평가 방법은 데이타에 라벨이 있는가 없는가에 따라서 방법이 나뉘어 진다. 사실 클러스터링은 라벨이 없는 데이타에 주로 사용을 하고, 라벨이 있는 경우에는 분류 모델을 사용한다. 클러스터링 모델에 대한 평가는 라벨이 없는 상태에서 클러스터의 응집도등을 평가하는데 대부분 그 정확도가 그리 높지 않기 때문에, 도메인 지식을 가지고 있는 전문가에 의한 휴리스틱한 방식의 평가 방식이 대부분이다.


분류 모델(Classification) 에 대한 모델 평가

라벨이 있는 경우에는 분류 모델에 대한 모델 평가 방법을 사용한다.

Confusion matrix

이진 분류 문제에서 암의 양성과 음성 데이타를 가지고 있는 데이타 가 있다고 하자


만약 모델의 정확도가 100%이면, 양성과 음성 데이타를 100% 잘 구분할것이다. 아래 그림과 같이, 양성으로 분 예측된 영역을 Positive prediction, 음성으로 분리된 영역을 Negative prediction 이라고 한다.


그런데 실제 세계에서는 정확도 100% 모델은 매우 드물고 실제로는 아래 그림과 같이 예측이 되는 경우가 많다.


양성과 음성 데이타가 각각 잘못되는 경우가 있다.

  • 양성인데, 양성으로 제대로 검출된것은 True Positive (TP)

  • 음성인데 음성으로 제대로 검출된것은 True Negative (TN)

  • 양성인데 음성으로 잘못 검출된것은 False Negative (FN)

  • 음성인데 양성으로 잘못 검출된것은 False Positive (FP)


라고 하고 그림으로 표현하면 다음과 같은 그림이 된다.


보통 이를 표로 표시하는데, 다음과 같이 표현이 된다.




P = TP + FN

N = FP + TN


그러면 이 지표를 가지고 무엇을 하느냐? 이 값을 기반으로 다음과 같은 지표들을 계산하여 모델 평가에 사용한다.

Accuracy

가장 대표적으로 사용되는 지표로 전체 데이타중에서, 제대로 분류된 데이타의 비율로


ACC = (TP + TN)  / (전체 데이타 수 = P + N)


모델이 얼마나 정확하게 분류를 하는지를 나타낸다.


Error Rate

Error Rate는 Accuracy 와 반대로, 전체 데이타 중에서 잘못 분류한 비율을 나타낸다


ERR = (FN+FP) / (전체 데이타수 = P+N)


Sensitivity (Recall or True positive Rate)

민감도라고도 하는데, Sensitive 또는  Recall이라고도 하는데, 원래 Positive 데이타 수에서 Positive로 분류된 수를 이야기 한다. 에를 들어 원본 데이타에 암 양성이 100개 있었는데, 모델에 있어서 90개가 분류되었으면, Sensitive Rate = 0.9 가된다.


SN = (TP) / P


모델이 얼마나 정확하게 Positive 값을 찾느냐를 나타낸다.

Recall (as opposed to precision) is not so much about answering questions correctly but more about answering all questions that have answer "true" with the answer "true". So if we simply always answer "true", we have 100% recall.


Precision

Precision (정밀성)은 Positive로 예측한 내용 중에, 실제 Positive의 비율을 뜻한다.


PREC = TP / (TP+FP)


Precision is about being precise. In common English, being precise means: if you give an answer, the answer will very likely be correct. So even if you answered only one question, and you answered this question correctly, you are 100% precise.


Specificity (True negative rate)

Specificity 값은 Negative 로 판단한것중에, 실제 Negative 값의 비율이다.


SP = TN / TN+FP


False Positive rate

원래는 Positive 값인데, 잘못해서 Negative로 판단한 비율로


FPR = FP / N


이 된다. 예를 들어 게임에서 어뷰징 사용자를 검출했을때 정확도도 중요하겠지만, FPR 값이 높으면, 정상 사용자를 비정상 사용자로 검출하는 경우가 많다는 의미가 된다. 어뷰징 사용자에 대해서는 계정 정지등 패널티를 주게 되는데, 모델이 아무리 어뷰징 사용자를 잘 찾아낸다 하더라도 FPR 값이 높게 되면, 정상적인 사용자를 어뷰징 사용자로 판단하여 선의의 사용자가 징계를 받게 되서, 전체적인 게임 충성도에 문제가 생길 수 있다. (어뷰징 사용자를 많이 찾아내는 것보다, 정상 사용자가 징계를 받게 되는 경우가 비지니스에 크리티컬 할때) 이런 경우에 FPR 값을 레퍼런스 할 수 있다.



그러면, Confusion Matrix를 통해서 계산된 결과를 가지고 모델을 어떻게 평가를 할까? 앞에서 나온 지표중에서 일반적으로 Accuracy 지표가 많이 사용되고, 그외에, ROC , Precision Recall Plot, F-Score 등이 많이 사용되는데 각각에 대해서 알아보자

ROC (Receiver Operating Characteristics)

ROC 그래프는 가로축을 FP Rate (Specificity) 값의 비율로 하고 세로축을 TP Rate (Sensitive) 로 하여 시각화 한 그래프이다.


  • Specificity = TN / TN+FP

  • Sensitive (Recall) = (TP) / P




보통 다음과 같은 그래프가 되고



(출처 : http://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html )


그래프가 위로 갈 수록 좋은 모델이고, 적어도 Y=X 그래프보다 위에 있어야 어느정도 쓸모 있는 모델로 볼 수 있다. 아래 그래프는 3개로 결과를 분류하는 모델에 대한 ROC 그래프 이다.


(출처 : http://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html )


ROC 그래프가 class 0, class 2, class 1 순서로 높은것을 볼 수 있다. 즉 이 모델은 class 0 을 제일 잘 분류하고 그 다음은 2,1 순서로 잘 분류 한다는 의미가 된다.

ROC는 그래프이기 때문에, 모델을 정확도를 하나의 숫자로 나타내기 어려워서 AUC (Area Under Curve) 라는 값을 사용하는데, ROC AUC값은 ROC 그래프의 면적이 된다. 최대값은 1이 된다. 위의 그래프를 보면 모델 0,2,1의 AUC값은 0.91, 0.79, 0.60 이 된다.

Precision Recall Plot

Precision Recall Plot (이하 PR 그래프)의 경우도 ROC 와 유사한데, 주로 데이타 라벨의 분포가 심하게 불균등 할때 사용한데, 예를 들어 이상 거래 검출 시나리오의 경우 정상 거래의 비율이 비정상 거래에 비해서 압도적으로 많기 때문에 (98%, 2%) 이런 경우에는 ROC 그래프보다 PR 그래프가 분석에 더 유리하다.


PR 그래프는 X 축을 Recall 값을, Y축을 Precision 값을 사용한다.


  • Sensitive (Recall) = (TP) / P

  • Precision = TP / (TP+FP)



다음은 이진 분류 (binary classification)의 PR 그래프의 예이다. 그래프가 위쪽으로 갈수록 정확도가 높은 모델이고, ROC와 마찬가지로 PR 그래프의 AUC (면적)값을 이용하여 모델의 정확도를 평가할 수 있다.



(출처 : http://scikit-learn.org/stable/auto_examples/model_selection/plot_precision_recall.html)


그러면 모델이 쓸만한 모델인지 아닌지는 어떤 기준을 사용할까? ROC 그래프의 경우에는 Y=X 그래프를 기준으로 그래프 윗쪽에 있는 경우 쓸만한 모델로 판단을 했는데, PR 그래프의 경우 Base line이라는 것을 사용한다.


Base line = P / (P+N) 으로 정하는데, P는 데이타에서 Positive 레이블의 수, N 은 전체 데이타의 수이다. 예를 들어 암 데이타에서 암 양성이 300개 이고, 전체 데이타가 700이면 Base line은 300/(700+300) = 0.3 이 된다.  


위의 PR 그래프에 Base line을 적용하여 모델이 좋고 나쁜 영역을 판단하는 그림이다.

아래 그림은 두 모델을 비교한 PR 그래프인데, 두 모델 다 베이스라인을 넘어서 쓸만한 모델이기는 하지만, 모델 A가 B모델보다 확연하게 위에 위치하고 있기 때문에, A 모델이 좋다고 이야기할 수 있다.


(출처 : https://classeval.wordpress.com/introduction/introduction-to-the-precision-recall-plot/)

F-Score

모델의 성능을 하나의 수로 표현할때, ROC나 PR 그래프의 AUC를 사용하면 되지만, AUC를 계산하려면 여러 Throughput에 대해서 Precision, Recall, Specificity 값을 측정해야 한다.

그렇다면 Throughput을 이미 알고 있거나 또는 다양한 Throughput에 대해서 어떤 Throughput이 좋은지를 하나의 수로 모델의 성능을 평가하려면 어떻게 해야할까? 이를 위해서 사용하는 것이 F-Score 라는 값이 있다.


When measuring how well you're doing, it's often useful to have a single number to describe your performance

When measuring how well you're doing, it's often useful to have a single number to describe your performance. We could define that number to be, for instance, the mean of your precision and your recall. This is exactly what the F1-score is.

https://www.quora.com/What-is-an-intuitive-explanation-of-F-score

F Score에 대한 계산은 다음 공식을 이용한다. 큰 의미상으로 보자면 Precision과 Recall에 대한 평균인데, 그냥 평균을 내면, 값의 외곡 현상이 생기기 때문에, 가중치를 주는 평균이라고 이해하면 된다.


특히 β가 1인 경우 (즉 F1)를 F1 Score라고 하고, 모델의 성능 평가 지표로 많이 사용한다.


참고 문서


DBSCAN (밀도 기반 클러스터링)


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

기본 개념

이번에는 클러스터링 알고리즘중 밀도 방식의 클러스터링을 사용하는 DBSCAN(Density-based spatial clustering of applications with noise) 에 대해서 알아보도록 한다.

앞에서 설명한 K Means나 Hierarchical 클러스터링의 경우 군집간의 거리를 이용하여 클러스터링을 하는 방법인데, 밀도 기반의 클러스터링은 점이 세밀하게 몰려 있어서 밀도가 높은 부분을 클러스터링 하는 방식이다.

쉽게 설명하면, 어느점을 기준으로 반경 x내에 점이 n개 이상 있으면 하나의 군집으로 인식하는 방식이다.


그러면 조금 더 구체적인 개념과 용어를 이해해보자

먼저 점 p가 있다고 할때, 점 p에서 부터 거리 e (epsilon)내에 점이 m(minPts) 개 있으면 하나의 군집으로 인식한다고 하자. 이 조건 즉 거리 e 내에 점 m개를 가지고 있는 점 p를 core point (중심점) 이라고 한다.

DBSCAN 알고리즘을 사용하려면 기준점 부터의 거리 epsilon값과, 이 반경내에 있는 점의 수 minPts를 인자로 전달해야 한다.


아래 그림에서 minPts = 4 라고 하면, 파란점 P를 중심으로 반경 epsilon 내에 점이 4개 이상 있으면 하나의 군집으로 판단할 수 있는데, 아래 그림은 점이 5개가 있기 때문에 하나의 군집으로 판단이 되고, P는 core point가 된다.



아래 그림에서 회색점 P2의 경우 점 P2를 기반으로 epsilon 반경내의 점이 3개 이기 때문에, minPts=4에 미치지 못하기 때문에, 군집의 중심이 되는 core point는 되지 못하지만, 앞의 점 P를 core point로 하는 군집에는 속하기 때문에 이를 boder point (경계점)이라고 한다.



아래 그림에서 P3는 epsilon 반경내에 점 4개를 가지고 있기 때문에 core point가 된다.



그런데 P3를 중심으로 하는 반경내에 다른 core point P가 포함이 되어 있는데, 이 경우 core point P와  P3는 연결되어 있다고 하고 하나의 군집으로 묶이게 된다.


마지막으로 아래 그림의 P4는 어떤 점을 중심으로 하더라도 minPts=4를 만족하는 범위에 포함이 되지 않는다. 즉 어느 군집에도 속하지 않는 outlier가 되는데, 이를 noise point라고 한다.


이를 모두 정리해보면 다음과 같은 그림이 나온다.


정리해서 이야기 하면, 점을 중심으로 epsilon 반경내에 minPts 이상수의 점이 있으면 그 점을 중심으로 군집이 되고 그 점을 core point라고 한다. Core point 가 서로 다른 core point의 군집의 일부가 되면 그 군집을 서로 연결되어 있다고 하고 하나의 군집으로 연결을 한다.

군집에는 속하지만, 스스로 core point가 안되는 점을 border point라고 하고, 주로 클러스터의 외곽을 이루는 점이 된다.

그리고 어느 클러스터에도 속하지 않는 점은 Noise point가 된다.

장점

DBSCAN 알고리즘의 장점은

  • K Means와 같이 클러스터의 수를 정하지 않아도 되며,

  • 클러스터의 밀도에 따라서 클러스터를 서로 연결하기 때문에 기하학적인 모양을 갖는 군집도 잘 찾을 수 있으며


    기하학적인 구조를 군집화한 예 (출처 : https://en.wikipedia.org/wiki/DBSCAN )

  • Noise point를 통하여, outlier 검출이 가능하다.

예제 코드

코드의 내용은 앞과 거의 유사하다.


model = DBSCAN(eps=0.3,min_samples=6)


모델 부분만 DBSCAN으로 바꿔 주고, epsilon 값은 eps에 minPts값은 min_samples 인자로 넘겨주면 된다. 이 예제에서는 각각 0.3 과 6을 주었다.


전체 코드를 보면 다음과 같다.


import pandas as pd
iris = datasets.load_iris()

labels = pd.DataFrame(iris.target)
labels.columns=['labels']
data = pd.DataFrame(iris.data)
data.columns=['Sepal length','Sepal width','Petal length','Petal width']
data = pd.concat([data,labels],axis=1)

data.head()



IRIS 데이타를 DataFrame으로 로딩 한 다음, 학습에 사용할 피쳐를 다음과 같이 feature 변수에 저장한다.


feature = data[ ['Sepal length','Sepal width','Petal length','Petal width']]
feature.head()


다음은 모델을 선언하고, 데이타를 넣어서 학습을 시킨다.


from sklearn.cluster import DBSCAN
import matplotlib.pyplot  as plt
import seaborn as sns

# create model and prediction
model = DBSCAN(min_samples=6)
predict = pd.DataFrame(model.fit_predict(feature))
predict.columns=['predict']

# concatenate labels to df as a new column
r = pd.concat([feature,predict],axis=1)


다음은 모델을 선언하고, 데이타를 넣어서 학습을 시킨다.

학습이 끝난 결과를 다음과 같이 3차원 그래프로 시각화 해보자. 아래 시각화는 3차원인데, 학습은 4차원으로 하였다. 그래서 다소 오류가 있어 보일 수 있다. 다차원 데이타를 시각화 하기위해서는 PCA나 t-SNE와 같은 차원 감소 (dimensional reduction) 기법을 사용해야 하는데,  이는 다음 글에서 다루도록한다.


from mpl_toolkits.mplot3d import Axes3D
# scatter plot
fig = plt.figure( figsize=(6,6))
ax = Axes3D(fig, rect=[0, 0, .95, 1], elev=48, azim=134)
ax.scatter(r['Sepal length'],r['Sepal width'],r['Petal length'],c=r['predict'],alpha=0.5)
ax.set_xlabel('Sepal lenth')
ax.set_ylabel('Sepal width')
ax.set_zlabel('Petal length')
plt.show()







마지막으로 Cross tabulazation 을 이용하여 모델을 검증해보면 다음과 같은 결과를 얻을 수 있다.

ct = pd.crosstab(data['labels'],r['predict'])
print (ct)



이 코드에 대한 전체 내용은 https://github.com/bwcho75/dataanalyticsandML/blob/master/Clustering/5.%20DBSCANClustering-IRIS%204%20feature-Copy1.ipynb 에서 확인할 수 있다.

Hierarchical clustering을 이용한 데이타 군집화


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


Hierarchical clustering (한글 : 계층적 군집 분석) 은 비슷한 군집끼리 묶어 가면서 최종 적으로는 하나의 케이스가 될때까지 군집을 묶는 클러스터링 알고리즘이다.

군집간의 거리를 기반으로 클러스터링을 하는 알고리즘이며, K Means와는 다르게 군집의 수를 미리 정해주지 않아도 된다. 참고로 이 글에서 사용된 예제 코드는 https://github.com/bwcho75/dataanalyticsandML/blob/master/Clustering/3.%20Hierarchical%20clustering-IRIS%204%20feature.ipynb 에 저장되어 있다.


예를 들어서 설명해보자

“진돗개,세퍼드,요크셔테리어,푸들, 물소, 젖소" 를 계층적 군집 분석을 하게 되면

첫번째는 중형견, 소형견, 소와 같은 군집으로 3개의 군집으로 묶일 수 있다.


이를 한번 더 군집화 하게 되면 [진돗개,셰퍼드] 와 [요크셔테리어,푸들] 군집은 하나의 군집(개)로 묶일 수 있다.


마지막으로 한번 더 군집화를 하게 되면 전체가 한군집(동물)으로 묶이게 된다.


이렇게 단계별로 계층을 따라가면서 군집을 하는 것을 계층적 군집 분석이라고 한다.

계층적 군집 분석은 Dendrogram이라는 그래프를 이용하면 손쉽게 시각화 할 수 있다.





계층형 군집화에 대한 좀 더 상세한 개념은 https://www.slideshare.net/pierluca.lanzi/dmtm-lecture-12-hierarchical-clustering?qid=94d8b25a-8cfa-421c-9ed5-03c0b33c29fb&v=&b=&from_search=1 를 보면 잘 나와 있다.


skLearn을 이용한 계층 분석 모델 구현

개념을 잡았으면 실제로 계층 분석 모델을 구현해보자.

데이타는 K Means에서 사용했던 IRIS 데이타를 똑같이 사용한다.

이번에는 4개의 피쳐를 이용해서 사용한다.


from sklearn import datasets
import pandas as pd
iris = datasets.load_iris()

labels = pd.DataFrame(iris.target)
labels.columns=['labels']
data = pd.DataFrame(iris.data)
data.columns=['Sepal length','Sepal width','Petal length','Petal width']
data = pd.concat([data,labels],axis=1)


다음은 IRIS 데이타를 이용하여 dendrogram을 그려보자

# Perform the necessary imports
from scipy.cluster.hierarchy import linkage, dendrogram
import matplotlib.pyplot as plt

# Calculate the linkage: mergings
mergings = linkage(data,method='complete')

# Plot the dendrogram, using varieties as labels
plt.figure(figsize=(40,20))
dendrogram(mergings,
          labels = labels.as_matrix(columns=['labels']),
          leaf_rotation=90,
          leaf_font_size=20,
)
plt.show()


먼저 linkage 함수를 import 한 다음 linkage 함수에 data를 넘겨주면 Hierarchical clustering을 수행한다. 이때 method=’complete’로 정했는데, 이 부분은 뒤에서 설명한다.

Hierarchical clustering 한 결과를 dendrogram 함수를 이용하여 dendrogram 그래프를 표현해 보면 다음과 같이 출력된다.




계층 분석 방식

앞의 코드에서, linkage 함수에서 method 를 사용했다. 이에 대해서 알아보자.

Hierachical clustering의 기본 원리는 두 클러스터 사이의 거리를 측정해서 거리가 가까운 클러스터끼리 묶는 방식이다.  그러면 두 클러스터의 거리를 측정할때 어디를 기준점으로 할것인가를 결정해야 하는데 다음 그림을 보자.



출처 : https://www.multid.se/genex/onlinehelp/hs515.htm


앞의 코드에서 사용한 complete linkage 방식은 두 클러스터상에서 가장 먼 거리를 이용해서 측정하는 방식이고 반대로  single linkage 방식은 두 클러스터에서 가장 가까운 거리를 사용하는 방식이다.

average linkage 방식은 각 클러스터내의 각 점에서 다른 클러스터내의 모든 점사이의 거리에 대한 평균을 사용하는 방식이다.


이 linkage 방식에 따라서 군집이 되는 모양이 다르기 때문에, 데이타의 분포에 따라서 적절한 linkage  방식을 변화 시켜가면서 적용해가는 것이 좋다.


계층 분석을 통한 군집의 결정

계층 분석은 최종적으로 1개의 군집으로 모든 데이타를 클러스터링 하는데, 그렇다면 n개의 군집으로 나누려면 어떻게 해야 하는가?

아래 dendrogram을 보자 y축이 각 클러스터간의 거리를 나타내는데, 위로 올라갈 수 록 클러스터가 병합되는 것을 볼 수 있다.




즉 적정 y 값에서 클러스터링을 멈추면 n개의 군집 까지만 클러스터링이 되는데, 위의 그림은 y 값을 3에서 클러스터링을 멈춰서 총 3개의 클러스터로 구분을 한 결과이다.


이렇게 계층형 분석에서 sklearn을 사용할 경우 fcluster 함수를 이용하면, 특정 y값에서 클러스터링을 멈출 수 있다. 다음 코드를 보자.


from scipy.cluster.hierarchy import fcluster

predict = pd.DataFrame(fcluster(mergings,3,criterion='distance'))
predict.columns=['predict']
ct = pd.crosstab(predict['predict'],labels['labels'])
print(ct)


앞의 코드에서 계층형 클러스터링을 한 mergings 변수를 fcluster 함수에 전달하고 두번째 인자에 y의 임계값을 3으로 지정하였다. Predict 컬럼에는 원본 입력데이타에 대한 예측 결과 (어느 클러스터에 속해있는지를 0,1,2로 입력 데이타의 수만큼 리턴한다.)를 리턴한다.


이를 원본 데이타의 라벨인 labels[‘label’]값과 Cross tabulation 분석을 해보았다.




세로축이 예측 결과, 가로측이 원래 값이다.

원래 label이 0인 데이타와 1인 데이타는 각각 잘 분류가 되었고, 2인 데이타는 34개만 정확하게 분류가 되었고 16개는 원본 레이블이 1인 데이타로 분류가 되었다.


지금까지 Hierachical clustering model에 대해서 알아보았다. K Means와 같은 군집화 모델이라도 내부 알고리즘에 따라서 군집화 결과가 다르기 때문에, 샘플 데이타의 분포를 보고 적절한 클러스터링 모델을 고르는 것이 필요하다. 다행이 sklearn의 경우 복잡한 수식 이해 없이도 간단한 라이브러리 형태로 다양한 클러스터링 모델 사용할 수 있도록 해놨기 때문에, 여러 모델을 적용해가면서 적정한 데이타 분류 방식을 찾아보는 것이 어떨까 한다.




클러스터링 #1 - KMeans

빅데이타/머신러닝 | 2017.10.09 22:41 | Posted by 조대협

클러스터링과 KMeans를 이용한 데이타의 군집화

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

클러스터링 문제

클러스터링은 특성이 비슷한 데이타 끼리 묶어주는 머신러닝 기법이다. 비슷한 뉴스나 사용 패턴이 유사한 사용자를 묶어 주는것과 같은 패턴 인지나, 데이타 압축등에 널리 사용되는 학습 방법이다.

클러스터링은 라벨링 되어 있지 않은 데이타를 묶는 경우가 일반적이기 때문에 비지도학습 (Unsupervised learning) 학습 방법이 사용된다.


클러스터링 알고리즘은 KMeans, DBSCAN, Hierarchical clustering, Spectral Clustering 등 여러가지 기법이 있으며, 알고르즘의 특성에 따라 속도나 클러스터링 성능에 차이가 있기 때문에, 데이타의 모양에 따라서 적절한 클러스터링 알고리즘을 선택하는 것이 중요하다. 다음은 sklearn에 나와 있는 각 클러스터링 알고리즘의 성능에 대한 비교표이다.



출처 : http://scikit-learn.org/stable/auto_examples/cluster/plot_cluster_comparison.html#sphx-glr-auto-examples-cluster-plot-cluster-comparison-py


이 글에서는 클러스터링 알고리즘 중에서 간단하게 사용할 수 있는 KMeans와 Hierachical Clustering 알고리즘을 파이썬 sklearn 라이브러리를 이용하여 설명한다.


KMeans

KMeans 클러스터링 알고리즘은 n개의 중심점을 찍은 후에, 이 중심점에서 각 점간의 거리의 합이 가장 최소화가 되는 중심점 n의 위치를 찾고, 이 중심점에서 가까운 점들을 중심점을 기준으로 묶는 클러스터링 알고리즘이다.

아래 그림을 보면 3개의 군집이 존재하는 것을 볼 수 있다. 각 군집별로 중심점이 찍혀 있는데, 이 중심점의 위치를 움직여 가면서 각 군집의 데이타와 중심점의 거리가 가장 작은 중심점을 찾는 것이다.



이 중심점은 결국 각 군집의 데이타의 평균값을 위치로 가지게 되는데, 이런 이유로 Means(평균) 값 알고리즘이라고 한다.


IRIS 데이타를 이용한 KMeans Clustering

그러면 파이썬 sklearn 라이브러리를 이용하여 IRIS 데이타를 KMeans 알고리즘을 이용하여 클러스터링 해보자

Iris 데이타는 붓꽃의 데이타를 머신러닝 학습용으로 잘 정리해놓은 테스트 데이타 셋으로 꽃잎(Petal)의 크기와 꽃받침(Petal)의 크기에 따라 Iris 꽃의 종류를 분리해놓았다.

이 Iris 데이타는 sklearn 라이브러리 안에 샘플 데이타로 제공되고 있다. 이 데이타셋에는 세가지 붓꽃의 종류별로 50장, 총 150장의 데이타를 샘플로 제공한다.



출처 : https://www.google.co.kr/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&ved=0ahUKEwi0u5aAxePWAhXCNpQKHbTlAWwQjRwIBw&url=https%3A%2F%2Fwww.datacamp.com%2Fcommunity%2Ftutorials%2Fkeras-r-deep-learning&psig=AOvVaw2LZqoz0__VGKTODVDAbJnu&ust=1507638255303298


전체 소스 코드는 https://github.com/bwcho75/dataanalyticsandML/blob/master/Clustering/1.%20KMeans%20clustering-IRIS%202%20feature.ipynb 에 있다.


먼저 Iris 데이타를 로딩해보자


데이타를 로딩한 후에, 이 예제에서는 두개의 속성만 사용해서 분류하기로 해보자.  “Sepal length”와 “Sepal width” 컬럼 두개만 추출하여 학습용 feature라는 데이타 프레임으로 학습용 데이타를 만든다. Iris 데이타는 skearn.datasets에 들어있고 이를 로딩하려면 iris = datasets.load_iris()를 하면 로딩이 된다.

데이타는 로딩된 iris 데이타의 iris.data 필드에 들어가 있고, label은 iris.labels 컬럼에 들어가 있다.


from sklearn import datasets

import pandas as pd

iris = datasets.load_iris()


labels = pd.DataFrame(iris.target)

labels.columns=['labels']

data = pd.DataFrame(iris.data)

data.columns=['Sepal length','Sepal width','Petal length','Petal width']

data = pd.concat([data,labels],axis=1)

feature = data[ ['Sepal length','Sepal width']]

feature.head()




다음 K Means 라이브러리를 이용하여 학습을 시켜보자.


from sklearn.cluster import KMeans

import matplotlib.pyplot  as plt

import seaborn as sns


# create model and prediction

model = KMeans(n_clusters=3,algorithm='auto')

model.fit(feature)

predict = pd.DataFrame(model.predict(feature))

predict.columns=['predict']


sklearn.cluster에서 KMeans 라이브러리를 import 한후에, KMeans 객체를 생성하여 model에 저장한다. 이때 3개의 클러스터로 데이타를 군집화할것이기 때문에, 인자로 n_clusters=3으로 클러스터의 수를 정해준다.

model.fit(학습데이타)를 실행하면 학습 데이타를 이용하여 클러스터링을 위한 학습을 시작하고 학습 데이타에 맞는 중심점 3개를 추출해낸다. 이 학습이 된 모델을 가지고 model.predict(데이타) 를 수행하면 데이타를 학습된 모델에 맞춰서 군집화를 해서 어느 클러스터로 군집화가 되었는지 라벨을 리턴해준다.


클러스터링시, 클러스터의 라벨은 자동으로 0,1,2로 지정되는데, 이 순서는 학습을 할때 마다 임의로 변경이 될 수 있다.  클러스터링 된 라벨과 Sepal length, Sepal width를 하나의 데이타 프레임 r에  저장해서 출력해보자


# concatenate labels to df as a new column

r = pd.concat([feature,predict],axis=1)

시각화

K Means를 이용해서 클러스터링된 데이타를 Scatter plot을 이용해서 시각화 해보자


plt.scatter(r['Sepal length'],r['Sepal width'],c=r['predict'],alpha=0.5)


Scatter plot을 이용하여 클러스터링된 데이타를 그리고, 각 클러스터링 된 데이타를 라벨 (0,1,2)에 따라 색을 다르게 표시한다.

그리고 각 클러스터의 중심점을 붉은 색으로 점을 찍어서 나타내자.

클러스터별 중심점은 model.clsuter_centers 값에 저장이 된다. 중심점을 읽어서 center_x, center_y에 에 각 클러스터의 중심점 좌표를 저장하고 출력하자


centers = pd.DataFrame(model.cluster_centers_,columns=['Sepal length','Sepal width'])

center_x = centers['Sepal length']

center_y = centers['Sepal width']

plt.scatter(center_x,center_y,s=50,marker='D',c='r')

plt.show()


그래프로  출력된 결과는 다음과 같다.




데이타 스케일링를 통한 학습 데이타 정재

학습 데이타의 각 속성의 값이 범위가 크게 차이가 나면 머신러닝 학습이 잘 안되는 경우가 있는데, 예를 들어 속성 A의 범위가 1~1000이고, 속성 B의 범위가 1~10이면, 학습이 제대로 되지 않을 수 있다. 그래서 각 속성의 값의 범위를 동일하게 맞추는 것을 스케일링 (Feature scaling)이라고 한다


그림 좌측은 스케일링전의 원본 데이타, 우측은 데이타는 모든 속성을 0~1 사이로 조정한 결과이다. .

( 데이타 스케일링 대한 내용은 http://bcho.tistory.com/tag/data%20frame 참고 )



여러가지 알고리즘이 있는데 여기서 사용하는 스케일링 방법은 속성의 모든 값을 0~1 사이로 만들어주는 StandardScaling 방법을 사용한다.


즉 학습이 되기전에 데이타를 StandardScaler를 이용하여 스케일링을 조정한 후에, 스케일된 데이타를 KMeans 모델에 넣어서 학습 시키는 방법으로 두 단계를 거치는데, 이렇게 여러 단계를 거쳐서 데이타가 정재되고 학습되는 것을 파이프라인이라고 하고, sklearn.pipeline을 이용하여 손쉽게 구현이 가능하다.

아래 코드를 보자


from sklearn.pipeline import make_pipeline

from sklearn.preprocessing import StandardScaler

from sklearn.cluster import KMeans


scaler = StandardScaler()

model = KMeans(n_clusters=3)

pipeline = make_pipeline(scaler,model)


먼저 StandardScaler 객체 scaler를 만든 후, KMeans 모델 객체를 model로 선언한다. 다음에 make_pipeline 메서드를 이용하여 scaler 아 kmeans 모델을 순차로 실행하도록 파이프라인을 만든다.


pipeline.fit(feature)

predict = pd.DataFrame(pipeline.predict(feature))


다음 pipeline.fit과 .predict 메서드를 이용하여 모델을 학습 시키고 예측을 수행한다.

위의 iris 예제의 경우 스케일링을 적용하더라도 크게 모델의 정확도가 향상된것을 확인할 수 없는데, 이유는 Sepal length의 범위가 4~8, Sepal width의 범위가 2~5로 각 범위의 편차가 크지 않기 때문에 스케일링이 효과가 없다.

Inertia value를 이용한 적정 군집수 판단

K Means를 수행하기전에는 클러스터의 개수를 명시적으로 지정해줘야 한다. 데이타를 2개로 군집화할것인지, 3개로 할것인지등을 정해야 하는데, 몇개의 클러스터의 수가 가장 적절할지는 어떻게 결정할 수 있을까? Inertia value 라는 값을 보면 적정 클러스터 수를 선택할 수 있는 힌트를 얻을 수 있는데, Inertia value는 군집화가된 후에, 각 중심점에서 군집의 데이타간의 거리를 합산한것이으로 군집의 응집도를 나타내는 값이다, 이 값이 작을 수록 응집도가 높게 군집화가 잘되었다고 평가할 수 있다.


이 inertia value는 KMeans 모델이 학습된 후에, model.inertia_ 값으로 뽑아 볼 수 있다.

다음은 iris 데이타를 가지고 1~6개의 클러스터로 클러스터링을 했을때, 각 클러스터 개수별로 inertia value를 출력해보는 코드이다.


ks = range(1,10)

inertias = []


for k in ks:

   model = KMeans(n_clusters=k)

   model.fit(feature)

   inertias.append(model.inertia_)

   

# Plot ks vs inertias

plt.plot(ks, inertias, '-o')

plt.xlabel('number of clusters, k')

plt.ylabel('inertia')

plt.xticks(ks)

plt.show()


다음은 출력된 그래프이나. Inertia 값이 급격하게 하강해서 3~5사이에서는 변화의 폭이 크지 않은 것을 볼 수 있다.


이 값을 보면, iris 데이타는 3~5개의 클러스터로 분류하는 것이 적절하다고 판단할 수 있다.

크로스 테이블 체크를 이용한 모델 판단

클러스터링 모델을 검증하는 방법이 inertia 값을 사용하는 방법도 있지만 학습용 데이타가 라벨링이 되어 있는 경우에는 Cross tabulation (교차 분석)를 통해서 모델을 검증할 수 있다.

Cross tabulation 은 Pandas 라이브러리의 .crosstab 함수를 이용하면 쉽게 수행이 가능하다.


ct = pd.crosstab(data['labels'],r['predict'])

print (ct)


다음은 iris 모델에 대한 교차 분석 결과 인데



새로 축이 원본 데이타의 라벨링 된 값을 나타내고 가로가 KMeans로 인해서 클러스터링 된 결과이다.

원래 라벨 값이 0 인 값이  KMeans 에서 클러스터링 된 결과 predict값을 보면, 2 로 결과가 나온것이 50개이다. 즉 49개는 제대로 분류했다는 이야기지만, label이 1로 된 데이타는 38 제대로 분리되고 12개는 잘못 분리된것을 볼 수 있다. 그리고 마지막으로 label이 2인 데이타는 35개가 제대로 분리되고 15개는 제대로 분리되지 않았음을 볼 수 있다.

KMeans 알고리즘의 문제점

K Means 알고리즘은 사용이 편하고 속도가 비교적 빠른 알고리즘인데 비해서 몇가지 문제점을 가지고 있다. 먼저 클러스터의 수를 정해줘야 하고, 결정적으로 K Means에서는 중심점을 측정할때 처음에 랜덤으로 중심점의 위치를 찾기 때문에,  잘못하면, 중심점과 점간의 거리가 Global optimum 인 최소 값을 찾는 게 아니라 중심점이 Local optimum 에 에 수렴하여 잘못된 분류를 할 수 있다는 취약점을 가지고 있다.



출처 : http://www.cenaero.be/Page.asp?docid=27087&langue=EN


다음 글에서는 비지도 학습 기반의 클러스터링 알고리즘중의 하나인 Hierachical Clustering 알고리즘에 대해서 소개해보도록 하겠다. Hierarchical Clustering은 이름에서도 알 수 있듯이 각 클러스터가 유사한 특징을 가지고 있는 여러 계층으로 되어 있을 때 효과적으로 사용할 수 있으며, 클러스터의 수 n을 정의하지 않고도 사용이 가능하다.