机器学习(二):二分K-means算法(进阶篇)

本文介绍二分K-means算法,它是k-means算法的优化,属于分层聚类的分裂法。该算法能加速执行、克服局部最优问题。文中阐述其步骤,还以Iris数据集为例进行实践,给出算法思路、原理、步骤及相关函数实现,最终实现二分K-means算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

机器学习(二):二分K-means算法

在前一节的内容已经介绍了k-means算法的原理和代码实现,如果没有了解过K-means的同学建议先了解机器学习(二):k-means算法(基础篇)

二分k-means是k-means算法的一种优化,二分k-means算法很好的解决了k-means算法的局部最优的问题。接下来我们来了解一下二分k-means的神奇之处

二分k-means算法

二分k-means算法是分层聚类(Hierarchical clustering)的一种,分层聚类是聚类分析中常用的方法。
分层聚类的策略一般有两种:

  • 聚合。这是一种自底向上的方法,每一个观察者初始化本身为一类,然后两两结合
  • 分裂。这是一种自顶向下的方法,所有观察者初始化为一类,然后递归地分裂它们

二分k-means算法是分裂法的一种。

二分k-means算法的优点

二分k-means算法是k-means算法的改进算法,相比k-means算法,它有如下优点:

  • 二分k-means算法可以加速k-means算法的执行速度,因为它的相似度计算少了
  • 能够克服k-means收敛于局部最小的缺点

二分k-means算法的步骤

二分k-means算法的一般流程如下所示:

  1. 把所有数据初始化为一个簇,将这个簇分为两个簇。
  2. 选择满足条件的可以分解的簇。选择条件综合考虑簇的元素个数以及聚类代价(也就是误差平方和SSE),误差平方和的公式如下所示,其中w(i) 表示权重值,y∗该簇所有点的平均值。
    在这里插入图片描述
  3. 使用k-means算法将可分裂的簇分为两簇
  4. 一直重复(2)(3)步,直到满足迭代结束条件。

以上过程隐含着一个原则是:因为聚类的误差平方和能够衡量聚类性能,该值越小表示数据点越接近于它们的质心,聚类效果就越好。
所以我们就需要对误差平方和最大的簇进行再一次的划分,因为误差平方和越大,表示该簇聚类越不好,越有可能是多个簇被当成一个簇了,所以我们首先需要对这个簇进行划分。

二分K-means算法的实践

扩展任务

  1. 现二分 K-means 代码并进行测试(会在下一节中提到)

数据集

数据集介绍:
Iris.data 数据集主要有如下:

sl 花萼长度
sw 花萼宽度
pl 花瓣长度
pw 花瓣宽度
variety 花的品种

实现二分k-means算法

(1) 算法思路:
二分 k-means 算法,此算法不需要标签变量,在 k-means 算法的基础上需要通过四个特征变量将 Iris 进行聚类。目标:通过 Iris 的四个特征值进行聚类,得到每个聚类中的质心,并把聚类结果写入文件中。

(2) 算法原理基础:
在原理上跟二分 k-means 上差不多相同。

(3) 算法步骤:

  1. 把整个数据集看成一个簇,计算质心
  2. 将这个簇分成两个簇
  3. 选择满足条件的可以分解的簇,选择条件为簇元素的个数和 SSE 大小
  4. 使用 k-mean 算法将可分裂的簇分成两个簇
  5. 重复(2)(3)步,直到满足 k 值

(4) 算法相关函数的实现:

  • loadDataSet(): 读入数据,得到四个特征变量
  • distEclud(): 欧式距离公式
  • randCent(): 生成随机 k 个质心
  • Kmeans(): k-means 函数
  • chooseK(): 画出肘部图
  • biKmeans():二分 k-means 的主函数,主要算法
  • writeTxt(): 写入文件

(5)代码实现:

# -*- coding:utf-8 -*-
import warnings
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

warnings.filterwarnings('ignore')   #忽略警告
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

#伪代码如下
# 将所有点看成一个簇
# 当簇数目小于k时
# 对于每一个簇
#     计算总误差
#     在给定的簇上面进行k-均值聚类(k=2)
#     计算将该簇一分为二之后的总误差
# 选择使得总误差最小的簇进行划分

def loadDataSet(filename):
    """
    函数说明:从文件中下载数据,并将分离除连续型变量和标签变量
    :parameter:
            data - Iris数据集
            attributes - 鸢尾花的属性
            type - 鸢尾花的类别
            sl-花萼长度 , sw-花萼宽度, pl-花瓣长度, pw-花瓣宽度
    :return:
    """
    iris_data = pd.read_csv(filename)   #打开文件
    iris_data = pd.DataFrame(data=np.array(iris_data), columns=['sl', 'sw', 'pl', 'pw', 'type'], index=range(149))   #给数据集添加列名,方便后面的操作
    attributes = iris_data[['sl', 'sw', 'pl', 'pw']]   #分离出花的属性
    iris_data['type'] = iris_data['type'].apply(lambda x: x.split('-')[1])  # 最后类别一列,感觉前面的'Iris-'有点多余即把class这一列的数据按'-'进行切分取切分后的第二个数据
    labels = iris_data['type']     #分理出花的类别
    attriLabels = []      #建立一个标签列表
    for label in labels:        #为了更方便操作,将三中不同的类型分别设为123
        if label == 'setosa':    #如果类别为setosa的话,设为1
            attriLabels.append(1)
        elif label 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值