c++折线平移算法_【MITA周刊】第十五周:聚类算法

本文介绍了MITA数据数模部的小组展示,重点关注了K-Means聚类算法,包括算法原理、SPSS、Python和MATLAB的实现。小组成员分享了各自的研究成果,如K-Means的Python代码实现和不同聚类方法的探讨,如层次聚类和DBSCAN。文章还简要提到了Sequential Leader Clustering算法及其优缺点。
摘要由CSDN通过智能技术生成
9aada47ba9d79079c8cf52e34c0b4a16.gif

K-Means算法

9aada47ba9d79079c8cf52e34c0b4a16.gif

超级长文预告 /!!!!!/

8af10d7f-383f-eb11-8da9-e4434bdf6706.svg 76c1d1e097ef4760a003f03fda5d5416.png 95f10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg

    李华:呼呼呼,上周就是魔鬼啊!!!MITA数据数模部小组展示 + 小美赛 + 1 mol的论文,我太难了~~~~

9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg c2b4085265b6452c2c18f4b5794cd45f.png 76c1d1e097ef4760a003f03fda5d5416.png 95f10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg

    李华:现在来回顾一下上次MITA数据数模部的小组展示吧!回顾完我就去复习(我说到做到)!

9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg

当数模部群里异常安静时

当数模部长和副会长已经做好尬讲聚类的打算时

12月3日晚上20:00惊喜来得很突然

那就让我们来看看

是什么

让部长落泪

让副会长惊喜

让同学们拍手称快

PART-1 小组展示

(因篇幅有限,小组展示内容以书名概括)

小组1

芜湖起飞(没错,他们的名字就很起飞)

 日语201 夏雨奇《python文本处理初步—教你做情侣聊天词云》

物理201 彭柳桢《我好像明白K-Means》

数学202 李振兴《炫酷介绍概率基础》

小组2

第四组(没错,他们的名字就是这么简约)

    数学201

应宇杰《我的boss要求真~多——excel数据透视表》

数学201 杨翰骁《MATLAB_K-Means聚类算法实现——教你手写算法》

小组3

国家首发数模队(没错,他们的名字就是这么炫酷)

机械类2003 项扬栋《K-Means算法原理介绍及python代码实现》 

材料类2005 陈柯任《其他聚类简介——比如让人很模糊的模糊聚类》

小组4

在学了在学了(没错,他们的名字就是这么直白)

物理202 胡玉《SPSS实现K-Means聚类与系统聚类与DBSCAN聚类MATLAB实现》

小组5

菲尔兹奖评审团(没错,他们的名字就叫大佬)

    物理201 杨启航《神奇的 Sequential Leader Clustering》

    经济类206 孙骏恺《PCA降维iris数据集并用python实现K-Means聚类》

PART-2 K-Means聚类

76c1d1e097ef4760a003f03fda5d5416.png 95f10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg

    李华:K-Means真奇妙!妈妈也不用担心我的数模了。什么!?你还没听说过K-Means?那就看下面的总结吧~~~

9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg

    K-Means聚类算法是以实现类间密集度尽可能小,类内密集程度尽可能大为最有目标的一种算法模式。对数据进行初始化后,由目标所需的K值来确定所需要分的簇的个数,也就是所需中心点的个数。

8731154acaaa23faa19c5bd02994c2f4.png f8b6a2c4100ef97624bea3b1f409f572.png

PART-3 K-Means实现

76c1d1e097ef4760a003f03fda5d5416.png 95f10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg

李华:是时候展现真正的技术了~~~

9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 313cf00c26f37b02766fea4d043780f1.png

1.SPSS操作

40fd0992b92e96c9e6c5486cb33e37cf.png

2. Python的实现,感兴趣的同学,可以发挥你们的检索能力自行查找

3. MALAB代码实现

clc

clear

%% 数据部分

% K值

cluster_count = 7;

% 随机生成原始数据点坐标

data_count = 60;

data = rand(data_count, 2) * 100; 

% 或者你想要手动输入数据,可以用下面的代码

% data = [];

% data_count = size(data, 1);

%% 计算部分

c1 = zeros(cluster_count, 2); % 新的中心点

c0 = data(1:cluster_count, 1:2); % 现有的中心点

clusters = zeros(cluster_count, 0, 2);

loop_count = 0;

while 1

    loop_count = loop_count + 1;

    count = zeros(cluster_count, 1); % 每一簇中的点的数量

    all_sum = zeros(cluster_count, 2); % 每一簇的坐标总和

    for i = 1:data_count

        % 当前点

        p = data(i, :);

        % 计算到各个中心的距离

        d = zeros(cluster_count, 1);

        for j = 1:cluster_count

            d(j) = sqrt(sum((c0(j, :) - p) .^ 2));

        end

        % 寻找最近的中心点

        k = 1;

        d_min = d(1, 1);

        for j = 2:cluster_count

            if d(j) < d_min

                k = j;

                d_min = d(j);

            end

        end

        % 把点加到最近的簇中

        count(k) = count(k) + 1;

        clusters(k, count(k), :) = p;

        all_sum(k, :) = all_sum(k, :) + p;

    end

    % 计算新的中心坐标

    for i = 1:cluster_count

        c1(i, :) = all_sum(i, :) / count(i);

    end

    if c0 == c1

        break;

    else

        c0 = c1;

    end

