机器学习——Kmeans聚类算法

2023-10-29

简介

K均值聚类算法是先随机选取K个对象作为初始的聚类中心。然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。

手肘法

最关键的问题是其中k值的确定方式
核心指标:SSE(sum of the squared errors,误差平方和)
在这里插入图片描述

  • Ci是第i个簇
  • p是Ci中的样本点
  • mi是Ci的质心(Ci中所有样本的均值)
  • SSE是所有样本的聚类误差,代表了聚类效果的好坏。

手肘法核心思想

  • 随着聚类数k的增大,样本划分会更加精细,每个簇的聚合程度会逐渐提高,那么误差平方和SSE自然会逐渐变小。

  • 当k小于真实聚类数时,由于k的增大会大幅增加每个簇的聚合程度,故SSE的下降幅度会很大,而当k到达真实聚类数时,再增加k所得到的聚合程度回报会迅速变小,所以SSE的下降幅度会骤减,然后随着k值的继续增大而趋于平缓,也就是说SSE和k的关系图是一个手肘的形状,而这个肘部对应的k值就是数据的真实聚类数

import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
 
df_features = pd.read_csv(r'C:\预处理后数据.csv',encoding='gbk') # 读入数据
'利用SSE选择k'
SSE = []  # 存放每次结果的误差平方和
for k in range(1,9):
    estimator = KMeans(n_clusters=k)  # 构造聚类器
    estimator.fit(df_features[['R','F','M']])
    SSE.append(estimator.inertia_) # estimator.inertia_获取聚类准则的总和
X = range(1,9)
plt.xlabel('k')
plt.ylabel('SSE')
plt.plot(X,SSE,'o-')
plt.show()

轮廓系数

但是问题就出在于如何通过图像确定k值?
直接通过肉眼判断是不可信的,因此选择使用轮廓系数
使用轮廓系数(silhouette coefficient)来确定,选择使系数较大所对应的k值

方法:

  • 计算样本i到同簇其他样本的平均距离ai。ai 越小,说明样本i越应该被聚类到该簇。将ai 称为样本i的簇内不相似度。
    簇C中所有样本的a i 均值称为簇C的簇不相似度。

  • 计算样本i到其他某簇Cj 的所有样本的平均距离bij,称为样本i与簇Cj 的不相似度。定义为样本i的簇间不相似度:bi =min{bi1, bi2, …, bik}
    bi越大,说明样本i越不属于其他簇。

  • 根据样本i的簇内不相似度a i 和簇间不相似度b i ,定义样本i的轮廓系数
    在这里插入图片描述

  • 判断:

  • 轮廓系数范围在[-1,1]之间。该值越大,越合理。
    si接近1,则说明样本i聚类合理;
    si接近-1,则说明样本i更应该分类到另外的簇;
    若si 近似为0,则说明样本i在两个簇的边界上。

  • 所有样本的s i 的均值称为聚类结果的轮廓系数,是该聚类是否合理、有效的度量。

  • 使用轮廓系数(silhouette coefficient)来确定,选择使系数较大所对应的k值

  • sklearn.metrics.silhouette_score sklearn中有对应的求轮廓系数的API

增加轮廓系数改进之后判断代码:

def cluster_para_est(train_x):
    k_num = 50
    sse = []
    for k in range(1, k_num):
        # kmeans算法
        kmeans = KMeans(n_clusters=k)
        kmeans.fit(train_x)
        # 计算inertia簇内误差平方和
        sse.append(kmeans.inertia_)
    x = range(1, k_num)
    plt.xlabel('K')
    plt.ylabel('SSE')
    plt.plot(x, sse, 'o-')
    plt.show()
    for idx in range(len(sse) - 1):
        if sse[idx] - sse[idx + 1] <= 1:
            print(idx + 1)
            return idx + 1

代码举例1

1、便于理解,首先创建一个明显分为2类20*2的例子(每一列为一个变量共2个变量,每一行为一个样本共20个样本):

import numpy as np
c1x=np.random.uniform(0.5,1.5,(1,10))
c1y=np.random.uniform(0.5,1.5,(1,10))
c2x=np.random.uniform(3.5,4.5,(1,10))
c2y=np.random.uniform(3.5,4.5,(1,10))
x=np.hstack((c1x,c2x))
y=np.hstack((c2y,c2y))
X=np.vstack((x,y)).T
print(X)

2、引用Python库将样本分为两类(k=2),并绘制散点图:

#只需将X修改即可进行其他聚类分析
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
 
kemans=KMeans(n_clusters=2)
result=kemans.fit_predict(X) #训练及预测
print(result)   #分类结果
 
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei'] #散点图标签可以显示中文
 
x=[i[0] for i in X]
y=[i[1] for i in X]
plt.scatter(x,y,c=result,marker='o')
plt.xlabel('x')
plt.ylabel('y')
plt.show()

