K-Means
先来看看相似度/距离的计算方法
闽可夫斯基距离(Minkowski)/欧式距离(p=2) :
杰卡德相似系数(Jaccard):
余弦相似度(cosine similarity )
Pearson相似系数
相对熵(K-L距离)
K-Means算法详解
K-Means算法,即k-均值算法,是一种广泛使用的聚类算法。
基本思想
对一个给定的含有N个对象的数据集,构造数据的k个簇, k≤N k ≤ N 。
首先给定k,给出初始划分,通过迭代改变样本和簇的隶属关系,使得每一次改进之后的划分方案都比前一次好。
伪代码
创建k个点作为起始质心(经常是随机选择)
当任意一个点的簇分配结果发生改变时
对数据集中的每个数据点
对每个质心
计算质心与数据点之间的距离
将数据点分配到距离最近的簇
对每一个簇,计算簇中所有点的均值作为质心
python代码实现
数据与代码来源于:《机器学习实战》
from numpy import *
import random
from matplotlib import pyplot as plt
def loadData(fileName):
data = []
with open(fileName) as fr:
for line in fr.readlines():
lines = line.strip().split('\t')
L = list(map(float, lines)) #注意与书中的不同
data.append(L)
return mat(data)
# 欧式距离计算
def distEclud(vecA,vecB):
return sqrt(sum(square(vecA-vecB)))
# 构建随机质心
def randCent(data,k):
m,n = shape(data)
centroids = mat(zeros((k,n)))
for i in range(k):
for j in range(n):
minJ = min(data[:, j]) # 找出每列中最小的值
rangeJ = float(max(data[:, j]) - minJ) # 找出每一列的范围值
centroids[(i,j)] = mat(minJ + rangeJ * random.random())
return centroids
def k_Means(data,k):
m,n = shape(data) # 每一行为一个simple,共有n个样本
# 初始化一个矩阵来存储每个点的簇分配结果 #
# 一列记录簇索引值,第二列存储误差(误差是指当前点到簇质心的距离,后面会使用该误差来评价聚类的效果)
clusterAssemt = mat(zeros((m,2)))
centroids = randCent(data,k)
clusterChanged = True
while clusterChanged:
clusterChanged = False
for i in range(m):
minDist = inf
minIndex = 0
for j in range(k):
distJI = distEclud(centroids[j,:],data[i,:]) #采用欧式距离
if distJI < minDist:
minDist = distJI
minIndex = j
# 找到每个样本最近距离的质点
if clusterAssemt[i,0] != minIndex:
clusterChanged = True
clusterAssemt[i,:] = minIndex, minDist **2
for cent in range(k):
ptsInClust = data[nonzero(clusterAssemt[:,0].A == cent)[0]]
centroids[cent,:] = mean(ptsInClust,axis=0)
return centroids,clusterAssemt
if __name__ == '__main__':
# data = loadData('testSet.txt')
data = loadData('testSet2.txt')
fig = plt.figure()
p1 = plt.scatter(data[:, 0].flatten().A[0], data[:, 1].flatten().A[0], marker='o')
myCentroids, clustAssing = k_Means(data,3)
print(myCentroids)
print(clustAssing)
p2 = plt.scatter(myCentroids[:,0].flatten().A[0],myCentroids[:,1].flatten().A[0], marker='x', edgecolors='r')
plt.show()
上述代码运行后,得到的图如下:
K-Means算法实现总结:
1、python版本的差异
我使用的是python3.x,书中的代码是python2
2、计算欧式距离时,无法使用pow(x,2)函数,报错为数据维数不符合。而改用直接用是sqart()
具体原因:未知。欢迎拍砖!
3、random.rand(k,1)这个也是无法使用。报错为:
random中无rand模块。我dir了一下,python3中确实没有。不知道是不是2和3的差异。要想在3中使用,只能用numpy模块中的rand模块了。
因此我相应的把代码改了。
4、使用数据预测时,出现了数据类型不符合的情况~
什么list、matrix等混乱~这个得我一条条代码调试,更改相应的数据类型~ 吐血!希望以后加强这个方面的训练,能尽量少报这方面的错误!
5、使用matplotlib画图时,总算明白了flatten()的奥妙之处~散点画图能力加强了~
二分K-Means 算法后面在总结