# Домашнє завдання · Інженерія ознак

> Лекція: [lecture.html](lecture.html) · Практика: [practice.ipynb](practice.ipynb) · Тест: [quiz.html](quiz.html)

Усі завдання — на тій самій дошці оголошень, що в практиці. Відкрий `practice.ipynb`,
дійди до клітинки, де таблиця вже зібрана й почищена, і працюй далі в ній.

Пам'ятай про три лінійки з лекції: **кореляція**, **AUC** (розділюваність класів) і
**взаємна інформація**. У практиці для них є готова функція `виміряти()`.

---

## 🟢 Рівень 1 — База

Побудуй три нові ознаки й виміряй кожну:

1. **`ціна ÷ медіанна ціна цього продавця`** — чи вибивається це оголошення серед власних
   оголошень продавця;
2. **`вік акаунта ÷ кількість оголошень продавця`** — скільки днів акаунта припадає на
   одне оголошення;
3. **`памʼять ÷ типова памʼять для цієї моделі`** (медіана памʼяті всередині моделі).

**Зроблено, якщо:** є таблиця з трьох рядків, у кожному — назва ознаки, кореляція, AUC і
взаємна інформація; і одне речення про кожну ознаку: краща вона за сиру ціну (AUC 0.666,
MI 0.069) чи ні.

---

## 🟡 Рівень 2 — Плюс

Візьми колонку `опубліковано` й побудуй ознаку **«скільки годин минуло від попереднього
оголошення цього самого продавця»**.

Підказка до техніки: відсортуй таблицю за продавцем і датою, далі `groupby("продавець")`
і `.diff()` по стовпцю з датою. У першого оголошення кожного продавця попереднього немає —
вирішиш сам, чим заповнити пропуск, і поясниш чому.

Далі:

* виміряй ознаку трьома лінійками;
* побудуй гістограму цієї ознаки окремо для чесних і шахрайських оголошень
  (`matplotlib`, дві напівпрозорі гістограми на одних осях);
* дай відповідь на питання: чому ознака «скільки годин **минуло від попереднього**
  оголошення» законна, а ознака «скільки годин **до наступного** оголошення» була б
  витоком із майбутнього.

**Зроблено, якщо:** ознака порахована, три числа виведені, графік побудований і підписаний,
а різниця між «від попереднього» й «до наступного» пояснена двома-трьома реченнями
своїми словами.

---

## 🔴 Рівень 3 — Виклик

Реалізуй **цільове кодування з виключенням себе** (leave-one-out target encoding) і покажи,
наскільки воно захищає від витоку.

Для кожного рядка код продавця рахується як середній таргет **інших** оголошень цього
продавця:

```
код = (сума таргета по групі − таргет цього рядка) / (розмір групи − 1)
```

Для продавців з єдиним оголошенням знаменник нульовий — підстав загальне середнє.

Порівняй **на тестовій частині** три способи кодування колонки «продавець»:

| спосіб | що очікуємо |
|---|---|
| наївний (`transform("mean")` по всій таблиці) | у практиці вийшло 0.657 |
| з виключенням себе, порахований по всій таблиці | ? |
| карта, побудована лише на `train` | у практиці вийшло 0.303 |

Потім зроби те саме з випадковим «кодом регіону» з практики — ознакою, у якої правдивого
звʼязку немає взагалі.

**Зроблено, якщо:** усі три числа для обох колонок пораховані й зведені в одну таблицю,
і ти письмово відповів на питання: чому кодування з виключенням себе все одно захищає
гірше, ніж карта, побудована тільки на `train`.

---

## Підказки

* `transform` повертає стовпець тієї самої довжини, що й таблиця, — саме це потрібно для
  ознаки. `agg` повертає по одному рядку на групу й для ознаки не годиться.
* Суму й розмір групи зручно дістати теж через `transform`: `transform("sum")` і
  `transform("size")`. Далі — звичайна арифметика над стовпцями.
* Якщо нова ознака дає кореляцію біля нуля — не викидай її одразу. Подивись на гістограму
  в розрізі таргета й на взаємну інформацію: у лекції ознака з кореляцією +0.018 виявилась
  однією з найкорисніших.
* Якщо нова ознака одразу дала кореляцію вище 0.9 — не радій, а шукай, звідки в неї
  потрапила відповідь.
