聚类
一种无监督学习,把无分类的数据分为K类
Kmeans(K均值)
1.指定K值,也就是最终要分成K类就指定K为几;
2.初始化K个中心点:随机找K个样本x1,x2,……xk,作为未来K类的K个中心点c1,c1……ck;
3.计算剩余样本所属类别:每个样本距离step2中选的K个中心点c1,c1……ck的距离d,谁的距离最近就归为哪一类;
4.重新选取中心点:step2中选取的中心点是随机初始化选的,不具有准确性,所以需要优化选择新的中心点。由于step3中已经初步分好了K类,对这些类别重新计算新的中心点。
5.重复step4、step5,直至中心点的位置不再变动。
Kmeans代码
1.导入必要的库
from sklearn import datasets
import matplotlib.pyplot as plt
import numpy as np
import math
import random
from IPython import display
2.人工创造数据点
def createData():
X, y = datasets.make_blobs(n_samples=1000, n_features=2,\
centers=[[2,0],[1,1],[2,2],[5,5],[4,1]], cluster_std=[0.3,0.3,0.5,0.1,0.5])
return X, y
X,y = createData()
plt.scatter(X[:,0],X[:,1],c=y,s=10)
plt.show()
3.定义初始化中心点的函数
def init_centers(data, k):
m,n = np.shape(data)
centers_ids = np.random.choice(m, k)
centers = data[centers_ids]
return centers
4.定义求点到点距离的函数
def cal_dist(ptA, ptB):
return np.linalg.norm(ptA - ptB)
5.kmeans实现
def KMeans(data, k):
m,n = np.shape(data)
# 最后的返回结果,一共两维,第一维是所属类别,第二维是到簇中心的距离
pred_y = np.zeros((m, ))
centers = init_centers(data, k) #step1:随机初始化中心点
keep_changing = True #迭代停止flag,标记中心点的变化情况,不变化了就停止迭代
iteration = 0 #记录迭代次数
while keep_changing: #只要中心点还变化就进行
# 遍历所有样本
keep_changing = False
for i in range(m):
min_dist = np.inf #初始化距离为无穷,先选取一个大的值,后继用求的dist更新
# 遍历到各个簇中心的距离
for center in range(k):
dis = cal_dist(centers[center,:], data[i, :])
if dis < min_dist:
min_dist = dis #更新距离
idx = center
# 如果所属类别发生变化
if pred_y[i] != idx:
keep_changing = True
pred_y[i] = idx
# 更新簇中心的坐标
for center in range(k):
cluster_data = data[pred_y == center]
centers[center,:] = np.mean(cluster_data, axis=0)
plt.scatter(data[:,0],data[:,1],c=pred_y,s=10)
plt.title(f'iteration {iteration}')
iteration +=1
plt.pause(1)
display.clear_output(wait=True)
return centers, pred_y
6.测试函数
centers,pred_y = KMeans(X,5)
Kmeans缺点
- K值要指定,通常这个值我们是事先不知道的,很难指定一个准确的K值
- 收敛的结果和初始值有关,不同的初始值瘦脸的效果是不一样的,这显然不是我们想看到的一个数据模型的学习效果。
Kmeans++
对Kmeans算法进行了改进,改进的是选中心点步骤:
1.从数据集中随机选择一个样本作为初始聚类中心
2.计算每个样本到最近聚类中心的距离
3.每一个样本都有一个长度,长度越大的样本,被选为下一个聚类中心的概率越高。
4.重复step2、3,直到得到预设的K个初始质心
假设有8个样本,分布如下图所示:
假设第一步选第一初始聚类中心的时候选中了6号点;
第二步要计算其他样本到6号样本的距离及其被选为聚类中心的概率:
其中P(x)就是每个样本被选为下一个聚类中心的概率,最后一行的Sum是概率P(x)的累加和。
轮盘法选择出第二个聚类中心:随机产生出一个0~1之间的随机数,判断它属于哪个区间,该区间对应的序号就是被选择出来的第二个聚类中心。(https://www.cnblogs.com/wang2825/articles/8696830.html)
KNN (K近邻)
把KNN写在Kmeans下面是为了防止两者混淆,两者毛关系都没有!Kmeans是无监督的聚类算法,KNN是有监督的分类算法。KNN是一种懒惰算法,“抄旁边人的答案”。基本思想是:取离新的预测点最近的K个点,对这K个点的结果进行统计,类别最多的那个类别就认为是这个新点的类别。所以KNN算法没有学习过程,就是一个单纯的vote。
通常距离公式采用欧式距离: