RussianCities
Что это за датасет
Заголовок раздела «Что это за датасет»RussianCities — встроенный датасет с данными о российских городах.
Он подходит для анализа городов по числовым характеристикам: населению, площади, географическому положению и году основания. В отличие от датасетов для классификации или регрессии, здесь нет заранее заданного ответа, который нужно предсказать.
Что внутри
Заголовок раздела «Что внутри»Файл данных:
russian_cities.csvВ программе датасет доступен так:
var ds := Datasets.RussianCities;var df := ds.Data;В таблице есть признаки, описывающие город:
city— название города;region— регион;population— население;area— площадь;lat,lon— географические координаты;founded— год основания.
Почему это задача без целевой переменной
Заголовок раздела «Почему это задача без целевой переменной»В RussianCities нет столбца вроде target, class или price, который задаёт правильный ответ для обучения модели.
Это значит, что здесь не нужно предсказывать заранее известный класс или число. Вместо этого можно искать структуру в самих данных: например, группы городов, похожих по населению и плотности. Такая задача относится к кластеризации.
Реальная задача с кластеризацией
Заголовок раздела «Реальная задача с кластеризацией»Представим, что у нас есть таблица городов, но нет заранее заданных классов вроде «крупный город», «малый город» или «плотный город». Эти группы нужно обнаружить по данным.
Например, можно попробовать разделить города по двум признакам:
- численность населения;
- плотность населения.
Но исходное население городов имеет очень большой разброс: от небольших городов до миллионников. Поэтому для кластеризации удобнее использовать не само население, а его логарифм:
log_population = Ln(population)Также полезно добавить новый признак density — плотность населения:
density = population / areaПосле этого можно искать группы городов с помощью KMeans.
Пример кластеризации городов
Заголовок раздела «Пример кластеризации городов»В этом примере мы сначала создаём два новых признака.
density показывает плотность населения: сколько жителей приходится на единицу площади города. Этот признак помогает отличать компактные плотные города от более “разреженных”.
log_population — логарифм населения. Он нужен потому, что население городов отличается очень сильно: небольшие города и миллионники находятся в совершенно разных масштабах. Логарифм сглаживает этот разброс и делает сравнение городов более устойчивым.
Эти новые признаки лучше описывают задачу кластеризации, чем сырые столбцы population и area по отдельности. После этого мы масштабируем признаки и применяем KMeans с тремя кластерами.
uses MLABC;
begin var ds := Datasets.RussianCities; var df := ds.Data;
df := df.WithColumnFloat( 'density', row -> row.Float('population') / row.Float('area') );
df := df.WithColumnFloat( 'log_population', row -> Ln(row.Float('population')) );
var features := ['log_population', 'density'];
var pipe := DataPipeline.BuildClustering( features, new StandardScaler, new KMeans(3, seed := 42) );
pipe.Fit(df);
// Вычисляем номера кластеров var labels := pipe.Predict(df);
// Добавляем к DataFrame столбец с номером кластера df := df.WithColumnInt('cluster', labels);
// Группируем города по кластерам var clusters := df.GroupBy('cluster').Groups;
foreach var cluster in clusters do begin Println; Println($'Кластер {cluster.Key.Int + 1}:');
cluster.Data .SortBy('population', descending := True) .Select(['city', 'population', 'density']) .Head(5) .Print; end;end.Вывод:
Кластеризация городов с помощью DataPipeline
Используемые признаки: [log_population,density]Число найденных кластеров: 3
Кластер 1: city population density Березники 139.20 0.32Новый Уренгой 118.00 0.52 Новошахтинск 106.60 0.78 Северск 106.50 0.22 Артем 105.70 0.86
Кластер 2: city population density Москва 12655.10 4.94Санкт-Петербург 5384.30 3.74 Новосибирск 1625.60 3.23 Екатеринбург 1493.70 1.34 Казань 1257.40 2.13
Кластер 3: city population densityБалашиха 507.40 7.52Подольск 308.10 7.63 Мытищи 235.50 6.81 Королев 225.90 6.28 Люберцы 205.30 15.95Как понимать результат
Заголовок раздела «Как понимать результат»KMeans(3) не знает заранее, какие группы городов нужно найти. Он просто делит объекты на три кластера так, чтобы города внутри одного кластера были похожи по выбранным признакам.
После кластеризации нужно посмотреть на сами кластеры и дать им содержательную интерпретацию. В таком учебном варианте обычно получаются группы вроде:
- крупные города;
- компактные города с высокой плотностью;
- малые и средние города.
Номера кластеров 0, 1, 2 сами по себе ничего не означают. Это просто номера найденных групп. Смысл кластеров появляется только после анализа: сколько в них городов, какое среднее население, какая плотность и какие города попали в каждую группу.
Почему используется StandardScaler
Заголовок раздела «Почему используется StandardScaler»KMeans сравнивает объекты по расстоянию. Если один признак имеет большие численные значения, он может начать слишком сильно влиять на результат.
Поэтому перед KMeans признаки обычно масштабируют. В примере это делает StandardScaler внутри конвейера:
new StandardScalerКонвейер сначала масштабирует признаки, а затем передаёт подготовленные числовые данные в модель кластеризации.