【人工智能基础】聚类实验分析

news2024/12/24 22:10:47

实验环境:anaconda、jupyter notebook、spyder

实现用到的类库:numpy、matplotlib、scikit-learn

k均值聚类(K-MEANS)

k均值聚类的原理:

  1. 选定k个聚类中心
  2. 把数据集中距离聚类中心i最近的点都归属到一个簇
  3. 根据每个簇中的点计算出新的聚类中心
  4. 如果聚类中心没有发生移动,则聚类完成,否则重复2,3,4

一、 根据k均值聚类的原理,尝试自己实现

k均值实现类

import math
import numpy as np
import matplotlib.pyplot as plt

class KMeans:
    def __init__(self):
        # 聚类的每一步
        self.clustering_step = []

    def train(self,data, num_clusters):
        self.data = data
        self.num_clusters = num_clusters

        count = data.shape[0]
        # 获取初始聚类中心
        self.center = self.init_clustering_center()
        # 存储原始状态
        self.clustering_step.append([np.copy([self.data]),np.copy(self.center)])

        # 聚类一次
        new_center,cluster = self.updata_clustering_center()

        # 如果聚类中心的位置产生了移动继续聚类
        while not KMeans.is_equal(new_center, self.center):
            self.center = new_center
            temp = [cluster,np.copy(self.center)]
            self.clustering_step.append(temp)
            new_center,cluster = self.updata_clustering_center()



    @staticmethod
    def is_equal(array1, array2):
        for i in range(len(array1)):
            if (array1[i][0] - array2[i][0])**2 > 1e-10 and (array1[i][1] - array2[i][1])**2 > 1e-10:
                return False
        return True


    def init_clustering_center(self):
        """
        初始化聚类中心
        洗牌数组后随机取k个数值
        """
        return self.data[np.random.permutation(self.data.shape[0])][:self.num_clusters]


    def updata_clustering_center(self):
        '''
        更新聚类中心
        '''
        # 记录每组的点
        cluster = []
        for _ in range(self.num_clusters):
            cluster.append([])

        for d in self.data:
            distance = []
            # 计算每个样本点到假定聚类中心的欧式距离
            for c in self.center:
                distance.append(np.sum((d - c))**2)
            # 每个点分配到最近的聚类中心
            min_index = np.argmin(distance)
            cluster[min_index].append(d)
            new_center = []
            # 计算新聚类中心的位置
            for c in cluster:
                if len(c) == 0:
                    new_center.append([0,0])
                    continue
                new_center.append(np.sum(c,axis=0) / len(c))
        cluster = [np.array(x) for x in cluster]
        return new_center,cluster



    def show_step(self,row):
        '''
        绘制聚类过程
        '''
        color = ['r','b','y']

        step = len(self.clustering_step)
        col = math.ceil(step / row)
        plt.figure(figsize=(row * 6, col * 5))

        for i in range(step):
            plt.subplot(row,math.ceil(step / row), i + 1)
            current_step = self.clustering_step[i]
            group = current_step[0]
            center = current_step[1]
            for g in group:
                plt.scatter(g[:,0], g[:,1])
            plt.scatter(center[:,0], center[:,1] ,c='k',marker='x')
            plt.title(label='clustering:{}'.format(i+1))

        plt.legend()
        plt.show()

2.运行k均值算法

这里使用的数据集是鸢尾花数据集

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

from my_work.k_means import KMeans

iris = datasets.load_iris()
data = iris.data
class_ = iris.target
print(class_)

x_axis = 2
y_axis = 3

x1 = data[:,x_axis]
x2 = data[:,y_axis]


# 绘制原始的图
plt.figure(figsize=(12,5))
plt.subplot(1,2,1)
for iris_type in np.unique(class_):
    plt.scatter(x1[class_==iris_type],
                x2[class_==iris_type],
                label=iris_type)
