Error in scan(file = file, what = what, sep = sep, quote = quote, dec = dec,
: line 3 did not have 5 elements
와 같은
(1) 에러 메시지가 뜨는 이유와
(2) 대처 방안
(3) 유의 사항
에 대해서 알아보겠습니다.
(1) 에러메시지 이유
Error in scan(file = file, what = what, sep = sep, quote = quote, dec = dec,
: line 3 did not have 5 elements
에러메시지가 뜨는 이유는 3번째 행(line 3)의 원소의 개수가 결측값(missing value) 때문에 총 5개가 안되기 때문입니다. (row name 1개, 행 4개 모두 포함해서 총 5개 원소)
아래에 간단한 예를 들어서 설명하겠습니다.
cat() 함수를 이용해서 V1, V2, V3, V4 라는 변수명을 가진 4개의 변수에 대해 First, Second, Third, Fourth라는 rowname을 가진 text 파일을 만들어보았습니다. 이때 의도적으로 3번째 행(3rd row, 3 line)에 원소를 row name 포함해서 4개만 만들어보았습니다. (다른 행은 모두 5개 원소, 3행만 4개 원소)
MyDocument 폴더에 가보면 test.txt 라는 파일이 생성되어 있음을 확인할 수 있으며, 그 파일을 열어보면 아래 화면 캡쳐한 것 처럼 데이터가 들어가 있으며, 3행은 원소가 총 4개이며, 다른 행 대비 1개가 모자람을 알 수 있습니다.
> ##-----------------------------------------------##
> ## Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,
> ## :line 3 did not have 5 elements
> ##-----------------------------------------------##
> > # exmaple with missing value in line 3 at 5th element
> cat("V1 V2 V3 V4\nFirst 1 2 3 4\nSecond 5 6 7 8\nThird 9 10 11\nFourth 13 14 15 16", file="test.txt")
이렇게 생긴 데이터를 read.table() 함수를 써서 읽어들여보겠습니다.
> read.table("test.txt", header = TRUE)
Error in scan(file = file, what = what, sep = sep, quote = quote, dec = dec, :
line 3 did not have 5 elements
In addition: Warning message:
In read.table("test.txt", header = TRUE) : 'test.txt'에서 readTableHeader에 의하여 발견된 완성되지 않은 마지막 라인입니다
다른 행은 총 5개의 원소(row name 1개, 변수 4개)가 있는데 반해, 3번째 행은 5개 원소가 아니라는 에러 메시지가 떴습니다. 원소가 일부 모자란다는 뜻입니다.
(2) 대처 방안
첫번째 방법은 파일을 열어서 결측값 위치를 찾아가서 그 값에 제대로 된 값을 채워넣는 것입니다. 파일의 데이터 개수가 몇 개 안되고 육안으로 확인해서 채워넣을 수 있는 경우에는 적용가능 하겠지만, 만약 데이터 개수가 수천, 수만, 수십만 개라면 많이 힘들겠지요? ^^;
두번째 방법은, 만약 원소의 개수가 모자라는 이유가 제일 마지막 열에 결측값(missing value)가 있기 때문이라면 fill = TRUE 옵션을 부가하면 NA 표기가 부가되면서 읽어들이기를 간단하게 해결할 수 있습니다.
> # missing value => NA : fill = TRUE
> testfile <- read.table("test.txt", header = TRUE, fill = TRUE)
Warning message:
In read.table("test.txt", header = TRUE, fill = TRUE) : 'test.txt'에서 readTableHeader에 의하여 발견된 완성되지 않은 마지막 라인입니다
>
> testfile
V1 V2 V3 V4
First 1 2 3 4
Second 5 6 7 8
Third 9 10 11 NA
Fourth 13 14 15 16
군집 간 거리를 측정하는 방법에 따라서 여러가지 알고리즘이 있는데요, 지난번 포스팅에서는 응집형 계층적 군집화(agglomerative hierarchical clustering) 알고리즘 중에서 (1-1) 단일(최단) 연결법 (single linkage method, MIN), (1-2) 완전(최장) 연결법 (complete linkage method, MAX) 에 대해 소개하였습니다.
이번 포스팅에서는 응집형 계층적 군집화 알고리즘 중에서 그래프 기반(Graph-based) 방법의 세번째로 (1-3) 평균 연결법 (average linkage method)에 대해서 알아보겠습니다.
평균 연결법은 서로 다른 군집 간의 모든 짝을(pair-wise) 이룬 점들의 평균 거리로 유사성을 측정합니다.
아래의 그래프 기반 군집 간 유사성 측정(graph-based mesaures of cluster proximity) 방법으로서 (1-1) 단일(최단) 연결법, (1-2) 완전(최장) 연결법과 (1-3) 평균 연결법의 수식, 그리고 도식을 보면 서로의 차이점을 이해할 수 있을 것입니다.
이제 2차원 공간(2-dimentional space)에 5개의 점을 가지고 간단한 예를 들어서 설명을 해보겠습니다.
지난번 포스팅의 단일(최단) 연결법, 완전(최장) 연결법 예시 데이터와 동일하며, 거리 계산 방법도 아래의 (1)번, (2)번까지는 똑같고, (3)번부터는 조금 다릅니다. 위의 수식 처럼 평균 개념이 들어가 있어서 단일 연결법, 완전 연결법 대비 조금 복잡한 감이 있습니다.
1) 데이터셋 준비, 탐색적 분석
응집형 계층적 군집화이므로 처음에 아래의 5개의 점, 5개의 군집에서부터 시작합니다.
R script도 같이 제시하면서 설명하겠습니다. 먼저, 데이터 입력 및 plotting (↑ 위의 산점도 그래프) 입니다.
> ##--------------------------------------------
> ## (1) Agglomerative Hierarchical Clustering
> ## (1-3) Average Linkage
> ##--------------------------------------------
> > x <- c(1, 2, 2, 4, 5)
> y <- c(1, 1, 4, 3, 4)
> > xy <- data.frame(cbind(x, y))
> > xy
x y
1 1 1
2 2 1
3 2 4
4 4 3
5 5 4
> > # scatter plot of xy
> plot(xy, pch = 19, xlab = c("x coordinate"), ylab = c("y coordinate"),
+ xlim = c(0, 6), ylim = c(0, 6),
+ main = "scatter plot of xy")
> > # adding student label
> text(xy[,1], xy[,2], labels = abbreviate(rownames(xy)),
+ cex = 0.8, pos = 1, col = "blue") # pos=1 : at the bottom
> > > # adding dotted line
> abline(v=c(3), col = "gray", lty = 2) # vertical line
> abline(h=c(3), col = "gray", lty = 2) # horizontal line
2) 유사성 측도로서 거리 행렬(Distance matrix) D 계산하기
거리 측도는 분석 목적, 데이터 특성에 맞게 선택해야 하는데요, 이번 예제에서는 '유클리드 제곱거리(squares of Euclidean distance)'를 사용하겠습니다. 계산 및 설명의 편의를 위해서 유클리드 거리를 제곱했습니다.
[distance matrix - no.1]
유클리드 제곱거리를 구하는 R script 입니다. dist(xy, method="euclidean") 에다가 뒤에 "^2"를 붙여서 제곱을 했습니다.(이해, 설명 편의를 위해... 유클리드 거리로 하면 매번 squared root 씌우는 것이 귀찮아서요.)
단일(최단) 연결법으로 하면 MIN값인 18 이 되며, 완전(최장) 연결법으로 하면 MAX값인 25가 되는 반면에, 평균 연결법으로 하면 단일 연결법과 완전연결법의 평균 지점인 21.5가 되었습니다. (MIN 값이든 MAX값이든 Average 값이든 간에 이상값, 특이값에 민감하다는 점은 유의해야 겠습니다)
아래 거리행렬의 d(P3, P4), d(P3, P5), d(P4, P5)는 위의 거리행렬 [distance matrix - no.1]에서 계산한 결과를 그대로 가져다가 썼습니다.
[distance matrix - no.2]
P4과 P5의 거리가 '2'로서 가장 가까우므로 → (P4, P5)를 새로운 군집으로 묶어줍니다(merge). 이제 군집이 처음 5개에서 3개로 줄었습니다.
수정된 2차원 부분집합그림은 아래와 같습니다. (P1, P2) 군집에 이어 두번째로 (P4, P5) 군집이 묶였습니다.
4) 군집(P1, P2)와 군집(P4, P4), 개체 P3 간의 거리를 평균 연결법(average linkage method)으로 수정한 거리행렬(distance matrix) 구하기
군집 간 거리 계산 방법은 동일하게 '평균 거리'를 계산하면 됩니다.
[distance matrix - no.3]
개체 P3와 군집 (P4, P5)의 거리가 '9'로서 가장 가까우므로 → P3과 (P4, P5)를 새로운 군집으로 묶어줍니다(merge). 반복(repeat)을 거듭할 수록 군집이 줄어서 이제 2개가 되었습니다.
(여기까지도 군집 묶이는 순서가 이전의 단일(최단) 연결법, 완전(최장) 연결법과 결과가 같습니다. 예제를 급하게 만들었더니 그만...^^; 서로 좀 다른게 있어야지 실감을 할텐데요... ^^;;; 그래도 군집 간 거리는 단일 연결법과 완전 연결법의 중간 즈음, 즉 MIN과 MAX사이의 평균값으로 바뀌었음을 알 수는 있습니다. ^^;;;;;)
여기까지 진행한 군집화 결과를 반영해 수정한 부분집합그림은 아래와 같습니다.
5) 군집(P1, P2)와 군집{P3, (P4, P5)} 간의 거리를 평균 연결법으로 수정한 거리행렬 구하기
군집 간 평균 연결법을 사용한 거리 계산은 아래와 같습니다. 조금 복잡해 보일 수도 있는데요, 단순 사칙연산의 연속입니다.
마지막으로 두개 남은 군집 (P1, P2)와 {P3, (P4, P5)}를 묶어줍니다(merge). → 드디어 반복(repeat)을 거듭한 끝에 군집이 1개로 줄어들었습니다. → 종료 (End)
마지막 군집이 병합된 이후의 수정된 부분집합그림은 아래와 같습니다.
이상의 '완전(최장) 연결법'에 의한 응집형 계층적 군집화를 위한 R script는 아래와 같습니다. 역시 단 한줄로 짧습니다.
> # Agglomerative Hierarchical Clustering : Average Linkage method
> hc_avg <- hclust(dist(xy)^2, method="average")
> hc_avg
Call:
hclust(d = dist(xy)^2, method = "average")
Cluster method : average
Distance : euclidean
Number of objects: 5
6) 덴드로그램(Dendrogram)으로 응집형 계층적 군집화(by 평균 연결법) 결과 확인해보기
아래 덴드로그램의 y축이 바로 군집 간 거리 (평균 연결법으로 구한) 를 나타냅니다.
plot(x, hang = -1) 옵션을 설정하면 아래 그램의 오른쪽 덴드로그램처럼 군집 묶어주는 선이 y=0 부터 시작합니다.
아래 덴드로그램의 Height가 위에서 수기로 계산한 군집 간 거리와 일치하지요? 가령, 가장 마지막에 병합된 군집 (P1, P2)와 군집 {P3, (P4, P5)} 간의 거리가 손으로 계산한 거리가 13.83이었으며, 아래 덴드로 그램도 14에서 조금 못미치고 있습니다.
> # dendrogram
> my_par = par(no.readonly = TRUE)
> par(oma = c(0, 0, 1, 0))
> par(mfrow = c(1, 2))
> plot(hc_avg)
> plot(hc_avg, hang = -1) # hang = -1 : line from the bottom
>
rev() 함수를 사용하면 군집 모델에 대한 정보를 알 수 있습니다.
- $method : 연결 방법(linkage method)
- $height : 군집 간 거리(distance between clusters)
- $merge : 군집 간 병합 순서 (merge sequence)
> > # custering information > rev(hc_avg) $dist.method [1] "euclidean"
이상으로 (1) 응집형 계층적 군집화(agglomerative hierarchical clustering) 알고리즘의 (1-3) 평균 연결법(Average linkage method) 에 대해서 알아보았습니다.
[Reference]
(1) "Introduction to Data Mining", Pang-Ning Tan(Michigan State University), Michael Steinbach(University of Minnesota), Vipin Kumar(University of Minnesota), Addison-Wesley Companion Book
(2) "Clustering Algorithm", Ana Fred, INSTITUTO SUPERIOR TECNICO, Universidade Techica de Lisboa, 2009
(3) "R, SAS, MS-SQL을 활용한 데이터마이닝", 이정진 지음, 자유아카데미, 2011
군집 간 거리를 측정하는 방법에 따라서 여러가지 알고리즘이 있는데요, 지난번 포스팅에서는 응집형 계층적 군집화(agglomerative hierarchical clustering) 알고리즘 중에서 (1-1) 단일(최단) 연결법 (single linkage method, MIN) 에 대해 소개하였습니다.
이번 포스팅에서는 응집형 계층적 군집화 알고리즘 중에서 그래프 기반(Graph-based) 방법의 두번째로 (1-2) 완전(최장) 연결법 (complete linkage method, MAX)에 대해서 알아보겠습니다.
단일(최단) 연결법이 군집 간 거리를 잴 때 다른 군집의 점들 중에서 가장 가까운 두 점 간의 거리를 사용하였다면, 완전(최장) 연결법은 반대로 '다른 군집의 점들 중에서 가장 멀리 떨어진 두 점 간의 거리를 가지고 군집 간 거리를 잽니다.
아래의 가운데 그림은 군집 k와 군집 i+j (← 군집 i와 군집 j가 합쳐진 새로운 군집) 간의 거리를 완전(최장) 연결법으로 구할 때의 이미지인데요, 보시면 금방 이해할 수 있을 것입니다.
이제 2차원 공간(2-dimentional space)에 5개의 점을 가지고 간단한 예를 들어서 설명을 해보겠습니다.
(지난번 포스팅의 단일(최단) 연결법 예시 데이터와 동일하며, 거리 계산 방법도 아래의 (1)번, (2)번까지는 똑같고, (3)번부터는 매우 유사함. 단일연결법을 정확히 이해했다면 이번 완전연결법은 그야말로 누워서 떡먹기임)
1) 데이터셋 준비, 탐색적 분석
응집형 계층적 군집화이므로 처음에 아래의 5개의 점, 5개의 군집에서부터 시작합니다.
(결측값, 이상값/특이값 여부 check)
R script도 같이 제시하면서 설명하겠습니다. 먼저, 데이터 입력 및 plotting (↑ 위의 산점도 그래프) 입니다.
> ##--------------------------------------------
> ## (1) Agglomerative Hierarchical Clustering
> ## (1-2) Complete Linkage, MAX
> ##--------------------------------------------
> > x <- c(1, 2, 2, 4, 5)
> y <- c(1, 1, 4, 3, 4)
> > xy <- data.frame(cbind(x, y))
> > xy
x y
1 1 1
2 2 1
3 2 4
4 4 3
5 5 4
> > # scatter plot of xy
> plot(xy, pch = 19, xlab = c("x coordinate"), ylab = c("y coordinate"),
+ xlim = c(0, 6), ylim = c(0, 6),
+ main = "scatter plot of xy")
> > # adding student label
> text(xy[,1], xy[,2], labels = abbreviate(rownames(xy)),
+ cex = 0.8, pos = 1, col = "blue") # pos=1 : at the bottom
> > > # adding dotted line
> abline(v=c(3), col = "gray", lty = 2) # vertical line
> abline(h=c(3), col = "gray", lty = 2) # horizontal line
2) 유사성 측도로서 거리 행렬(Distance matrix) D 계산하기
거리 측도는 분석 목적, 데이터 특성에 맞게 선택해야 하는데요, 이번 예제에서는 '유클리드 제곱거리(squares of Euclidean distance)'를 사용하겠습니다. 계산 및 설명의 편의를 위해서 유클리드 거리를 제곱했습니다.
[distance matrix - no.1]
유클리드 제곱거리를 구하는 R script 입니다. dist(xy, method="euclidean") 에다가 뒤에 "^2"를 붙여서 제곱을 했습니다.(이해, 설명 편의를 위해... 유클리드 거리로 하면 매번 squared root 씌우는 것이 귀찮아서요.)
P1과 P2의 거리가 '1'로서 가장 가까우므로 (즉, 유사하므로) → (P1, P2)를 새로운 군집으로 묶어줍니다(merge). 이제 군집이 처음 5개에서 4개로 줄었습니다.
2차원 데이터에 대해서는 아래처럼 부분집합그림(Nested cluster diagram)을 그려볼 수 있습니다.
3) 군집 (P1, P2)와 개체 P3, P4, P5 간의 거리를 완전(최장) 연결법으로 수정한 거리행렬 구하기
완전(최장) 연결법은 다른 군집에 속한 가장 멀리 떨어져 있는 두 점의 거리를 군집 간 거리로 측정하는 방법이므로 아래의 계산 절차를 따릅니다.
한개만 예를 들자면, 군집 (P1, P2)와 개체 P5 간의 거리는 d(P1, P5)=25, d(P2, P5)=18 의 두 거리 중에서 최대값(MAX)인 '25'가 됩니다.(↔ 단일(최단) 연결법은 최소값(MIN)을 거리로 채택). 단일(최단) 연결법 대비 군집-군집(개체) 간 거리가 더 길어졌습니다.
아래 거리행렬의 d(P3, P4), d(P3, P5), d(P4, P5)는 위의 거리행렬 [distance matrix - no.1]에서 계산한 결과를 그대로 가져다가 썼습니다.
[distance matrix - no.2]
P4과 P5의 거리가 '2'로서 가장 가까우므로 → (P4, P5)를 새로운 군집으로 묶어줍니다(merge). 이제 군집이 처음 5개에서 3개로 줄었습니다.
(※ 혹시 완전(최장) 연결법이므로 이 단계에서 최장(가장 큰) 값을 가지고 군집을 묶는 것으로 혼돈하시면 안됩니다. 최장 거리(MAX)는 거리행렬(distance matrix) 구하는 단계에서 사용했구요, 새로운 군집 merge할 때는 서로 가까운 점들 끼리 묶어주어야 합니다. 공교롭게도 아래의 부분집합그림이 이전 포스팅의 단일연결법의 결과와 같습니다. ^^; 거리의 길이는 완전(최장) 연결법이 더 멀리 떨어진 것으로 좀 달라졌구요.)
4) 군집(P4, P5)와 군집(P1, P2), P3 간의 거리를 완전(최장) 연결법으로 수정한 거리행렬 구하기
군집 간 거리 계산 방법은 동일하게 '최대값(MAX)'을 찾으면 됩니다.
[distance matrix - no.3]
개체 P3와 군집 (P4, P5)의 거리가 '9'로서 가장 가까우므로 → P3과 (P4, P5)를 새로운 군집으로 묶어줍니다(merge). 반복(repeat)을 거듭할 수록 군집이 줄어서 이제 2개가 되었습니다.
(여기까지도 군집 묶이는 순서가 이전의 단일(최소) 연결법과 결과가 같습니다. 예제를 급하게 만들었더니 그만...^^; 서로 좀 다른게 있어야지 실감을 할텐데요... ^^;;;)
5) 군집(P1, P2)와 군집{P3, (P4, P5)} 간의 거리를 완전(최장) 연결법으로 수정한 거리행렬 구하기
마지막으로 두개 남은 군집 (P1, P2)와 {P3, (P4, P5)}를 묶어줍니다(merge). → 드디어 반복(repeat)을 거듭한 끝에 군집이 1개로 줄어들었습니다. → 종료 (End)
이상의 '완전(최장) 연결법'에 의한 응집형 계층적 군집화를 위한 R script는 아래와 같습니다. 역시 단 한줄로 짧습니다. 참 편한 세상입니다. ㅎㅎ
이상으로 (1) 응집형 계층적 군집화(agglomerative hierarchical clustering) 알고리즘의 (1-2) 완전(최장) 연결법(complete linkage method, MAX) 에 대해서 알아보았습니다.
[Reference]
(1) "Introduction to Data Mining", Pang-Ning Tan(Michigan State University), Michael Steinbach(University of Minnesota), Vipin Kumar(University of Minnesota), Addison-Wesley Companion Book
(2) "Clustering Algorithm", Ana Fred, INSTITUTO SUPERIOR TECNICO, Universidade Techica de Lisboa, 2009
(3) "R, SAS, MS-SQL을 활용한 데이터마이닝", 이정진 지음, 자유아카데미, 2011
지난번 포스팅에서는 군집분석의 유형과 알고리즘 종류, 그리고 유사성 측도로서의 거리에 대해서 알아보았습니다.
이번 포스팅에서는 세부적인 분석 알고리즘의 첫번째로서, 각 데이터에서 시작해서 유사한(즉, 가까운) 데이터끼리 순차적으로 군집을 묶어나가는응집형 계층적 군집화 (Agglomerative Hierarchical Clustering, "Bottom-up") 알고리즘에 대해서 알아보겠습니다.
(↔ 참고로, 분리형(Divisive) 계층적 군집화 알고리즘은 하나의 군집에서 시작해 Top-down으로 군집을 나누어가서 각 데이터가 하나의 군집이 될 때까지 분화 반복)
응집형 계층적 군집화 알고리즘은 아래와 같습니다. 거리 행렬을 가지고 군집 간 유사성을 측정해서 모든 데이터가 하나의 군집으로 응집/병합될 때까지 반복적으로 군집화를 수행합니다.
위의 알고리즘에 보면 유사성 행렬(proximity matrix), 거리 행렬(distance matrix)가 나오는데요, 지난번 포스팅에서 소개했었던 다양한 거리 측도 중에서 데이터 특성, 분석 목적에 맞는 거리 측도를 선택해서 가능한 모든 쌍의 데이터 간 거리를 계산하면 됩니다. (유사성 측도로 거리를 사용하면 => "거리가 짧을 수록 유사하다"고 해석)
응집형 계층적 군집화 방법에는 "군집 간 거리를 측정하는 방법"에 따라서 여러가지가 있습니다. 이번 포스팅에서는 그래프 기반(Graph-based)의 연결법으로 '단일(최단) 연결법 (Single linkage method)'를 소개하겠습니다. 그래프 기반 연결법은 각 데이터를 Node로 하고, Nodes 간 연결(connectivity)한 선을 Link or Arc로 하며, 이들 Link or Arc 의 길이를 가지고 거리를 측정합니다.
"단일 연결법(Single linkage method)"은 "최단(MIN) 연결법"이라고도 하며, 다른 군집에 속한 가장 가까운 두 점 사이의 거리를 군집 간의 거리로 측정하는 방법입니다.
아래 그림은 군집 k와 군집 i+j (← 군집 i와 군집 j가 합쳐진 새로운 군집) 간의 거리를 단일(최단) 연결법으로 구할 때의 이미지입니다.
이제 2차원 공간(2-dimentional space)에 5개의 점을 가지고 간단한 예를 들어서 설명을 해보겠습니다.
1) 데이터셋 준비, 탐색적 분석
아래의 5개의 점 하나 하나가 각 군집(cluster)이 되겠습니다. 응집형 계층적 군집화이므로 처음에 아래의 5개의 점, 5개의 군집에서부터 시작합니다.
데이터셋에 결측값 없고, 산점도를 그려보니 이상값/특이값(outlier)도 없어 보이는군요.
R script도 같이 제시하면서 설명하겠습니다. 먼저, 데이터 입력 및 plotting (↑ 위의 산점도 그래프) 입니다.
> ##--------------------------------------------
> ## (1) Agglomerative Hierarchical Clustering
> ## (1-1) Single Linkage, MIN
> ##--------------------------------------------
> > x <- c(1, 2, 2, 4, 5)
> y <- c(1, 1, 4, 3, 4)
> > xy <- data.frame(cbind(x, y))
> > xy
x y
1 1 1
2 2 1
3 2 4
4 4 3
5 5 4
> > # scatter plot of xy
> plot(xy, pch = 19, xlab = c("x coordinate"), ylab = c("y coordinate"),
+ xlim = c(0, 6), ylim = c(0, 6),
+ main = "scatter plot of xy")
> > # adding student label
> text(xy[,1], xy[,2], labels = abbreviate(rownames(xy)),
+ cex = 0.8, pos = 1, col = "blue") # pos=1 : at the bottom
> > > # adding dotted line
> abline(v=c(3), col = "gray", lty = 2) # vertical line
> abline(h=c(3), col = "gray", lty = 2) # horizontal line
2) 유사성 측도로서 거리 행렬(Distance matrix) D 계산하기
거리 측도는 분석 목적, 데이터 특성에 맞게 선택해야 하는데요, 이번 예제에서는 '유클리드 제곱거리(squares of Euclidean distance)'를 사용하겠습니다. 계산 및 설명의 편의를 위해서 유클리드 거리를 제곱했습니다.
[distance matrix - no.1]
유클리드 제곱거리를 구하는 R script 입니다. dist(xy, method="euclidean") 에다가 뒤에 "^2"를 붙여서 제곱을 했습니다.(이해, 설명 편의를 위해...)
P1과 P2의 거리가 '1'로서 가장 가깝군요. → (P1, P2)를 새로운 군집으로 묶어줍니다(merge). 이제 군집이 처음 5개에서 4개로 줄었습니다.
2차원 데이터에 대해서는 아래처럼 부분집합그림(Nested cluster diagram)을 그려볼 수 있습니다.
3) 군집 (P1, P2)와 개체 P3, P4, P5 간의 거리를 단일(최단) 연결법으로 수정한 거리행렬 구하기
단일(최단) 연결법은 다른 군집에 속한 가장 가까운 두 점의 거리를 군집 간 거리로 측정하는 방법이므로 아래의 계산 절차를 따릅니다.
한개만 예를 들자면, 군집 (P1, P2)와 개체 P5 간의 거리는 d(P1, P5)=25, d(P2, P5)=18 의 두 거리 중에서 최소값(MIN)인 '18'이 됩니다. 아래 거리행렬의 d(P3, P4), d(P3, P5), d(P4, P5)는 위의 거리행렬 [distance matrix - no.1]에서 계산한 결과를 그대로 가져다가 썼습니다.
[distance matrix - no.2]
P4과 P5의 거리가 '2'로서 가장 가깝군요. → (P4, P5)를 새로운 군집으로 묶어줍니다(merge). 이제 군집이 처음 5개에서 3개로 줄었습니다.
4) 군집(P4, P5)와 군집(P1, P2), P3 간의 거리를 단일(최단) 연결법으로 수정한 거리행렬 구하기
군집 간 거리 계산 방법은 동일하게 '최소값'을 찾으면 됩니다.
[distance matrix - no.3]
개체 P3와 군집 (P4, P5)의 거리가 '5'로서 가장 가깝군요. → P3과 (P4, P5)를 새로운 군집으로 묶어줍니다(merge). 반복(repeat)을 거듭할 수록 군집이 줄어서 이제 2개가 되었습니다.
5) 군집(P1, P2)와 군집 {P3, (P4, P5)} 간의 거리를 단일(최단) 연결법으로 수정한 거리행렬 구하기
마지막으로 두개 남은 군집 (P1, P2)와 {P3, (P4, P5)}를 묶어줍니다(merge). → 드디어 반복(repeat)을 거듭한 끝에 군집이 1개로 줄어들었습니다. → 종료 (End)
이상의 '단일(최단) 연결법'에 의한 응집형 계층적 군집화를 위한 R script는 아래와 같습니다. 너무 짧다고 놀라지 마세요. ㅋㅋ
위에서 알고리즘 설명한다고 개난리를 쳤는데요, R로는 단 1줄이면 끝납니다.
(설명자료 쓰고 그리는데는 토요일 반나절 투자, R script 짜는데는 5분... )
> # Agglomerative Hierarchical Clustering : Single Linkage method (MIN)
> hc_sl <- hclust(dist(xy)^2, method="single")
> hc_sl
Call:
hclust(d = dist(xy)^2, method = "single")
Cluster method : single
Distance : euclidean
Number of objects: 5
6) 덴드로그램(Dendrogram)으로 응집형 계층적 군집화(by 단일(최단) 연결법) 결과 확인해보기
덴드로그램(Dendrogram)은 (a) '무슨 군집과 무슨 군집이 서로 묶였는지 (서로 유사한지, 근접한지)', (b) '어떤 순서로 차례대로 묶여갔는지', (c) '군집 간 거리는 얼마나 되는지'를 알 수 있는 매우 유용한 그래프입니다.
아래 덴드로그램의 y축이 바로 군집 간 거리 (단일(최소) 연결법으로 구한) 를 나타냅니다.
plot(x, hang = -1) 옵션을 설정하면 아래 그램의 오른쪽 덴드로그램처럼 군집 묶어주는 선이 y=0 부터 시작합니다.
> # dendrogram
> my_par = par(no.readonly = TRUE)
> par(oma = c(0, 0, 1, 0))
> par(mfrow = c(1, 2))
> plot(hc_sl)
> plot(hc_sl, hang = -1) # hang = -1 : line from the bottom
이상으로 (1) 응집형 계층적 군집화 : (1-1) 단일(최단) 연결법(Single link, MIN) 소개를 마치도록 하겠습니다. 다 쓰고 보니 스크롤 압박이 상당히 심한...블로그에는 부적절한 글이 되어버렸습니다. ㅜ_ㅠ
[Reference]
(1) "Introduction to Data Mining", Pang-Ning Tan(Michigan State University), Michael Steinbach(University of Minnesota), Vipin Kumar(University of Minnesota), Addison-Wesley Companion Book
(2) "Clustering Algorithm", Ana Fred, INSTITUTO SUPERIOR TECNICO, Universidade Techica de Lisboa, 2009
(3) "R, SAS, MS-SQL을 활용한 데이터마이닝", 이정진 지음, 자유아카데미, 2011
지난번 포스팅에서는 (구간식 또는 비율식 데이터 속성의 다변수일 경우의) 유사성, 비유사성 측도로서 다양한 거리의 정의에 대해서 알아보았습니다.
이번 포스팅에서는 하나의 예를 가지고 R을 사용하여 각 거리 종류별 거리를 계산, 비교해보도록 하겠습니다.
예로 사용할 데이터는 5명의 학생의 '선형대수(linear algebra)'와 '기계학습(machine learning)' 기말고사 시험성적입니다. 이 중에서 1번째와 2번째 학생(아래 산점도의 빨간점)의 선형대수와 기계학습 시험점수의 거리를 (1) 맨하탄 거리(manhattan distance), (2) 유클리드 거리(euclidean distance), (3) 표준화 거리(standadized distance), (4) 마할라노비스 거리(mahalanobis distance)로 계산해보도록 하겠습니다.
dist(dataset, method = "manhattan") 함수를 사용하여 맨하탄 거리를 계산할 수 있습니다.
아니면 아래의 두번째 방법처럼 두 변수의 관측치별 차이 절대값을 더해주면 됩니다 ( <- 달랑 2개 관측치 거리를 계산하는 거니깐 이 방식도 사용할만 하지만요, 만약 관측치 학생 1,000 명의 거리를 구하는 것이라면요? ^^; 두 방식의 결과값 포맷이 조금 다르다는 점도 눈여겨 봐주세요.)
지난번 포스팅에서는 군집분석(Cluster Analysis)의 개념과 유형에 대해서 알아보았습니다.
군집분석은 데이터를 유사한 혹은 동질의 군집(cluster)으로 묶어주는 것이라고 했었는데요, 그렇다면 "유사하다"(Similarity) 혹은 "유사하지 않다"(Dis-similarity)를 어떻게 측정할 수 있을지에 대한 방법이 이번 포스팅의 주제입니다.
이번에 살펴볼 거리 측도는 데이터와 데이터간 (비)유사성을 보는 군집분석뿐만이 아니라 변수와 변수간 관계를 보는 다변량 통계 분석에서도 기본기가 되는 중요한 내용이므로 유심히 보시기 바랍니다.
데이터 간의 비유사성(Dis-similarity)은 거리(Distance)를 가지고 주로 측정하며, 유사성(Similarity)은 비유사성과 반비례의 관계에 있다고 보면 됩니다. 거리 말고 상관계수(Correlation coefficient)를 쓰기도 하는데요(→ collaborative filtering에서 상관계수 사용함), 이번 포스팅에서는 거리만 설명하도록 하겠습니다.
거리는 데이터의 속성, 구조에 따라서 적합한 것을 사용해야 하는데요, 이번 포스팅에서는 다중 변수의 구간식(Interval data type) 또는 비율식(Ratio data type) 데이터 속성에 대한 비유사성 측도로서 '거리'(Distance as a dis-similarity mesaure)척도로서,
(1) 맨하탄 거리 (Manhattan distance)
(2) 유클리드 거리 (Euclid distance)
(3) 표준화 거리 (Standardized distance)
(4) 마할라노비스 거리 (Mahalanobis distance)
에 대해서 소개하겠습니다. 이밖에 확장 자카르드 계수(Extended Jaccard Coefficient), 상관계수(Correlation Coefficient), 브레그만 거리(Bregman Divergence)는 생략합니다.
[ 표기 관련 (denotation) ]
- 두 변수값 x와 y의 비유사성 척도로서 거리(distance) 는 d(x, y) 또는 간단히 d 로 표기함
[ 거리 척도 (Distance measures) ]
(1) 맨하탄 거리 (Manhattan distance)
맨하탄 거리는 뉴욕의 택시가 출발지에서 도착지로 갈 때 빌딩을 피해 동, 서, 남, 북의 격자 모양의 도로를 직선으로 갈 때의 거리(즉, 가로 블록 + 세로 블록 절대합)를 본따서 이름을 붙힌 거리입니다. ("Manhattan distance" is a rectilinear distance, named after the number of blocks north, south, east, or west a taxicab must travel on to reach its destination on the grid of streets in parts of New York City. - from Wikipedia -). 물리적인 길거리를 생각하면 쉽습니다. 자동차가 아무리 마음이 급하다고 길과 길 사이에 있는 빌딩(방해물, obstacle)을 뚫고 대각선으로 지나갈 수는 없는 노릇이며, 좋으나 싫으나 아래 그림처럼 빌딩을 피해 '도로'가 놓여진 한계 안에서 '최단 route'를 찾는 수밖에 없습니다. (<= 바로 이런 상황의 데이터를 분석해야할 때 맨하탄 거리를 사용하면 됩니다)
다른 말로 "City block distance", "Chessboard distance", "Chebyshev distance" 라고도 합니다. 서양 체스의 Rook move (상/하/좌/우, 동/서/남/북 방향으로만 이동 가능)를 생각하면 됩니다.
두 점의 값(starting point -> destination)에 대한 맨하탄 거리(Manhattan Distance)를 그림과 수식으로 나타내면 아래와 같습니다. 그래프 이론(Graph theory)에서는 두 지점의 거리를 '최단 경로(shortest route)'로 정의하는데요, 아래 그림에서 보면 각 도러의 블록별 단위거리가 동일하다고 하면 최단경로가 route 1, route 2, route 3, .... 많습니다 (좌에서 우로 8번 & 하에서 상으로 7번 경로 조합인 모든 route).
맨하탄 거리(Manhattan distance)는 민코우스키 거리(Minkowski distance)에서 r=1 인 거리이기도 합니다. r=2 (2-norm distance) 인 경우는 유클리드 거리 (Euclidean distance) 입니다.
For a point (x1, x2, ...,xm) and a point (y1, y2, ...,ym), Minkowski distance is...
(2) 유클리드 거리 (Euclidean distance)
유클리드 거리는 두 점을 잇는 가장 짧은 직선 거리입니다. 아래 그림을 예로 들면, 헬리콥터를 타고 x 지점에서 y지점으로 날아간다고 했을 때 x와 y 지점 사이에 아무리 많은 빌딩(방해물)이 있더라도 상관없이 최단 직선 코스로 날아갈 수 있다고 연상하면 쉽게 이해할 수 있을 것입니다. 창공을 나는 새의 관점(from a bird's eye view)으로 본 거리입니다. (↔ 위의 택시를 타고 가는 맨하탄 거리와의 차이를 비교해보세요)
서양 체스로 치면 상, 하, 좌, 우, 대각선 어느 방향으로나 이동이 자유로운 King move 나 Queen move 를 생각하면 되겠네요. (↔ 맨하탄 거리는 Rook move)
m차원 유클리드 공간 (Euclidean space ) 에서 두 점 (x1, x2), (y1, y2)의 거리는 피타고라스 정리(Pythagorean theorem)에 의해서 아래 그림에서 제시한 공식으로 구할 수 있습니다.
민코우스키 거리(Minkowski distance)에서 r=2 (2-norm distance) 인 거리가 바로 유클리드 거리 (Euclidean distance) 입니다
만약 세 점 (x1, x2, x3), (y1, y2, y3) (in three-space) 간의 거리는 어떻게 구하면 될까요? 이 또한 피타고라스 정리에 의해서 아래처럼 유클리드 거리 공식으로 구하면 됩니다.
아주 많은 분석에서 유클리드 거리를 사용하며, 그렇다보니 대부분 '거리'하면 '유클리드 거리'를 가장 먼저 떠올리게 되곤 합니다. 그만큼 친숙하고도 아주 유용한 거리 개념입니다.
그런데 유클리드 거리에도 한가지 고려해야 할 점이 있습니다. 만약 두 변수의 분산, scale이 서로 다르다면 어떻게 될까요? ☞ 표준화 거리에 대해서 얘기할 시간이군요.
(3) 표준화 거리 (Standardized distance)
표준화 거리는 각 변수를 해당변수의 표준편차(standard deviation)로 척도 변환한 후에 유클리드 거리를 계산한 거리입니다. 표준화를 하게 되면 척도(scale)의 차이, 분산의 차이로 인한 왜곡을 피할 수 있습니다.
표준화 거리는 다른 말로 통계적 거리 (Statistical distance) 라고도 합니다.
표준화 거리를 이용하여 한 점에서 거리가 같은 점들의 집합을 구하면 표본평균을 중심으로 좌표축에 장축(major axis)과 단축(minor axis)이 반듯하게 놓인 타원(Ellipse) 또는 타원체를 이루게 됩니다. 변수가 2개인 경우 두 개체간의 표준화 거리를 구하면 타원의 중심은 각 변수의 평균값이 위치한 곳이 되며, 아래 그림과 같은 형태로 그려져 각 변수의 평균점을 중심으로 하는 타원이 됩니다. ("R 다변량 통계분석", 김재희)
(4) 마할라노비스 거리 (Mahalanobis distance)
마할라노비스 거리는 변수의 표준편차와 더불어 변수 간 상관성(correlation)까지 고려한 거리측도입니다. (참고로, 마할라노비스(Prasanta Chandra Mahalanobis, 29 June 1893 – 28 June 1972) 는 인도의 과학자 겸 응용통계학자로서 '마할라노비스 거리'를 제안한 분입니다.)
한 점에서 마할라노비스 거리가 같은 점들의 집합을 구하면 표본평균을 중심으로 축이 회전된 타원체(rotated ellipse)를 이루게 됩니다. 변수간의 상관성이 있을 때의 거리 측도로서 방향성을 고려하여 아래의 그림과 같이 회전된 축을 생각할 수 있습니다. ("R 다변량 통계분석", 김재희)
(↔ 바로 앞의 그림 '표준화 거리를 이용해 구한 한점에서 거리가 같은 점들의 집합 : 타원'과 비교해보세요)
맨하탄 거리와 유클리드 거리는 그래도 제법 접해봤을 기회가 있었을 것 같은데요, 표준화 거리와 마할라노비스 거리는 낯설기도 하고 수식도 선형대수 표기법이 나오고 해서 이해하기가 좀 어려울것 같습니다.
수식을 자세히 보시면 SVD(Singular Value Decomposition), 특이값 분해(축 rotation -> scale 변환 -> 축 rotation)와 비슷함을 알 수 있습니다.
다변량통계분석 하는 분이라면 Hotelling's T-squared 통계량 수식과 매우 유사함을 알 수 있을거예요. 마할라노비스 거리를 1/n 로 나누어주면 Hotelling's T-squared 통계량이 됩니다. 재미있죠? ^^
다음번 포스팅에서는 간단한 예를 들어서 유클리드 거리, 표준화 거리, 마할라노비스 거리를 설명하고, R script 도 소개하도록 하겠습니다.
이번 포스팅에서는 Y값에 대한 Label이 없는 비지도학습(unsupervised learning)의 두번째 기법으로 '군집분석 (Cluster Analysis, Clustering)'에 대해서 소개하도록 하겠습니다.
1) 군집분석(cluster analysis)이란?
군집분석이란 데이터가 속해 있는 군집을 모르는 상태에서(Y값 label 없음) 유사한 혹은 동질의 데이터끼리 군집(cluster)로 묶어 주는 분석기법입니다.
사자성어 중에 보면
"유유상종(類類相從)", "끼리 끼리 모인다"라는 말이 있는데요, 군집분석을 잘 나타내는 말 같습니다.
서양 속담에도 비슷한 것이 있습니다.
"Birds of a feather flock together"
* 그림 출처 : http://www.winglish.com/free/asp/mrwin_default_com.asp?j_num=6
군집분석은 유의미하거나 유용한 데이터의 구조를 파악하여 활용(clustering for utility)하거나, 데이터의 구조를 이해(understanding)하는 목적으로 분석 초기 탐색적 분석 단계에서 아주 많이 활용하곤 합니다.
군집분석은 마케팅, 심리학, 사회학, 통계, 패턴 인식, 기계학습, 데이터마이닝 등에 다방면에 사용됩니다. 마케팅, CRM에 종사하는 분들은 고객세분화(cutomer segmentation) 하는데 군집분석 & 프로파일링 (customer clustering & profiling) 에 대해서 들어보았거나 시도를 해봤을 것 같습니다.
(1) 군집분석으로 고객세분화를 먼저 수행하고 (un-supervised learning) -> (2) Decision Tree를 사용해서 군집분석을 통해 만든 군집들을 분류(Classification, supervised learning)하는 모델을 만드는 semi-supervised learning approach를 취하는 것도 생각해 볼 수 있을 것입니다.
데이터가 X와 Y의 2차원으로만 구성되어 있다면 산점도(scatter plot)을 그려서 눈으로 확인해보는 것만으로도 데이터셋에 내재한 패턴, 군집 유무, 데이터 간 관계를 어림짐작할 수 있습니다. 3차원도 (좀 보기에 헷갈리기는 하지만) 3D plot을 그려서 눈으로 확인할 수 있습니다. 하지만 4차원 이상 넘어가면 사람 눈으로 군집 유무 여부를 확인, 판단하는게 어려워집니다. 이때 군집분석을 활용하면 좋겠지요?! 개별 나무를 몰라도 (데이터셋에 대한 사전지식이 없어도) 숲에 대한 조감도(군집)를 찾을 수 있다니 군집분석은 참 유용한 데이터 마이닝 (숨은 지식, 패턴 캐내기) 기법입니다.
2) 군집분석의 원리(Principal of custer analysis)는?
군집분석은 데이터가 어떤 군집에 속해있는지 알 수 있는 Y값 Label이 없는 상태에서 진행된다고 하였으므로 지도학습(supervised learning)처럼 명쾌한 모델성능평가가 쉽지가 않습니다. 군집을 몇 개로 하느냐에 따라서도 군집화가 영향을 많이 받기도 하는데요, 보통은 데이터 내 군집이 몇 개 있는지 모르는 경우가 많습니다.
그렇다면 군집분석에서 모델 생성, 평가는 무슨 기준으로 하는 것일까 하는 의문이 들 것입니다. 군집분석에서는 주로 응집도(cohesion)과 분리도(separation) 척도를 많이 사용하는 편인데요, 군집분석을 컴퓨터가 이해하도록 수식, 척도를 가지고 군집화의 원리를 나타내보면
(1) 군집 內 응집도를 최대화하고, (maximizing cohesion within cluster, i.e. minimizing sum of distance b/w x and y)
& (2) 군집 間 분리도를 최대화하도록 (maximizing separation between clusters)
군집을 형성한다는 것입니다.
군집분석 알고리즘의 근간에는 최적화(optimization) 개념이 들어있음을 알 수 있습니다.
Graph-based clustering과 Prototype-base clustering 의 두 가지 approach별로 나누어서 응집도(cohesion)와 분리도(separation)의 개념을 수식과 시각화로 같이 나타내면 아래와 같습니다.
(2-a) 그래프 기반 응집도와 분리도 (Graph-based view of cohesion and separation)
(2-b) 프로토타입 기반 응집도와 분리도 (Prototype-base view of cohesion and separation)
아래에 군집의 중심(centroid)을 기준으로 군집 내 데이터와 중심 간 거리를 가지고 응집도를, 군집 중심 간의 거리를 가지고 분리도를 나타내보았습니다.
3) 군집분석에에는 어떤 유형이 있나? 어떻게 구분할 수 있나?
군집분석을 구분할 수 있는 기준이 여러개 있을 수 있는데요, 한 군집 안에 부분군집이 있느냐 없느냐에 따라서 계층적 군집(hierarchical clustering)과 분할적 군집(partitional clustering)으로 나눌 수 있습니다. 계층적 군집은 한 군집 안에 부분군집이 있는 반면, 분할적 군집은 군집간 부분집합이나 중복없이 상호 배타적으로(exclusive) 존재합니다. 아래 그림의 이미지를 참고하시면 이해하기 쉬울거예요.
(3-a) 계층적 군집분석 (Hierarchical Clustering)
계층적 군집분석은 (3-a-1) 개별 데이터에서 시작해서 유사한 데이터끼리 군집으로 차근차근 묶어가는 기법인 응집형 방법 (Aggolomerative, Bottom-up method)과, 응집형과는 반대로 (3-a-2) 모든 데이터를 하나의 군집에 속한다고 놓고, 차근차근 세부 군집으로 나누어가는 분리형 방법 (Divisive, Top-down method) 으로 구분할 수 있습니다.
일반적으로 군집 간 합치기와 분할은 greedy manner (각 단계별 국소 최적해를 찾아가는 휴리스틱 최적화 알고리즘) 에 의해서 결정이 됩니다. 일반적인 경우 응집형(agglomerative) 군집화의 복잡도(complexity)는 으로서 큰 규모의 데이터셋에 적용하기에는 시간이 너무 오래 걸려서 무리일 수 있습니다. 일부 특별한 경우로, 단일(최단) 연결법(single-linkage (SLINK)), 완전(최장) 연결법(complete-linkage, CLINK)는 복잡도가 로서 최적의 효과적인 응집형 방법으로 알려져 있습니다. 모든 관측치를 상호배타적으로 탐색하는 경우의 분리형(divisive) 군집화는 복잡도가 으로서 아주 끔찍한 수준입니다. ^^; (from Wikipedia)
앞으로 연재할 때 복잡도가 어마무시 높은 분리형 군집화는 제외하도록 할께요.
응집형(Agglomerative) 방법에는 군집간 거리 척도와 연결법에 따라서 단일(최단) 연결법 (Single Linkage Method), 완전(최장) 연결법 (Complete Linkage Method), 평균 연결법 (Average Linkage Method), 중심 연결법 (Centroid Linkage Method), Ward 연결법 (Ward Linkage Method)이 있습니다.
분리형(Divisive) 방법에는 DIANA 방법(DIANA algorithm)이 있습니다.
분할적 군집(Partitional clustering) 방법에는 거리 기반 군집화 (distance-based clustering), 밀도 기반 군집화(density-based clustering), 신경망 기반 군집화 (neural network-based clustering) 등이 있습니다.
(3-b-2) 분포 기반(Distribution-based) 군집화에는 혼합분포 군집(Mixture distribution clustering)이 있습니다.
(3-b-3) 밀도 기반(Density-based) 군집화 기법에는 중심 밀도 군집(Center density clustering), 격자 기반 군집(Grid-based clustering), 커넬 기반 군집(Kernel-based clustering) 등이 있습니다.
(3-b-4) 그래프 기반(Graph-based) 군집화에는 코호넨 군집(Kohenen clustering) 이 있습니다.
보통 군집분석 공부한다고 하면 'K-means clustering' 알고리즘 공부하고 끝내는 경우가 있는데요 (좀더 공부한다면 계층적 군집화 일부...), 위에 제시한 것처럼 군집분석 기법/알고리즘이 상당히 많이 있습니다. 분석 기법이 많다보니 뭘 써야하나 혼란스러울 수 있는데요, 군집분석 알고리즘별로 데이터 특성과 구조, 분석 목적에 맞게 보다 적절한 알고리즘이 있습니다. 따라서 분석가는 각 알고리즘의 개념, 특성, 장점과 단점을 알고 있어야 하고, 분석 목적, 데이터 특성에 맞게 잘 선택해서 사용할 줄 알아야 하겠습니다.
위에서는 분석 기법 이름만 구조를 잡아서 나열을 했는데요, 앞으로 하나씩 차근차근 알고리즘 설명과 예시, 그리고 R script를 풀어보도록 하겠습니다.
[Reference]
1) "Introduction to Data Mining", Pang-Ning Tan(Michigan State University), Michael Steinbach(University of Minnesota), Vipin Kumar(University of Minnesota), Addison-Wesley Companion Book
2) Wikipedia
다음번 포스팅에서는 기초체력을 다지고 시작한다는 의미에서 군집분석에서 유사성(similarity), 비유사성(dis-similarity)의 척도에 대해서 알아보도록 하겠습니다.
지난 포스팅에서는 시간/순서를 고려한 순차 패턴 분석 (sequence pattern analysis)에 대해서 알아보았습니다.
이번 포스팅에서는 연관규칙 분석의 대상이 되는 항목의 분류체계 (Taxonomy)와 가상 항목 (Virtual Item)에 대해서 알아보겠습니다.
이번 포스팅에서 다루려는 주제는 1~2시간 짜리 연관규칙 교육 프로그램에서는 시간이 부족한 관계로 잘 안다루는 내용입니다만, 매우 중요한 부분입니다. 실전 프로젝트에서 보면 "써먹을 수 있는 규칙"이 나오느냐, 안나오느냐에 상당히 관련이 있는 부분이구요, 사실 순서상으로 보면 지금 쓰는 이 글이 연관규칙 분석을 할 때 현업(業 전문가, domain expert)과 함께 프로젝트 초반에 분석 시나리오 잡을 때 의사결정을 해야만 하는 매우 중요한 부분입니다.
1) 항목 분류 체계 (Taxonomy)
상품 구매 연관규칙을 분석한다고 가정했을 때, 상품 분류 체계를 예로 생각하시면 됩니다. 백화점, 마트, 홈쇼핑, 인터넷쇼핑몰, 슈퍼마켓 등... 유통업체는 아래와 같은 형태의 대/중/소/세/세부속성별로 계층(Hierarchy)을 가진 상품 분류 체계를 가지고 있습니다.
* Reference: "Data Mining Techniques", by Michael J.A.Berry, Gordon S.Linoff
소분류 -> 중분류 -> 대분류 방향으로 올라갈 수록 일반화(generalization), 추상화 되며, 소분류 -> 세분류 -> 세부속성 방향으로 내려갈 수록 구체적(detail)인 항목이 됩니다.
이게 연관규칙 도출에 왜 중요한지에 대해서 예를 들어서 설명해보겠습니다.
너무 상위 항목 (대분류, 혹은 중분류)을 가지고 연관규칙을 분석하면 "실행 가능한 수준의 규칙"이 아닌 경우가 많습니다. 한마디로 업무에 적용하기가 애매한 경우입니다. 가령, 대분류를 가지고 분석을 해서 "{냉동식품} → {아동의류} 라는 연관규칙이 나왔다고 해봅시다. '냉동식품'이나 '아동의류' 담당 매니저, 마케터에게 이 규칙을 가져가면 아마 "so what?", "나보고 뭘 어쩌라고요?" 소리 듣기 십상입니다.
반면에, 너무 하위 항목 (가령, 세부속성의 '브랜드')을 가지고 연관규칙 분석을 수행하면 당장 실행가능한 규칙이 나올 여지는 있습니다만, 단점으로는 일단 연산 시간이 무척 많이 걸립니다. 그리고 빈도수가 너무 작은 다수의 '브랜드'들의 경우 비빈방항목 pruning 원칙에 의해 규칙에 안나타날 수 있습니다.
결국 너무 상위 level이어도 안되고, 너무 하위 level이어도 안좋고 해서, 적당한(?) 수준을 찾아서 분석을 수행해야 합니다. 그리고 여기서 '적당한(?)'은 "분석 목적이 무엇인가?", "어디에 써 먹을려고 연관규칙 분석을 하는 것인가?", "최종 사용자는 누구이며 그 사용자가 만족하는 수준은 어느 level인가?" 등의 질문에 답하는 과정에서 결정이 된다고 보면 됩니다. 이런 질문에 답하려면 현업(domain expert)이 꼭 필요하겠지요? 業은 잘 모르는 분석전문가가 현업 참여없이 단독으로 taxonomy 분석 level 정해놓고 '연관규칙이 이렇게 나왔네요'하고 가져가면 그 규칙을 사용할 현업한테서 한 소리 (가령, '이거 왜 하셨어요?', '이걸로는 암것도 못하겠는걸요...') 듣고 분석을 처음부터 다시 수행해야할 수도 있습니다.
사실, 더 큰 문제는 상품분류체계(taxonomy) 관리가 잘 안되는 경우가 매우 많다는 점입니다. MD 담당자가 새로 바뀌면 기존의 상품분류체계와 align을 안시키고 이상한 상품코드를 새로 추가하는 경우도 있구요, 단종된 상품코드는 그때 그때 정리를 해줘야 하는데요, 그대로 두고 있는 경우도 있습니다. 이거 교통정리하는게 참 고역인데요, 자칫 연관규칙 분석하는 업무량보다 상품분류체계 정비하는게 더 시간을 많이 잡아먹는, 배보다 배꼽이 더 큰 웃긴 일이 생길 수도 있습니다. -_-;
또 하나 문제는요, 상품분류체계가 마케텅의 입맛에 딱 안맞을 수 있다는 점입니다. 보통은 MD가 상품분류체계를 기획하고, 정보를 입력하고, 관리를 합니다. 그러다 보니 '마케팅' 부서의 활용 관점은 안들어가 있다고 보면 됩니다. 바로 여기서 가상항목(virtual item)에 대한 필요성이 생깁니다.
2) 가상 항목 (Virtual Item)
가상 항목 (virtual item) 이란 원래의 항목분류체계(taxonomy)에는 없는 가상의 항목을 새로 만들어 사용하는 것입니다. 가령, 아래의 예처럼 원래의 항목분류체계에는 'Handbag'과 'Watch'의 카테고리에 각 각 속해있던 상품(item)들을 '브랜드'라는 새로운 관점을 가지고 묶어서 'GUCCI handbag'과 'GUCCI watch'를 'GUCCI Products'라는 새로운 가상의(기존에는 없었던) 항목(virtual item)으로 만들고, 'DKNY handbag'과 'DKNY watch'를 'DKNY products'라는 새로운 가상의 항목(virtual item)으로 만들어서 연관규칙 분석에 사용하게 됩니다.
위의 예에서는 상품 카테고리 간 동일한 브랜드별로 virtual item을 만들어보았습니다.
이 외에도 분석해서 사용하려는 목적에 따라서 다양한 아이디어를 생각해볼 수 있습니다.
가령, 식품을 수입품과 국산품으로 구분하는 virtual item 이라든지, 유아식품 중 아토피 관련 식품이나 유기농 식품 여부 virtual item도 생각해볼 수 있습니다. 상품구매 요일(평일, 공휴일)이나 시즌, 아니면 event 성 (생일, 기념일, 00day 관련 등) 상품에 대한 virtual item도 생각해 볼 수 있겠습니다.
비빈발항목을 묶어서 빈발항목으로 만든 다음에 이에 적당한 naming을 해서 가상항목으로 만들어서 분석을 하는 것도 재치있는 분석요령입니다.
3) Segmented multiple sets mining
마지막으로, 실무 분석할 때 요긴하게 써먹곤 했던 것 하나 더 말씀드리자면, 연관규칙 도출에 영향이 클 것으로 예상되는 특정 기준, 관점이 있다면 이를 가지고 사전에 데이터셋을 나누어서 연관규칙 분석을 하라는 것입니다.
가령, 아래의 예처럼 상품 연관구매 규칙을 분석한다고 했을 때, 성(gender)과 연령(age)에 따라서 상품 구매 패턴이 큰 차이를 보일 것이라고 예상을 한다면 성별과 연령대별로 segments를 나누어서 각 segment별로 나누어서 연관구매규칙을 분석하면 된다는 뜻입니다.
물론 지지난번에 포스팅했던 '범주형 및 연속형 데이터의 연관규칙 분석' 방법을 활용해서 연령대, 성별을 이항변수화(binarization)하여 연관규칙 분석을 수행해도 되긴 합니다. 편한 방법을 사용하시면 되겠습니다.
지난번 포스팅에서는 범주형 및 연속형 데이터에 대한 연관규칙 분석에 대하여 알아보았습니다.
이번 포스팅에서는 시간(time), 순서(sequence)를 고려한 순차패턴분석(sequence pattern analysis)에 대하여 소개하겠습니다.
먼저, 연관규칙(association rule)과 순차패턴규칙의 차이점을 '분석 주안점', '활용 데이터 항목', '흥미도/유용성 평가 척도'의 관점에서 표로 비교해보면 아래와 같습니다.
If A then B 형식의 데이터 속에 숨겨져있는 규칙을 찾아낸다는 면에서는 같습니다만, 순차패턴분석의 경우 "What goes AFTER what?" 과 같이 시간/순서에 따른 사건의 규칙을 찾는다는 점, 데이터셋에 Identity information (Customer Identifier, or Event ID), TimeStamp (Sequence information, or Sequence ID) 변수가 있어야 한다는 점, 그리고 Support 척도만 제공할 뿐 연관규칙에서 썼던 Confidence, Lift는 없다는 점이 연관규칙과는 다릅니다.
순차패턴분석에서 사용하는 데이터셋은 아래처럼 고객ID (or Event ID)별로 TimeStampe (or Sequence ID)의 시간 순서로 거래 데이터가 정리된 형태(ordered by customer ID and TimeStamp)로 되어있습니다.
항목집합을 순서로 나타낸 리스트를 sequence라고 하며,
를 j번째 항목집합이라고 할 때
으로 표기합니다.
순차패턴분석에서 사용하는 규칙 흥미도 척도인 Support(s) = Sequence s를 포함하는 고객의 비율 입니다.
특정 최소 지지도(support) 이상을 가지는 sequence를 빈발 시퀀스(large sequence) 라고 합니다. 순차적 패턴 탐사 문제는 빈발 시퀀스 중에서 최대 시퀀스(maximal sequence)들을 찾는 것이라고 할 수 있습니다.
순차 패턴 분석 알고리즘 (Agrawal and Srikant, 1995)은 다음의 단계들로 구성되어 있습니다.
1) 정렬 단계 : Transaction database를 고객 sequence data로 전환한다.
2) 빈발항목집합 단계 : 고객 시퀀스의 항목집합 또는 이의 부분집합 중 최소 지지도(고객비율 사용) 이상인 것들을 빈발항목집합으로 도출한다. 편의상 각 빈발 항목집합에 일련번호를 부여한다.
3) 변환 단계 : 고객 시퀀스를 빈발항목집합을 사용한 시퀀스로 변환한다.
4) 시퀀스 단계 : 빈발 시퀀스를 도출한다.
5) 최대화 단계 : 빈발 시퀀스로부터 최대 시퀀스를 탐색한다.
(* 출처 : 데이터마이닝 기법과 응용, 전치혁 지음, 한나래 아카데미)
순차적 패턴 탐사 알고리즘에 대해서는 깊이 들어가지는 않겠으며, R의 arulesSequences package 사용법 중심으로 이번 포스팅을 이어가겠습니다.
1) "arulesSequences" package installation and loading
arulesSequences package는 M. Zaki가 개발한cSPADE 알고리즘을 사용하여 빈발 순차 패턴을 탐색합니다. 이 알고리즘은 효율적인 격자 탐색 기법과 함께 temporal joins을 이용하며 시간 제약을 제공합니다. (Mining frequent sequential patterns with the cSPADE algorithm. This algorithm utilizes temporal joins along with efficient lattice search techniques and provides for timing constraints. - help(arulesSequences) -)
##----------------------------------------
## sequence analysis
##----------------------------------------
## 'arulesSequences' package installation, loading
install.packages("arulesSequences")
#Installing package into ‘C:/Users/Owner/Documents/R/win-library/3.3’
#(as ‘lib’ is unspecified)
#also installing the dependency ‘arules’
#
#trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.3/arules_1.4-1.zip'
#Content type 'application/zip' length 1889108 bytes (1.8 MB)
#downloaded 1.8 MB
#
#trying URL 'https://cran.rstudio.com/bin/windows/contrib/3.3/arulesSequences_0.2-15.zip'
#Content type 'application/zip' length 4002231 bytes (3.8 MB)
#downloaded 3.8 MB
#
#package ‘arules’ successfully unpacked and MD5 sums checked
#package ‘arulesSequences’ successfully unpacked and MD5 sums checked
#
#The downloaded binary packages are in
#C:\Users\Owner\AppData\Local\Temp\RtmpOOKTl5\downloaded_packages
library(arulesSequences)
#필요한 패키지를 로딩중입니다: arules
#필요한 패키지를 로딩중입니다: Matrix
#
#다음의 패키지를 부착합니다:
#‘arules’ The following objects are masked from ‘package:base’:
#abbreviate, write
## zaki transaction Dataset > data(zaki)
str(zaki)
#Formal class 'transactions' [package "arules"] with 3 slots
#..@ data :Formal class 'ngCMatrix' [package "Matrix"] with 5 slots
#.. .. ..@ i : int [1:27] 2 3 0 1 2 0 1 5 0 2
#... .. .. ..@ p : int [1:11] 0 2 5 8 12 15 16 19 22 24
#... .. .. ..@ Dim : int [1:2] 8 10
#.. .. ..@ Dimnames:List of 2
#.. .. .. ..$ : NULL
#.. .. .. ..$ : NULL
#.. .. ..@ factors : list()
#..@ itemInfo :'data.frame': 8 obs. of 1 variable:
#.. ..$ labels: chr [1:8] "A" "B" "C" "D"
#... ..@ itemsetInfo:'data.frame': 10 obs. of 3 variables:
#.. ..$ sequenceID: int [1:10] 1 1 1 1 2 2 3 4 4 4
#.. ..$ eventID : int [1:10] 10 15 20 25 15 20 10 10 20 25
#.. ..$ SIZE : int [1:10] 2 3 3 4 3 1 3 3 2 3
help(zaki)
> help(zaki)
zaki
R Documentation
Zaki Data Set
Description
A small example database for sequence mining provided as an object of classtransactionsand as a text file.
Usage
data(zaki)
Details
The data set contains the sequential database described in the paper by M. J. Zaki for illustration of the concepts of sequence mining.sequenceIDandeventIDdenote the sequence and event (time) identifiers of the transactions.
Source
M. J. Zaki. (2001). SPADE: An Efficient Algorithm for Mining Frequent Sequences.Machine Learning Journal,42, 31–60.
순차 규칙 내 원소의 개수(element size)가 2개 이상인 규칙만 선별해보겠습니다.
## making the sequence rule as a DataFrame
seq_rule_1_df <- as(seq_rule_1, "data.frame")
## calculate the size of the elements per each rule
seq_rule_1_size <- size(seq_rule_1)
## combine the element size with the sequence rule DataFrame
seq_rule_1_df <- cbind(seq_rule_1_df, seq_rule_1_size)
## subsetting the rules which have moer the 2 elements in the rule
seq_rule_1_df_size_2 <- subset(seq_rule_1_df,
subset = seq_rule_1_size >= 2)
## checking the result
seq_rule_1_df_size_2
# sequence support seq_rule_1_size
#7 <{D},{F}> 0.5 2
#8 <{D},{B,F}> 0.5 2
#11 <{D},{B}> 0.5 2
#12 <{B},{A}> 0.5 2
#13 <{D},{A}> 0.5 2
#14 <{F},{A}> 0.5 2
#15 <{D},{F},{A}> 0.5 3
#16 <{B,F},{A}> 0.5 2
#17 <{D},{B,F},{A}> 0.5 3
#18 <{D},{B},{A}> 0.5 3