Clustering

군집화는 데이터를 클러스터(유사 아이템의 그룹)으로 자동 분리하는 자율(unsupervised) 머신 러닝 작업이다. 그룹이 어떻게 보이게 될지 사전에 듣지 못하고 군집화가 이루어지므로 예측보다는 지식의 발견에 사용된다.

머신 러닝 작업으로서 군집화

군집화는 작업이 자율 분류(unsupervised classification)으로 언급되기도 하는데 군집화는 레이블이 없는 예시를 분류하기 때문이다.

K-means clustering

k 평균 군집 알고리즘은 n개의 데이터를 k개의 클러스터 중 하나에 할당한다. k는사전에 결정된 숫자이다. 목표는 클러스터 내의 차이를 최소화하고 클러스터 간 차이를 최대화하는 것이다. 그리고 지역 최적해를 찾는 휴리스틱 과정을 사용한다. 초기의 추정으로 부터 할당을 조금 수정하여 클러스터 내 동질성을 향상시키는 지를 확인한다. (greedy algorithm과 유사)

절차

k개의 초기 클러스터 집합에 예시 데이터를 할당하고, 현재 클러스터에 분류된 예시 데이터에 따라 클러스터 경계를 조정하여 할당을 수정한다. 할당과 수정 과정은 변경이 더 이상 클러스터 적합도가 향상하지 못할 때까지 발생하고 중단되며 클러스터는 완성된다.

문제와 해결

k-평균 알고리즘은 클러스터 중심의 출발 위치에 매우 민감한데, 시작 조건을 약간 변경해도 최종 클러스터 집합 결과에 상당한 영향을 준다. 그래서 k-평균의 초기 중심을 선택하는 방법을 다르게 한다.

할당 단계

  1. 각 예시 데이터를 클러스터에 임의로 할당하여 알고리즘 수정 단계로 바로 진행한다.
  2. 초기 클러스터 중심을 선택하고 각 예시 데이터는 거리 함수에 따라 가장 가까운 클러스터 중심에 할당한다.
  3. 거리 함수로 각 예시 데이터와 각 클러스터 중심 사이의 거리를 알아낸다.

거리 함수

k 평균은 전통적으로 유클리드 거리를 사용하고, 이외에 맨해튼 거리, 민코스키 거리도 사용한다.

# 5번의 컴퓨터 과학 발표와 1번 수학 발표를 한 게스트와 0번 컴퓨터 과학 논문과 2번의 수학 논문을 쓴 게스트 비교한 유클리드 거리
sqrt((5-0)^2 + (1-2)^2)
## [1] 5.09902

수정 단계

  1. 초기 중심을 새로운 위치(중심점, centroid)로 이동시키기
  2. 중심점은 해당 클러스터에 현재 할당된 점들의 평균 위치로 계산
  3. 클러스터 중심이 새로운 중심점으로 이동할 때 보로노이 다이어그램 경계 이동(일종의 결정 경계)
  4. 재할당 및 재수정
  5. 재할당이 일어나지 않는 경우 종료

최종 클러스터 보고

  1. 각 예시에 대해 클러스터 할당을 간단히 보고(A,B,C 클러스터)
  2. 최종 수정 후 클러스터 중심점의 좌표 보고
  3. 이를 통해 중심점 계싼하거나 각 예시 데이터를 가장 가까운 클러스터에 할당하여 클러스터 경계 정의

적합한 클러스터 개수(k) 선택

k-평균은 클러스터 수에 매우 민감하다. k가 매우 크면 클러스터 동질성이 향상되고, 과적합 위험이 있다. 1. 실제 그룹에 대한 선험적(사전) 지식 기반 2. 경험 법칙으로 k를 (n/2)의 제곱근과 동일하게 설정 3. 엘보법, 실루엣 방법, gap statistics

예제: 10대 시장의 세분화

데이터 수집