plt.subplot(1,2,2)
plt.scatter(x1, x2)
plt.legend()
plt.show()

# 绘制经过kmeans算法得到的训练过程
x_train = np.c_[x1,x2]
kmeans = KMeans()
num_clusters = np.unique(class_).shape[0]
kmeans.train(x_train, num_clusters)
kmeans.show_step(3)

3.结果

我们自己实现的算法能够完成k均值分类的任务

鸢尾花数据集真实聚类

鸢尾花数据集k均值算法聚类

二、scikit-learn提供的kmeans算法

1.实验准备

import numpy as np
import os
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 14
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12
import warnings
warnings.filterwarnings('ignore')
np.random.seed(42)

2.初始化样本数据集

创建数据集

# 引入椭圆
from sklearn.datasets import make_blobs

# 指定五个中心
blob_centers = np.array(
    [[0.2,2.3],
    [-1.5,2.3],
    [-2.8,1.8],
    [-2.8,2.8],
    [-2.8,1.3]]
)

blob_std = np.array([0.4,0.3,0.1,0.1,0.1])

x,y = make_blobs(
    # 样本个数
    n_samples=2000,
    # 中心点
    centers=blob_centers,
    # 发散程度
    cluster_std=blob_std,
    random_state=7
)

绘制数据集

# 绘图函数
def plot_clusters(x, y= None):
    plt.scatter(x[:,0],x[:,1],c=y,s=1)
    plt.xlabel('$x_1$',fontsize=14)
    plt.ylabel('$x_2$',fontsize=14)
# 绘制图像    
plt.figure(figsize=(8,4))
plot_clusters(x)
plt.show()

我们创建了五个聚类中心的数据集

椭圆数据集

3.使用kmeans算法实现聚类

实现聚类

from sklearn.cluster import KMeans
# 聚类中心个数
k = 5
kmeans = KMeans(n_clusters = k, random_state=42,n_init='auto')
# 打印每个点所属的的聚类
print(kmeans.labels_)
print(kmeans.fit_predict(x))
# 打印聚类中心的位置
print(kmeans.cluster_centers_)
# 预测这些点所属的聚类中心
x_new = np.array([[0,2],[3,2],[-3,-3],[-3,2.5]])
print(kmeans.predict(x_new))

绘制函数

def plot_data(x):
    """
    绘制入参的图像
    """
    plt.plot(x[:,0],x[:,1],'k.',markersize=2)

def plot_centroids(centroids, weights=None, circle_color='w',cross_color='k'):
    """
    绘制中心点
    """
    if weights is not None:
        centroids = centroids[weights > weights.max() / 10]
    plt.scatter(centroids[:,0],
                centroids[:,1],
                marker='o',
                s=30,
                linewidths=8, 
                color=circle_color, 
                zorder=10,
                alpha=0.9)
    plt.scatter(centroids[:,0],
                centroids[:,1],
                marker='x',
                s=50,
                linewidths=1, 
                color=cross_color, 
                zorder=11,
                alpha=1)

def plot_decision_boundaries(clusterer, x, resolution=100, show_centroids=True,
                            show_xlabels=True,show_ylabels=True):
    """
    绘制聚类器对参数x的聚类结果
    """
    mins = x.min(axis=0) - 0.1
    maxs = x.max(axis=0) + 0.1
    xx,yy = np.meshgrid(np.linspace(mins[0],maxs[0],resolution),
                        np.linspace(mins[1],maxs[1],resolution))
    z = clusterer.predict(np.c_[xx.ravel(),yy.ravel()])
    z = z.reshape(xx.shape)
    plt.contourf(z, extent=(mins[0],maxs[0],mins[1],maxs[1]), cmap='Pastel2')
    plt.contour(z, extent=(mins[0],maxs[0],mins[1],maxs[1]),linewidths=1,colors='k')
    plot_data(x)
    if show_centroids:
        plot_centroids(clusterer.cluster_centers_)
    if show_xlabels:
        plt.xlabel('$x_1$',fontsize=14)
    else:
        plt.tick_params(labelbottom='off')
    if show_ylabels:
        plt.ylabel('$x_2$',fontsize=14,rotation=0)
    else:
        plt.tick_params(labelleft='off')

