聚类
聚类(或聚类分析)是将一组对象划分为称为 "群组 "的组。在每个群组中都应该有 "相似 "的对象,而不同群组中的对象应该尽可能不同。聚类与分类的主要区别在于,组的列表没有指定,而是在算法过程中确定的。
本示例将展示如何使用 K-means 方法(K-means)和模糊聚类方法(C-means)进行聚类。
连接必要的库:
Pkg.add(["RDatasets", "Clustering"])
using Plots
using Clustering
为聚类分析加载数据集
using RDatasets
iris = dataset("datasets", "iris");
将数据集中观察对象的属性定义为一个单独的变量:
iris_species = iris[:,5];
在三维图形上可视化原始数据:
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")
转换为二维图形,以便进一步比较聚类结果和原始数据:
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)
将数据转换成可接受的格式,以便用聚类方法进行处理:
features = collect(Matrix(iris[:, 1:4])')
K-means 方法
最流行的聚类方法之一是 K-means 法(K-means)。该方法的基本思想是迭代重复两个步骤:
1.将样本对象分配到聚类中;
2.重新计算聚类中心。
将聚类方法应用于原始数据:
result_kmeans = kmeans(features, 3); #метод kmeans() принимает как аргументы набор данных и количество кластеров
使用点阵图直观显示解决方案:
plotlyjs()
p2 = scatter(iris.SepalLength, iris.SepalWidth,
marker_z = result_kmeans.assignments,
color =:red, legend = false, markersize = 5)
包含结果的变量(result_kmeans)中的赋值参数包含一列为每个观测值分配的聚类数。点阵图的颜色与特定聚类的数量相对应。
K-means 算法结果与原始数据的比较:
plot(p1, p2)
从图中可以看出,该算法的结果令人满意,观测值被聚类在与原始数据非常接近的聚类中。
模糊优化法
模糊聚类法可以看作是一种改进的 k-means 方法,其中对所考虑的集合中的每个元素都计算了其属于每个聚类的程度。
将聚类方法应用于原始数据:
result_fuzzy = fuzzy_cmeans(features, 3, 2, maxiter=2000, display=:iter)
根据观察对象的四个属性计算三个聚类的中心点:
M = result_fuzzy.centers
计算观察对象的权重(属于某个群组的程度):
memberships = result_fuzzy.weights
从 0 到 1 的数字表示与聚类中心的距离,其中 1 表示最大归属度(位于中心),0 表示与中心的最大距离。
模糊逻辑方法结果的可视化:
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)
前三幅图显示了模糊逻辑法的结果,其中色标显示了属于某个群组的程度。
最后一张图显示的是初始(可靠)数据。
将鼠标光标首先指向原始数据图,然后指向使用该方法得到的点图,就可以比较结果,直观地评估该方法的准确性。
结论
在本例中,我们研究了两种最常用的聚类方法。用于实现这些方法的函数是从 Clustering.jl 库中调用的,该库还提供了许多其他更高级的方法。
应用这些方法得到的结果很好,但并不完美,需要更多的数据来提高算法的质量。