【机器学习】利用numpy实现K-Means聚类算法(Python代码)

简介: 【机器学习】利用numpy实现K-Means聚类算法(Python代码)

简 介:下面是我在学习时候的记录并加上自己的理解。本文意在记录自己近期学习过程中的所学所得,如有错误,欢迎大家指正。

 

关键词:Python、机器学习、K-Means聚类

"""
 * Created with PyCharm
 * 作者: 阿光
 * 日期: 2021/7/18
 * 时间: 14:19
 * 描述: 利用numpy自己实现K-Means算法
"""
import random
import warnings
import numpy as np
import pandas as pd
from Draw import draw
warnings.filterwarnings('ignore')
# 加载数据
data = pd.read_csv("../../data/cluster_500-10_7.csv", encoding="gbk")
X = data.iloc[:, 1:-2].values
y = data.iloc[:, -1].values.flatten()
cluster = 7  # 定义簇的个数
iter_ = 500  # 每轮的k-means的迭代次数
epochs = 20  # 模型的迭代轮数
label_ = np.zeros(len(X))  # 定义样本分类集合,代表每个样本所属的簇类别,[0,1,4,2]
best_label = []  # 保存最好的聚类效果
best_score = 99999  # 保存模型最优效果下的DB指数
def kmeans(x):
    """
     * 描述: K-Means算法的入口
     * 参数: x即样本数据
     * 返回值:
    """
    # 随机选择k个样本作为初始向量
    # test = random.sample(range(0, x.shape[0]), cluster)
    # print(test)
    x_center = x[random.sample(range(0, x.shape[0]), cluster), :]
    # x_center = init_cluster(X, cluster)
    # 新的簇的向量中心
    new_center = x_center.copy()
    k = 0  # 记录迭代轮数
    # 进行迭代更新,只要上一次和本次的簇中心不一致就继续迭代
    while True:
        if ((x_center == new_center).sum() == x_center.shape[0] * x_center.shape[1] and k != 0) or k > iter_:
            break
        x_center = new_center
        k += 1
        # 计算样本到簇中心的距离
        matrix = distance(x_center, x)
        # 更新每个样本的所属簇分类
        update_cluster(matrix)
        # 根据新的样本划分情况,更新每个簇的中心
        new_center = update_center(x)
    # print("聚类结束,共迭代{}轮".format(k))
def run(X):
    """
     * 描述: k-means算法的主调函数
     * 参数: X为样本数据
     * 返回值:
    """
    # 迭代多个epoch,根据DBI指数选取最好的结果
    for epoch in range(epochs):
        kmeans(X)  # 调用kmeans
        # 计算DBI指数
        DBI = optimizer_score(cluster, X)
        global best_score, best_label
        # 如果当前轮数的效果好于上一次的,记录最优的DBI指数,以及最好的聚类结果
        if DBI < best_score:
            best_score = DBI
            best_label = label_
def init_cluster(X, cluster):
    x_center = np.zeros((cluster, X.shape[1]))
    i = 0
    res = set()
    while True:
        if i == 0:
            index = random.sample(range(0, X.shape[0]), 1)
            res.add(index[0])
            x_center[i, :] = X[index]
            i += 1
        else:
            distance_ = np.zeros((X.shape[0], i))
            for j in range(i):
                row = x_center[j, :]
                distance_[:, j] = np.sqrt(((X - row) ** 2).sum(axis=1))
            distance_ = (distance_ - distance_.mean(axis=0)) / distance_.std(axis=0)
            rank = np.argsort(distance_, axis=0)
            rank = (rank - rank.mean(axis=0)) / rank.std(axis=0)
            loc = np.sum(rank, axis=1)
            # distance_ = np.sum(distance_, axis=1)
            # location = np.where(distance_ == distance_.max())
            index = np.argmax(loc)
            print(res)
            if index not in res:
                x_center[i, :] = X[index]
                res.add(index)
                i += 1
            else:
                while index < X.shape[0] - 2:
                    index = index + 1
                    if index not in res:
                        x_center[i, :] = X[index]
                        res.add(index)
                        i += 1
                        break
        if i == cluster:
            break
    return x_center
def optimizer_score(cluster, X):
    """
     * 描述: 计算DBI优化指标
     * 参数:
            cluster:聚类簇数
            X:样本数据
     * 返回值: 模型的DBI指数
    """
    # 用于计算簇内平均值
    def avg_C(label):
        distance_ = np.zeros((X[label_ == label, :].shape[0], X[label_ == label, :].shape[0]))
        for i, row in enumerate(X[label_ == label, :]):
            distance_[i, :] = np.sqrt(np.sum((X[label_ == label, :] - row) ** 2, axis=1))
        distance_ = distance_.sum() / (X.shape[0] * (X.shape[0] - 1))
        return distance_
    # 用于计算簇间中心的距离
    def d_cen(cluster_i, cluster_j):
        X_i = X[label_ == cluster_i, :]
        X_j = X[label_ == cluster_j, :]
        X_i_mean = X_i.mean(axis=0)
        x_j_mean = X_j.mean(axis=0)
        return np.sqrt(((X_i_mean - x_j_mean) ** 2).sum())
    DBI = 0
    # 迭代每个簇,计算每个簇的DB指数,然后求平均值
    for i in range(cluster):
        dis_list = []
        for j in range(cluster):
            if i != j:
                dis_list.append((avg_C(i) + avg_C(j)) / d_cen(i, j))
        DBI += max(dis_list)
    return DBI / cluster
