聚类算法介绍
k-means算法介绍
k-means聚类是最初来自于信号处理的一种矢量量化方法,现被广泛应用于数据挖掘。k-means聚类的目的是将n个观测值划分为k个类,使每个类中的观测值距离该类的中心(类均值)比距离其他类中心都近。
k-means聚类的一个最大的问题是计算困难,然而,常用的启发式算法能够很快收敛到局部最优解。这通常与高斯分布的期望最大化算法相似,这两种算法都采用迭代求精的方法。此外,它们都使用聚类中心来对数据进行建模
k-means算法的提出与发展
詹姆斯·麦奎恩(James MacQueen)1967年第一次使用这个术语“k-means”,虽然这个想法可以追溯到1957年的雨果·斯坦豪斯(Hugo Steinhaus)。
标准算法首先由Stuart Lloyd在1957年提出,作为脉冲编码调制技术,尽管直到1982年才发布在贝尔实验室以外。
1965年,E. W. Forgy发表了基本相同的方法,这就是为什么它有时被称为Lloyd-Forgy。
k-means算法的优势适应问题
- k-means算法优点
是解决聚类问题的一种经典算法,简单、快速。
对处理大数据集,该算法是相对可伸缩和高效率的。因为它的复杂度是\(O(nkt)\), 其中, n 是所有对象的数目, k 是簇的数目, t 是迭代的次数。通常\(k\ll n\)且\(t\ll n\) 。
当结果簇是密集的,而簇与簇之间区别明显时, 它的效果较好。
- k-means算法缺点
在簇的平均值被定义的情况下才能使用,这对于处理符号属性的数据不适用。
必须事先给出k(要生成的簇的数目),而且对初值敏感,对于不同的初始值,可能会导致不同结果。
它对于“躁声”和孤立点数据是敏感的,少量的该类数据能够对平均值产生极大的影响。
k-means算法的思想介绍
(1) 选定某种距离作为数据样本件的相似性度量
由于k-means聚类算法不适合处理离散型数据,因此在计算个样本距离时,可以根据实际需要选择欧氏距离、曼哈顿距离或者明可夫斯基距离中的一种来作为算法的相似性度量。
假设给定的数据集\(X=\{x_m|m=1,2,...,total\}\),\(X\)中的样本用d个属性\(A_1,A_2,...,A_d\)来表示,并且d个描述属性都是连续型数据。数据样本\(x_i=(x_{i1},x_{i2},x_{id}),x_j=(x_{j1},x_{j2}...,x_{jd})\),其中,\(x_{i1},x_{i2},x_{id}\)和\(x_{j1},x_{j2}...,x_{jd}\)分别是样本\(x_i\)和\(x_j\)对应的d个描述属性\(A_1,A_2,...,A_d\)的具体取值。样本\(x_i\)和\(x_j\)之间的相似度通常用他们之间的距离d(\(x_i,x_j\))来表示,距离越小,样本\(x_i\)和\(x_j\)越相似,差异度越小。距离越大,样本\(x_i\)和\(x_j\)越不相似,差异越大。
欧氏距离公式如下:
\[d(x_i,x_j)=\sqrt{\sum_{k=1}^d(x_{ik}-x_{jk})^2}\]
曼哈顿距离如下:
\[d(x_i,x_j)=\sum_{k=1}^d|x_{ik}-x_{jk}|\]
明可夫斯基距离如下:
\[d(x_i,x_j)=\sqrt[p]{\sum_{k=1}^d|x_{ik}-x_{jk}|^p}\]
当\(p=1\)时,明氏距离即为曼哈顿距离,当\(p=2\)时,明氏距离即为欧氏距离,当\(p=\infty\)时,明氏距离即为切比雪夫距离。
(2) 选择评价聚类性能的准则函数
k-means聚类算法使用误差平方和准则函数来评价聚类性能。给定数据集X,其中只包含描述属性,不包含类别属性。假设X包含k个聚类子集\(X_1,X2,...,X_k\),各个聚类子集中的样本量分别为\(n_1,n_2,...,n_k\),各个聚类子集均值代表点分别为\(m_1,m_2,...,m_k\),则误差平方和准则函数公式为:
\[E=\sum_{i=1}^k \sum_{p\in X_i}(p-m_i)^2\]
(3) 相似度的计算根据一个簇中对象的平均值来进行
将所有对象随机分配到k个非空的簇中。
计算每个簇的平均值,并用该平均值代表相应的簇。
根据每个对象与各个簇中心的距离,分配给最近的簇。
然后转2,重新计算每个簇的均值。这个过程不断重复知道满足某个准则函数为止。
k-means实现流程:分步骤写
k-means算法2个核心问题,一是度量记录之间的相关性的计算公式,此处采用欧氏距离。一是更新簇内质心的方法,此处用平均值法,即means。
此时的输入数据为簇的数目k和包含n个对象的数据库——通常在软件中用数据框或者矩阵表示。输出k个簇,使平方误差准则最小。
下面为实现k-means聚类的Python代码
# (1)选择初始簇中心。
# (2)对剩余的每个对象,根据其与各个簇中心的距离,将它赋给最近的簇。
# (3)计算新的簇中心。
# (4)重复(2)和(3),直至准则函数不再明显变小为止。
from numpy import *
#定义加载数据的函数。如果数据以文本形式存储在磁盘内,可以用此函数读取
def loadDataSet(fileName)
dataMat = []
fr = open(fileName)
for line in fr.readlines()
curLine = line.strip().split('\t')
fltLine = list(map(float,curLine))
dataMat.append(list(fltLine))
return dataMat
#该函数计算两个向量的距离,即欧氏距离
def distEclud(vecA,vecB)
return sqrt(sum(power(vecA - vecB,2)))
#曼哈顿距离
def Manhattan(vecA,vecB)
return sum(abs(vecA-vecB))
#明考夫斯基距离
def MinKowski(vecA,vecB,p)
return power(sum(power(abs(vecA-vecB),p)),1/p)
#此处为构造质心,而不是从数据集中随机选择k个样本点作为质心,
#也是比较合理的方法
def randCent(dataSet,k)
n = shape(dataSet)[1] #n为dataSet的列数
centroids = mat(zeros((k,n))) #构造k行n列的矩阵,就是k个质心的坐标
for j in range(n) #
minJ = min(dataSet[,j]) #该列数据的最小值
maxJ = max(dataSet[,j]) #该列数据的最大值
rangeJ = float(maxJ-minJ) #全距
#随机生成k个数值,介于minJ和maxJ之间,填充J列
centroids[,j] = minJ + rangeJ * random.rand(k,1)
return centroids
#定义kMeans函数
def kMeans(dataSet,k,distMeas=distEclud,createCent=randCent)
m = shape(dataSet)[0] #m为原始数据的行数
#clusterAssment包含两列,一列记录簇索引值,一列存储误差
clusterAssment = mat(zeros((m,2)))
centroids = createCent(dataSet,k) #构造初始的质心
clusterChanged = True #控制变量
while clusterChanged #当控制变量为真时,执行下述循环
clusterChanged = False
for i in range(m)
minDist = inf #首先令最小值为无穷大
minIndex = -1 #令最小索引为-1
for j in range(k) #下面是一个嵌套循环
#计算点数据点I和簇中心点J的距离
distJI=distMeas(centroids[j,],dataSet[i,])
if distJI < minDist
minDist = distJI
minIndex = j
if clusterAssment[i,0] != minIndex
clusterChanged = True
clusterAssment[i,] = minIndex,minDist**2
print(centroids)
#更新质心的位置
for cent in range(k)
#mat.A意味着将矩阵转换为数组,即matrix-->array
ptsInClust = dataSet[nonzero(clusterAssment[,0].A==cent)[0]]
centroids[cent,] = mean(ptsInClust,axis=0)
return centroids,clusterAssment
k-means与EM算法
EM是机器学习十大算法之一,是一种好理解,但是推导过程比较复杂的方法。
下面将原英文版的EM算法介绍翻译一遍,在翻译的过程中也加深一点自己的理解。
Jensen不等式
假设\(f\)是一个定义域为实数的函数。回忆一下,如果对于所有的\(x \in R,f''(x) \geq 0\),则\(f\)是一个凸函数。 如果\(f\)的输入值是一个向量,则当\(x\)的海塞矩阵(hessian矩阵\(H\))是半正定矩阵时,\(f\)是凸函数。如果对于所有的\(x\),\(f''(x)>0\)恒成立,那么我们说\(f\)是严格凸函数(如果\(x\)是一个向量,则当\(H\)是严格半正定矩阵时,写做\(H>0\),则\(f\)是严格凸函数)。
设\(f\)是一个凸函数,并且\(X\)是一个随机变量,则:
\[E[f(X)] \geq f(EX).\]
当且仅当\(x=\)常数时,\(E[f(X)]=f(EX)\)\(.\)
进一步说,如果\(f\)是一个严格凸函数,则当P{X=E(X)}=1时,满足\(E[f(X)] = f(EX).\)
由于我们在写某一随机变量的期望时,习惯上是不写方括号的,因此在上述式子中,\(f(EX)=f(E[X])\)
为了解释上述理论,可以用图1帮助理解。
如图1所示,实黑线表示凸函数\(f\),