KMeans、KNN、Mean-shift

无监督学习

机器学习方法的一种,没有给出事先标记过的训练数据,根据输入自动分类或分群。

优点:算法不受监督信息(偏见)的约束,可能考虑到新的信息。

不要标签数据,极大程度扩大数据样本。

主要应用:聚类分析、关联规则、维度缩减

应用最广:聚类分析

聚类分析:根据对象属性中的某些相似度,将其化为不同的类别。

KMeans聚类:

1、根据数据与中心点距离划分类别

2、根据类别数据更新中心点

3、重复过程直到收敛

特点:

1、实现简单、收敛快

2、需要指定类别数量

Mean-shift(均值漂移)

1、在中心点的一定区域内检索数据点

2、更新中心

3、重复流程到中心点稳定(我理解是中心点周边数据点最多)

特点:

1、自动发现类别数量,无需人工选定。

2、需要选择区域半径。

DBSCAN算法

1、基于区域点密度筛选有效数据

2、基于有效数据向空间扩展,知道没有新点加入

=================================================

KMeans analysis K均值聚类

以空间中的k个点为中心聚类,对最靠近他们的“对象”进行归类,是聚类算法中最为基础但也最为重要的算法。

总的来说就是指定几个初始化的中心点,计算所有数据点到这些个中心点的距离,距离最小点划归该中心点,所有数据都划归后,对每一个类别的数据组求均值,更新为中心点,重复以上步骤直至中心点的值不再变化。

优点:

1、原理简单,方便实用,快速收敛

2、参数少

缺点:

1、必须明确簇的数量(分类数量)

2、随机选择初始中心,可能缺乏一致性

容易和KMeans算法搞混的KNN算法

KNN算法是监督学习

给定一个训练数据集,当输入一个新的实例,在该训练集中找到与该实例最临近的K个实例,这K个实例中的多数属于某类,那么该实例就属于此类。

Meanshift 均值漂移算法

均值漂移算法:一种基于密度梯度上升的聚类算法(沿着密度上升方向寻找聚类中心点)

在均值漂移聚类里,“访问频率” 这个概念其实很好理解,我用大白话给你解释一下:

核心逻辑

  • 在算法运行时,同一个数据点可能会被多个不同的初始中心点的漂移过程 “扫到”(也就是被包含在不同中心点的带宽集合 S 里)。
  • “访问频率” 就是统计一个数据点被多少个不同的漂移中心点 “扫到” 并归为该类的次数。

举例说明

  1. 初始中心点 A 在漂移过程中,把点 X 纳入了它的集合 S,那么点 X 就被 A 的类 “访问” 了 1 次。
  2. 之后另一个初始中心点 B 在漂移时,也把点 X 纳入了它的集合 S,那么点 X 又被 B 的类 “访问” 了 1 次。
  3. 最终,点 X 会被分配给访问它次数最多的那个中心点对应的聚类。

============================================================

实战阶段

#Kmeans算法 2D类数据类别划分
#load data
import pandas as pd
import numpy as np
data = pd.read_csv('data.csv')
data.head()
#define X and Y
X = data.drop(['labels'],axis=1)
Y = data.loc[:,'labels']
print(X)
print(Y)
#画出图形
from matplotlib import pyplot as plt
fig1 = plt.figure()
label0 = plt.scatter(X.loc[:,'V1'][Y==0],X.loc[:,'V2'][Y==0])
label1 = plt.scatter(X.loc[:,'V1'][Y==1],X.loc[:,'V2'][Y==1])
label2 = plt.scatter(X.loc[:,'V1'][Y==2],X.loc[:,'V2'][Y==2])
plt.xlabel('V1')
plt.ylabel('V2')
plt.legend((label0,label1,label2),('label0','label1','label2'))
plt.show()

================

from sklearn.cluster import KMeans 
#n_clusters=3 需要明确分为3类
#random_state=0,核心作用是固定算法的随机行为,让聚类结果完全可复现,简单说就是只要代码、数据、参数不变,无论运行多少次,得到的簇划分、质心位置都是一模一样的。
'''KMeans 的聚类流程第一步是随机选择 k 个样本作为初始质心(你这里 k=3),如果不固定random_state,
每次运行算法都会随机挑不同的初始质心,最终可能得到不同的聚类结果(尤其是数据分布较散时)。
而random_state=0就是给这个 “随机选择初始质心” 的操作,
指定一个随机数种子(0 是种子的具体数值,也可以设 1、42、100 等任意整数),让随机过程变成 “伪随机”—— 看似随机,实则按固定规则执行,结果自然完全一致。'''
KM = KMeans(n_clusters=3,random_state=0)   
KM.fit(X)
#看下中心点
centers = KM.cluster_centers_
print(centers)

# 预测 v1=-10 v2=20 属于哪一类
y_predict = KM.predict([[-10,20]])
print(y_predict)

输入为[1],从输出可以看到分类是1,与实际的label并不一致。这很好解释,因为训练出来的分类没有和实际标记分类关联上,做下映射就行。

预测结果和实际分布是不一样的

#计算下不修正情况下的精确度
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(Y,y_predict)
print(accuracy)

精确度只有0.336,是很低的

#画图做下对比
fig3 = plt.subplot(121)

label0 = plt.scatter(X.loc[:,'V1'][Y==0],X.loc[:,'V2'][Y==0])
label1 = plt.scatter(X.loc[:,'V1'][Y==1],X.loc[:,'V2'][Y==1])
label2 = plt.scatter(X.loc[:,'V1'][Y==2],X.loc[:,'V2'][Y==2])
label3 = plt.scatter(centers[:,0],centers[:,1])
plt.xlabel('V1')
plt.ylabel('V2')
plt.legend((label0,label1,label2,label3),('label0','label1','label2','center'))

fig3 = plt.subplot(122)

label0 = plt.scatter(X.loc[:,'V1'][y_predict==0],X.loc[:,'V2'][y_predict==0])
label1 = plt.scatter(X.loc[:,'V1'][y_predict==1],X.loc[:,'V2'][y_predict==1])
label2 = plt.scatter(X.loc[:,'V1'][y_predict==2],X.loc[:,'V2'][y_predict==2])
label3 = plt.scatter(centers[:,0],centers[:,1])
plt.xlabel('V1')
plt.ylabel('V2')
plt.legend((label0,label1,label2,label3),('label0','label1','label2','center'))


plt.show()

可以看出原分布图和通过模型预测的分布图,形状是非常接近的,但是标记的类型是不同的,预测结果中的0号分类是实际训练模型的1号分类,预测结果中的1号分类是实际训练模型的0号分类,2号分类相同,因此需要对模型预测的结果做修正。

# correct predictdata
y_correct= []
for i in y_predict:
    if i==0:
        y_correct.append(1)
    elif i==1:
        y_correct.append(0)
    else:
        y_correct.append(2)

print(accuracy_score(Y,y_correct))

可以看到修正后的准确度已经很高了

更多推荐