Engee 文档
Notebook

聚类化

聚类(或聚类分析)是将一组对象划分为称为聚类的组的任务。 每个组内部应该有"相似"的对象,来自不同组的对象应该尽可能不同。 聚类和分类之间的主要区别在于组列表没有指定,并且在算法的操作过程中确定。

本示例将演示如何使用K均值方法和模糊聚类方法(C均值)执行聚类。

连接必要的库:

In [ ]:
Pkg.add(["RDatasets", "Clustering"])
In [ ]:
using Plots
using Clustering 

上传数据集以进行聚类分析:

In [ ]:
using RDatasets
iris = dataset("datasets", "iris");

从一个数据集到一个单独的变量中确定观察对象的特征:

In [ ]:
iris_species = iris[:,5];

源数据在三维图形上的可视化:

In [ ]:
plotlyjs()
setosaIndex = findall(x->x=="setosa", iris_species)
versicolorIndex = findall(x->x=="versicolor", iris_species)
virginicaIndex = findall(x->x=="virginica", iris_species)
scatter(Matrix(iris[setosaIndex, [:SepalLength]]), Matrix(iris[setosaIndex, [:SepalWidth]]), Matrix(iris[setosaIndex, [:PetalLength]]), color="red")
scatter!(Matrix(iris[versicolorIndex, [:SepalLength]]), Matrix(iris[versicolorIndex, [:SepalWidth]]), Matrix(iris[versicolorIndex, [:PetalLength]]), color="blue")
scatter!(Matrix(iris[virginicaIndex, [:SepalLength]]), Matrix(iris[virginicaIndex, [:SepalWidth]]), Matrix(iris[virginicaIndex, [:PetalLength]]), color="green")
Out[0]:

转换为二维图,用于聚类结果与初始数据的进一步比较:

In [ ]:
gr()
s1 = scatter(Matrix(iris[setosaIndex, [:SepalLength]]), Matrix(iris[setosaIndex, [:SepalWidth]]), color="red", markersize = 5, label="setosa")
s2 = scatter!(Matrix(iris[versicolorIndex, [:SepalLength]]), Matrix(iris[versicolorIndex, [:SepalWidth]]), color="blue", markersize = 5, label="versicolor")
s3 = scatter!(Matrix(iris[virginicaIndex, [:SepalLength]]), Matrix(iris[virginicaIndex, [:SepalWidth]]), color="green", markersize = 5, label="virginica")
p1 = plot(s3)
Out[0]:

以可接受的格式准备数据,以便通过聚类方法进行处理:

In [ ]:
features = collect(Matrix(iris[:, 1:4])')
Out[0]:
4×150 Matrix{Float64}:
 5.1  4.9  4.7  4.6  5.0  5.4  4.6  5.0  …  6.8  6.7  6.7  6.3  6.5  6.2  5.9
 3.5  3.0  3.2  3.1  3.6  3.9  3.4  3.4     3.2  3.3  3.0  2.5  3.0  3.4  3.0
 1.4  1.4  1.3  1.5  1.4  1.7  1.4  1.5     5.9  5.7  5.2  5.0  5.2  5.4  5.1
 0.2  0.2  0.2  0.2  0.2  0.4  0.3  0.2     2.3  2.5  2.3  1.9  2.0  2.3  1.8

K-means方法

最流行的聚类方法之一是K-means方法。 该方法的主要思想是两个步骤的迭代重复。:

  1. 按群集分布样本对象;
  2. 集群中心的重新计算。

将聚类方法应用于源数据:

In [ ]:
result_kmeans = kmeans(features, 3); #метод kmeans() принимает как аргументы набор данных и количество кластеров

使用点图可视化解决方案:

In [ ]:
plotlyjs()
p2 = scatter(iris.SepalLength, iris.SepalWidth, 
        marker_z = result_kmeans.assignments, 
        color =:red, legend = false, markersize = 5)
Out[0]:

包含结果的变量(result_kmeans)中的assignments参数包含一列,其中为每个观测值分配了群集编号。 图形上点的颜色对应于特定聚类的数量。

K-means算法结果与初始数据的比较:

In [ ]:
plot(p1, p2)
Out[0]:

这些图表显示了算法的令人满意的结果,观察结果被分成足够接近原始数据的簇。

模糊优化方法

模糊聚类方法可以被认为是改进的k-means方法,其中对于来自所考虑的集合的每个元素,计算其属于每个聚类的程度。

将聚类方法应用于源数据:

In [ ]:
result_fuzzy = fuzzy_cmeans(features, 3, 2, maxiter=2000, display=:iter)
  Iters      center-change
----------------------------
      1       7.771477e+00
      2       4.739898e-01
      3       1.200676e+00
      4       6.755399e-01
      5       3.645266e-01
      6       2.000300e-01
      7       8.829159e-02
      8       4.021639e-02
      9       2.069955e-02
     10       1.182799e-02
     11       7.198234e-03
     12       4.523367e-03
     13       2.885398e-03
     14       1.852891e-03
     15       1.193257e-03
     16       7.693420e-04
Fuzzy C-means converged with 16 iterations (δ = 0.0007693420314963082)
Out[0]:
FuzzyCMeansResult: 3 clusters for 150 points in 4 dimensions (converged in 16 iterations)

基于观测对象的四个特征计算三个聚类的中心:

In [ ]:
M = result_fuzzy.centers
Out[0]:
4×3 Matrix{Float64}:
 5.00396   5.88825  6.77419
 3.41412   2.76082  3.05214
 1.48276   4.36295  5.64575
 0.253522  1.3968   2.05315

计算观测对象的权重(属于特定集群的程度):

In [ ]:
memberships = result_fuzzy.weights
Out[0]:
150×3 Matrix{Float64}:
 0.996624    0.00230446   0.00107189
 0.975835    0.016663     0.00750243
 0.979814    0.0137683    0.00641748
 0.967404    0.0224829    0.0101134
 0.99447     0.0037622    0.00176788
 0.934536    0.0448343    0.0206299
 0.97948     0.0140129    0.00650756
 0.999547    0.000311776  0.000141288
 0.930335    0.0477519    0.0219135
 0.982709    0.0119456    0.00534496
 0.968026    0.0217691    0.0102053
 0.99213     0.00543676   0.0024328
 0.97062     0.020198     0.00918222
 ⋮                        
 0.0217694   0.748803     0.229428
 0.00347922  0.0288342    0.967687
 0.00507985  0.0376451    0.957275
 0.0153794   0.129099     0.855522
 0.0293134   0.614578     0.356108
 0.00527622  0.0338633    0.96086
 0.00971574  0.0631961    0.927088
 0.0112318   0.105921     0.882848
 0.0257965   0.506297     0.467907
 0.0120658   0.155488     0.832446
 0.0215546   0.188514     0.789932
 0.0269334   0.580575     0.392492

从0到1的数字表示与群集中心的接近程度,其中1是最大隶属关系(位于中心),0是与中心的最大距离。

模糊逻辑方法结果的可视化:

In [ ]:
p3 = scatter(iris.SepalLength, iris.SepalWidth, 
        marker_z = memberships[:,1], 
        legend = true, markersize = 5)

p4 = scatter(iris.SepalLength, iris.SepalWidth, 
        marker_z = memberships[:,3], 
        legend = false, markersize = 5)

p5 = scatter(iris.SepalLength, iris.SepalWidth, 
        marker_z = memberships[:,2], 
        legend = false, markersize = 5)

plot(p3, p4, p5, p1, legend = false)
Out[0]:

前三个图显示了模糊逻辑方法的结果,其中色标显示了属于特定聚类的程度。

最后一个图表显示了初始(可靠)数据。

通过首先将鼠标光标悬停在具有初始数据的图形上,然后在具有使用该方法获得的点的图形上,可以比较结果并直观地评估该方法的准确性。

结论:

在这个例子中,考虑了两种最常用的聚类方法。 用于实现这些方法的函数是从聚类库中调用的。jl,它还提供了许多其他更先进的方法。

在应用过程中得到的结果很好,但并不理想,需要更多的数据来提高算法的质量。