Задача

Лучший первый вопрос

классификация дерево жадность сортировка

Решающее дерево начинается с одного вопроса «x ≤ t?». Есть n примеров: у каждого числовой признак xi и ответ yi — 0 или 1. Вопрос делит примеры на две непустые группы, и хороший вопрос — тот, после которого неопределённость меньше всего. Найдите порог t с наибольшим приростом информации

$$\mathrm{IG} = H(\text{все}) - \frac{n_{\le}}{n}\,H(\text{группа } x \le t) - \frac{n_{>}}{n}\,H(\text{группа } x > t),$$

где H — энтропия группы в битах: если в группе доля единиц p, то H = −p log₂ p − (1 − p) log₂ (1 − p) (слагаемое с нулевой долей считается нулём).

Два теста — землетрясения магнитудой от 5 за 2015–2021 годы из каталога USGS: признак — магнитуда (в сотых) или расстояние до ближайшего города от 10 тысяч жителей (км), ответ — сообщил ли кто-нибудь, что почувствовал толчок.

Вход

В первой строке n (2 ≤ n ≤ 200 000). В каждой из следующих n строк — целые xi (|xi| ≤ 10⁹) и yi ∈ {0, 1}.

Выход

Если все xi одинаковы, выведите -: ни один вопрос не делит примеры. Иначе выведите два числа: порог t и прирост информации. Подходит любой порог, при котором обе группы непустые и прирост отличается от наибольшего возможного не больше чем на 10⁻⁹; прирост проверяется с погрешностью 10⁻⁶.

Примеры

Пример 1

Вход
8
1 0
2 0
3 0
4 1
5 0
6 1
7 1
8 1
Выход
3.5 0.548794941

Пример 2

Вход
3
42 1
42 0
42 1
Выход
-

Ограничения

Время · Python
6000 мс
Время · Go
1500 мс
Память
256 МБ
Проверка
8 тестов

Разбор

Открывайте по ступеням: каждая следующая подсказывает больше. Можно сразу к решению — но задача, решённая с одной подсказкой, запоминается лучше.

1Подсказка 1

Порогов, которые стоит проверить, немного: вопрос «x ≤ t?» делит примеры одинаково при всех t между двумя соседними различными значениями x. Сколько различных делений бывает у n чисел?

2Подсказка 2

Для каждого деления нужны лишь размеры групп и число единиц в каждой. Если примеры отсортированы по x, как получить эти числа для следующего деления из предыдущего за O(1)?

3Идея

Сортируем примеры по x и идём слева направо, перенося по одному примеру из правой группы в левую и обновляя число единиц слева. Каждый раз, когда соседние значения различаются, перед нами одно из возможных делений: считаем для него прирост информации и запоминаем лучший. Порог — середина между соседними значениями; подойдёт и любое число между ними.

4Разбор

Энтропия всех примеров не зависит от вопроса, так что максимизировать прирост — то же, что минимизировать среднюю энтропию групп, взвешенную их размерами. Веса здесь главное: группа из одного примера всегда «чистая», её энтропия ноль, но описывает она один пример из тысячи.

Одинаковые x нельзя разделить: вопрос «x ≤ t?» отправляет их все в одну сторону. Поэтому деление между равными значениями пропускаем — иначе программа посчитает прирост для разбиения, которого не бывает. Если все x равны, делений нет вовсе.

На землетрясениях 2015–2021 годов лучший вопрос о расстоянии — «до города не больше 106,5 км?» с приростом 0,172 бита, а лучший вопрос о магнитуде — «магнитуда не больше 5,85?» с приростом всего 0,042. Поэтому дерево из статьи начинает с расстояния.

4+Решение
5Сложность

O(n log n) на сортировку и O(n) на проход. Перебор порогов с пересчётом групп заново — O(n²) — на двухстах тысячах примеров не успевает.

6Типичные ошибки
  • Среднее энтропий без весов. Отрезанный крайний пример даёт чистую группу с нулевой энтропией, и такой «вопрос» побеждает. Седьмой тест построен на этом: одинокий пример на дальнем краю.
  • Деление между равными значениями. Посчитанный прирост принадлежит невозможному разбиению, а выведенный порог даёт другое.
  • log(0). Пустая доля в энтропии считается нулём: −0·log₂0 = 0 по непрерывности, а не ошибка вычисления.

Алгоритмы задачи