3、如果K值未知,可采用肘部法选择K值(假设最大分类数为9类,分别计算分类结果为1-9类的平均离差,离差的提升变化下降最抖时的值为最优聚类数K)

import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
 
K=range(1,10)
meanDispersions=[]
for k in K:
    kemans=KMeans(n_clusters=k)
    kemans.fit(X)
    #计算平均离差
    m_Disp=sum(np.min(cdist(X,kemans.cluster_centers_,'euclidean'),axis=1))/X.shape[0]
    meanDispersions.append(m_Disp)
 
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei'] #使折线图显示中文
 
plt.plot(K,meanDispersions,'bx-')
plt.xlabel('k')
plt.ylabel('平均离差')
plt.title('用肘部方法选择K值')
plt.show()

代码举例2

文件读取的部分可以写一个独立的函数判断更加方便

import numpy as np
import matplotlib.pyplot as plt

# 加载数据
def loadDataSet(fileName):
    data = np.loadtxt(fileName,delimiter='\t')
    return data

# 欧氏距离计算
def distEclud(x,y):
    return np.sqrt(np.sum((x-y)**2))  # 计算欧氏距离

# 为给定数据集构建一个包含K个随机质心的集合
def randCent(dataSet,k):
    m,n = dataSet.shape
    centroids = np.zeros((k,n))
    for i in range(k):
        index = int(np.random.uniform(0,m)) #
        centroids[i,:] = dataSet[index,:]
    return centroids

# k均值聚类
def KMeans(dataSet,k):

    m = np.shape(dataSet)[0]  #行的数目
    # 第一列存样本属于哪一簇
    # 第二列存样本的到簇的中心点的误差
    clusterAssment = np.mat(np.zeros((m,2)))
    clusterChange = True

    # 第1步 初始化centroids
    centroids = randCent(dataSet,k)
    while clusterChange:
        clusterChange = False

        # 遍历所有的样本(行数)
        for i in range(m):
            minDist = 100000.0
            minIndex = -1

            # 遍历所有的质心
            #第2步 找出最近的质心
            for j in range(k):
                # 计算该样本到质心的欧式距离
                distance = distEclud(centroids[j,:],dataSet[i,:])
                if distance < minDist:
                    minDist = distance
                    minIndex = j
            # 第 3 步:更新每一行样本所属的簇
            if clusterAssment[i,0] != minIndex:
                clusterChange = True
                clusterAssment[i,:] = minIndex,minDist**2
        #第 4 步:更新质心
        for j in range(k):
            pointsInCluster = dataSet[np.nonzero(clusterAssment[:,0].A == j)[0]]  # 获取簇类所有的点
            centroids[j,:] = np.mean(pointsInCluster,axis=0)   # 对矩阵的行求均值

    print("Congratulations,cluster complete!")
    return centroids,clusterAssment

def showCluster(dataSet,k,centroids,clusterAssment):
    m,n = dataSet.shape
    if n != 2:
        print("数据不是二维的")
        return 1

    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
    if k > len(mark):
        print("k值太大了")
        return 1

    # 绘制所有的样本
    for i in range(m):
        markIndex = int(clusterAssment[i,0])
        plt.plot(dataSet[i,0],dataSet[i,1],mark[markIndex])

    mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb']
    # 绘制质心
    for i in range(k):
        plt.plot(centroids[i,0],centroids[i,1],mark[i])

    plt.show()
dataSet = loadDataSet("kk.txt")
k = 5
centroids,clusterAssment = KMeans(dataSet,k)
showCluster(dataSet,k,centroids,clusterAssment)

实例

已完成有空再整理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习——Kmeans聚类算法 的相关文章

