Документация Engee

Кластеризация

Кластеризация (или кластерный анализ) — это задача разбиения множества объектов на группы, называемые кластерами. Внутри каждой группы должны оказаться «похожие» объекты, а объекты разных групп должны быть как можно более отличны. Главное отличие кластеризации от классификации состоит в том, что перечень групп не задан и определяется в процессе работы алгоритма.

В этом примере будет показано, как выполнить кластеризацию с использованием метода K-средних (K-means) и метода нечёткой кластеризации (C-means).

Подключение необходимых библиотек:

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")

interactive-scripts/images/data_analysis_clustering_algorithms/839d935928c65ab91438af696fa9b1308fbd6877

Преобразование в двухмерный график для дальнейшего сравнения результатов работы кластеризации с исходными данными:

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)

interactive-scripts/images/data_analysis_clustering_algorithms/9cb12370fc6355eb3f2556e7f1f745be0062cbf6

Подготовка данных в формат, приемлимый для обработки методами кластеризации:

features = collect(Matrix(iris[:, 1:4])')
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-средних

Один из наиболее популярных методов кластеризации — это метод K-средних (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)

interactive-scripts/images/data_analysis_clustering_algorithms/4f782f7a22e06d9271c375f4a9e925675c2254f2

Параметр assignments в переменной, содержащей результаты (result_kmeans), содержит столбец с номерами кластеров, присвоенных каждому наблюдению. Цвет точки на графике соответствует номеру конкретного кластера.

Сравнение результатов работы алгоритма K-средних с исходными данными:

plot(p1, p2)

interactive-scripts/images/data_analysis_clustering_algorithms/cb91f30c04532edbb9ae5833643b7cc44c4e47ef

Графики показывают удовлетворительный результат работы алгоритма, наблюдения разбиты по кластерам, которые достаточно близки с исходным данным.

Метод нечёткой оптимизации

Метод нечеткой кластеризации можно рассматривать как усовершенствованный метод k-средних, при котором для каждого элемента из рассматриваемого множества рассчитывается степень его принадлежности каждому из кластеров.

Применение метода кластеризации к исходным данным:

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)
FuzzyCMeansResult: 3 clusters for 150 points in 4 dimensions (converged in 16 iterations)

Расчёт центров трёх кластеров по четырём признакам объектов наблюдений:

M = result_fuzzy.centers
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

Расчёт весов (степеней принадлежности к конкретному кластеру) объектов наблюдений:

memberships = result_fuzzy.weights
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 - максимальное удаление от центра.

Визуализация результатов работы метода нечёткой логики:

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)

interactive-scripts/images/data_analysis_clustering_algorithms/f9ecaf2411e18a8edf3ae9c8f930da04dcbce20c

На первых трёх графиках представлены результаты работы метода нечёткой логики, где цветовая шкала показывает степень принадлежности к конкретному кластеру.

На последнем графике - исходные (достоверные) данные.

Наведя курсор мыши сначала на график с исходными данными, а затем на графики с полученными, с помощью метода, точками, можно сопоставить результаты и визуально оценить точность работы метода.

Вывод

В данном примере были рассмотрены два самых часто применяемых метода кластеризации. Функции, с помощью которых реализовывались эти методы, были вызваны из библиотеки Clustering.jl, которая также предоставляет множество других, более продвинутых методов.

Результаты, полученные в ходе их применения, хороши, но не идеальны, для улучшения качества работы алгоритмов требуется больше данных.