K-means 聚类算法学习笔记

news/2024/5/20 9:13:36 标签: 算法, kmeans, 聚类

K-means 聚类算法 是一种无监督学习算法,用来将 n n n 个样本点分成 k k k 类,使得整个数据集的误差平方和 S S E SSE SSE 最小。在本例中,样本点是指平面直角坐标系上的点,聚类中心也是平面直角坐标系上的点,而每个点的损失函数则是它到聚类中心的距离。即:找出 2 个点,使得所有点到这 2 个点的距离的更小者之和最小。

K-means 聚类算法流程如下:

  1. 随机指定 k k k 个样本点为聚类中心;
  2. 计算所有点对每个样本点的距离,选择最近的样本点;
  3. 计算同一类的所有点的重心,并将重心作为新的聚类中心;
  4. 重复2.3.,直到所有点选定的最近样本点均不再改变。

其中

S S E = ∑ i = 1 k ∑ x ∈ C i ∑ j = 1 m ( x j − S i j ) 2 SSE=\sum_{i=1}^{k}\sum_{x\in C_i}\sum_{j=1}^m(x_j-S_{ij})^2 SSE=i=1kxCij=1m(xjSij)2

理论上说, S S E SSE SSE 会随着 k k k 的变大而单调递减。

参考文献。

function [ClusterID,Means] = KMeansClustering(S, K, plot_flag)
% 输入参数:
% S: 用于聚类的数据,每一行对应一个样本的特征向量,每一列对应一个特征
% K:需要聚成的簇的数量
% plot_flag: 是否需要可视化每一次迭代的更新结果

% 输出参数:
% ClusterID:聚类结果,表示每个样本被聚类至第几个簇
% Means:由簇中心向量组成的矩阵,每一行对应一个簇的中心

%% 初始参数设置
maxiter = 10000;            % 这里的maxiter为迭代算法设置了最大迭代次数,防止算法陷入死循环
iter = 0;                   % 用于表示当前算法已迭代的次数
n = size(S, 1)             % 样本数量

%% 随机初始化聚类均值
ClusterID = zeros(n,1);
rk = randperm(n);
k=rk(1:K);
Means= S(k,:);

%% 开始迭代优化
while iter<maxiter
    OldClusterID = ClusterID;
    %% 将样本分配到距离自己最近的簇中
    
    %%% ###### 需要你完成: ###### %%%
    % 1. 计算每个样本到聚类中心的距离Dist
    Dist = zeros(n,K);
    for i=1:n
        for j=1:K
            for l=1:size(S,2)
                Dist(i,j)=Dist(i,j)+(S(i,l)-Means(j,l))^2;
            end
        end
    end
    % 2. 根据每个样本到各个簇的距离,把每个样本指定到与自己最近的簇中,并生成簇结果ClusterID
     dis=size(n,1);
     [dis,ClusterID]=min(Dist,[],2);

%     Dist
%      ClusterID
%     k
%     pause(1)
% end
    %%% ######################### %%%
    %% 根据新分配的样本,重新计算簇中心
    % 按簇更新
    for i = 1:K
    
        %%% ###### 需要你完成: ###### %%%
        % 1. 首先找到属于该簇的样本
        id = zeros(n,1);
        cnt=0;
        for j=1:n
            if ClusterID(j)==i
                cnt=cnt+1;
                id(cnt)=j;
            end
        end
        % 2. 根据上一步得到的属于该簇的样本,计算这些样本的均值作为该簇的中心Means(i,:)
        Means(i,:) = zeros(size(S,2),1);
        for j=1:size(S,2)
            for l=1:cnt
                Means(i,j)=Means(i,j)+S(id(l),j);
            end
            Means(i,j)=Means(i,j)/cnt;
        end
        %%% ######################### %%%
    end
    
    %% 对每一次迭代的结果进行可视化
    if plot_flag == 1
        if iter==0
            figure
        end
    i1 = find(ClusterID==1);
    i2 = find(ClusterID==2);
    plot_cluster(S,i1,i2,Means);
    title(cat(2,'第',int2str(iter+1),'轮聚类结果'));
    set(gca,'fontsize',15)
    pause(1)
    end
    
    %% 判断迭代退出的条件
    if ClusterID == OldClusterID
        break;
    end
    iter = iter+1;
end

http://www.niftyadmin.cn/n/5035483.html

相关文章

Vue3 菜鸟入门(二)超详细:基本框架 模板语法和指令

【学习笔记】Vue3 菜鸟入门&#xff08;二&#xff09;超详细&#xff1a;基本框架 模板语法和指令 关键词&#xff1a;Vue 、Vue 3、Java、Spring Boot、Idea、数据库、一对一、培训、教学本文主要内容含Vue 基本框架 模板语法、指令计划1小时完成&#xff0c;请同学尽量提前…

Bard人工智能9月19日重大更新

1、巴德现在可以回复来自谷歌地图、航班、酒店和YouTube的实时信息&#xff0c;因此您可以在一个地方完成更多工作。 2、Bard 可能会与其他服务共享您的部分对话和其他相关信息&#xff0c;例如您的位置。这些服务可能会使用该信息进行改进&#xff0c;即使您以后删除了您的 Ba…

校园网web免认真,大量服务器

服务器加满了&#xff0c;没有几个人来&#xff0c;传点图片看实力 什么方法解web认证方式校园网&#xff1f; 一般的校园网是对学生免费开放的&#xff0c;假如你是学生输入学号密码上网就是了&#xff0c;假如你不是那就是想蹭网了&#xff0c;再假如你不想让管理员或上网行为…

sqlserver查询表中所有字段信息

精简 SELECT 字段名 a.name,主键 case when exists(SELECT 1 FROM sysobjects where xtypePK and parent_obja.id and name in (SELECT name FROM sysindexes WHERE indid in( SELECT indid FROM sysindexkeys WHERE id a.id AND colida.colid))) then √ else …

vue3 element plus获取el-cascader级联选择器选中的当前结点的label值 附vue2获取当前label

各位大佬&#xff0c;有时我们在处理级联选择组件数据时&#xff0c;不仅需要拿到id,还需要拿到label名称&#xff0c;但是通常组件直接绑定的是id,所以就需要我们用别的方法去拿到label,此处官方是有这个方法的&#xff0c;具体根据不同的element 版本进行分别处理。 VUE3 e…

Android Studio CMake 中的 aux_source_directory 有什么作用?

Android Studio CMake 中的 aux_source_directory 有什么作用&#xff1f; Author: Lycan Note: 以下问题解答通过大模型生成&#xff0c;主要用于个人学习和备忘&#xff0c;仅供参考&#xff0c;若有错误或者侵权&#xff0c;请联系我修正&#xff0c;谢谢。 问题 Android…

微服务如何改变软件开发:实战经验与最佳实践分享

文章目录 什么是微服务&#xff1f;微服务实战经验1. 定义明确的服务边界2. 使用API网关3. 自动化部署和持续集成4. 监控和日志记录 微服务最佳实践1. 文档和通信2. 弹性设计3. 安全性4. 版本控制5. 监控和警报 微服务的未来 &#x1f389;欢迎来到架构设计专栏~微服务如何改变…

Android SurfaceFlinger导读(01)MessageBase

该系列文章总纲链接&#xff1a;Android GUI系统之SurfaceFlinger 系列文章目录 说明&#xff1a; 关于导读&#xff1a;导读部分主要是方便初学者理解SurfaceFlinger代码中的机制&#xff0c;为后面分析代码打下一个更好的基础&#xff0c;这样就可以把更多的精力放在surfac…