K-Means算法
超级长文预告 /!!!!!/
李华:呼呼呼,上周就是魔鬼啊!!!MITA数据数模部小组展示 + 小美赛 + 1 mol的论文,我太难了~~~~
李华:现在来回顾一下上次MITA数据数模部的小组展示吧!回顾完我就去复习(我说到做到)!
当数模部群里异常安静时
当数模部长和副会长已经做好尬讲聚类的打算时
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聚类
李华:K-Means真奇妙!妈妈也不用担心我的数模了。什么!?你还没听说过K-Means?那就看下面的总结吧~~~
K-Means聚类算法是以实现类间密集度尽可能小,类内密集程度尽可能大为最有目标的一种算法模式。对数据进行初始化后,由目标所需的K值来确定所需要分的簇的个数,也就是所需中心点的个数。
PART-3 K-Means实现
李华:是时候展现真正的技术了~~~
1.SPSS操作
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 小组展示中的其他方面
李华:你以为这就是小组学习的全部了吗?呵,too young too naive
系统聚类(层次聚类)
算法简介
系统聚类的合并算法,是通过计算两类数据点间的距离,对最为接近的两类数据点进行组合,并反复迭代这一过程,直到将所有数据点合成一类,并生成聚类谱系图。
步骤一:将每个样本看作一类,计算每两个类之间的最小距离
步骤二:将距离最小的两个类合并成一个新类
步骤三:重新计算每两个类(包括新类)间的距离
步骤四:重复二三步骤,直到所有类最后合并成一类
SPSS操作如下
肘部法则
系统聚类的个数可以自己从图中决定。
当然我们也有更科学的方法:肘部法则(前文未解释清楚)(通过图形大致的估计出最优的聚类数量)先说几个重要定义:
各个类畸变程度之和:对于一个类,它的重心到各个样本的距离平方再求和称作各个类畸变程度之和
聚和系数:所有类的畸变程度之和称作聚合系数
上图的解释:
根据聚合系数折线图可知,K值从1到5时,畸变程度变化最大。超过5以后,畸变程度变化显著降低。因此肘部就是K=5,故可将类别数设定为5.(当然,K=3时已经趋于平缓,所以也可以选择3)
DBSCAN聚类
亿些定义:
核心点:在半径Eps内含有不少于MinPts数目的点
边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内
噪音点:既不是核心点也不是边界点的点
问题所在:
在这幅图里,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
%代码源自网络
Sequential leader clustering
算法思想:
“如果把k-means看成把一群人聚集到教室再进行分类的话sequential leader就是对每一个进来的同学按顺序进行分类。”这种算法先取定一个中心点,对于其他数据点,计算它与所有已有中心点的距离的最小值,如果不大于阈值,则将其归入最近的一个簇;如果大于阈值,则将其本身作为中心点形成一个簇。依次对每一个数据点进行上述操作,直至所有数据点都被归到某个簇中。
相对于k-means算法,sequential leader只需进行一次线性计算,不需要多次迭代,时间复杂度大致为点的个数*类别数。同时,噪点由于会被单独归为一簇,不会对聚类产生过多影响。处理多维数据问题时,只需将各坐标维度化为标准分数(减去均值再除以标准差),便可以用欧氏距离公式计算。
算法缺陷一:阈值
但如此便捷的算法也自然有缺陷。因为簇的尺度基本为阈值所决定,所以如果一组数据点过于庞大(如尺度为阈值的数倍),则会被划分为许多簇。对于类似下图的数据分布,sequential leader的聚类方式不够合理。
算法缺陷二:取点顺序
取点的顺序一定程度上也会影响最终的聚类结果。如对于阈值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、简书等网站的各位大牛!