Files
grabber-ai/docs/dataset-coverage.md
T
Denozordec 0f359837c5
docker / build (push) Successful in 1m20s
Датасет: полное покрытие data/raw (71 339 строк из 30 401 релиза), правки парсеров и аудит
Переразбор всех страниц data/raw: legacy-страницы импорта, форматы префиксов ([*]Перевод (1):, Озвучка:, №2, диапазоны), дорожки только в строках «Аудио» (в т.ч. «(Русский, X)», «| Rus | Звук: …»), «Язык озвучки», несколько студий в одной строке, студия без типа. Кодек-строки: «Аудио #N Русский:», «Аудио pic RUS:», «Звук N:», «Аудиодорожка 01:», кириллические АVO/МVO. «Авторский» без числа голосов -> авт. одноголосый, «двугоголосый». Чистка студий: языки, кодеки, «по заказу», «в составе контейнера», отказы от озвучки.

Итог: страниц с метками 30 260 (85.5 %), страниц с дорожкой без меток 1 259 -> 223; data/pages 30 444; после prepare_data 60 944 строки (train 54 686 / test 6 258).

Новый tools/coverage_audit.py + reports/coverage_audit.md, docs/dataset-coverage.md. Переобучен models/best (base): на общем тесте type acc 0.976 против 0.949 у прежней, span 0.674 против 0.643; e2e kinozal 0.805/0.867, rt 0.771/0.740, nnm 0.752/0.693.
2026-11-09 13:29:53 +07:00

12 KiB
Raw Blame History

Покрытие страниц data/raw датасетом: аудит сборщика

Отчёт о том, как сборщик (tools/collect.py → tools/harvest/harvest_core.py → src/prepare_data.py) превращает сохранённые страницы в обучающий датасет, какие форматы строк он терял и что исправлено. Цифры получены на всех страницах data/raw (35 385 шт.), а не на выборке.

Инструмент замера — tools/coverage_audit.py (пишет reports/coverage_audit.md, data/raw/_coverage_pages.csv, data/raw/_coverage_lines.csv). Строка считается «дорожкой» независимым от парсеров детектором (префикс «Перевод/Озвучка/Аудио…», слово типа озвучки или блок |студия|), а «покрытой» — если для неё есть строка labels.csv этого релиза (raw / audio_raw / role_raw).

Как устроен сборщик и где терялись данные

Пять стадий, у каждой свой кэш:

стадия вход → выход кэш / версия
collect браузер → data/raw/<трекер>/<id>.json + .html _state.json
build data/raw → data/pages/<release_id>.txt + строки data/labels.csv _built.json, PARSE_VERSION
meta страницы → data/meta.csv _meta_cache.json, META_VERSION
prepare_data labels.csv → data/processed/dataset.json —
train dataset.json → models/best, reports/ —

До этого аудита датасет собирался из 28 155 релизов (56 131 строка), хотя страниц в data/raw было 35 385: 7 371 страница не дала ни одной строки. Часть из них законно не содержит озвучки (русский оригинал, «Перевод: не требуется», немое кино, музыка/сканы), но не менее 1 259 страниц с настоящими дорожками в датасет не попадали. Причины — в порядке убывания потерь:

  1. legacy-страницы не переразбирались. Импорт старого harvest дал 2 633 страницы только с текстом поста (.legacy.json); build брал лишь пары json+html, поэтому их метки остались от старых регулярок и больше не обновлялись.
  2. Форматы строк, которых не понимали префиксы. [*]Перевод (1):, ►Перевод:, Перевод №2:, Перевод 01-02:, Аудио RUS 1-3:, Озвучка:, Озвучивание: (nnm/rutracker) не совпадали с RT_RE_FIELD / NNM_RE_PEREVOD, потому что те ждали ровно «Перевод:» или «Перевод 2:».
  3. Дорожки, названные только строкой «Аудио» (nnm/rutracker, аниме-раздачи): Аудио 4: AC3 … (внешние) (Русский, Anilibria), | Rus | Звук: Zendos & Eladiel, Аудио RUS: … Озвучка: двухголосая (… ). Студия была в скобках после языка или в хвосте «Звук:/Озвучка:», а разметка такие строки не читала: у nnm требовался «(MVO, Студия)», а язык — только «Русский/Английский/Украинский».
  4. Студия без типа озвучки («Перевод: Dreamers Team», «Перевод: CrunchyRoll», «Озвучка: Persona99») выбрасывалась: translation_type давал «неизвестно», и строка отбрасывалась вместе с автором. Для головы автора это потеря: на странице автора назвали.
  5. Несколько студий в одной строке («Профессиональный (многоголосый) — Jaskier, TVShows, HDrezka Studio, LostFilm», «| ОРТ, KidsCo»): в метки шла одна студия или склеенное «Jaskier, TVShows».
  6. Строка «Язык озвучки: Русский (Berofu, Takera, Euji [AniMaunt])» (nnm, аниме) вообще не считалась дорожкой.
  7. kinozal читал только одну вкладку. Если в «Релизе» была строка «Перевод:», «Техданные» игнорировались (и наоборот) — терялись типы или студии второй вкладки.
  8. Кодек-строки мимо правил сервиса (segmenter.RE_AUDIO_TRACK, release.RE_CODEC_TRACK): «Аудио pic RUS:», «Аудио #1 Русский:», «Аудио N Rus:», «Звук N:», «Аудиодорожка 01:», «Audio #3:», кириллические «АVO/МVO». Это дыра не только в метках сегментатора, но и в запасном пути инференса.