def distance(center, x):
    """
     * 描述: 计算每个样本到簇中心的距离
     * 参数:
            center:簇中心,形状为(10,5)10个簇,5个特征属性
            x:数据样本,形状(100,5),100个样本,5个特征
     * 返回值: 返回每个样本到各个簇中心的距离,形状为(100,10),每一行代表每个样本到各个簇的距离
    """
    matrix = np.random.rand(x.shape[0], center.shape[0])
    # 迭代每一行,进行计算到各个簇中心的距离
    for i, row in enumerate(x):
        matrix[i, :] = np.sum((row - center) ** 2, axis=1)  # 平方差,然后按照每一行进行求和
    return matrix
def update_cluster(matrix):
    """
     * 描述: 更新每个样本所属的簇分类
     * 参数: matrix就是样本到簇中心的距离矩阵
     * 返回值:
    """
    global label_
    # 返回每行的最小值的下标,即返回距离最近的簇中心所属的类别
    label_ = np.argmin(matrix, axis=1)
def update_center(x):
    """
     * 描述: 更新每个簇的中心
     * 参数: x,样本数据
     * 返回值:
    """
    new_center = np.zeros((cluster, x.shape[1]))
    # 依次迭代每个类别下的数据,计算该类数据的均值
    for category in range(cluster):
        new_center[category, :] = x[label_ == category, :].mean(axis=0)
    return new_center
if __name__ == "__main__":
    run(X)  # 调用算法
    draw(X, y, best_label, cluster)  # 将聚类结果可视化

目录
相关文章
|
12天前
|
开发框架 数据建模 中间件
Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器是那些静悄悄的幕后英雄。它们不张扬,却能默默地为函数或类增添强大的功能。本文将带你了解装饰器的魅力所在,从基础概念到实际应用,我们一步步揭开装饰器的神秘面纱。准备好了吗?让我们开始这段简洁而富有启发性的旅程吧!
23 6
|
5天前
|
数据可视化 Python
以下是一些常用的图表类型及其Python代码示例,使用Matplotlib和Seaborn库。
通过这些思维导图和分析说明表,您可以更直观地理解和选择适合的数据可视化图表类型,帮助更有效地展示和分析数据。
36 8
|
10天前
|
Python
探索Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器就像是给函数穿上了一件神奇的外套,让它们拥有了超能力。本文将通过浅显易懂的语言和生动的比喻,带你了解装饰器的基本概念、使用方法以及它们如何让你的代码变得更加简洁高效。让我们一起揭开装饰器的神秘面纱,看看它是如何在不改变函数核心逻辑的情况下,为函数增添新功能的吧!
|
11天前
|
程序员 测试技术 数据安全/隐私保护
深入理解Python装饰器:提升代码重用与可读性
本文旨在为中高级Python开发者提供一份关于装饰器的深度解析。通过探讨装饰器的基本原理、类型以及在实际项目中的应用案例,帮助读者更好地理解并运用这一强大的语言特性。不同于常规摘要,本文将以一个实际的软件开发场景引入,逐步揭示装饰器如何优化代码结构,提高开发效率和代码质量。
34 6
|
机器学习/深度学习 算法 搜索推荐
Python数据挖掘与机器学习,快速掌握聚类算法和关联分析
前文数据挖掘与机器学习技术入门实战与大家分享了分类算法,在本文中将为大家介绍聚类算法和关联分析问题。分类算法与聚类到底有何区别?聚类方法应在怎样的场景下使用?如何使用关联分析算法解决个性化推荐问题?本文就为大家揭晓答案。
16309 0
|
11天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
10天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
17天前
|
存储 索引 Python
Python编程数据结构的深入理解
深入理解 Python 中的数据结构是提高编程能力的重要途径。通过合理选择和使用数据结构,可以提高程序的效率和质量
129 59
|
10天前
|
小程序 开发者 Python
探索Python编程:从基础到实战
本文将引导你走进Python编程的世界,从基础语法开始,逐步深入到实战项目。我们将一起探讨如何在编程中发挥创意,解决问题,并分享一些实用的技巧和心得。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你提供有价值的参考。让我们一起开启Python编程的探索之旅吧!
33 10
|
13天前
|
机器学习/深度学习 人工智能 Java
Python 语言:强大、灵活与高效的编程之选
本文全面介绍了 Python 编程语言,涵盖其历史、特点、应用领域及核心概念。从 1989 年由 Guido van Rossum 创立至今,Python 凭借简洁的语法和强大的功能,成为数据科学、AI、Web 开发等领域的首选语言。文章还详细探讨了 Python 的语法基础、数据结构、面向对象编程等内容,旨在帮助读者深入了解并有效利用 Python 进行编程。