Евклидово расстояние — это длина прямого отрезка между двумя точками в пространстве, вычисленная по теореме Пифагора. В кластеризации оно служит мерой различия объектов: чем меньше расстояние, тем объекты ближе и вероятнее попадут в один кластер. Важно сразу развести три вещи, которые часто путают: само расстояние (мера различия), сходство (обратная величина, растет при сближении) и квадрат расстояния (та же метрика без извлечения корня, ее использует k-means). Ниже — формула для 2D и n-мерного пространства, роль в k-means, сравнение с манхэттенским и косинусным расстоянием и разбор того, почему без нормализации признаков метрика врет.
Содержание
Формула: 2D и n-мерное пространство
На плоскости расстояние между точками a = (x1, y1) и b = (x2, y2) равно корню из суммы квадратов разностей координат: d = sqrt((x1 — x2)^2 + (y1 — y2)^2). Это прямое следствие теоремы Пифагора — разности координат образуют катеты, расстояние — гипотенузу.
В n-мерном пространстве формула обобщается на любое число признаков: d = sqrt(sum((p_i — q_i)^2)) по всем координатам i от 1 до n. Каждый признак объекта (возраст, доход, число покупок) — это одна координата. Геометрическая интуиция та же, просто измерений больше двух, и нарисовать их нельзя.
Считать вручную не нужно — в Python есть numpy.linalg.norm и scipy.spatial.distance.euclidean, оба дают тот же результат:
import numpy as np
from scipy.spatial import distance
a = np.array([1.0, 2.0])
b = np.array([4.0, 6.0])
# вручную по формуле: sqrt(3^2 + 4^2) = 5
d = ((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2) ** 0.5
print(d) # 5.0
print(np.linalg.norm(a - b)) # 5.0
print(distance.euclidean(a, b)) # 5.0
# n-мерное пространство: 4 координаты
p = np.array([1.0, 2.0, 3.0, 4.0])
q = np.array([2.0, 0.0, 5.0, 4.0])
print(np.linalg.norm(p - q)) # 3.0 = sqrt(1 + 4 + 4 + 0)
Роль в k-means
k-means — самый распространенный алгоритм разбиения на кластеры — завязан именно на евклидову метрику, а точнее на ее квадрат. Алгоритм ищет такие центры кластеров (центроиды), при которых минимальна сумма квадратов евклидовых расстояний от каждой точки до центра ее кластера. Эту сумму в scikit-learn называют инерцией (inertia).
Работает он итеративно: назначает каждую точку ближайшему по евклидову расстоянию центроиду, затем пересчитывает центроид как среднее точек кластера, и повторяет до стабилизации. Именно среднее (а не медиана) минимизирует сумму квадратов евклидовых расстояний — поэтому связка «квадрат евклида + среднее» внутренне согласована.
Это же и граница применимости: k-means корректно работает с евклидовой метрикой и не рассчитан на произвольную. Для манхэттенского расстояния используют k-medoids (PAM), где центр кластера — реальный объект, а не среднее. Пример на нормализованных данных (о нормализации — ниже):
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
rng = np.random.default_rng(42)
c1 = rng.normal([20, 30000], [2, 3000], size=(20, 2)) # моложе, доход ниже
c2 = rng.normal([40, 90000], [2, 3000], size=(20, 2)) # старше, доход выше
data = np.vstack([c1, c2])
data_z = StandardScaler().fit_transform(data) # нормализуем ДО кластеризации
km = KMeans(n_clusters=2, n_init=10, random_state=42).fit(data_z)
print(np.bincount(km.labels_)) # [20 20] - две группы по 20 точек
print(round(km.inertia_, 4)) # 1.2633 - сумма квадратов расстояний до центров
Евклидово, манхэттенское, косинусное: когда какое
Евклидово — не единственная метрика. Выбор зависит от природы данных, а не от привычки. Манхэттенское (city block) — сумма модулей разностей координат; оно не возводит разности в квадрат, поэтому слабее реагирует на выбросы по отдельной координате и часто устойчивее в пространствах высокой размерности. Косинусное — это 1 минус косинус угла между векторами; оно измеряет различие в направлении и игнорирует длину векторов, поэтому его берут для текстов (мешок слов, TF-IDF, эмбеддинги), где важна тема, а не общий объем.
| Метрика | Что измеряет | Чувствительность к масштабу длины | Когда брать |
|---|---|---|---|
| Евклидово | Прямое геометрическое расстояние | Высокая, реагирует на выбросы | Плотные числовые признаки соизмеримого масштаба; k-means |
| Манхэттенское | Сумма модулей разностей | Умеренная, устойчивее к выбросам | Много признаков, разреженные или зашумленные данные; k-medoids |
| Косинусное | Угол (направление) между векторами | Игнорирует длину вектора | Тексты, эмбеддинги, высокая размерность, важна тема |
Разницу видно на простом примере. Векторы u = (2, 0) и w = (4, 0) смотрят в одну сторону, но разной длины — евклидово расстояние это заметит, косинусное обнулится:
from scipy.spatial import distance
import numpy as np
u = np.array([2.0, 0.0])
v = np.array([0.0, 2.0])
w = np.array([4.0, 0.0])
# u и v: разные направления, одинаковая длина
print(distance.euclidean(u, v)) # 2.8284
print(distance.cityblock(u, v)) # 4.0
print(distance.cosine(u, v)) # 1.0 (угол 90 градусов)
# u и w: одно направление, разная длина
print(distance.euclidean(u, w)) # 2.0
print(distance.cosine(u, w)) # 0.0 (угол 0 градусов)
Отдельно стоит квадрат евклидова расстояния — та же метрика без корня. Он не меняет порядок близости (ближайшая точка остается ближайшей), но экономит вычисление корня и сильнее разводит далекие пары; k-means оперирует именно им.
Влияние масштаба признаков и нормализация
Главная практическая ловушка евклидова расстояния: оно складывает квадраты разностей по всем координатам как есть, поэтому признак с большим числовым диапазоном подавляет остальные. Возраст меняется в пределах десятков, доход — десятков тысяч; в сумме квадратов доход перевесит возраст целиком.
Возьмем трех человек: разница по доходу дает расстояние в тысячи, а 20 лет разницы в возрасте почти не видны:
import numpy as np
from scipy.spatial import distance
# признаки: возраст (лет) и доход (руб/мес)
X = np.array([
[25, 40000],
[26, 90000],
[45, 41000],
], dtype=float)
print(distance.euclidean(X[0], X[1])) # 50000.00001 (разница только в доходе)
print(distance.euclidean(X[0], X[2])) # 1000.2 (разница 20 лет почти не видна)
По сырым данным объект 0 «ближе» к объекту 2, хотя между ними 20 лет разницы — потому что доход задавил возраст. Лечится это нормализацией: приводим каждый признак к сопоставимому масштабу до вычисления расстояния. Частый способ — z-нормализация (стандартизация): из каждого значения вычитаем среднее по столбцу и делим на стандартное отклонение. После этого признаки становятся соизмеримыми, и вклад дает уже возраст:
import numpy as np
from scipy.spatial import distance
X = np.array([
[25, 40000],
[26, 90000],
[45, 41000],
], dtype=float)
# z-нормализация по столбцам: (x - mean) / std
Xz = (X - X.mean(axis=0)) / X.std(axis=0)
print(distance.euclidean(Xz[0], Xz[1])) # 2.1452
print(distance.euclidean(Xz[0], Xz[2])) # 2.1740
После нормализации расстояния стали одного порядка, и объект 0 оказался чуть дальше от объекта 2 (большой разрыв в возрасте) — картина перевернулась и стала осмысленной. Альтернатива стандартизации — min-max масштабирование в диапазон [0, 1]; выбор зависит от наличия выбросов (при сильных выбросах z-нормализация надежнее). Важная оговорка: нормализацию считают на обучающей выборке и теми же параметрами применяют к новым данным, иначе метрика поедет.
Выводы
- Евклидово расстояние — длина прямого отрезка между точками; в кластеризации это мера различия объектов, формула обобщается с 2D на любое число признаков через сумму квадратов разностей координат.
- k-means минимизирует сумму квадратов евклидовых расстояний до центроидов и завязан именно на эту метрику; для манхэттенской берут k-medoids.
- Манхэттенское устойчивее к выбросам, косинусное измеряет направление и игнорирует длину вектора — метрику выбирают под природу данных, а не по умолчанию.
- Без нормализации признак с большим диапазоном подавляет остальные; z-нормализация или min-max приводят признаки к сопоставимому масштабу до расчета расстояний.
- Считать метрики удобно через numpy и scipy, а параметры нормализации фиксировать на обучении и применять к новым данным теми же.
Где применяется / связь с практикой
Евклидово расстояние и нормализация признаков — базовый инструмент любого проекта по кластеризации и обучению без учителя: сегментация клиентов, поиск похожих объектов, обнаружение аномалий, сжатие данных через типичных представителей. Разобраться, где какая метрика уместна и как готовить признаки, чтобы модель не врала, удобнее на практических задачах с разбором.
Освойте тему на практике
Системно эти темы (k-means, метрики близости, подготовка признаков, оценка качества кластеров) собраны на курсе Machine Learning. Basic. Посмотреть формат и уровень до старта можно на открытых уроках — там разбирают реальные задачи с кодом.
Смежные темы: Введение в Data Science: первые шаги в анализе данных, Статистическая значимость в исследованиях и анализе.
FAQ
Чем евклидово расстояние отличается от его квадрата и что использует k-means?
Квадрат — это та же сумма квадратов разностей, но без извлечения корня. Порядок близости он не меняет, зато экономит вычисление корня, поэтому k-means минимизирует именно сумму квадратов евклидовых расстояний до центроидов.
Всегда ли нужно нормализовать признаки перед евклидовым расстоянием?
Почти всегда, если признаки в разных единицах и диапазонах, иначе крупномасштабный признак подавит остальные. Исключение — когда все признаки уже в одной шкале (например, пиксели изображения 0-255) или масштаб намеренно несет смысл.
Работает ли евклидово расстояние в пространствах высокой размерности?
С ростом числа признаков расстояния между всеми точками сближаются и хуже различают объекты — это «проклятие размерности». В таких случаях помогает снижение размерности (например, PCA) либо переход к манхэттенской или косинусной метрике.



