pascalabcnet/InstallerSamples/MachineLearning/04_Models/09_ClusteringDensityVsKMeans.pas

76 lines
2.5 KiB
ObjectPascal
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Сравнение KMeans и DBSCAN на данных с шумом и разной плотностью.
//
// Оба алгоритма находят одинаковое число кластеров (k = 5),
// поэтому сравнение по ARI является корректным.
//
// KMeans предполагает компактные и одинаковые по форме кластеры,
// а также чувствителен к шуму, что снижает качество разбиения.
//
// DBSCAN выделяет кластеры как области высокой плотности
// и автоматически игнорирует шумовые точки (label = -1),
// благодаря чему лучше восстанавливает структуру данных.
//
// В результате DBSCAN показывает более высокий ARI,
// так как точнее отражает реальную геометрию кластеров.
// KMeans ARI: 0.8973
// DBSCAN ARI: 0.9496
uses MLABC, PlotML;
begin
// --- данные (сложный случай: разная плотность + шум)
var (X, yTrue) := Datasets.MakeBlobs(
n := 400,
centers := 3,
nFeatures := 2,
clusterStd := 0.9,
clusterStdVar := 1.0,
centerBox := 6.0,
classBalance := 1.0,
noisePoints := 60,
shuffle := True,
seed := 1
);
// --- модели
var kmeans := new KMeans(5);
kmeans.Fit(X);
var yKM := kmeans.Predict(X);
kmeans.ClustersCount.Println;
var db := new DBSCAN(0.7, 5);
var yDB := db.FitPredict(X);
db.ClustersCount.Println;
// --- метрики
var ariKM := Metrics.AdjustedRandIndex(yTrue, yKM);
var ariDB := Metrics.AdjustedRandIndex(yTrue, yDB);
Println('--- Clustering ---');
Println($'KMeans ARI: {ariKM,0:F4}');
Println($'DBSCAN ARI: {ariDB,0:F4}');
Println;
// --- координаты
var x1 := X.Col(0);
var x2 := X.Col(1);
// --- визуализация
var fig := Plot.Grid(1, 2);
// KMeans
//fig[0,0].SetPalette(Palettes.Bright);
fig[0,0].Points(x1, x2, yKM, size := 6);
fig[0,0].Title := $'KMeans (ARI={ariKM,0:F3})';
var yDB_plot := new integer[yDB.Length];
for var i := 0 to yDB.Length - 1 do
yDB_plot[i] := if yDB[i] = -1 then 0 else yDB[i] + 1;
// DBSCAN
//fig[0,1].SetPalette(Palettes.Bright);
fig[0,1].Points(x1, x2, yDB_plot, size := 6);
fig[0,1].Title := $'DBSCAN (ARI={ariDB,0:F3})';
end.