绘制聚类结果

plt.figure(figsize=(10,3))
plot_decision_boundaries(kmeans,x)
plt.show()

kmeans聚类结果

三、聚类过程

创建三个kmeans对象,分别进行1,2,3次迭代聚类

kmeans__iter1 = KMeans(n_clusters = 5, init='random',n_init=1, max_iter=1,random_state=1)
kmeans__iter1.fit(x)
kmeans__iter2 = KMeans(n_clusters = 5, init='random',n_init=1, max_iter=2,random_state=1)
kmeans__iter2.fit(x)
kmeans__iter3  = KMeans(n_clusters = 5, init='random',n_init=1, max_iter=3,random_state=1)
kmeans__iter3.fit(x)

绘制图像

plt.figure(figure=(10,8))

plt.subplot(321)
plot_data(x)
plot_centroids(kmeans__iter1.cluster_centers_,circle_color='r',cross_color='k')
plt.title('Update cluster_centers')

plt.subplot(322)
plot_data(x)
plot_decision_boundaries(kmeans__iter1,x,show_xlabels=False,show_ylabels=False)
plt.title('Label')

plt.subplot(323)
plot_decision_boundaries(kmeans__iter1,x,show_xlabels=False,show_ylabels=False)
plot_centroids(kmeans__iter2.cluster_centers_,circle_color='r',cross_color='k')

plt.subplot(324)
plot_decision_boundaries(kmeans__iter2,x,show_xlabels=False,show_ylabels=False)


plt.subplot(325)
plot_decision_boundaries(kmeans__iter2,x,show_xlabels=False,show_ylabels=False)
plot_centroids(kmeans__iter3.cluster_centers_,circle_color='r',cross_color='k')

plt.subplot(326)
plot_decision_boundaries(kmeans__iter3,x,show_xlabels=False,show_ylabels=False)

plt.show()

kmeans聚类过程

四、kmeans的不稳定性

kmeans初始的聚类中心不同可能会得到不同的聚类结果

def plot_clusterer_comparison(c1,c2,x):
    c1.fit(x)
    c2.fit(x)

    plt.figure(figsize=(12,4))
    plt.subplot(121)
    plot_decision_boundaries(c1,x)
    plt.subplot(122)
    plot_decision_boundaries(c2,x)
c1 = KMeans(n_clusters = 5, init='random',n_init=1, random_state=11)
c2 = KMeans(n_clusters = 5, init='random',n_init=1, random_state=49)
plot_clusterer_comparison(c1,c2,x)

kmeans不稳定性

五、寻找合适的k值(只是参考)

inertia指标

inertia指标:每个样本与其质心的距离 使用kmeans对象.inertia_来查看

根据inertia指标的转折点

# 获得聚类数为1~10的10个kmeans对象
kmeans_per_k = [KMeans(n_clusters = k).fit(x) for k in range(1,10)]
# 获得这些kmeans对象的inertia指标
interias = [model.inertia_ for model in kmeans_per_k]
# 绘制inertia指标变化图
plt.figure(figsize=(8,4))
plt.plot(range(1,10),interias,'bo-')
plt.show()

根据这个图像,我们认为最佳的聚类数应该是4,实际应该是5,这个指标做为参考,不一定是最优结果

inertia指标变化图

根据轮廓系数

轮廓系数规定参数:

  • ai:计算样本i到同簇其他样本的平均距离。簇内不相似度
  • bi:计算样本到其他某簇Cj的所有样本的平均距离bij。簇间不相似度
  • si = (bi - ai) / max{ai.bi}

