K-Means算法属于聚类算法的一种。聚类算法是根据样本之间的相似性,将样本划分到不同的类别中。K-Means算法主要步骤可以分为三步:
1.初始化常数k,随机选取k个点作为质心
2.计算样本与每个质心之间的相似度,将样本归类到最相似的质心中。再次计算质心,直到质心不再改变
3.输出最终的质心以及每个类
原始数据集:
实际上,k-means的本质是最小化目标函数,此处目标函数为每个点到其簇质心的距离的平方和:
∑
i
=
0
N
(
a
r
g
m
i
n
j
∣
∣
x
i
−
c
j
∣
∣
2
2
)
\sum_{i=0}^N(argmin_j||x_i-c_j||_2^2)
i=0∑N(argminj∣∣xi−cj∣∣22)
其中N为元素个数,x表示元素,
c
j
c_j
cj代表第j簇的质心
实现步骤:
1.处理数据 数据集来源:[数据集](https://github.com/fuqiuai/datamining_algorithms/blob/master/K-means/testSet)
def down_load(file):
dataList = []
with open(file) as f:
for line in f.readlines():
l = line.strip().split('\t')
dataList.append(list(map(float,l)))
return dataList
作出原始数据图像:
dataList = down_load('test.txt')
figure1 = plt.figure(1)
dataList = np.array(dataList)
plt.scatter(dataList[:,1],dataList[:,0])
plt.show()
2.随机产生K个质心:
def make_cent(k,dataList):
dimension = dataList.shape[1]
cent_array = np.mat(np.zeros((k,dimension)))
for i in range(dimension):
min_ = min(dataList[:,i])
max_ = max(dataList[:,i])
range_ = max_-min_
cent_array[:,i] = np.mat(min_+range_*np.random.rand(k,1))
return cent_array
3.计算各个样本到质心的距离
cent_array = make_cent(k,dataList)
height = dataList.shape[0]
clasterAssesment = np.mat(np.zeros((height,2)))
if_continue = True
while if_continue:#若质心位置不变,则退出循环
if_continue = False
for i in range(height):
dis = []
for j in range(k):
#np.linalg.norm:计算矩阵范数,默认为二范数,即平方和开根号
dis.append(np.linalg.norm(np.array(dataList[i,:])-np.array(cent_array[j,:])))
min_index = dis.index(min(dis))
if clasterAssesment[i,0]!=min_index:
if_continue = True
clasterAssesment[i,0],clasterAssesment[i,1] = min_index,min(dis)
每次计算之后,更新质心位置
for cent in range(k):
#np.nonzero():返回非零元素的目录。返回值为元祖,包含两个维度
now_in_claster = dataList[np.nonzero(clasterAssesment[:,0]==cent)[0]]
cent_array[cent,:] = np.mean(now_in_claster[:,0],axis = 0),np.mean(now_in_claster[:,1],axis = 0)
return clasterAssesment,cent_array
当质心位置不再改变后,停止循环
4.画出分类后数据集的图像
K-Means算法评价
优点:
1.原理简单,实现容易
2.可以实现非线性分类
3.聚类效果较好
缺点:
1.无法确定K个个数
2.是局部最优解,但不是全局最优
3.对离群点敏感