机器学习(三):聚类

780 阅读5分钟

一、方法介绍

1、聚类(Cluster)

聚类是将大规模、纷繁复杂的数据归为不同类别,进而针对每一类别数据发掘分析和理解的视角来深入把握数据价值并指导生产生活。如电子商务中不同客户群的分类、细分市场研究消费者行为寻找潜在市场、多元分析的预处理。聚类是无监督学习方法,属于探索性分析,不同研究者或不同方法得到的结论不同。

2、常见的聚类方法类别

基于划分的聚类算法方法
基于划分K-means、K-medoids、CLARA
基于层次BIRCH、CUBE
基于密度DBSCAN、OPTICS
基于网格STING、WaveCluster
基于神经网络自组织神经网络SOM
基于统计学COBWeb、AutoClass

3、K-Means算法

基本思想是将每个样本分配给最近中心(均值)的类中。先从无标签的集合中随机抽取k个元素作为各子集的中心,分别计算剩下元素到k个中心的距离并将其归类为最近的子集中,重新计算并更新各子集的中心并重新上述聚类过程,直至聚类结果不再发生变化。 (1)K-Means算法优化:k值的选择问题——k个初始质心的选择容易陷入局部最小值,且不同用户指定的k值不同得到的结果也会不一样。可以采用的方法有:1、多次随机初始化后选择代价函数值最小的结果;2、使用肘部法;3、Mini Batch K-means算法(大数据集)。

(2)算法优化——肘部法 (3)算法优化——轮廓系数法 a(i):样本i到同簇内其他样本的平均距离,簇内相似度 b(i):样本i到其他簇内所有样本的平均距离(bi1,bi2,...)中的最小值,簇间不相似度 s(i)——>1说明样本i聚类合理,s(i)——>-1说明样本i聚类不合理,接近0说明样本在边界上。

(4)算法优化——Mini Batch K-means算法

是K-Means的变种,每次训练算法时随机抽取数据子集进行训练,比如10万数据分成100批次*/1000个,小批量确定并更新质心,直到质心不再变化就停止。参数有:1、n_clusters(质心个数);2、batch_size(每次的样本批量);3、max_no_improvement(连续?批质心未发生改变则停止)。

(5)K-Means的优缺点

优缺点归纳
优点1、计算时间短、速度快;2、容易解释;3、对球状聚类效果不错(凸数据集)
缺点1、对离群点和孤立点敏感(归一化、离群点处理);2、k值要子集选择;3、对初始聚类中心敏感(多次选择);4、只能发现球状簇(不适用非凸数据)

4、DBSCAN算法

将簇定义为密度相连的点组成的最大集合,由密度可达关系导出最大密度相连的样本集合即为簇,通过指定合适的E和Min-points,计算所有样本点并创建新簇,反复寻找核心点密度可达的点加入相应簇,直至没有新点可以添加就结束。参数有:E(邻域,即对象的半径);Min-points(给定对象E邻域内最少的样本点数)。

  • DBSCAN的优缺点
优缺点归纳
优点不用输入聚类个数,适用于任意形状的稠密数据集(非凸数据);2、可以发现异常点,对异常点不敏感;3、不存在K-Means初始值选择对结果影响很大的问题。
缺点1、样本不均匀时聚类效果较差;2、样本集较大时聚类收敛时间较长;3、调参较K-Means更复杂(对E和Min-points联合调参)。

二、Python代码实现:

(一)K-Means法及k值优化

# 导包
from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt
# 读取txt文件数据
data = np.genfromtxt('kmeans.txt',delimiter=' ')
# 设置k值=4
model = KMeans(n_clusters=4)
# 聚类结束
model.fit(data)   

# 四个质心
model.cluster_centers_ 

# 样本所对应的标签
model.labels_ 

# 预测
model.predict(data) 
# 迭代次数
model.n_iter_ 
# SSE,累加平方误差
model.inertia_ 
predictions=model.predict(data) 
centers=model.cluster_centers_ 
# 画样本点
mark = ['or','ob','og','oy']
for i,d in enumerate(data):
    plt.plot(d[0],d[1],mark[predictions[i]])  
# 画分类中心点
mark = ['*r','*b','*g','*y']
for i,center in enumerate(centers):
    plt.plot(center[0],center[1],mark[i],markersize=20)
plt.show()

  • 肘部法
SSE=[]
for k in range(2,10):
    model = KMeans(n_clusters=k)
    model.fit(data)
    SSE.append(model.inertia_)
plt.plot(range(2,10),SSE)
plt.xlabel('k')
plt.ylabel('SSE')
plt.show()

  • 轮廓系数法
from sklearn import metrics
silhouette_all=[]
for k in range(2,10):
    model = KMeans(n_clusters=k)
    model.fit(data)
    labels = model.labels_
    silhouette_score = metrics.silhouette_score(data, labels, metric='euclidean')
    silhouette_all.append(silhouette_score)
plt.plot(range(2,10),silhouette_all)
plt.xlabel('k')
plt.ylabel('silhouette_score')
plt.show()

  • Mini Batch K-means算法
from sklearn.cluster import MiniBatchKMeans
model = MiniBatchKMeans(n_clusters=4,batch_size=100)
model.fit(data)

# 质心
centers = model.cluster_centers_
# 预测
predictions = model.predict(data)
# 画样本点
mark = ['or','ob','og','oy']
for i,d in enumerate(data):
    plt.plot(d[0],d[1],mark[predictions[i]])   
# 画分类中心点
mark = ['*r','*b','*g','*y']
for i,center in enumerate(centers):
    plt.plot(center[0],center[1],mark[i],markersize=20)
plt.show()

  • (二)DBSCAN算法
from sklearn.cluster import DBSCAN
# 载入数据并画散点图
data = np.genfromtxt("kmeans.txt", delimiter=" ")
plt.scatter(data[:,0],data[:,1]) #散点图
plt.show()

# 训练模型
# eps为距离阈值,min_samples核心对象在eps邻域的样本数阈值
model = DBSCAN(eps=1.7, min_samples=4)
model.fit(data)

# 标签
model.labels_ 
# 预测
result = model.fit_predict(data)
# 画出各个数据点,用不同颜色表示分类
mark = ['ok', 'ob', 'og', 'oy', 'ok', '*r']
for i,d in enumerate(data):
    plt.plot(d[0], d[1], mark[result[i]])
plt.show()

(三)非凸稠密数据集运用两种方法的对比

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
%matplotlib inline
# 生成圆形和气球型数据集
x1, y1 = datasets.make_circles(n_samples=2000, factor=.3, noise=.05)#x1为坐标,y1为标签,这里不需要标签
x2, y2 = datasets.make_blobs(n_samples=1000, centers=[[1.2,1.2]], cluster_std=[[.1]])

x = np.concatenate((x1, x2))
plt.scatter(x[:, 0], x[:, 1], marker='o')
plt.show()

# K-Means算法
from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=3).fit_predict(x) #0,1,2
plt.scatter(x[:, 0], x[:, 1], c=y_pred)
plt.show()

# DBSCAN算法
from sklearn.cluster import DBSCAN
y_pred = DBSCAN(eps = 0.2,min_samples=50).fit_predict(x)
plt.scatter(x[:, 0], x[:, 1], c=y_pred)
plt.show()