天天看点

数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

一、聚类

1、聚类:属于无监督学习,物以类聚人以群分。

2、监督学习:有Y

3、无监督学习:无y,聚类属于无监督学习,即训练集数据是不含有标签的,聚类的目的是根据样本数据内部的特征,将数据分为若干个类别,每个类别就是一个簇,结果使得簇内的数据相似度大,不同簇内的数据相似度小。其样本的相似性是根据距离来度量的。

4、聚类算法步骤:

数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

5、优化目标:

数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

要使得每一个簇,以及簇内的所有点距离质心的距离最小,用SSE来衡量。

6、怎样判断某个模型的SSE大于另外一个模型:不仅需要保证样本数量相同,同时还需要簇的数量也相同,在满足这两个条件下,在使用SSE来判断模型效果才有意义。

7、算法的优缺点:

数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

8、聚类的使用场景:

  • 商业群体,产品定位,商品推荐;
  • 对相似的文档内容进行划分;
  • 社交网络自动识别推荐人际圈,相互引荐;
  • 数据处理对数据异常值进行检测;

二、程序实现

1、首先来绘制一下学生的散点图:

import numpy as np 
import matplotlib.pyplot  as plt 
plt.rcParams["font.family"]="SimHei"
plt.rcParams["axes.unicode_minus"]=False
plt.rcParams["font.size"]=12 

np.random.seed(1)
x=np.random.randint(70,100,size=(50,2))
plt.scatter(x[:,0],x[:,1])
plt.xlabel("语文")
plt.ylabel("数学")
           

输出:Text(0, 0.5, ‘数学’)

数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

2、训练:使用sklearn中的kmeans进行均值聚类,当完成训练后可以通过KMEANS来获得相关属性值。

from sklearn.cluster import KMeans
kmeans=KMeans(n_clusters=4)#n是簇的数量
kmeans.fit(x)
#获取聚类后的质心
print("质心:",kmeans.cluster_centers_)
#获取每个样本所属的簇,标签的数值对应所属簇的索引
print("标签:",kmeans.labels_)
#获取SSE,也叫簇惯性
print("SSE:",kmeans.inertia_)
#获取迭代次数
print("迭代次数:",kmeans.n_iter_)
#聚类的分值,分值越大,效果越好,直接取SSE的相反数
print("分值:",kmeans.score(x))

输出:
质心: 
 [[91.        77.58333333]
 [93.16666667 89.83333333]
 [75.4        78.33333333]
 [77.45454545 94.27272727]]
标签: [2 2 2 2 2 2 2 0 1 0 1 3 3 1 0 1 3 0 0 2 3 1 2 1 3 3 0 0 2 3 1 2 1 2 1 0 0 1 2 1 3 3 0 0 2 1 3 3 0 2]
SSE: 1582.0924242424242
迭代次数: 7
分值: -1582.092424242399
           

3、预测:对训练集之外的样本进行预测,KMeans的算法的预测很简单,就是看预测样本与哪个质心的距离最近,就将其测为那个类别。

#预测
unknown=np.array([[76,99],[94,80]])
y_hat=kmeans.predict(unknown)
print(y_hat)

输出:
[3 0]
           

可以看到前一个样本属于第三个簇,而第二个样本属于第二个簇。

4、绘制图形,实现可视化

def plot_cluster(model,train,test=None):
    color=np.array(["r","g","b","orange"])
    cc=model.cluster_centers_
    label=model.labels_
    plt.scatter(cc[:,0],cc[:,1],marker="+",s=150,c=color)
    plt.scatter(train[:,0],train[:,1],c=color[label])
    if test is not None:
        y_hat=model.predict(test)        plt.scatter(test[:,0],test[:,1],marker="*",s=150,c=color[y_hat])
        plt.xlabel("语文")
        plt.ylabel("数学")
        plt.title(f"SSE:{model.inertia_:.2f}迭代次数:{model.n_iter_}")
plot_cluster(kmeans,x,unknown)
           