teens = read.csv('snsdata.csv')
str(teens)
## 'data.frame':    30000 obs. of  40 variables:
##  $ gradyear    : int  2006 2006 2006 2006 2006 2006 2006 2006 2006 2006 ...
##  $ gender      : Factor w/ 2 levels "F","M": 2 1 2 1 NA 1 1 2 1 1 ...
##  $ age         : num  19 18.8 18.3 18.9 19 ...
##  $ friends     : int  7 0 69 0 10 142 72 17 52 39 ...
##  $ basketball  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ football    : int  0 1 1 0 0 0 0 0 0 0 ...
##  $ soccer      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ softball    : int  0 0 0 0 0 0 0 1 0 0 ...
##  $ volleyball  : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ swimming    : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ cheerleading: int  0 0 0 0 0 0 0 0 0 0 ...
##  $ baseball    : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ tennis      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ sports      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ cute        : int  0 1 0 1 0 0 0 0 0 1 ...
##  $ sex         : int  0 0 0 0 1 1 0 2 0 0 ...
##  $ sexy        : int  0 0 0 0 0 0 0 1 0 0 ...
##  $ hot         : int  0 0 0 0 0 0 0 0 0 1 ...
##  $ kissed      : int  0 0 0 0 5 0 0 0 0 0 ...
##  $ dance       : int  1 0 0 0 1 0 0 0 0 0 ...
##  $ band        : int  0 0 2 0 1 0 1 0 0 0 ...
##  $ marching    : int  0 0 0 0 0 1 1 0 0 0 ...
##  $ music       : int  0 2 1 0 3 2 0 1 0 1 ...
##  $ rock        : int  0 2 0 1 0 0 0 1 0 1 ...
##  $ god         : int  0 1 0 0 1 0 0 0 0 6 ...
##  $ church      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ jesus       : int  0 0 0 0 0 0 0 0 0 2 ...
##  $ bible       : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ hair        : int  0 6 0 0 1 0 0 0 0 1 ...
##  $ dress       : int  0 4 0 0 0 1 0 0 0 0 ...
##  $ blonde      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ mall        : int  0 1 0 0 0 0 2 0 0 0 ...
##  $ shopping    : int  0 0 0 0 2 1 0 0 0 1 ...
##  $ clothes     : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ hollister   : int  0 0 0 0 0 0 2 0 0 0 ...
##  $ abercrombie : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ die         : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ death       : int  0 0 1 0 0 0 0 0 0 0 ...
##  $ drunk       : int  0 0 0 0 1 1 0 0 0 0 ...
##  $ drugs       : int  0 0 0 0 1 0 0 0 0 0 ...

결측값 제거

