机器学习-Kmeans算法
Posted YEN_csdn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习-Kmeans算法相关的知识,希望对你有一定的参考价值。
学习彭亮《深度学习基础介绍:机器学习》课程
归类
聚类(clustering) 属于非监督学习 (unsupervised learning),无类别标记(class label)
K-means 算法
Clustering 中的经典算法,数据挖掘十大经典算法之一
算法接受参数 k ;然后将事先输入的n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。
算法思想
以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果
算法描述
- 适当选择c个类的初始中心;
- 在第k次迭代中,对任意一个样本,求其到c各中心的距离,将该样本归到距离最短的中心所在的类;
- 利用均值等方法更新该类的中心值;
- 对于所有的c个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变,则迭代结束,否则继续迭代。
算法流程
输入:k, data[n];
- 选择k个初始中心点,例如c[0]=data[0],…c[k-1]=data[k-1];
- 对于data[0]….data[n], 分别与c[0]…c[k-1]比较,假定与c[i]差值最少,就标记为i;
- 于所有标记为i点,重新计算c[i]= 所有标记为i的data[j]之和/标记为i的个数;即重新计算均值。
- 重复(2)(3),直到所有c[i]值的变化小于给定阈值。
算法优缺点
- 优点:速度快,简单
- 缺点:最终结果跟初始点选择相关,容易陷入局部最优,需直到k值
实例
假设有四个药品,知道他们的重量指标和PH指标,需要把它们分为两类。
在坐标轴中描出是个药品:
第一次迭代
K=2,随机选取两个点,计算所有点到这两个点的距离,假设选中的点位两个星形的点
D矩阵中第一行表示所有点到左边这个星的距离,第二行表示所有点到右边这个星的距离
G矩阵表示把左边的星化为一类,剩下的三个点化为一类
C1的中心即为左边星的坐标,同时更新第二类的中心点为C2
第二次迭代
星形表示当前分类中心
所以从左到右前两个为第一类,后两个为第二类,更新中心点坐标
第三次迭代
此时分类不再更新=>结束,得到结果为:
代码
#coding=utf-8
# @Author: yangenneng
# @Time: 2018-01-20 15:53
# @Abstract:Kmeans算法
import numpy as np
'''
# X:数据集
# k:分为多少类
# maxIt:最多迭代多少次
'''
def kmeans(X,k,maxIt):
# 返回行、列 即数据集的形状
numPoints,numDim=X.shape
# 给数据集多加一列
dataSet = np.zeros((numPoints,numDim+1))
# 把前numDim列=X
dataSet[:,:-1] = X
# # 随机选取K个中心点
# centroids=dataSet[np.random.randint(numPoints,size=k),:]
# 故意选择中心点为前两个,对应上述例子
centroids=dataSet[0:2,:]
# 初始化中心点的最后一列
centroids[:,-1]=range(1,k+1)
iterations=0
# 储存旧的中心点
oldCentroids=None
# 只要不停止(新、旧中心点不一致)或(循环了maxIt次,当前为iterations次)
while not shouldStop(oldCentroids,centroids,iterations,maxIt):
print "循环到第"+str(iterations)+"次:\\n"
print "数据集dataSet:\\n",dataSet
print "中心点centroids:\\n",centroids
# 不能直接赋值,否则会同步更新,所以用复制
oldCentroids=np.copy(centroids)
iterations += 1
# 更新数据集所属标签
updateLables(dataSet,centroids)
# 更新中心点
centroids=getCentroids(dataSet,k)
return dataSet
# 是否停止
def shouldStop(oldCentroids,centroids,iterations,maxIt):
if iterations>maxIt:
return True
return np.array_equal(oldCentroids,centroids)
def updateLables(dataSet,centroids):
numPoints,numDim=dataSet.shape
for i in range(0,numPoints):
dataSet[i,-1]=getLableFormClosetCentroid(dataSet[i,:-1],centroids)
'''
# dataSetRow 当前行
# centroids 中心点
# 返回当前点和那个中心点最近,即标签
'''
def getLableFormClosetCentroid(dataSetRow,centroids):
label=centroids[0,-1]
# np.linalg.norm算两个向量的距离
minDist=np.linalg.norm(dataSetRow-centroids[0,:-1])
for i in range(1,centroids.shape[0]):
# 不算最后一列 因为最后一列是标签
dist=np.linalg.norm(dataSetRow-centroids[i,:-1])
if dist<minDist:
minDist=dist
label=centroids[i,-1]
print "minDist:",minDist
return label
def getCentroids(dataSet,k):
result=np.zeros((k,dataSet.shape[1]))
for i in range(1,k+1):
# 把所有分类为i的找出来
oneCluster=dataSet[dataSet[:,-1]==i,:-1]
result[i-1,:-1]=np.mean(oneCluster,axis=0)
result[i-1, -1]=i
return result
'''
# ..........................主程序...............................
'''
x1=np.array([1,1])
x2=np.array([2,1])
x3=np.array([4,3])
x4=np.array([5,4])
# 把四个点纵向的堆起来
testX=np.vstack((x1,x2,x3,x4))
result=kmeans(testX,2,10)
print "final result:",result
以上是关于机器学习-Kmeans算法的主要内容,如果未能解决你的问题,请参考以下文章