聚类算法-基于划分-K-Means
一、聚类和分类
聚类:数据无标签,不了解每一类的特点。聚类算法根据自己的规则来判断数据之间的相似性,认为相似的数据归为一类,特点需要人工分析。
分类:有标签的数据,已知待分类数据可以分为哪几类,算法研究被标记数据的特点,对待分类数据进行判断,分类目标已知。
二、K-Means
K-Means是最常用的基于划分聚类算法;
优点:简单、运行速度快。
缺点:只能用于连续型的数据、需要指定分类数K和初始质心。
K-Means聚类步骤:
1、给类别数K(期望聚类算法能将数据分为K组);
2、随机选择K个初始点(质心);
3、分别计算待聚类数据到K个质心的距离(相似度),更新质心(让质心更精确的描述该簇的特征);
4、当新的质心与上一质心的距离小于某阈值,我们认为聚类算法已经趋于收敛或稳定,可以停止聚类;
5、若距离还是比较大,需要继续计算3-4,直到质心收敛。
三、 需要的公式
距离计算公式(相似度):
1、欧几里得距离(欧氏距离):任意维度空间两个点的真实距离。
x=(x1,x2,......,xn),y=(y1,y2,......,yn)
2、余弦相似度:余弦相似度通过计算两个数据之间的夹角来判断其相似度。
余弦值为-1:两个数据含义完全相反;
1:含义完全一样;
0:没有任何关系。
其中A,B为两个向量(A1,A2......,An),(B1,B2......,Bn)。
还有其他的一些计算距离的方法,但是都是欧氏距离和余弦相似度的衍生,简单罗列如下:明可夫斯基距离、切比雪夫距离、曼哈顿距离、马哈拉诺比斯距离、调整后的余弦相似度、Jaccard相似系数……
四、注意事项
1、K的确定,一般来说都是去经验值,即多次运行之后取效果最好的K值,也可以通过判断不同K值聚类后,簇内误差平法和(SSE)来判断簇内是否紧凑来选择K。
2、初始质心的确定,随机,经验值。也有很多优化算法。
3、数据需要标准化处理,保证单位一致,标准化计算后忽略单位,数据统一度量,一般用Z-Score或Min-Max算法。
4、更新时的质心时通过计算 簇内已有数据的平均值获得的,也有改进算法。
四、K-Means Python实现
数据集:80*2
numpy+pandas:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
def Kmeans(data,n,k):
showtable(data)
plt.show()
#k:k个类别
cls = np.zeros((n), dtype=np.int) # 定义数组cls,存放每一个数据的类别,初始值为0
Knum=np.random.random(size=k)#随机选择K数据,(0-1)之间
Knum=np.floor(n*Knum)#初始化K个质心在数据中的索引,floor取小于参数的最大整数
Knum=Knum.astype(int)#将下标转换为整数,得到索引
Kcenter=data[Knum]#初始化质心的值
print('初始center=\n', Kcenter)
run=True
time=0
while run:
time=time+1
for i in range(n):
temp=data[i]-Kcenter#求数据data[i]与质心的差值
temp=np.square(temp)#求差值平方
temp=np.sum(temp,axis=1)#按行求和
cls[i]=np.argmin(temp)#将列表展平,输出最小值的索引号
run=False #没有修改质心,则退出
for i in range(k):
club=data[cls==i]#找出属于类i的数据data
newCenter=np.mean(club,axis=0)#按列求均值,获得新的质心。axis=1按列
error=np.abs(newCenter-Kcenter[i])#求新质心与原始质心的距离abs()取绝对值,得到的是向量形式
if np.sum(error,axis=0)>1e-4:#判断新老质心误差是否小于阈值
Kcenter[i]=newCenter
run=True
print("新质心:",newCenter)
print("迭代次数:",time)
#绘图
for i in range(k):
club=data[cls==i]
showtable(club)
showtable(Kcenter)
def showtable(data):
x=data.T[0]
y=data.T[1]
plt.scatter(x,y)
if __name__ == "__main__":
data = pd.read_csv("./Kmeans.txt")
Kmeans(data.values,80,4)#调用kmeans函数
plt.show()
原始数据:
聚类后:
python sklearn实现Kmeans
sklearn-kmeans手册:
https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans
#使用sklearn实现Kmeans
import pandas as pd
from sklearn.cluster import KMeans
data=pd.read_csv("./Kmeans.txt")
#直接调用KMeans()
#常用参数:n_clusters K类,
#max_inter 最大迭代次数
#init 初始化质心选择,默认为K-means++ (让初始质心尽量远)
# {‘k-means++’, ‘random’, ndarray, callable}, default=’k-means++’
kmeans = KMeans(n_clusters=3,max_iter=5).fit(data)
center=kmeans.cluster_centers_
print("聚类结束后质心:",center)
#用训练好的模型对新数据进行预测
pre=kmeans.predict([[0, 0], [12, 3]])
print(pre)
print(kmeans.labels_)