pascalabcnet/InstallerSamples/MachineLearning/01_GettingStarted/03_FirstClustering_DataFrame.pas

85 lines
3.5 KiB
ObjectPascal
Raw Normal View History

// Первый пример кластеризации.
//
// В этом примере:
// 1) загружаем готовый датасет городов России;
// 2) выбираем признаки для кластеризации;
// 3) обучаем алгоритм KMeans;
// 4) получаем номер кластера для каждого города;
// 5) выводим несколько представителей каждого кластера.
//
// Важно:
// здесь кластеры отражают прежде всего географическую близость городов,
// потому что для кластеризации используются только широта и долгота.
// Население нужно только для выбора самых заметных представителей кластера.
//
// При числе кластеров k = 4 результат можно интерпретировать так:
// • один кластер обычно соответствует Европейской части России;
// • один - Уралу, Поволжью и соседним территориям;
// • один - Сибири;
// • один - Дальнему Востоку и северо-востоку.
uses MLABC;
begin
// Загружаем учебный датасет с городами России
var ds := Datasets.RussianCities;
// Берём таблицу данных из датасета
var df := ds.Data;
// Для первого примера используем только координаты города
var features := ['lat', 'lon'];
// Преобразуем выбранные признаки в числовую матрицу
var X := df.ToMatrix(features);
// Создаём модель KMeans и просим разбить города на 4 группы.
// Для первого примера этого достаточно, чтобы увидеть общую структуру данных.
var model := new KMeans(4, seed := 42);
// Обучаем модель на всех объектах
model.Fit(X);
// Получаем номер кластера для каждого города
var labels := model.PredictLabels(X);
// Получаем названия городов
var cities := df.GetStrColumn('city');
// Получаем численность населения городов
var populations := df.GetFloatColumn('population');
// Выводим, сколько кластеров нашёл алгоритм
Println($'Число кластеров: {model.ClustersCount}');
Println;
Println('Примеры городов в каждом кластере (в скобках - тыс. жителей):');
// Для каждого кластера выводим три самых крупных города
for var cluster := 0 to model.ClustersCount - 1 do
begin
Println;
Println($'Кластер {cluster + 1}:');
var clusterIndices := new List<integer>;
for var i := 0 to labels.Length - 1 do
if labels[i] = cluster then
clusterIndices.Add(i);
clusterIndices := clusterIndices
.OrderByDescending(i -> populations[i])
.ToList;
var shown := 0;
foreach var i in clusterIndices do
begin
Println($' {cities[i]} ({populations[i]:F0})');
shown += 1;
if shown = 4 then
break;
end;
end;
end.