由此我们可以知道:

  1. si越接近1,说明样本i聚类合理
  2. si接近-1,说明样本i更应该分到别的簇
  3. si近似为0,说明样本在两个簇的边界
from sklearn.metrics import silhouette_score
scores = [silhouette_score(x, model.labels_) for model in kmeans_per_k[1:]]
plt.figure(figsize=(8,4))
plt.plot(range(2,10),scores,'bo-')
plt.show()

根据这个图像,我们认为最佳的聚类数应该是4,实际应该是5,这个指标做为参考,不一定是最优结果

轮廓系数变化图

六、kmeans进行图像分割

使用的图像是,把这个图像放在python脚本文件相同目录下

ladybug

from matplotlib.image import imread
# 读入图像
image = imread('ladybug.png')
# 图像本身是三维数据,需要转换成二维进行处理
x = image.reshape(-1,3)
# 存储图像分类结果
segmented_imgs = []
# 表示颜色的种类数量
n_colors = (10,8,6,4,2)
# 按不同和的颜色种类数量训练模型
for n_clusters in n_colors:
    kmeans = KMeans(n_clusters=n_clusters, random_state=42).fit(x)
    # 用聚类中心的颜色来替代整个簇的颜色
    segmented_img = kmeans.cluster_centers_[kmeans.labels_]
    segmented_imgs.append(segmented_img.reshape(image.shape))
#绘制图像
plt.figure(figsize=(10,5))
plt.subplot(231)
plt.imshow(image)
plt.title('original image')
for idx,n_clusters in enumerate(n_colors):
    plt.subplot(232+idx)
    plt.imshow(segmented_imgs[idx])
    plt.title('{}colors'.format(n_clusters))
plt.show()

kmeans图像分割

DBSCAN

DBSCAN算法:找到图中的核心对象,把核心对象核心对象ε-邻域中的点都聚为一类,若ε-邻域中的点也是核心对象,则继续本类的聚类

  • 核心对象:若某个点的密度达到算法设定的阈值,则其为核心点(r邻域内点的数量不小于minPts)
  • ε-邻域的距离阈值:设定的半径r
  • 直接密度可达:若某点p在点q 的r邻域内,且q是核心点,则称p-q直接密度可达
  • 密度可达:若有一个点的序列q0、q1……qk,对任意qi-qi-1是直接密度可达的,则q0到qk密度可达(直接密度可达的传播)

创建数据集

from sklearn.datasets import make_moons
x, y = make_moons(n_samples=1000,noise=0.05,random_state=42)
plt.plot(x[:,0],x[:,1],'b.')
plt.show()

这个数据集不适合使用kmeans算法进行聚类

DBSCAN数据集

执行聚类学习

from sklearn.cluster import DBSCAN
dbscan = DBSCAN(eps=0.05,min_samples=5)
dbscan.fit(x)

dbscan2 = DBSCAN(eps=0.2,min_samples=5)
dbscan2.fit(x)

图像绘制函数

def plot_dbscan(dbscan,x,size,show_xlabels=True, show_ylabels=True):
    core_mask = np.zeros_like(dbscan.labels_,dtype=bool)
    core_mask[dbscan.core_sample_indices_]=True
    anomalies_mask = dbscan.labels_ == -1
    non_core_mask = ~(core_mask | anomalies_mask)

    cores=dbscan.components_
    anomalies=x[anomalies_mask]
    non_cores=x[non_core_mask]

    plt.scatter(cores[:,0],cores[:,1],
               c=dbscan.labels_[core_mask], marker='o',s=size,cmap='Paired')
    plt.scatter(cores[:,0],cores[:,1],marker='*',s=20,c=dbscan.labels_[core_mask])
    plt.scatter(non_cores[:,0],non_cores[:,1],c=dbscan.labels_[non_core_mask],marker='.')
    if show_xlabels:
        plt.xlabel('$x_1$',fontsize=14)
    else:
        plt.tick_params(labelbottom='off')
    if show_ylabels:
        plt.ylabel('$x_2$',fontsize=14,rotation=0)
    else:
        plt.tick_params(labelleft='off')
    plt.title('eps={:.2f}, min_samples={}'.format(dbscan.eps, dbscan.min_samples),fontsize=14)

