你可能用了一个"假的"Kmeans

年三十晚,想起之前写Kmeans聚类的一些感悟。

今天在高铁上,看了一本书,书上又再次出现了这么一句话,我觉得挺好,大体意思是:

在写代码这个事情上,没有人能告诉你怎么做一定对,但是总有人能告诉你,怎么做一定不对

其实在数据分析上,也是如此。分享成功是没有意义的,或者并没有太多价值,反而,分享失败或总结错误,往往能给自己甚至是别人带来更多警示。

在我的认知里面,聚类的方法有很多,但我基本只会用层次聚类里面的hclust(这里以R语言内置函数为例,因为TBtools的聚类算法都是重新用Java实现并以R语言的算法为参照)和动态聚类里面的Kmeans。

其中,今天主要要聊的是R语言Kmeans函数的 坑!!!

Kmeans聚类的大概逻辑是:

1. 设置K个初始聚类中心(存在非常多的选择方法,随机选择几个样本点是比较常用的做法)

2. 按照样本点与聚类中心的距离,将所有样本点各自分配到一个中心(距离最近),这样就得到K个聚类中心

3. 针对K个聚类中心,分别重新计算聚类中心的中心点(存在较多的中心点计算方法,一般直接计算平均值)

4. 分别计算每个聚类中心的平方差,并加和

5. 比较4.计算得到的平方差总和与上一次迭代结果的平方差总和,如果大于上一次平方差总和,那么就结束并输出上一迭代的结果,如果小于上一次平方差综合,那么就继续重复2-5,直到收敛。

这个算法的实现简单粗暴,但是算法本身也存在一些问题

1. 初始聚类中心的个数,和初始聚类中心的选择,直接影响最终结果

2. 按照迭代终止条件,很容易得到一个局部最优值

前者已有报道的改善方法,包括先做hclust,然后kmeans,取距离最大的点

后者也有较多的改善方法提出,包括后续用退火算法,遗传算法等...嗯。。。我差点也在TBtools里面加上退火算法了....

虽然有以上问题,也有挺多的应对方法被提出,然而,被广泛使用的,依然是default mode的Kmeans(虽然默认的Kmeans本身也有很多类别,类别之间没有太多差距,无需担心)

以下必然是中文资料,甚至包括英文资料里面,我个人对R语言内置函数Kmeans的参数理解,

kmeans(x, centers, iter.max = 10, nstart = 1,

            algorithm = c("Hartigan-Wong", "Lloyd", "Forgy",

                          "MacQueen"), trace=FALSE)

x: numeric matrix of data, or an object that can be coerced to

such a matrix (such as a numeric vector or a data frame with

all numeric columns). # 输入的向量

centers: either the number of clusters, say k, or a set of initial

(distinct) cluster centres.  If a number, a random set of

(distinct) rows in 'x’ is chosen as the initial centres.    # 输入初始聚类中心向量 或者 初始聚类中心个数

iter.max: the maximum number of iterations allowed.    # 设置迭代次数

nstart: if 'centers’ is a number, how many random sets should be

chosen?    # 如果前述输入的是 初始聚类中心个数,那么设置重复进行Kmeans的次数,最终会从所有Kmeans执行结果中选择一个最优的

algorithm: character: may be abbreviated.  Note that '"Lloyd"’ and

'"Forgy"’ are alternative names for one algorithm.    # 以下略,因为确实没太大影响

object: an R object of class '"kmeans"’, typically the result

'ob’ of 'ob <- kmeans(..)’.

method: character: may be abbreviated. '"centers"’ causes

'fitted’ to return cluster centers (one for each input

point) and '"classes"’ causes 'fitted’ to return a vector

of class assignments.

trace: logical or integer number, currently only used in the default

method ('"Hartigan-Wong"’): if positive (or true), tracing

information on the progress of the algorithm is produced.

Higher values may produce more tracing information.

R语言内置Kmeans函数里面,设置了两个默认参数,往往并不合适

1. iter.max = 10 设置这个参数,意味着迭代10次之后,即使未收敛, 也直接终止并输出结果,这就意味着,连局部最优都尚未达到...这个当然可能节省时间,但是在我们做数据分析过程中,Kmeans实在太快,没必要卡10次,或者最好不要只卡10次,建议更高....如果不是脚本执行,那么可以直接默认10次出结果,因为如果未收敛,R会出警告信息;然而脚本执行,那么就要注意啦。。。比如夸张点,你调整到100

    2. nstart = 1 这个参数,怎么说呢,存在风险。往往我们并没有预制的聚类心中列表,那么就会随机选择K个样本点并开始迭代,nstart的次数,意味着重新选择并迭代的次数。也就相当于对统一数据运行多少次Kmeans聚类分析,这样会得到多个结果,Kmeans这个函数会选择一个最优的输出(也就是聚类内平方差总和最低的结果)。如果这个设置为1,那么得到局部最优的几率就比较大,相反这个值设置越高,那么就是对不同起始聚类中心集合进行不同次数的Kmeans,那么就更有可能得到全局最优(这个才是我们想要的)。...R语言是不会提示是不是全局最优的。一般,不是很着急的话,这个值应该调整在20~25(运行时间也会大概在20~25倍,一般一样是秒速,除非数据集合真的也不小)

    总体上,我只是想说,其实,你可能用了一个“假的”Kmeans。。。。

(0)

相关推荐