一. 聚类基础
聚类是一种无监督学习,它将相似的对象归到一个簇中。聚类与分类的最大不同在于,分类的目标事先已知,而聚类则不一样。因其产生的结果与分类相同,只是类别没有预先定义,聚类有时也被称为无监督分类。
K-均值是发现给定数据集的k个簇的算法。簇个数k是用户给定的,每一个簇通过其质心,即簇中所有点的中心来描述。它的工作流程为:首先,随机确定k个初始点作为质心,然后将数据集中的每个点分配到一个簇中,再将簇的质心更新为该簇所有点的平均值。该过程的伪代码如下:
1
2
3
4
5
6
7
|
创建k个点作为起始质心(经常是随机选择)
当任意一个点的簇分配结果发生改变时
对数据集中的每个数据点
对每个质心
计算质心与数据点之间的距离
将数据点分配到距其最近的簇
对每个簇,计算簇中所有点的均值并将均值作为质心
|
二. K-均值聚类
1. 一般流程
K-均值聚类的一般流程为:
(1)收集数据:使用任意方法
(2)准备数据:需要数值型数据来计算距离
(3)分析数据:使用任意方法
(4)训练算法:不适用于无监督学习
(5)测试算法:应用聚类算法、观察结果,可以使用量化的误差指标如误差平方和
(6)使用算法:通常情况,簇质心可以代表整个簇的数据来做出决策
(2)准备数据:需要数值型数据来计算距离
(3)分析数据:使用任意方法
(4)训练算法:不适用于无监督学习
(5)测试算法:应用聚类算法、观察结果,可以使用量化的误差指标如误差平方和
(6)使用算法:通常情况,簇质心可以代表整个簇的数据来做出决策
2. 算法的代码实现
(1) 辅助函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
from
numpy
import
*
def
loadDataSet(filename):
dataMat
=
[]
fr
=
open
(fileName)
for
line
in
fr.readlines():
curLine
=
line.strip().split(
'\t'
)
fltLine
=
map
(
float
,curLine)
dataMat.append(fltLine)
return
dataMat
def
distEclud(vecA, vecB):
return
sqrt(
sum
(power(vecA
-
vecB,
2
)))
def
randCent(dataSet, k):
n
=
shape(dataSet)[
1
]
centroids
=
mat(zeros((k,n)))
for
j
in
range
(n):
minJ
=
min
(dataSet[:,j])
rangeJ
=
float
(
max
(dataSet[:,j])
-
minJ)
centroids[:,j]
=
minJ
+
rangeJ
*
random.rand(k,
1
)
return
centroids
|
(2) 聚类算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
def
kMeans(dataSet, k, distMeas
=
distEclud, createCent
=
randCent):
m
=
shape(dataSet)[
0
]
clusterAssment
=
mat(zeros((m,
2
)))
centroids
=
createCent(dataSet, k)
clusterChanged
=
True
while
clusterChanged:
clusterChanged
=
False
for
i
in
range
(m):
minDist
=
inf; minIndex
=
-
1
for
j
in
range
(k):
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):
ptsInClust
=
dataSet[nonzero(clusterAssment[:,
0
].A
=
=
cent)[
0
]]
centroids[cent,:]
=
mean(ptsInClust, axis
=
0
)
return
centroids, clusterAssment
|
3. 算法测试过程
1
2
3
4
5
6
7
8
9
|
import
kMeans
from
numpy
import
*
datMat
=
mat(kMeans.loadDataSet(
'testSet.txt'
)) #数据格式:1.658985 4.285136
kMeans.randCent(datMat,
2
)
kMeans.distEclud(datMat[
0
],datMat[
1
])
myCentroids,clustAssing
=
kMeans.kMeans(datMat,
4
)
|
参考文献:
1. 机器学习(第九版)