К содержанию

Подтема 3 из 6

Центр кластера

Центр — точка кластера с наименьшей суммой расстояний: перебор кандидатов, почему средняя точка не подходит, своя формула расстояния и взвешенная сумма.

Центр — точка кластера

Какую точку кластера считать его центром?

Центр — одна из точек самого кластера: та, у которой сумма расстояний до остальных точек наименьшая. Найти её можно перебором — проверить каждую точку как кандидата. Кандидат — точка, которую сейчас проверяем: «а что, если центр — она?»

Возьмём кластер из пяти точек на прямой: (0; 0), (1; 0), (2; 0), (3; 0) и (100; 0). На одной горизонтали расстояние — модуль разности x. Для (0; 0) сумма до остальных 1 + 2 + 3 + 100 = 106, для (1; 0) — 1 + 1 + 2 + 99 = 103. Пройди так всех пятерых:

  1. Центр — одна из точек кластера. Проверим каждую по очереди, как кандидата.
  2. Кандидат (0; 0): 1 + 2 + 3 + 100 = 106. Пока это лучшая сумма.
  3. Кандидат (1; 0): 1 + 1 + 2 + 99 = 103. Пока это лучшая сумма.
  4. Кандидат (2; 0): 2 + 1 + 1 + 98 = 102. Пока это лучшая сумма.
  5. Кандидат (3; 0): 3 + 2 + 1 + 97 = 103. Хуже, чем 102.
  6. Кандидат (100; 0): 100 + 99 + 98 + 97 = 394. Хуже, чем 102.
  7. Все кандидаты проверены: центр (2; 0), наименьшая сумма 102.

Центр — (2; 0) с суммой 102. У соседней (3; 0) сумма 103, у далёкой (100; 0) — 394.

Центр, центроид, медоид и среднее расстояние

В условиях такую точку называют «центром» или «центроидом», в математике — медоидом. Решай по определению из условия, а не по слову.

Если в условии минимизируется среднее расстояние до остальных точек, центр тот же: среднее — сумма, делённая на m − 1, а делитель одинаков для всех кандидатов кластера. Но если просят вывести само среднее, деление нужно: для нашего центра 102 / 4 = 25,5 до остальных точек и 102 / 5 = 20,4 по всем пяти, включая сам центр.

Программа

Как записать перебор кандидатов программой?

Двумя вложенными циклами: внешний перебирает кандидатов, внутренний складывает расстояния от кандидата до всех точек кластера. Лучшую сумму и её кандидата запоминают.

from math import dist  def center_sum(cluster):    best_point = cluster[0]    best_sum = float("inf")    for candidate in cluster:        total = 0.0        for point in cluster:            total += dist(candidate, point)        if total < best_sum:            best_sum = total            best_point = candidate    return best_point  cluster = [(0, 0), (1, 0), (2, 0), (3, 0), (100, 0)]print(center_sum(cluster))
(2, 0)
  • float("inf") — бесконечность: любая настоящая сумма меньше, поэтому первый кандидат сразу становится лучшим.
  • total = 0.0 стоит внутри внешнего цикла: у каждого кандидата своя сумма. Поставь её до цикла — и суммы разных кандидатов сложатся вместе.
  • total += … — , то же, что total = total + ….
  • Сравнивать с лучшей суммой можно только после внутреннего цикла, когда сумма кандидата посчитана целиком.

Функция находит центр наверняка: она проверяет всех кандидатов и для каждого считает ровно ту величину, что стоит в условии. Угадывать центр по рисунку не нужно.

Расстояние до себя, равные суммы и одинаковые точки

Расстояние от кандидата до самого себя равно нулю, поэтому проверка if point != candidate: не нужна: сумма до всех точек равна сумме до остальных. Хуже того, она выбросит и другую запись с теми же координатами — а совпадающие точки удалять нельзя, если условие этого не просит.

При равных суммах сравнение < оставляет первого из равных кандидатов, <= — последнего. Обычно условие гарантирует, что центр единственный.

Сколько работы делает перебор

Для каждого из m кандидатов считаются m расстояний — всего m²:

Точек в кластереВычислений расстояния
10010 000
1 0001 000 000
5 00025 000 000

Расстояния считают только внутри своего кластера: 9 000 точек в трёх кластерах по 3 000 — это 27 миллионов вычислений, а не 81. В файлах экзамена сотни или тысячи точек, и перебор занимает секунды.

Среднее — не центр

Нельзя ли вместо перебора просто взять среднюю точку кластера?