绘制两个DBSCAN聚类器的图像

plt.figure(figsize=(9,4))

plt.subplot(121)
plot_dbscan(dbscan,x,size=100)

plt.subplot(122)
plot_dbscan(dbscan2,x,size=60,show_ylabels=False)

plt.show()

DBSCAN聚类结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1633387.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux开发 第十二篇】搭建JavaEE环境

搭建开发环境 搭建javaEE环境 搭建javaEE环境 在Linux下开发JavaEE需要安装软件包: 安装jdk 安装步骤: 在opt目录下创建jdk目录通过xftp上床到jdk目录中进入到jdk目录中,解压jdk压缩包在/usr/local下创建java目录将解压完成的jdk文件移动…

Docker的介绍及应用

1.什么是Docker 我们在部署大型项目的时候,肯定会遇到这种问题,大学项目组件较多,运行环境复杂,部署时会碰到一些问题:例如node、redis、mysql等这些应用都有自己的依赖和函数库。这种复杂的依赖关系很容易出现兼容问…

笔试刷题-Day11

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 一、游游的水果大礼包 题目链接:https://ac.nowcoder.com/acm/problem/255193 类型:求一个表达式的最值(并不是贪心,因为该题条件太少&…

毕业设计注意事项(嘉庚学院2024届更新中)

1.开题 根据学院发的开题报告模板完成,其中大纲部分可参考资料。 2.毕设以及实习 2.1 毕设 根据资料中的毕设评价标准,对照工作量 2.2 实习材料提交 2.2.1 校外实习 实习前:根据学院要求,填写好实习承诺书,实习单位…

贝叶斯统计实战:Python引领的现代数据分析之旅

贝叶斯统计这个名字取自长老会牧师兼业余数学家托马斯贝叶斯(Thomas Bayes,1702—1761),他最先推导出了贝叶斯定理,该定理于其逝世后的1763年发表。但真正开发贝叶斯方法的第一人是Pierre-Simon Laplace(1749—1827),因此将其称为…

清华同方电脑c盘满了怎么清理?别慌,学会这几个实用技巧

随着日常使用电脑,C盘(通常是系统盘)往往会积累大量的文件、程序和系统缓存,导致磁盘空间逐渐减少。当C盘空间不足时,电脑的性能可能会受到影响,甚至导致一些程序无法正常运行。对于清华同方电脑的用户来说…

2000.1-2023.8中国经济政策不确定性指数数据(日度、月度)

2000.1-2023.8中国经济政策不确定性指数数据(日度、月度) 1、时间:日度:2001.1.1-2022.06.17,月度2000.1-2023.8 2、指标:CNEPU(经济政策不确定性指数) 3、来源:China…

[BJDCTF 2020]base??(古典密码)

