Python 과 머신러닝/III. 머신러닝 모델

[Python 머신러닝] 8장. 군집분석 (Cluster Analysis)

JoyfulS 2019. 10. 29. 15:54

 

군집분석이란?

서로 유사한 정도에 따라 다수의 객체를 군집으로 나누는 작업 또는 이에 기반한 분석을 의미한다.

- 유사도가 높은 데이터끼리 그룹화 (대표적으로 유클리드 거리식 이용)

- 계층형 클러스터링과 비계층형 클러스터링으로 분류

- 주요 알고리즘 : k-means, hierarchical

 

> 군집분석의 특징

- 종속변수(y변수)가 없는 데이터 마이닝 기법 (비지도 학습)

- 유클리드 거리 기반 유사 객체 묶음 (유사성 = 유클리드 거리)

- 전체적인 데이터 구조를 파악하는데 이용

- 분석결과에 대한 가설 검정 없음 (타당성 검증 방법 없음)

- 계층적 군집분석(탐색적), 비계층적 군집분석(확인적)

- 고객 DB -> 알고리즘 적용 -> 패턴 추출(rule) -> 근거리 모형으로 군집 형성

- 척도 : 등간, 비율척도   => 명목척도를 만듦

 

1) 유클리드 거리

- 두 점 사이의 거리를 계산하는 방법

- 이 거리를 이용하여 유클리드 공간 정의

 

2) 계층적 군집분석 (hierarchical)

- 유클리드 거리를 이용한 군집분석 방법

- 계층적으로 군집 결과 도출

- 탐색적 군집분석

- 계층적 군집분석의 결과

    => 덴드로그램 (Dendrogram) : 표본들이 군을 형성하는 과정을 나타내는 나무 형식의 그림

- 군집 수는 사용자가 정할 수 있음 (2집단, 3집단, ... 등)

- 군집화 방식 

① 단일기준결합방식 : 각 군집에서 중심으로부터 거리가 가까운 것 1개씩 비교하여 가장 가까운 것끼리 군집화

② 완전기준결합방식 : 각 군집에서 중심으로부터 가장 먼 대상끼리 비교하여 가장 가까운 것끼리 군집화

③ 평균기준결합방식 : 한 군집 안에 속해 있는 모든 대상과 다른 군집에 속해있는 모든 대상의 쌍 집합에 대한 거리를 평균 계산하여 가장 가까운 것끼리 군집화

 

 

3) 비계층적 군집분석 (k-Means)

- 계층적 군집분석보다 속도 빠름

- 군집의 수를 알고 있는 경우 이용

- k는 미리 정하는 군집 수

- 확인적 군집분석

- 계층적 군집화의 결과에 의거하여 군집 수 결정

- 변수보다 관측대상 군집화에 많이 이용

- 군집의 중심(Cluster Center)은 사용자가 정함

 

> k-평균(k-Menas) 군집분석 알고리즘

① k값을 초기값으로, k개의 centroid 선정 (랜덤)

② 각 데이터 포인터를 가장 가까운 centroid에 할당

③ centroid에 할당된 모든 데이터 포인트의 중심 위치 계산 (centroid 재조정)

④ 재조정된 centroid와 가장 가까운 데이터 포인트 할당

⑤ centroid 재조정이 발생되지 않을 때까지 , 단계 반복

 

 


<실습한 내용>

1. hierachical (hierarchy)

2. kMeans 실습(1)

3. kMeans 실습(2)

 

 

1. hierachical (hierarchy)

"""
계층적 군집분석
 - 유클리드 거리계산식 이용
 - 상향식(Bottom-up)으로 군집을 형성
"""

import pandas as pd # dataset load
from sklearn.datasets import load_iris
# 계층적 군집 model
from scipy.cluster.hierarchy import linkage, dendrogram


# 1. dataset load

iris.csv
0.00MB

iris = pd.read_csv("../data/iris.csv")
iris.info()

cols = list(iris.columns)
iris_x = iris[cols[:4]]
iris_x.head()

 

iris['Species'].value_counts() # 'Species' : y변수
'''
versicolor    50
virginica     50
setosa        50
'''

# 2. y변수 수치화
X, y = load_iris(return_X_y=True)

# 사이킷런 라이브러리에서 제공하는 데이터셋을 불러오면 범주값을 숫자로 받을 수 있음
y  # 0,1,2로 구성됨

labels = pd.DataFrame(y, columns = ['labels'])

# df = df + df
irisDF = pd.concat([iris_x, labels], axis = 1)
irisDF.head()
irisDF.tail()  # x변수들과 수치화된 y변수(labels)로 데이터프레임 만들어진 것을 확인

 



# 3. 계층적 군집분석 model
clusters = linkage(y=irisDF, method='complete', metric='euclidean')
clusters
clusters.shape # (149, 4)
'''
연결방식 
 1. 단순연결방식(single)
 2. 완전연결방식(complete)
 3. 평균연결방식(average)
'''

# 4. 덴드로그램 시각화 : 군집수 결정
import matplotlib.pyplot as plt
plt.figure( figsize = (25, 10) )
dendrogram(clusters, leaf_rotation=90, leaf_font_size=12,)
# leaf_rotation=90 : 글자 각도
# leaf_font_size=20 : 글자 사이즈
plt.show() 

 

 

 

 

# 5. 클러스터링(군집) 결과
from scipy.cluster.hierarchy import fcluster # 지정한 클러스터 자르기

cut_tree = fcluster(clusters, t=3, criterion='distance')
cut_tree # prediction