end

%% 输出部分

% 输出到控制台

disp("迭代次数=" + loop_count);

disp("centers coordinates:");

disp(c1);

% 图像样式

cluster_colors = ["r", "g", "b", "y", "c", "k", "m"];

data_styles = cluster_colors + ".";

center_styles = cluster_colors + "x";

% 绘制数据点

for i = 1:cluster_count

    plot( ...

        clusters(i, 1:count(i), 1), ...

        clusters(i, 1:count(i), 2), ...

        data_styles(i), ...

        'MarkerSize', 15 ...

    );

    hold on

end

% 绘制中心点

for i = 1:cluster_count

    plot( ...

        c1(i, 1), ...

        c1(i, 2), ...

        center_styles(i),...

        'LineWidth', 2, ...

        'MarkerSize', 15 ...

    );

    hold on

end

hold off

% 其他设置

set(gca, 'LineWidth', 2);

title('K-means demo', 'FontSize', 12);

%代码源自网络

PART-4  小组展示中的其他方面

76c1d1e097ef4760a003f03fda5d5416.png 95f10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg

李华:你以为这就是小组学习的全部了吗?呵,too young too naive

9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 9bf10d7f-383f-eb11-8da9-e4434bdf6706.svg 5cc6002df2f998eb3848678b8b542edb.png

系统聚类(层次聚类)

算法简介

    系统聚类的合并算法,是通过计算两类数据点间的距离,对最为接近的两类数据点进行组合,并反复迭代这一过程,直到将所有数据点合成一类,并生成聚类谱系图。

    步骤一:将每个样本看作一类,计算每两个类之间的最小距离

    步骤二:将距离最小的两个类合并成一个新类

    步骤三:重新计算每两个类(包括新类)间的距离

    步骤四:重复二三步骤,直到所有类最后合并成一类

SPSS操作如下

626dd870444dfeb9cb9eaacf672e1e31.png 057847ba03017d977239a03713620907.png 3e60cadd2f05e09f582f39df3857dd1b.png e2fc12695895d2604aa5fee6b4c4004b.png

肘部法则

    系统聚类的个数可以自己从图中决定。

    当然我们也有更科学的方法:肘部法则(前文未解释清楚)(通过图形大致的估计出最优的聚类数量)先说几个重要定义:

    各个类畸变程度之和:对于一个类,它的重心到各个样本的距离平方再求和称作各个类畸变程度之和

1d0a4da12a7d247151cd6a41f567cbc2.png

    聚和系数:所有类的畸变程度之和称作聚合系数

739bab5e2f467140bae4305883da3332.png 107c0680dcae554e7142ab57220a1939.png 2c8dfa60e0ad03d6a2bbc52ba722ab75.png

上图的解释:

    根据聚合系数折线图可知,K值从1到5时,畸变程度变化最大。超过5以后,畸变程度变化显著降低。因此肘部就是K=5,故可将类别数设定为5.(当然,K=3时已经趋于平缓,所以也可以选择3)

DBSCAN聚类

亿些定义:

    核心点:在半径Eps内含有不少于MinPts数目的点

    边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内

    噪音点:既不是核心点也不是边界点的点

4789712cbd2ed19351e55e382ca43097.png

问题所在:

    在这幅图里,MinPts= 4,点A和其他红色点是核心点,因为它们的ε-邻域(图中红色 圆圈)里包含最少4 个点(包括自己),由于它们之间相互相可达,它们形成了一个聚类。点B和点C不是核心点,但它们可由A经其他核心点可达,所以也和A属于同一个聚类。点N是局外点,它既不是核心点,又不由其他点可达。

DBSCAN 算法的 MTALAB 实现及演示

function [IDX,isnoise]=DBSCAN(X,epsilon,MinPts)

    C=0;

    n=size(X,1);

    IDX=zeros(n,1);  

    D=pdist2(X,X);

    visited=false(n,1);

    isnoise=false(n,1);

    for i=1:n

        if ~visited(i)

            visited(i)=true;

            Neighbors=RegionQuery(i);

            if numel(Neighbors)

                % X(i,:) is NOISE

                isnoise(i)=true;

            else

                C=C+1;

                ExpandCluster(i,Neighbors,C);

            end

        end

    end

    function ExpandCluster(i,Neighbors,C)

        IDX(i)=C;

        k = 1;

        while true

            j = Neighbors(k);

            if ~visited(j)

                visited(j)=true;

                Neighbors2=RegionQuery(j);

                if numel(Neighbors2)>=MinPts

                    Neighbors=[Neighbors Neighbors2];   %#ok

                end

            end

            if IDX(j)==0

                IDX(j)=C;

            end

            k = k + 1;

            if k > numel(Neighbors)

                break;

            end

        end

    end

    function Neighbors=RegionQuery(i)

        Neighbors=find(D(i,:)<=epsilon);

    end

