K-means 是最常见的一种聚类分析算法。直觉上来讲,它的步骤非常简单:
K
个聚类中心在R
中,K-means聚类算法的函数原型为kmeans(x, centers)
(第5行),其中参数x
的类型是matrix
或data frame
,代表一个数值型的数据集(如数据集不是数值型,则应选择一种合适的编码方法);而参数centers
则是无符号整型,是K-means中的K
值,也即聚类的个数。
一般来说,我们可以通过比较聚类内部和聚类之间的相似程度,来作为衡量聚类效果的方法,从统计的角度来说也叫做方差分析。下面的wssplot
函数比较了不同K
值下的组内方差,这样我们就用画图的办法来确定最优的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 Group Variance")
}
因为K-means算法对聚类中心的初始值有一定敏感度,通过set.seed()
确定随机数种子(这里设为1234),我们可以得到一致的聚类结果。
下面我们通过一个例子来学习如何在R
中进行K-means聚类分析。
我们这里使用的意大利红酒数据集可以在UCI 机器学习数据库下载。在R
里也可以通过rattle
包来直接调取数据集。
data(wine, package="rattle")
head(wine)
这个数据集里包含了对每个红酒样本13种不同化学成分的测量结果,共计有178个样本。
为了保证可靠的方差分析,我们先用scale
函数对样本特征的取值范围进行归一化。
df <- scale(wine[-1])
下面的图表现了不同K
值下组内方差的结果。x轴代表聚类个数,y轴代表平均组内方差。我们可以看到,当聚类数目越大的时候,每组的组内方差就越小。
wssplot(df)
但显然K
值并不是越大越好。K
值越大,聚类结果的信息量越低。在这个数据集中,我们从上图可以看到,大概在K=3
之前,组内方差下降比较明显,K=3
之后组内方差下降放缓。看起来K=3
是一个比较好的选择。
我们将K=3
时的聚类结果保存在fit.km
变量中。
fit.km <- kmeans(df, 3, nstart=25)
每一类的样本个数:
fit.km$size
每一类的聚类中心:
round(fit.km$centers, 2)
注意我们在聚类之前,对特征进行了归一化,所以上表中是归一化之后的特征取值。下表则是在原范围内的取值:
round(aggregate(wine[-1], by=list(cluster=fit.km$cluster), mean), 2)
聚类分析属于机器学习中的无监督学习,所以一般来说较难评估其效果。幸运的是,在原数据集中附带了样本的分类信息,也正好是3类,我们可以用混淆矩阵来评估聚类结果:
table(wine$Type, fit.km$cluster)
可以看到聚类结果较好,分别只有3个第2类的样本被错误归类到了第1类和第3类之中。