Кластеризация
Кластеризация (или кластерный анализ) — это задача разбиения множества объектов на группы, называемые кластерами. Внутри каждой группы должны оказаться «похожие» объекты, а объекты разных групп должны быть как можно более отличны. Главное отличие кластеризации от классификации состоит в том, что перечень групп не задан и определяется в процессе работы алгоритма.
В этом примере будет показано, как выполнить кластеризацию с использованием метода K-средних (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-средних
Один из наиболее популярных методов кластеризации — это метод K-средних (K-means). Основная идея метода — итеративное повторение двух шагов:
- Распределение объектов выборки по кластерам;
- Пересчёт центров кластеров.
Применение метода кластеризации к исходным данным:
result_kmeans = kmeans(features, 3); #метод kmeans() принимает как аргументы набор данных и количество кластеров
Визуализация решения с помощью точечного графика:
plotlyjs()
p2 = scatter(iris.SepalLength, iris.SepalWidth,
marker_z = result_kmeans.assignments,
color =:red, legend = false, markersize = 5)
Параметр assignments в переменной, содержащей результаты (result_kmeans), содержит столбец с номерами кластеров, присвоенных каждому наблюдению. Цвет точки на графике соответствует номеру конкретного кластера.
Сравнение результатов работы алгоритма K-средних с исходными данными:
plot(p1, p2)
Графики показывают удовлетворительный результат работы алгоритма, наблюдения разбиты по кластерам, которые достаточно близки с исходным данным.
Метод нечёткой оптимизации
Метод нечеткой кластеризации можно рассматривать как усовершенствованный метод k-средних, при котором для каждого элемента из рассматриваемого множества рассчитывается степень его принадлежности каждому из кластеров.
Применение метода кластеризации к исходным данным:
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, которая также предоставляет множество других, более продвинутых методов.
Результаты, полученные в ходе их применения, хороши, но не идеальны, для улучшения качества работы алгоритмов требуется больше данных.