각 개체에 대해 여러 변수값들로부터 n개의 유사한 성격의 군집으로 군집화하고 군집간 관계를 분석하는 기법
KernSmooth 2.23 loaded
Copyright M. P. Wand 1997-2009
가장 유사한 개체를 묶어 나가는 과정을 반복하여 원하는 개수의 군집을 형성하는 방법. 작은 군집으로부터 출발하여 을 병합해 나가는 방법(병합적 방법)과 큰 군집으로부터 군집을 분리해 나가는 방법(분할적 방법)이 있다.
민코우스키(MinKowski) 거리 : Dist(x,y)=[∑(xri−xsi)p]1/p
맨하튼 거리 : 두 점 간의 차이의 절대값을 합한 값, r=1일 때의 민코우스키의 거리와 같음. Dist(x,y)=∑|xi−yi|
유클리드 거리 : 민코우스키거리의 특별 경우(r=2) 자료의 분포적 특성을 고려할 수 없으며, 단위 또한 같아야한다는 단점이 존재. Dist(x,y)=√∑(xri−xsi)2=√[Xr−Xs]T[Xr−Xs]
체비셰프 거리(=maximum distance) : 두 집단에서 가장 긴 지점에서의 거리 max(|x1−y1|,⋯,|xp−yp|
표준화 거리 : 유클리드 거리를 공분산으로 나눈 거리 [(Xr−Xs)TD−1(Xr−Xs)]1/2,D=diag(S11,⋯,Spp)
마할라노비스(Mahalanobis) 거리 : 공분산 구조를 함께 고려한 통계적 거리, 자료의 분포적 특성을 고려하기 위한 방법. [(Xr−Xs)TS−1(Xr−Xs)]1/2,S=표본공분산행렬
참고:공분산이 단위행렬이 되면 유클리드거리와 같아지는데 이러한 변환을 화이트닝변환이라 한다.
method에 euclidean, maximum, manhattan, canbera, minkowski 등이 들어갈 수 있다.
x1=rnorm(30)
x2=rnorm(30)
dist(rbind(x1,x2),method='euclidean')
x1
x2 8.833439
#거리계산 패키지
library('lsa')
Loading required package: SnowballC
x1=sample(c(0,1),30,replace = T)
x2=sample(c(0,1),30,replace = T)
#코사인 거리 계산
cosine(x1,x2)
[,1]
[1,] 0.5477226
hclust 함수의 method 옵션에는 “ward.D”, “ward.D2”, “single”, “complete”, “average”, “mcquitty”, “median” or “centroid”이 있다.
자료 설명 미국 내 50개 주의1973년에 발생한 범죄관련 통계자료
library(cluster)
data(USArrests)
str(USArrests)
'data.frame': 50 obs. of 4 variables:
$ Murder : num 13.2 10 8.1 8.8 9 7.9 3.3 5.9 15.4 17.4 ...
$ Assault : int 236 263 294 190 276 204 110 238 335 211 ...
$ UrbanPop: int 58 48 80 50 91 78 77 72 80 60 ...
$ Rape : num 21.2 44.5 31 19.5 40.6 38.7 11.1 15.8 31.9 25.8 ...
rownames(USArrests)
[1] "Alabama" "Alaska" "Arizona" "Arkansas" "California"
[6] "Colorado" "Connecticut" "Delaware" "Florida" "Georgia"
[11] "Hawaii" "Idaho" "Illinois" "Indiana" "Iowa"
[16] "Kansas" "Kentucky" "Louisiana" "Maine" "Maryland"
[21] "Massachusetts" "Michigan" "Minnesota" "Mississippi" "Missouri"
[26] "Montana" "Nebraska" "Nevada" "New Hampshire" "New Jersey"
[31] "New Mexico" "New York" "North Carolina" "North Dakota" "Ohio"
[36] "Oklahoma" "Oregon" "Pennsylvania" "Rhode Island" "South Carolina"
[41] "South Dakota" "Tennessee" "Texas" "Utah" "Vermont"
[46] "Virginia" "Washington" "West Virginia" "Wisconsin" "Wyoming"
#인구비율이 가장 높은 지역의 정보
USArrests[which.max(USArrests$UrbanPop),]
Murder <dbl> | Assault <int> | UrbanPop <int> | Rape <dbl> | |
---|---|---|---|---|
California | 9 | 276 | 91 | 40.6 |
#살인비율이 가장 높은 지역의 정보
USArrests[which.max(USArrests$Murder),]
Murder <dbl> | Assault <int> | UrbanPop <int> | Rape <dbl> | |
---|---|---|---|---|
Georgia | 17.4 | 211 | 60 | 25.8 |
#살인비율이 가장 늦은 지역의 정보
USArrests[which.min(USArrests$Murder),]
Murder <dbl> | Assault <int> | UrbanPop <int> | Rape <dbl> | |
---|---|---|---|---|
North Dakota | 0.8 | 45 | 44 | 7.3 |
작은 군집으로부터 출발하여 을 병합해 나가는 방법
#유클리드거리 계산
d <-dist(USArrests, method="euclidean")
#평균연결법을 활용한 계층적군집
fit <-hclust(d, method="average")
#시각화
plot(fit)
plot(fit,hang=-1)
병합적 방법(1)
metric 옵션을 통해 거리계산의 종류를 지정해 줄 수 있다. metric 대신 daisy함수를 통해 거리계산 가능 stand 옵션을 TRUE로 주면 거리 계산 전에 표준화를 수행한다.
#계층적 군집 관련 패키지
library(cluster)
#병합적방법
#stand=T이면 표준화 진행
agn1 <-agnes(USArrests, metric="manhattan", stand=TRUE)
plot(agn1)
#최장연결법으로 계층적 군집 실행
agn2 <-agnes(daisy(USArrests), diss=TRUE, method="complete")
plot(agn2)
(분할적 방법) 큰 군집으로부터 군집을 분리해 나가는 방법
library(cluster)
#분할적 방법
#stand=T이면 표준화 진행
agn1 <-diana(USArrests, metric="manhattan", stand=TRUE)
plot(agn1)
#최장연결법으로 계층적 군집 실행
agn2 <-diana(daisy(USArrests), diss=TRUE, metric ="complete")
plot(agn2)
K개(원하는 군집수)의 초기값을 지정하고 각 자료를 가까운 초깃값에 할당하여 군집을 형성한 뒤, 각 군집의 평균을 계산하여 초깃값을 갱신하는 것을 반복하는 군집 방법
집단 내 제곱합의 그래프를 통한 군집수 결정
#집합내 잔차제곱합을 활용하여 군집 수 최적화
wssplot<-function(data, nc=15, seed=1234){
wss<-(nrow(data)-1)*sum(apply(data,2,var))
for (i in 2:nc){
set.seed(seed)
wss[i] <-sum(kmeans(data, centers=i)$withinss)}
plot(1:nc, wss, type="b", xlab="Number of Clusters",
ylab="Within groups sum of squares")}
wssplot(USArrests)
package를 이용
library(NbClust)
set.seed(1234)
nc=NbClust(USArrests,min.nc=2,max.nc=15,method='kmeans')
*** : The Hubert index is a graphical method of determining the number of clusters.
In the plot of Hubert index, we seek a significant knee that corresponds to a
significant increase of the value of the measure i.e the significant peak in Hubert
index second differences plot.
*** : The D index is a graphical method of determining the number of clusters.
In the plot of D index, we seek a significant knee (the significant peak in Dindex
second differences plot) that corresponds to a significant increase of the value of
the measure.
*******************************************************************
* Among all indices:
* 9 proposed 2 as the best number of clusters
* 6 proposed 3 as the best number of clusters
* 1 proposed 4 as the best number of clusters
* 3 proposed 5 as the best number of clusters
* 3 proposed 7 as the best number of clusters
* 1 proposed 11 as the best number of clusters
* 1 proposed 15 as the best number of clusters
***** Conclusion *****
* According to the majority rule, the best number of clusters is 2
*******************************************************************
nc$Best.n[1,,drop=F]
KL CH Hartigan CCC Scott Marriot TrCovW TraceW Friedman Rubin Cindex DB Silhouette
Number_clusters 5 5 3 2 7 7 3 3 11 7 4 2 2
Duda PseudoT2 Beale Ratkowsky Ball PtBiserial Frey McClain Dunn Hubert SDindex Dindex
Number_clusters 2 2 2 2 3 2 3 2 5 0 3 0
SDbw
Number_clusters 15
which.max(table(nc$Best.n[1,]))
2
2
set.seed(1234)
#2개의 군집 생성
fit.km <-kmeans(USArrests, 2, nstart=25)
fit.km$size
[1] 29 21
#시각화
plot(USArrests, col=fit.km$cluster)
#군집별 변수별 평균값
aggregate(USArrests, by=list(cluster=fit.km$cluster), mean)
cluster <int> | Murder <dbl> | Assault <dbl> | UrbanPop <dbl> | Rape <dbl> |
---|---|---|---|---|
1 | 4.841379 | 109.7586 | 64.03448 | 16.24828 |
2 | 11.857143 | 255.0000 | 67.61905 | 28.11429 |
밀도 기반의 클러스터링은 점이 세밀하게 몰려 있어서 밀도가 높은 부분을 클러스터링 하는 방식. epsilon 반경 내에 최소 n개의 개수의 점이 있으면 군집으로 인식
dbscan() : 밀도기반 군집을 생성하는 코드, eps와 MinPts를 옵션으로 주어야 하며, eps는 epsilon, MinPts는 반경 내의 최소 점의 개수를 의미한다.
library(fpc)
#밀도기반 군집
test.dbscan1 <-dbscan(USArrests, eps=20, MinPts=7)
n <-max(test.dbscan1$cluster)
dscenter<-as.data.frame(matrix(0, nrow=1, ncol=2))
for (i in 1:n){
dscenter[i,] <-colMeans(USArrests[test.dbscan1$cluster == i,])
}
plot(USArrests, col=test.dbscan1$cluster+1)
#아래 그림과 같은 분포의 자료 생성 (test.sample1)
set.seed(7979)
get.sample<-function (n=1000, p=0.7) {
x1 <-rnorm(n)
y1 <-rnorm(n)
r2 <-7+rnorm(n)
t2 <-runif(n,0,2*pi)
x2 <-r2*cos(t2)
y2 <-r2*sin(t2)
r <-runif(n)>p
x <-ifelse(r,x1,x2)
y <-ifelse(r,y1,y2)
d <-data.frame(x=x, y=y)
d
}
test.sample1 <-get.sample()
plot(test.sample1)
library(KernSmooth)
r <-bkde2D(test.sample1, bandwidth=c(0.5,0.5))
persp(r$fhat, scale=T, expand=0.3, col="white", theta = 30, phi = 30)
library(fpc)
#밀도기반 군집
test.dbscan1 <-dbscan(test.sample1, eps=0.8, MinPts=5)
n <-max(test.dbscan1$cluster)
dscenter<-as.data.frame(matrix(0, nrow=1, ncol=2))
for (i in 1:n){
dscenter[i,] <-colMeans(test.sample1[test.dbscan1$cluster == i,])
}
plot(test.sample1, col=test.dbscan1$cluster+1,main='DBSCAN')
#k means 군집
test.kmeans1 <-kmeans(test.sample1, centers=2)
plot(test.sample1, col=test.kmeans1$cluster+1,main='k-means')
장점
단점
iris2=iris[,1:4]
dist=dist(iris2)
#계층적 군집
hcl=hclust(dist,method='average')
#군집 수 3개로 설정
cut=cutree(hcl,k=3)
#군집 시각화
plot(hcl,hang=-1,cex=.8)
rect.hclust(hcl,k=3)
#실제 자료의 분류
plot(iris[,-5],col=iris$Species)
#계층적 군집 분류 시각화
plot(iris[,-5],col=cut,pch=cut)
#분류 비율
class=as.factor(cut)
levels(class)= levels(iris$Species)
table(class)
class
setosa versicolor virginica
50 64 36
#정오분류표
table(class,iris$Species)
class setosa versicolor virginica
setosa 50 0 0
versicolor 0 50 14
virginica 0 0 36
library(NbClust)
set.seed(1234)
#kmeans 군집
fit.km <-kmeans(iris[,-5], 3, nstart=25)
fit.km$size
[1] 50 38 62
#실제 자료의 분류
plot(iris[,-5],col=iris$Species)
#kmean 군집의 분류
plot(iris[,-5], col=fit.km$cluster)
#kmean 군집의 분류별 평균
aggregate(iris[,-5], by=list(cluster=fit.km$cluster), mean)
cluster <int> | Sepal.Length <dbl> | Sepal.Width <dbl> | Petal.Length <dbl> | Petal.Width <dbl> |
---|---|---|---|---|
1 | 5.006000 | 3.428000 | 1.462000 | 0.246000 |
2 | 6.850000 | 3.073684 | 5.742105 | 2.071053 |
3 | 5.901613 | 2.748387 | 4.393548 | 1.433871 |
#분류비율
class=as.factor(fit.km$cluster)
levels(class)= levels(iris$Species)
table(class)
class
setosa versicolor virginica
50 38 62
#정오분류표
table(class,iris$Species)
class setosa versicolor virginica
setosa 50 0 0
versicolor 0 2 36
virginica 0 48 14
library(fpc)
#밀도기반 군집
test.dbscan1 <-dbscan(iris[,-5], eps=0.8, MinPts=5)
n <-max(test.dbscan1$cluster)
dscenter<-as.data.frame(matrix(0, nrow=1, ncol=2))
for (i in 1:n){
dscenter[i,] <-colMeans(iris[,-5][test.dbscan1$cluster == i,])
}
#실제 자료의 분류
plot(iris[,-5],col=iris$Species)
#밀도기반군짐의 분류
plot(iris[,-5], col=test.dbscan1$cluster+1)
#분류비율
class=as.factor(test.dbscan1$cluster+1)
levels(class)= levels(iris$Species)
table(class)
class
setosa versicolor virginica
2 50 98
#정오분류표
table(class,iris$Species)
class setosa versicolor virginica
setosa 0 0 2
versicolor 50 0 0
virginica 0 50 48
library(fpc)
#밀도기반 군집(적은 변수로)
test.dbscan1 <-dbscan(iris[,-c(1,4:5)], eps=0.8, MinPts=7)
test.dbscan1
dbscan Pts=150 MinPts=7 eps=0.8
1 2
border 0 4
seed 50 96
total 50 100
n <-max(test.dbscan1$cluster)
n
[1] 2
dscenter<-as.data.frame(matrix(0, nrow=1, ncol=2))
for (i in 1:n){
dscenter[i,] <-colMeans(iris[,-5][test.dbscan1$cluster == i,])
}
#실제자료의 분류
plot(iris[,-5],col=iris$Species)
#밀도기반군집의 분류
plot(iris[,-5], col=test.dbscan1$cluster+1)
#분류비율
class=as.factor(test.dbscan1$cluster+1)
levels(class)= levels(iris$Species)
table(class)
class
setosa versicolor virginica
50 100 0
#정오분류표
table(class,iris$Species)
class setosa versicolor virginica
setosa 50 0 0
versicolor 0 50 50
virginica 0 0 0