题目: 从题目我们看出dict是一个python的字典,但与原始的base64的表不同,所以我们想到通过替换原始的表,来对密文解密。 my_dict{0: J, 1: K, 2: L, 3: M, 4: N, 5: O, 6: x, 7: y, 8: U, 9: V, 10: z, 11: A, 12: B, 13: C, 14:…

2024五一杯ABC题资料合集+代码+参考论文!!!

一.赛题思路 (赛题出来以后第一时间在群内分享) 二.比赛日期和时间 比赛开始时间:2024年5月1日(周三)10;00 比赛结束时间:2024年5月4日(周六)12:00 三.将在明天分享的资料合集如下 4.我们这边会分享22年的题目完整全部的过程 5.数学建模的29个通用模型及MATLAB…

吴恩达2022机器学习专项课程(一)7.2 逻辑回归的简化成本函数

问题预览/关键词 本节课内容逻辑回归的损失函数简化之后的形式是?为什么可以简化?成本函数的通用形式是?逻辑回归成本函数的最终形式是?逻辑回归为什么用对数损失函数计算成本函数?为什么不直接给出逻辑回归损失函数的…

Makefile 快速入门

参考自:Makefile 20分钟入门,简简单单,展示如何使用Makefile管理和编译C代码_哔哩哔哩_bilibili 注: 视频中用的是C,博主这里用C语言实现 喜欢老师的于老师的还请多多点赞,觉得博主写得不错的,也可以点赞、收藏哦 本…

面对网络安全,做好风险评估对企业会带来哪些帮助

随着信息技术的飞速发展,网络安全问题日益凸显,成为企业不容忽视的重要议题。企业作为社会经济活动的主要参与者,其网络安全不仅关系到自身的生存与发展,更与国家的经济安全、社会稳定息息相关。因此,企业必须高度重视…

UG NX二次开发(C#)-去掉模型更新的警报提示窗口

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2 、解决方案 1、前言 在我的微信群《UG NX二次开发学习讨论》中有个群友发出一个问题,就是参数化模型修改后,有时更新是正确的&…

STM32开启停止模式,用外部中断唤醒程序运行

今天学习了一下STM32的停止模式,停止模式下,所有外设的时钟和CPU的电源都会被关闭,所以会很省电,打破这种停止模式的方式就是外部中断可以唤醒停止模式。要想实现这个功能,其实设置很简单的,总共就需要两步…

【数据结构初阶】时间复杂度和空间复杂度详解

今天我们来详细讲讲时间复杂度和空间复杂度,途中如果有不懂的地方可翻阅我之前文章。 个人主页:小八哥向前冲~-CSDN博客 数据结构专栏:数据结构【c语言版】_小八哥向前冲~的博客-CSDN博客 c语言专栏:c语言_小八哥向前冲~的博客-CS…

OceanBase 助力同方智慧能源,打造安全可靠、高性能的能源数据架构

本文作者:丁泽斌,同方智慧能源数据库工程师 业务背景 作为同方股份有限公司旗下的领军企业,同方智慧能源集团矢志成为全球领先的综合智慧能源解决方案提供商。凭借中核集团和清华大学的科技实力,专注于向建筑、交通、工业、北方供…

Linux工具篇 之 vim概念 操作 及基础指令讲解

学校不大 创造神话 讲桌两旁 陨落的王 临时抱佛脚 佛踹我一脚 书山有路勤为径 游戏玩的很起劲 想要计算机学的好,我的博客列表是个宝 –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀-正文开始-❀–❀–❀–❀–❀–❀–❀–❀…

linux的lcd屏幕调试

x2600-lcd的sat101cp50d24b1屏幕的驱动调试 1.硬件关联 屏幕型号:sat101cp50d24b1 原理图: 很显然,这是RGB666显示格式的屏幕,RGB管脚DATA0-DATA17--为数据线 DEN 数据使能线。 VSYNC 垂直同步信号线。 HSYNC 水平同步信号线。…

vue-print-nb插件来实现打印功能——打印布局及尺寸处理

之前写过一篇文章是关于vue-print-nb插件实现打印功能, vue插件——vue-print-nb 实现打印功能:http://t.csdnimg.cn/ahuxp 但是在实际使用过程中,打印的效果不尽如人意。下面把打印页面和遇到的问题做一下汇总: 1.html代码——给打印元素绑…

vivado Aurora 8B/10B IP核(6)-本地流量控制(Native Flow Control)

Aurora 8B/10B 协议包括本地流控制(NFC)接口,其允许接收机通过指定必须 放入数据流的空闲数据跳数来控制接收数据的速率。 甚至可以通过请求发送器临时发送空闲(XOFF) 来完全关闭数据流.NFC 通常用于防止 FIFO 溢出条…