输出:

数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

5、初始质心的影响:

#初始质心的影响
seed=[10,17]
plt.figure(figsize=(15,5))
for i in range(1,3):
    plt.subplot(1,2,i)
    kmeans=KMeans(n_clusters=4,init="random",n_init=1,random_state=seed[i-1])
    kmeans.fit(x)
    plot_cluster(kmeans,x)   
           
数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

改进:随机初始化多组质心,执行多次,然后选择SSE最小的初始化质心。把之前的n_init=1改成n_init=10

plt.figure(figsize=(15,5))
for i in range(1,3):
    plt.subplot(1,2,i)    
    kmeans=KMeans(n_clusters=4,init="random",n_init=10,random_state=seed[i-1])
    kmeans.fit(x)
    plot_cluster(kmeans,x)
           
数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

三、各种算法对比

1.KMeans++

数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

基于概率性的选择。倾向于选择距离当前质心较远的样本作为下一个质心。

kmeans=KMeans(n_clusters=4,init="k-means++")
kmeans.fit(x)
plot_cluster(kmeans,x)
           
数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

2.Mini Batch K-Means

1、概述和算法步骤

数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

2、程序实现:

import time
import pandas as pd
from sklearn.cluster import MiniBatchKMeans, KMeans
from sklearn.metrics.pairwise import pairwise_distances_argmin 
from sklearn.datasets import make_blobs

centers = [[1, 1], [-1, -1], [1, -1]] # 生成用于聚类的数据。
# n_samples:样本数量。
# n_features:特征数量。
# centers:聚类中心。
# cluster_std:簇的标准差。可以统一指定,也可以为每个簇指定不同的标准差。
# random_state:随机种子,用来生成样本数据。
X, y = make_blobs(n_samples=3000, n_features=2, centers=centers,cluster_std=0.7, random_state=0)
colors = np.array(["red", 'green', 'blue']) 
plt.scatter(X[:, 0], X[:, 1], c=colors[y], marker=".")
           
数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

对比一下KMeans与Mini Batch k-means++的效果:

# 定义函数,用于计算模型训练时间。 
def elapsed_time(model, data):
    start = time.time() 
    model.fit(data) 
    end = time.time() 
    return end - start
n_clusters = len(centers)
kmeans = KMeans(init='k-means++', n_clusters=n_clusters, n_init=10) 
mbk = MiniBatchKMeans(init='k-means++', n_clusters=n_clusters,batch_size=100, n_init=10)
kmeans_time = elapsed_time(kmeans, X)
mbk_time = elapsed_time(mbk, X) 
print("K-Means消耗时间:", kmeans_time)
print("Mini Batch K-Means消耗时间:", mbk_time) 
print("K-Means SSE:", kmeans.inertia_ )
print("Mini Batch K-Means SSE:", mbk.inertia_ ) 
print("K-Means的质心:", kmeans.cluster_centers_) 
print("Mini Batch K-Means的质心:", mbk.cluster_centers_)
输出:
K-Means消耗时间: 0.2605900764465332
Mini Batch K-Means消耗时间: 0.16374659538269043
K-Means SSE: 2470.583458090532
Mini Batch K-Means SSE: 2474.8568874307243
K-Means的质心: [[ 1.07705469 -1.06730994]
 [-1.07094261 -1.00512907]
 [ 0.96835544  1.01900336]]
Mini Batch K-Means的质心: [[ 0.95075134  1.07067177]
 [-1.03843646 -0.9962812 ]
 [ 1.11699156 -1.08205516]]
           

3.如何确定合适的k值

使用肘部法则:

sse=[]
scope=range(1,10)
for k in scope:
    kmeans=KMeans(n_clusters=k)
    kmeans.fit(x)
    sse.append(kmeans.inertia_)
plt.xticks(scope)
plt.plot(scope,sse,marker="o")
    
           
数理统计——Kmeans一、聚类二、程序实现三、各种算法对比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

因此使用肘部法则,选择k=3。