首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在MATLAB中利用函数kmeans对K-均值进行聚类

在MATLAB中利用函数kmeans对K-均值进行聚类
EN

Stack Overflow用户
提问于 2014-11-30 03:48:59
回答 1查看 5.1K关注 0票数 1

我有一个矩阵:

代码语言:javascript
运行
复制
x = [2+2*i 2-2*i -2+2*i -2-2*i];

我想模拟它的传输和添加噪音到它。我代表复数的组成部分如下:

代码语言:javascript
运行
复制
A = randn(150, 2) + 2*ones(150, 2); C = randn(150, 2) - 2*ones(150, 2);

在接收端,我收到以下向量,其中组件是根据我最初发送的内容(即x的组件)排序的。

代码语言:javascript
运行
复制
X = [A A A C C A C C];

现在我想应用kmeans(X)来拥有四个集群,所以kmeans(X, 4)。我遇到了以下问题:

  1. 我不确定是否可以表示上面X中所示的复数。
  2. 我无法绘制kmeans的结果来显示集群。
  3. 我无法理解星系团的质心结果。
  4. 如果这个例子表示一个通信系统,并且在接收端使用-means聚类来决定发送的信号是什么,我如何才能找到最佳的错误率?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-11-30 05:58:51

如果您不“理解”集群的质心结果,那么您就不了解k-means是如何工作的。我将在这里作一个小摘要。

K-的工作原理是,对于某些数据,您希望将它们分组为k组。您最初在数据中选择k个随机点,这些点将具有来自1,2,...,k的标签。这就是我们所称的质心。然后,确定其余数据与这些点中的每一点有多近。然后对这些点进行分组,以便无论哪一个点最接近这些k点,都可以将这些点分配给属于该特定组(1,2,...,k)的点。然后,对于每个组的所有点,更新质心,它实际上被定义为每个组的代表点。对于每个组,计算每个k组中所有点的平均值。它们成为下一次迭代的新的质心。在下一次迭代中,确定数据中的每个点与每个质心的距离有多近。你不断地重复这个行为,直到质心不再移动,或者它们很少移动。

现在,让我们逐一回答你的问题。

1.复数表示

MATLAB中的k-means并没有定义如何处理复杂的数据。人们处理复杂编号数据的一个常见方法是将真实和想象的部分分割成不同的维度,就像你所做的那样。这是对复杂值数据使用k-means的一种非常有效的方法。

有关详细信息,请参阅MathWorks MATLAB论坛上的这篇文章:螺纹/78306

2.绘制结果

您没有正确地构造矩阵X。注意,AC都是150个x2矩阵。您需要构造X,使每个都是一个点,而每个列都是一个变量。因此,您需要连接您的AC 逐行。因此:

代码语言:javascript
运行
复制
X = [A; A; A; C; C; A; C; C];

注意,您有重复点。实际上,就X = [A; C];而言,这与执行kmeans并没有什么不同。也许您应该生成X,然后添加噪声,而不是使用AC,添加噪声,然后构造信号。

现在,如果您想要绘制结果以及质心,您需要做的是使用2输出版本的kmeans,如下所示:

代码语言:javascript
运行
复制
[idx, centroids] = kmeans(X, 4);

idx将包含X中每个点所属的集群号,centroids将是一个4x2矩阵,其中每行将告诉您数据中每个集群的平均值。如果您想要绘制数据以及集群,只需执行以下操作。我将循环遍历每个集群成员,并在一个图形上绘制结果。我还将在每个星系团的平均值所在的地方涂上颜色:

代码语言:javascript
运行
复制
x = X(:,1);
y = X(:,2);
figure;
hold on;
colors = 'rgbk';
for num = 1 : 4
    plot(x(idx == num), y(idx == num), [colors(num) '.']);
end

plot(centroids(:,1), centroids(:,2), 'c.', 'MarkerSize', 14);
grid;

上面的代码贯穿每个集群,以不同的颜色绘制它们,然后用稍微大一点的厚度用青色绘制质心,这样你就可以看到图的样子了。

我得到的是:

3.了解质心结果

这可能是因为您没有正确地构造X。这就是我得到的我的质心:

代码语言:javascript
运行
复制
centroids =

   -1.9176   -2.0759
    1.5980    2.8071
    2.7486    1.6147
    0.8202    0.8025

这是相当不言自明的,我在前面谈到了它的结构。

4.信号的最佳表示

您可以做的是多次重复聚类,然后算法将决定这些时间中最好的聚类是什么。您只需使用Replicates标志,并指示要运行多少次。显然,运行这个程序的次数越多,您的结果就越好。因此,做以下事情:

代码语言:javascript
运行
复制
[idx, centroids] = kmeans(X, 4, 'Replicates', 5);

这将运行kmeans 5次,并给您最好的质心这5次。

现在,如果要确定所传输的最佳序列是什么,则必须将X分成150个行(因为随机序列是150个元素),然后在每个子集上运行一个单独的kmeans。您可以尝试通过每次使用Replicates标志来找到序列的每个部分的最佳表示形式。所以你可以做这样的事情:

代码语言:javascript
运行
复制
for num = 1 : 8
    %// Look at 150 points at a time
    [idx, centroids] = kmeans(X((num-1)*150 + 1 : num*150, :), 4, 'Replicates', 5);

    %// Do your analysis
    %//...
    %//...
end

idxcentroids将是发送信号的每个部分的结果。您可能希望在每次迭代时查看centroids,以确定哪个符号在特定时间被传输。

如果您想要绘制决策区域,那么您可能正在寻找一个Voronoi图。您所做的就是给出一组在问题域中定义的点,您只需确定每个点属于哪个集群即可。考虑到我们的数据跨在-5 <= (x,y) <= 5之间,让我们遍历网格中的每个点并确定每个点属于哪个集群。然后,我们给它所属的星系团涂上适当的颜色。

类似于:

代码语言:javascript
运行
复制
colors = 'rgbk';
[X,Y] = meshgrid(-5:0.05:5, -5:0.05:5);
X = X(:);
Y = Y(:);
figure;
hold on;
for idx = 1 : numel(X)
    [~,ind] = min(sum(bsxfun(@minus, [X(idx) Y(idx)], centroids).^2, 2));
    plot(X(idx), Y(idx), [colors(ind), '.']);
end
plot(centroids(:,1), centroids(:,2), 'c.', 'MarkerSize', 14);

上面的代码将绘制特定配置的决策区域/ Voronoi图,以及集群中心所在的位置。请注意,代码没有经过优化,生成图需要一段时间,但我想快速编写一些东西来说明我的观点。

以下是决策区域的样子:

希望这能有所帮助!祝好运!

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27209796

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档