table(teens$gender, useNA = 'ifany')
## 
##     F     M  <NA> 
## 22054  5222  2724
summary(teens$age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   3.086  16.312  17.287  17.994  18.259 106.927    5086

na는 총 5086개가 존재한다. 또한, 최대 최소도 상식적이지 않다. 3세나 106세는 고등학교 다니지 않는다. 이를 방지하고자 나이를 제한한다.

teens$age = ifelse(teens$age >= 13 & teens$age < 20, teens$age, NA)
summary(teens$age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   13.03   16.30   17.27   17.25   18.22   20.00    5523

결측치 더미 코딩

teens$female = ifelse(teens$gender == 'F' & !is.na(teens$gender), 1, 0)
teens$no_gender = ifelse(is.na(teens$gender),1,0)
table(teens$gender, useNA = "ifany")
## 
##     F     M  <NA> 
## 22054  5222  2724
table(teens$female, useNA = "ifany")
## 
##     0     1 
##  7946 22054
table(teens$no_gender, useNA = "ifany")
## 
##     0     1 
## 27276  2724
aggregate(data = teens, age ~ gradyear, mean, na.rm = TRUE)
##   gradyear      age
## 1     2006 18.65586
## 2     2007 17.70617
## 3     2008 16.76770
## 4     2009 15.81957
ave_age <- ave(teens$age, teens$gradyear, FUN = function(x) mean(x, na.rm = T))
teens$age = ifelse(is.na(teens$age), ave_age, teens$age)
summary(teens$age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   13.03   16.28   17.24   17.24   18.21   20.00

결측치가 완전히 제거 되었다. 이제 데이터에 대해 모델 훈련시킨다.

k-means clustering in stats package

library(stats)
# myclusters = kmeans(mydata, k)
# mydata는 군집화될 예시가 있는 행렬 혹은 데이터 프레임
# k는 희망 클러스터의 개수
# 이 함수는 클러스터에 대한 정보를 저장하는 클러스터 객체 반환

# mycluster$cluster 는 kmeans() 함수에서 얻은 클러스터의 할당된 벡터
# mycluster$centers 는 각 특징과 클러스터 조합별 평균값 나타내는 행렬
# myclusters$size 각 클러스터에 할당된 데이터 개수

36개 특징만을 이용한 데이터 프레임을 만들고 이를 기반으로 클러스터 분석을 시작한다. 분석할 때 거리 계산을 할 경우 일반적으로 분석 전에 정규화, z-점수 표준화 한다.

interests = teens[5:40]
interests_z = as.data.frame(lapply(interests, scale))

lapply는 행렬로 반환하므로 이를 다시 데이터 프레임 형태로 강제 반환해야 한다. 마지막으로 클러스터의 희망 개수인 k를 결정해야 한다.

k-평균 알고리즘은 임의의 출발점을 사용하므로, 반복해서 같은 결과를 얻으려면 seed 값을 부여하라.

set.seed(2345)
teen_clusters = kmeans(interests_z, 5)

평가하기

모델의 성능을 평가해보자. 이 알고리즘이 10대의 관심사 데이터를 얼마나 잘 분리했는지 조사해서 확인한다.

teen_clusters$size
## [1]   871   600  5981  1034 21514

여기서 5개 클러스터를 확인해보자. 가장 작은 클러스터는 600명의 10대이고, 가장 큰 클러스터는 21528명을 가진다. 각 클러스터의 격차가 조금 커서 우려되지만, 이 그룹들을 좀 더 신중하게 살펴보지 않으면 문제인지 모를 것이다.

teen_clusters$centers
##    basketball   football      soccer    softball  volleyball    swimming
## 1  0.16001227  0.2364174  0.10385512  0.07232021  0.18897158  0.23970234
## 2 -0.09195886  0.0652625 -0.09932124 -0.01739428 -0.06219308  0.03339844
## 3  0.52755083  0.4873480  0.29778605  0.37178877  0.37986175  0.29628671
## 4  0.34081039  0.3593965  0.12722250  0.16384661  0.11032200  0.26943332
## 5 -0.16695523 -0.1641499 -0.09033520 -0.11367669 -0.11682181 -0.10595448
##   cheerleading    baseball      tennis      sports        cute
## 1    0.3931445  0.02993479  0.13532387  0.10257837  0.37884271
## 2   -0.1101103 -0.11487510  0.04062204 -0.09899231 -0.03265037
## 3    0.3303485  0.35231971  0.14057808  0.32967130  0.54442929
## 4    0.1856664  0.27527088  0.10980958  0.79711920  0.47866008
## 5   -0.1136077 -0.10918483 -0.05097057 -0.13135334 -0.18878627
##            sex        sexy         hot      kissed       dance        band
## 1  0.020042068  0.11740551  0.41389104  0.06787768  0.22780899 -0.10257102
## 2 -0.042486141 -0.04329091 -0.03812345 -0.04554933  0.04573186  4.06726666
## 3  0.002913623  0.24040196  0.38551819 -0.03356121  0.45662534 -0.02120728
## 4  2.028471066  0.51266080  0.31708549  2.97973077  0.45535061  0.38053621
## 5 -0.097928345 -0.09501817 -0.13810894 -0.13535855 -0.15932739 -0.12167214
##      marching      music        rock         god      church       jesus
## 1 -0.10942590  0.1378306  0.05905951  0.03651755 -0.00709374  0.01458533
## 2  5.25757242  0.4981238  0.15963917  0.09283620  0.06414651  0.04801941
## 3 -0.10880541  0.2844999  0.21436936  0.35014919  0.53739806  0.27843424
## 4 -0.02014608  1.1367885  1.21013948  0.41679142  0.16627797  0.12988313
## 5 -0.11098063 -0.1532006 -0.12460034 -0.12144246 -0.15889274 -0.08557822
##         bible        hair       dress      blonde        mall    shopping
## 1 -0.03692278  0.43807926  0.14905267  0.06137340  0.60368108  0.79806891
## 2  0.05863810 -0.04484083  0.07201611 -0.01146396 -0.08724304 -0.03865318
## 3  0.22990963  0.23612853  0.39407628  0.03471458  0.48318495  0.66327838
## 4  0.08478769  2.55623737  0.53852195  0.36134138  0.62256686  0.27101815
## 5 -0.06813159 -0.20498730 -0.14348036 -0.02918252 -0.18625656 -0.22865236
##         clothes  hollister abercrombie          die       death
## 1  0.5651537331  4.1521844  3.96493810  0.043475966  0.09857501
## 2 -0.0003526292 -0.1678300 -0.14129577  0.009447317  0.05135888
## 3  0.3759725120 -0.0553846 -0.07417839  0.037989066  0.11972190
## 4  1.2306917174  0.1610784  0.26324494  1.712181870  0.93631312
## 5 -0.1865419798 -0.1557662 -0.14861104 -0.094875180 -0.08370729
##          drunk       drugs
## 1  0.035614771  0.03443294
## 2 -0.086773220 -0.06878491
## 3 -0.009688746 -0.05973769
## 4  1.897388200  2.73326605
## 5 -0.087520105 -0.11423381

결과를 보면 cluster 1은 공주, cluster 3은 운동선수 그룹, cluster 4 는 범죄자 그룹임을 추측할 수 있다. cluster 5은 평범한 집단으로 전반적인 수준이 낮다.

teens$cluster = teen_clusters$cluster
teens[1:5, c("cluster","gender","age","friends")]
##   cluster gender    age friends
## 1       5      M 18.982       7
## 2       3      F 18.801       0
## 3       5      M 18.335      69
## 4       5      F 18.875       0
## 5       4   <NA> 18.995      10
aggregate(data = teens, age ~ cluster, mean)
##   cluster      age
## 1       1 16.86497
## 2       2 17.39037
## 3       3 17.07656
## 4       4 17.11957
## 5       5 17.29849
aggregate(data = teens, female ~ cluster, mean)
##   cluster    female
## 1       1 0.8381171
## 2       2 0.7250000
## 3       3 0.8378198
## 4       4 0.8027079
## 5       5 0.6994515
aggregate(data = teens, friends ~ cluster, mean)
##   cluster  friends
## 1       1 41.43054
## 2       2 32.57333
## 3       3 37.16185
## 4       4 30.50290
## 5       5 27.70052

인기있으면 친구도 많다.