end

%代码源自网络

68fe5a7c16f2434dc5fb2adef87bc75f.png

 Sequential leader clustering

算法思想:

    “如果把k-means看成把一群人聚集到教室再进行分类的话sequential leader就是对每一个进来的同学按顺序进行分类。”这种算法先取定一个中心点,对于其他数据点,计算它与所有已有中心点的距离的最小值,如果不大于阈值,则将其归入最近的一个簇;如果大于阈值,则将其本身作为中心点形成一个簇。依次对每一个数据点进行上述操作,直至所有数据点都被归到某个簇中。

    相对于k-means算法,sequential leader只需进行一次线性计算,不需要多次迭代,时间复杂度大致为点的个数*类别数。同时,噪点由于会被单独归为一簇,不会对聚类产生过多影响。处理多维数据问题时,只需将各坐标维度化为标准分数(减去均值再除以标准差),便可以用欧氏距离公式计算。

144d563656562875dc4cd70efbfedecd.png

算法缺陷一:阈值

    但如此便捷的算法也自然有缺陷。因为簇的尺度基本为阈值所决定,所以如果一组数据点过于庞大(如尺度为阈值的数倍),则会被划分为许多簇。对于类似下图的数据分布,sequential leader的聚类方式不够合理。

3b175f89dde4b71754fcf0110754c212.png

算法缺陷二:取点顺序   

    取点的顺序一定程度上也会影响最终的聚类结果。如对于阈值1.5,对于数据点(1,1)和(2,1),考虑其与中心点(0,0)的距离。若先考虑(1,1),则(1,1)和(0,0)为一簇,(2,1)为一簇;若先考虑(2,1),则(1,1)和(2,1)为一簇,(0,0)为一簇。同样的数据点,以不同的顺序选取便被归入不同的簇中。仅仅这些可能并不足以说明问题,仍以(0,0)(1,1)(2,1)为例,若按照先考虑(1,1)的分法,最终(1,1)点归属于以(0,0)为中心点的簇。这时如果再考虑数据点(0.9,1),它会被归入(2,1)的簇中,而(1,1)却不在这个簇中,这是因为考虑(1,1)点时,(2,1)点并未作为中心点考虑在内,这样便出现了簇的交错。考虑更多点的聚类情况时,这种交错会在各簇的交界处更为明显。

Python 实现及演示(基于iris数据集)

import matplotlib.pyplot as plt

import pandas as pd

import sklearn.decomposition as dp

#读入数据集

p_data = pd.read_excel('sequential.xlsx',header = 0)

#调用pca算法,主成分数目为2,并保存在data之中

pca=dp.PCA(n_components=2)

data=pca.fit_transform(p_data)

#作图函数

def draw_data(_groups):

    #fig=plt.figure(dpi=180)

    plt.title("画图")

    for xys in _groups.values():

        xs=[xy[0] for xy in xys]

        ys=[xy[1] for xy in xys]

        plt.scatter(xs,ys)

    plt.show()

#输入阈值

threshhold=eval(input())

#遍历所有的数据

results={}

for x,y in data:

    min_distance=100000

    #遍历所有的现存簇

    for center_x,center_y in results.keys():

        distance=(x-center_x)**2+(y-center_y)**2

        if distance

            min_distance=distance

            min_x=center_x

            min_y=center_y

    if min_distance<=threshhold:

        #如果这个点和当前现存簇中心的距离比阈值小 ,那就加入这个簇,并更新簇的中心

        results[(min_x,min_y)].append([x,y])

        sum_x=0

        sum_y=0

        len_values=len(results[(min_x,min_y)])

        for x_,y_ in results[(min_x,min_y)]:

            sum_x+=x_

            sum_y+=y_

        results[(sum_x/len_values,sum_y/len_values)]=results.pop((min_x,min_y))

    else:       

        #新建一簇的条件是这个点和其他簇的距离比阈值要大 or 还没有簇

        results[(x,y)]=[[x,y]]

#输出最后的聚类情况

draw_data(results)

print("done")

%代码源自网络

总结

    数模部小组学习展示内容实在太丰富,太精彩了!!!对上述未详细介绍的问题感兴趣的同学也可以去自学哦。

    聚类算法,是数据处理的一种算法,在小组学习时,已经有同学提到了别的数据处理算法,如PCA(主成分分析法)等等。数据题是数模中最好上手的题型,数据处理也是实验或各种工作都需要的能力。

    在此,祝贺MITA数据数模部所有部员在11月的小组学习中取得优异成果,也非常感谢大家的辛苦付出,才有了本次周刊的精彩内容。

    这学期MITA周刊就到这里结束了,我们下学期再见。风里雨里,MITA等你。

说明:本文部分文字素材、图片来自网络,感谢CSDN、简书等网站的各位大牛!

90d49624ee536ba165ce8513ad963723.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值