labels = irisDF['labels'] # 정답

df = pd.DataFrame({'pred':cut_tree, 'labels':labels})

con_mat = pd.crosstab(df['pred'], df['labels'])
con_mat
'''
labels   0   1   2
pred              
1       50   0   0
2        0   0  34
3        0  50  16
'''

 

# irisDF에 군집 예측치 추가
irisDF.head()
irisDF['cluster'] = cut_tree
irisDF.head()


# 클러스터 단위 산점도 시각화
plt.scatter(x=irisDF['Sepal.Length'], y=irisDF['Petal.Length'], c=irisDF['cluster'])

# 클러스터 빈도수
irisDF['cluster'].value_counts()
'''
3    66
1    50
2    34
'''

# 각 클러스터별 통계(평균)
cluster_g = irisDF.groupby('cluster')
cluster_g.mean()
'''
         Sepal.Length  Sepal.Width  Petal.Length  Petal.Width    labels
cluster                                                                
1            5.006000     3.428000      1.462000     0.246000  0.000000
2            6.888235     3.100000      5.805882     2.123529  2.000000
3            5.939394     2.754545      4.442424     1.445455  1.242424
'''

 

 

2. kMeans 실습(1)

"""
kMeans 알고리즘
 - 확인적인 군집분석
 - 군집 수 k를 알고 있는 경우 이용
"""

import pandas as pd # dataset load
from sklearn.cluster import KMeans # model
import matplotlib.pyplot as plt # 시각화

 

# 1. dataset load

# 위와 똑같은 iris.csv 파일 이용

iris.csv
0.00MB

iris = pd.read_csv("../data/iris.csv")
iris.info()

irisDF = iris[['Sepal.Length', 'Petal.Length']]  # 두 개의 칼럼만 이용
irisDF.head()

 

# 2. 비계층적 군집 분석 model
model = KMeans(n_clusters=3, random_state=0, algorithm='auto')
# n_clusters=3 : 군집의 개수 (k) (이미 알고 있음)
# random_state=0 : seed 역할 (모델을 일정하게 생성 = 랜덤X)
model.fit(irisDF)

 

# 3. 클러스터링(군집) 결과
pred = model.predict(irisDF)
pred
len(pred) # 150 (관측치 개수만큼 예측치 생성됨)

# 4. 군집결과 시각화
plt.scatter(x=irisDF['Sepal.Length'], y=irisDF['Petal.Length'], c=pred)


# 군집별 중앙값
centers = model.cluster_centers_
centers

'''
array([[5.00784314, 1.49215686],
       [5.87413793, 4.39310345],
       [6.83902439, 5.67804878]])
'''


# 군집별 중앙값 시각화
plt.scatter(x=centers[:,0], y=centers[:,1], marker='D', c='r')
# marker='D', c='r' : 마커 모양은 Diamond, 색깔은 red
plt.show()

# 군집결과와 중앙값 함께 시각화

plt.scatter(x=irisDF['Sepal.Length'], y=irisDF['Petal.Length'], c=pred) 

plt.scatter(x=centers[:,0], y=centers[:,1], marker='D', c='r')
plt.show() 

# 블럭 실행

 

 

 

3. kMeans 실습(2)

"""
kMeans 알고리즘
 - testSet.txt 파일 데이터셋 이용
"""

testSet.txt
0.00MB


import pandas as pd
from sklearn.cluster import KMeans # model
import matplotlib.pyplot as plt # 시각화
import numpy as np # dataset

 

# testSet 데이터는 다음과 같은 형태로 입력되어 있음


# dataset 생성 함수
def loadDataSet(fileName) :
    rows = [] # 전체 행(80개)
    f = open(fileName, mode='r')
    
    lines = f.readlines()  # 줄단위 전체 행 읽기
    
    for row in lines :   # 줄 단위 읽기 : 1.658985 4.285136
        line = row.split('\t')  # '1.658985' '4.285136'
        row = []  # 1줄 행
        for l in line :
            row.append( float(l) )  # ['1.658985', '4.285136']
    
        rows.append(row)  # [['1.658985', '4.285136'], .... ]
    
    return np.array(rows)  # 2차원(80, 2) 행렬 구조로 return

# 1. 함수 호출
dataset = loadDataSet("../data/testSet.txt")
dataset.shape # (80, 2)
type(dataset) # numpy.ndarray

dataset
dataset[:10, :] # 10행

plt.plot(dataset[:,0], dataset[:,1], 'go')   # 0번째 열은 x값, 1번째 열은 y값,  'go' : green 색깔의 o 모양 마커
plt.show()



# 2. df 생성
dataDF = pd.DataFrame(dataset, columns = ['x', 'y'])
dataDF.info()


# 3. kMeans model
model = KMeans(n_clusters=4, algorithm='auto') # k = 4
model.fit(dataDF)

# kMeans 예측치
pred = model.predict(dataDF)
pred # 0~3, 총 4개의 도메인으로 군집 형성

plt.scatter(x=dataDF['x'], y=dataDF['y'], c=pred)


# 각 군집의 중앙값
centers = model.cluster_centers_
centers

plt.scatter(x=centers[:,0], y=centers[:,1], marker='D', c='r')
plt.show()

# 예측치부터 블럭실행


# 4. 원형 데이터에 군집 예측치 추가
dataDF['cluster'] = pred
dataDF.head()

 


Example

exam01.py
0.00MB
exam02.py
0.00MB
bodycheck.csv
0.00MB
product_sales.csv
0.00MB