随机推荐

  • 性价比排序

    链接 https ac nowcoder com acm contest 329 D 来源 牛客网 处女座靠着自己的家教本领赚够了去比赛的钱 于是开启了疯狂训练 在每个夜深人静第二天不收作业的夜晚 他都会开始刷题 今日又是一个刷题的夜晚 他
  • Vulnhub靶机渗透之环境搭建及JIS-CTF入门

    Vulnhub靶机渗透之环境搭建及JIS CTF入门 目录 Vulnhub靶机渗透之环境搭建及JIS CTF入门 一 JIS CTF题目描述 二 Vulnhub环境配置 三 Vulnhub靶机渗透详解 1 信息收集 2 First flag
  • K8s卸载

    sudo kubeadm reset f systemctl stop kubelet kubeadm kubectl yum y remove kubelet kubeadm kubectl sudo rm rvf HOME kube s
  • 基于GEC6818的智能火锅点餐系统

    本次项目开发环境 gec6818 QT5 14 2 SecureCRT 所使用的相关技术 c s架构 STL库 C 封装 标准化代码编写 实现的功能 用户登录页面 食品分区在不同页面 用户点餐页面 用户买单页面 数据整合并发送至后台 后台成
  • 请勿私信或者留言,请写信给我:i@brightguo.com

    请勿留言或者私信给我 一来csdn通知系统经常不及时通知我收到了你们的信息 二来我越来越少上csdn了 这两个原因导致您发了信息给我 我过几个月看到也是正常的 所以请邮件 实时看到您的邮件 像收到短信一样 有空就回复你 i brightgu
  • 操作系统主要知识点

    1 进程管理 1 进程是具有独立功能程序在某个数据集合上的一次执行过程 线程是进程内的一个执行实体或执行单元 进程和线程的区别 a 不同进程的地址空间是独立的 而同一进程内的线程共享同一地址空间 一个进程的线程在另一个进程内是不可见的 b
  • MySQL 数据库 (实现JDBC工具类)

    JDBC工具类 package com itcast ma import java sql Connection import java sql DriverManager import java sql PreparedStatement
  • 用c++写一个贪吃蛇的游戏

    写一个贪吃蛇游戏需要涵盖以下几个方面的知识 图形绘制 使用控制台的图形绘制函数 例如在 Windows 中使用的是 conio h 中的图形绘制函数 游戏逻辑 包括贪吃蛇的移动 食物的生成 检测蛇是否撞墙或撞到自己等 数据存储 使用数组或链
  • 缓存知多少?详解@Cacheable@CacheEvict@Caching

    缓存注解 一 基础概念 1 Cache介绍 2 Cacheable CachePut CacheEvict 的主要参数 二 Cacheable使用demo 三 CacheEvict使用demo 四 Caching使用demo 一 基础概念
  • 代理IP和Socks5代理:跨界电商与爬虫的智能引擎

    跨界电商 作为全球市场的一部分 对数据的需求越来越大 同时 随着互联网的发展 爬虫技术也在不断演进 成为了跨界电商的关键工具之一 然而 随之而来的是网站的反爬虫机制和网络安全风险 在这种情况下 代理IP和Socks5代理应运而生 为企业提供
  • 安卓代码获取系统属性值

    安卓代码获取系统属性值 前言 代码实现 前言 大家可能知道 使用adb shell getprop命令可以直接获取系统属性值 但有时候需要在JAVA代码中获取系统属性 接下来说一下如何实现 代码实现 在build gradle的androi
  • C++获取CPUID

    include
  • 客户流失预测--基于R语言C5.0

    对于中国各大电信运营商而言 在整体市场规模相对稳定的情况下 能否维护好现有的客户是保证其收益的重中之重 因此 预测客户流失的可能性与否 直接关系到运营商的客户维护的重点正确与否 本文将基于 狗熊会 基础案例 收集客户流失 来演示基于C5 0
  • flutter webview 在iOS上不显示的问题

    使用的插件是 webview flutter 0 3 22 1 在android中可以正常显示 但是在ios端中既没有报错 又没有显示出来 后来查看插件使用说明才发现 忘记在ios端中端配置文件中进行配置了 此时我们需要在ios的runne
  • java 包扫描器

    java 包扫描器 扫描指定包下的所有java文件 并返回class数组 直接上代码 import java io File import java net URISyntaxException import java net URL im
  • 【Linux】gcc编译过程、make和makefile的概念与区别、Linux简单进度条实现

    文章目录 1 gcc编译过程 1 1预处理 1 2编译 1 3汇编 1 4链接 2 自动化构建工具 make和makefile 2 1使用背景 2 2两者的概念和区别 2 3项目清理 3 Linux简单进度条的实现 1 gcc编译过程 1
  • ubuntu安装qt

    ubuntu安装qt 第一步 下载安装包https download qt io archive qt 5 14 5 14 2 第二步 更改权限 sudo chmod x qt opensource linux x64 5 12 12 ru
  • JS中使用正则表达式g模式和非g模式的区别

    g是global的缩写啊 就是匹配全部可匹配结果 如果你不带g 在正则过程中 字符串是从左至右匹配的 如果匹配成功就不再继续向右匹配了 如果你带g 它会重头到尾的把正确匹配的字符串挑选出来 例如 1 2 3 4 5 var str aaaa
  • C++ std::vector删除元素的几种方式及区别

    容器vector在删除过程中 常用的函数 函数 作用 pop back 删除 vector 容器中最后一个元素 该容器的大小 size 会减 1 但容量 capacity 不会发生改变 erase iter 删除 vector 容器中ite
  • 机器学习——Kmeans聚类算法

    目录 简介 手肘法 手肘法核心思想 轮廓系数 代码举例1 代码举例2 实例 简介 K均值聚类算法是先随机选取K个对象作为初始的聚类中心 然后计算每个对象与各个种子聚类中心之间的距离 把每个对象分配给距离它最近的聚类中心 聚类中心以及分配给它