Что исправлено

tools/harvest/harvest_core.py (PARSE_VERSION 4 → 6), src/html_extract.py, src/release.py, src/segmenter.py, src/trackinfo.py, tools/collect.py, src/prepare_data.py, src/studio_norm.py:

  • общий разбор префикса дорожки: декоративные [*] ► •, номер (1), №2, диапазоны 01-02, «Озвучка/Озвучивание/Дубляж» — для rutracker, nnm и kinozal;
  • build переразбирает legacy-страницы (метки обновляются, страница не перезаписывается);
  • nnm: студии из (Русский, Anilibria), | Rus | Звук: …, язык RUS/Rus/RU; строка «Язык озвучки»; несколько студий в «Перевод:» → по строке на студию; студия без типа сохраняется с типом «неизвестно»;
  • rutracker: разбор (Русский, Студия) и [студия], хвостов «Озвучка:»/«Звук:», списков студий; те же правила для «Перевод/Озвучка/Озвучивание»;
  • kinozal: обе вкладки, несколько студий в строке, «Отсутствует/Без перевода» не считаются автором;
  • кодек-строки: префиксы «Аудио #N Русский:», «Аудио pic RUS:», «Звук N:», «Аудиодорожка 01:», «Audio #3:», «Track #2:», «Title :»; тип-слова с кириллическими двойниками (АVO/МVO/DVO); если у релиза нет ни одной строки, из кодек-строки берётся дорожка без имени (тип без студии);
  • чистка имён: «Русский, - AlexFilm» → AlexFilm, «X по заказу Y» → X, «озвучил - N» → N; мусор (коды/каналы/языки/«по умолчанию»/«в составе контейнера»/«Отсутствует»/эпизоды) отбрасывается; в prepare_data строки-отказы от озвучки удаляются отдельным счётчиком.

Результат

было стало
страниц в data/raw 35 385 35 385
релизов в labels.csv 28 155 30 401
строк в labels.csv 56 131 71 339
страниц с метками 28 014 30 260 (85.5 %)
страниц без меток, но с дорожкой (по детектору) 1 259 223
data/pages (страниц для сегментатора) 28 198 30 444
строк после prepare_data 46 894 60 944 (train 54 686 / test 6 258)
строк со студией (спан найден) 38 583 (82.3 %) 50 477 (82.8 %)
уникальных текстов 25 614 30 761
дорожек 18+ 1 006 1 156

По трекерам (строки labels.csv → строки после подготовки, включая аугментацию):

  • kinozal: 21 773 → 23 969 (15 188 после подготовки);
  • nnm: 18 384 → 27 092 (24 453);
  • rutracker: 15 974 → 20 278 (21 303).

Остаток 223 страниц — почти весь музыка/OST-раздачи, где «дорожкой» оказался трек-лист, плюс единичные нестандартные строки («Аудио 6: двухголосая закадровая Flowers Media» без кодек-параметров, «Аудио ShinkaDan: …», «Аудио #1: Russian … | Original | Censor»). Они перечислены в data/raw/_coverage_lines.csv и годятся для следующей итерации правил.

Непокрытые строки на страницах с метками (12 908 из 56 921) — в основном не потерянные дорожки, а дубли: строка «Аудио N:» той же дорожки, что уже размечена из «Перевод:», дорожки оригинала/другого языка и техданные. Их доля видна в reports/coverage_audit.md.

Как воспроизвести

# замер покрытия (кэш текстов ускоряет повтор)
.venv\Scripts\python tools\coverage_audit.py --cache data\raw\_coverage.pkl

# переиндексация: страницы + метки + meta (после правки парсеров поднять PARSE_VERSION)
.venv\Scripts\python tools\collect.py build --rewrite --relabel

# подготовка датасета и аудит
.venv\Scripts\python -m src.prepare_data

Переиндексация всех 35 тыс. страниц одним процессом занимает ~30 мин (основное время — запись новых страниц и meta.csv); на нескольких процессах — в разы быстрее (Runner(workers)), но в песочнице DSH процессы с именованными каналами недоступны.

Что это дало модели

Переобучение на расширенном датасете (held-out test 6 258 строк, обе модели оценены на одном тесте):

модель type acc type macro-F1 span exact joint exact
прежняя models/best (02.11) 0.949 0.880 0.643 0.615
новая models/best (09.11) 0.976 0.906 0.674 0.658

E2E по релизам (пары тип + студия, precision / recall; те же 400 страниц на трекер): прежняя модель — kinozal 0.752 / 0.830, rutracker 0.729 / 0.700, nnm 0.669 / 0.604; новая — 0.805 / 0.867, 0.771 / 0.740, 0.752 / 0.693. Абсолютный span exact на новом тесте ниже прежних 0.922 из-за того, что в тест попали форматы, которых раньше в датасете не было; сравнение «на одном тесте» показывает рост по всем головам.