Нет: средняя точка обычно не совпадает ни с одной точкой кластера, и даже ближайшая к ней точка не обязательно центр. Средняя точка наших пяти — x̄ = (0 + 1 + 2 + 3 + 100) / 5 = 21,2, ȳ = 0: далёкая точка (100; 0) сильно её смещает. Ближайшая к (21,2; 0) точка кластера — (3; 0). Проверим её сумму:

mean = (sum(p[0] for p in cluster) / 5, 0)print(mean) nearest = cluster[0]for p in cluster:    if dist(p, mean) < dist(nearest, mean):        nearest = p best = center_sum(cluster)print(nearest, sum(dist(nearest, p) for p in cluster))print(best, sum(dist(best, p) for p in cluster))
(21.2, 0) (3, 0) 103.0 (2, 0) 102.0

У (3; 0) сумма 103, у настоящего центра (2; 0) — 102. Один пример опровергает сразу оба соблазнительных правила: и «центр — средняя точка», и «центр — ближайшая к средней».

Сумма квадратов

А если ради скорости убрать корень и сравнивать суммы квадратов расстояний?

Нельзя: сумма квадратов — другая величина, и её минимум бывает у другой точки. Сравним кандидатов 2 и 3 из нашего кластера:

for c in [(2, 0), (3, 0)]:    plain = sum(dist(c, p) for p in cluster)    squares = sum(dist(c, p) ** 2 for p in cluster)    print(c, plain, squares)
(2, 0) 102.0 9610.0 (3, 0) 103.0 9423.0

По сумме расстояний лучше кандидат 2, по сумме квадратов — 3: 2² + 1² + 0² + 1² + 98² = 9610, а 3² + 2² + 1² + 0² + 97² = 9423. Квадрат сильнее раздувает большие расстояния, и сократить одно большое выгоднее, чем несколько маленьких.

Сравнивать квадраты можно, когда сравниваешь одно расстояние с порогом (подтема 1), но не суммы. Центр по сумме квадратов встречается в редких задачах — он разобран в дополнительном уроке.

Своя формула расстояния

Что меняется, если в условии своя формула расстояния?

Только функция расстояния — перебор кандидатов остаётся прежним. Добавим в center_sum параметр d — функцию расстояния; по умолчанию это обычная dist:

def center_sum(cluster, d=dist):    best_point = cluster[0]    best_sum = float("inf")    for candidate in cluster:        total = 0.0        for point in cluster:            total += d(candidate, point)        if total < best_sum:            best_sum = total            best_point = candidate    return best_point

Например, манхэттенское расстояние d(A, B) = |x₁ − x₂| + |y₁ − y₂| — длина пути, если ходить только по горизонтали и вертикали. Для (1; 2) и (4; 6) это 3 + 4 = 7, а не 5. — модуль числа:

def manhattan(a, b):    return abs(a[0] - b[0]) + abs(a[1] - b[1])  group = [(0, 3), (3, 0), (1, 6), (1, 0)]print(center_sum(group), center_sum(group, manhattan))
(0, 3) (1, 0)

Для одних и тех же четырёх точек евклидов центр — (0; 3), а манхэттенский — (1; 0): формула расстояния меняет ответ.

Так устроена и задача темы: «расстояние» между частицами — модуль разности их энергий |E₁ − E₂|, а координаты в выборе центра не участвуют. Функции read_particles, energy и energy_groups — из подтем 1 и 2:

def energy_gap(a, b):    return abs(energy(a) - energy(b))  particles = read_particles("27-4.txt")groups = energy_groups(particles, [3.5, 7, 10.5])for g in groups:    c = center_sum(g, energy_gap)    print(len(g), c[5], round(energy(c), 3))
125 V 2.028 103 IV 5.362 93 I 8.964 81 I 12.503

У центров четырёх кластеров энергии 2,028, 5,362, 8,964 и 12,503. Q₂ задачи темы — наибольшая из них; ответ соберём в подтеме 5.

Взвешенная сумма

Как найти центр, если точки неравноценны — например, деревья разной высоты?

Каждое расстояние умножают на вес той точки, до которой его считают; в остальном перебор прежний. Такая задача есть в подборках: деревья свозят к точке сбора, «сложность» доставки дерева — расстояние, умноженное на его высоту, а точка сбора — дерево с наименьшей суммарной сложностью.

Пять деревьев у дороги: (0; 0) высотой 2, (1; 0), (2; 0) и (3; 0) высотой 1 и (8; 0) высотой 4. Сравним обычную и взвешенную суммы каждого кандидата:

КандидатСумма расстоянийСумма с весами
(0; 0)1438
(1; 0)1133
(2; 0)1030
(3; 0)1129
(8; 0)2634

Без весов центр — (2; 0), с весами — (3; 0): высокое дерево (8; 0) тянет точку сбора к себе. В программе меняется одна строка — к расстоянию добавляется множитель:

trees = [(0, 0, 2), (1, 0, 1), (2, 0, 1), (3, 0, 1), (8, 0, 4)]  def center_weighted(trees):    best, best_sum = None, float("inf")    for c in trees:        total = 0.0        for t in trees:            total += dist(c[:2], t[:2]) * t[2]        if total < best_sum:            best, best_sum = c, total    return best, best_sum  print(center_weighted(trees))
((3, 0, 1), 29.0)

Множитель — t[2], высота дерева, которое везут, а не кандидата c. Перепутать их — значит решить другую задачу.

Итого

  • Центродна из точек кластера, наименьшая сумма расстояний
  • Переборвнешний цикл — кандидаты, внутренний — сумма
  • totalобнуляется для каждого кандидата
  • Средняя точкане центр; ближайшая к ней — тоже не обязательно
  • Своя формуламеняется только функция d, перебор тот же
  • Весрасстояние × вес точки, до которой считаем

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1
Среди точек (0, 0), (4, 0), (5, 0), (6, 0), (20, 0) найди центр по наименьшей сумме расстояний. Совпадает ли он с ближайшей к средней точке?
ОтветСкрыть ответ
Ответ
(5, 0): сумма 22 (у (4, 0) и (6, 0) — по 23). Средняя точка 7, ближайшая к ней (6, 0) — не центр.
Вопрос 2
Найди центр кластера (0, 0), (4, 0), (4, 3), (0, 3), (1, 1) и его сумму расстояний.
ОтветСкрыть ответ
Ответ
(1, 1): сумма ≈ 10,418; у углов суммы от 13,414 до 15,606.
Вопрос 3
Строку total = 0.0 поставили до внешнего цикла. Что тогда сравнивается с best_sum для второго кандидата?
ОтветСкрыть ответ
Ответ
Сумма первого и второго кандидатов вместе: она заведомо больше суммы первого, и второй кандидат никогда не выиграет.
Вопрос 4
Найди центр кластера (2, 6), (3, 6), (3, 1), (4, 2) по евклидову и по манхэттенскому расстоянию.
ОтветСкрыть ответ
Ответ
Евклидово — (4, 2) (≈ 10,01), манхэттенское — (3, 6) (сумма 11, у остальных по 13).
Вопрос 5
Деревья (0, 0) высотой 1, (2, 0) высотой 1 и (3, 0) высотой 5. Где точка сбора по сумме «расстояние × высота дерева» и где центр без весов?
ОтветСкрыть ответ
Ответ
С весами — (3, 0): суммы 17, 7 и 4. Без весов — (2, 0): суммы 5, 3 и 4.

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Центр левого кластера

В файле 27-1.txt записаны точки двух кластеров (граница — из задачи 7 подтемы 3). Центр кластера — его точка с наименьшей суммой расстояний до остальных точек кластера. Найди центр кластера, расположенного левее. В ответе запиши целые части произведений его абсциссы и ординаты на 10 000.

27-1.txtТочки двух кластеровТекстовый файл · 3,6 КБ

Введите два целых числа через пробел.

Центр по энергиям

В файле 27-4.txt записаны частицы; они делятся на 4 кластера по кинетической энергии (R = 2). Центр кластера — частица с наименьшей суммой модулей разностей энергий с остальными частицами кластера. Найди энергию центра кластера с наименьшими энергиями. В ответе запиши целую часть произведения этой энергии на 10 000.

27-4.txtЧастицы: координаты, скорость, масса, признакТекстовый файл · 14,3 КБ

Введите число.

Точка сбора деревьев

На участке растут семь деревьев (x, y, высота): (2, 3, 1), (5, 1, 1), (4, 6, 1), (8, 2, 1), (6, 5, 1), (3, 8, 3), (9, 7, 1). Сложность доставки дерева — расстояние от него до точки сбора, умноженное на его высоту. Точка сбора — одно из деревьев, для которого суммарная сложность доставки остальных деревьев наименьшая. Найди координаты точки сбора.

Введите два числа через пробел: сначала x, затем y.