215 lines
17 KiB
Markdown
215 lines
17 KiB
Markdown
# Разметка датасета и выбор правила метки
|
||
|
||
Документ описывает, откуда берутся метки снимков, как проверялось правило
|
||
разметки и какие результаты из этого следуют. Числа проверяемы: ссылки на
|
||
источники приведены рядом.
|
||
|
||
## 1. Задача разметки
|
||
|
||
Экспертная оценка в наборе сделана на уровне **исследования**: в таблице
|
||
`разметка.xlsx` по каждому исследованию отмечены критерии качества, а не по
|
||
отдельному снимку. Модель же работает со снимками, поэтому вердикт исследования
|
||
нужно было перенести на каждый снимок — без догадок и без потери информации о
|
||
том, откуда метка взялась.
|
||
|
||
## 2. Экспертная таблица
|
||
|
||
Столбцы (две строки заголовков, данные с третьей):
|
||
|
||
| Столбец | Смысл | Тип нарушения |
|
||
|---|---|---|
|
||
| 2 | Позвоночник: укладка | `positioning` |
|
||
| 3 | Позвоночник: ось | `axis_deviation` |
|
||
| 4 | Позвоночник: артефакты, наложения | `artifact` |
|
||
| 5, 6 | Бедро R: позиционирование/ротация, область интереса | `rotation`, `roi_incorrect` |
|
||
| 7, 8 | Бедро L: то же | `rotation`, `roi_incorrect` |
|
||
| 9, 10, 11 | Итог по области | — |
|
||
| 12 | Комментарий эксперта | — |
|
||
|
||
**Семантика значений** установлена по данным, а не по формулировкам заголовков:
|
||
|
||
- `1` в столбце критерия означает **нарушение**, хотя часть заголовков
|
||
сформулирована положительно («корректная укладка»);
|
||
- итог области равен логическому ИЛИ критериев: бёдра 72/72 и 78/78,
|
||
позвоночник 96/99;
|
||
- три расхождения позвоночника (два случая «итог без критериев», один «критерий
|
||
без итога») трактуются как нарушение — по правилу «хотя бы один существенный
|
||
пункт нарушен»;
|
||
- заполненность: позвоночник 99/100, бедро R 72/100, бедро L 78/100; у 23
|
||
исследований есть комментарий.
|
||
|
||
## 3. Перенос вердикта на снимок
|
||
|
||
| Шаг | Что делается | Почему так |
|
||
|---|---|---|
|
||
| Ключ склейки | имя каталога исследования | таблица ссылается на каталог (`2.25…`), а в DICOM лежит другой идентификатор (`1.2.643…`); соответствие каталог → тег 100/100 |
|
||
| Склейка дублей | по хешу пиксельных данных | 544 файла — это 252 уникальных снимка |
|
||
| Область снимка | голосование по именам файлов группы | один снимок назван и как позвоночник, и как бедро; при равенстве голосов область остаётся неопределённой (такой снимок один) |
|
||
| Вердикт | оценка области переносится на её снимок | **каждая область встречается в исследовании ровно один раз**, поэтому не нужно решать, какой из нескольких снимков «плохой» |
|
||
| Сторона бедра | при единственном снимке бедра берётся единственный заполненный столбец | в 71 из 72 исследований с двумя бёдрами столбцы совпадают с именами файлов; в 7 исследованиях с одним снимком заполнена противоположная сторона. Факт переноса фиксируется флагом `laterality_mirrored`; теги `Laterality` в DICOM пусты |
|
||
| Тип нарушения | только из структурированных критериев | комментарии («сколиоз», «эндопротезирование ТБС») сохранены дословно: перекладывать свободный текст в код — догадка |
|
||
|
||
## 4. Правило метки и почему оно такое
|
||
|
||
Метка могла строиться двумя способами: только из таблицы или с добавлением
|
||
пометок, которые вручную проставлялись в именах файлов (суффикс `_bad`). Пометки
|
||
в именах оказались ненадёжными: они расходились с оценкой эксперта в **15 случаях
|
||
из 252**. Выбор сделан измерением, а не по вкусу.
|
||
|
||
**Постановка.** Разбиение по исследованиям зафиксировано один раз, оба варианта
|
||
обучены пятью seed'ами на нём, оценены по одному эталону — вердикту эксперта на
|
||
снимках валидации. Снимки валидации не участвуют в обучении ни в одном варианте.
|
||
|
||
Воспроизведение: `python -m src.dxa.excel_labels --label-rule {table,union,expert}`
|
||
и `python -m src.dxa.compare_labels --split-file labels/split_expert_seed42.json`.
|
||
|
||
**Результат** (53 снимка валидации, 16 нарушений по эталону, 5 seed'ов):
|
||
|
||
| Метрика (эталон) | только таблица | таблица или суффикс `_bad` |
|
||
|---|---|---|
|
||
| ROC-AUC | **0.6764** [0.6309, 0.7218] | 0.6199 [0.5840, 0.6559] |
|
||
| PR-AUC | **0.4759** [0.4141, 0.5377] | 0.4046 [0.3702, 0.4391] |
|
||
| F1 | **0.5676** [0.5270, 0.6082] | 0.5426 [0.5073, 0.5778] |
|
||
| Recall | 0.7000 | 0.8625 |
|
||
| Precision | 0.4857 | 0.4043 |
|
||
|
||
Парная разница («только таблица» − «с суффиксами»):
|
||
|
||
| Метрика | Δ, среднее [95 % ДИ] | Знаки по seed'ам |
|
||
|---|---|---|
|
||
| ROC-AUC | **+0.0564** [+0.0403, +0.0725] | `+++++` |
|
||
| PR-AUC | **+0.0713** [+0.0398, +0.1028] | `+++++` |
|
||
| F1 | +0.0251 [−0.0056, +0.0558] | `+++-+` |
|
||
| Precision | +0.0815 [+0.0590, +0.1039] | `+++++` |
|
||
| Recall | −0.1625 [−0.2715, −0.0535] | `--0--` |
|
||
|
||
**Решение: принято правило «только экспертная таблица».** Дополнительные пометки
|
||
из имён файлов ухудшали согласие модели с экспертом на невиданных
|
||
исследованиях: вариант с ними чаще срабатывал (recall 0.86), но за счёт
|
||
точности, а по беспороговым метрикам проигрывал на всех пяти seed'ах.
|
||
|
||
Оговорка: эталон — та же экспертная таблица, поэтому вариант, обучавшийся
|
||
непосредственно на ней, находится в выигрышном положении. Значимо здесь другое:
|
||
добавление ненадёжных пометок **снижает** согласие с экспертом, что и служит
|
||
аргументом против них.
|
||
|
||
## 5. Словарь типов нарушений
|
||
|
||
| Код | Подпись | Область | Источник |
|
||
|---|---|---|---|
|
||
| `positioning` | Некорректная укладка | позвоночник | таблица |
|
||
| `axis_deviation` | Отклонение оси | позвоночник | таблица |
|
||
| `artifact` | Артефакты и импланты | любая | таблица |
|
||
| `rotation` | Ротация, позиционирование | бедро | таблица |
|
||
| `roi_incorrect` | Некорректная область интереса | любая | таблица |
|
||
| `motion` | Движение, размытие | любая | критерии методики |
|
||
| `incomplete_anatomy` | Анатомия видна не полностью | любая | критерии методики |
|
||
| `labeling_error` | Ошибка разметки | позвоночник | критерии методики |
|
||
| `unspecified` | Нарушение без уточнения | любая | служебный |
|
||
|
||
Распределение в разметке: `rotation` 36, `artifact` 17, `axis_deviation` 10,
|
||
`roi_incorrect` 7, `positioning` 6, `unspecified` 5.
|
||
|
||
Словарь один на всё решение (`src/dxa/violations.py`): коды используют инференс,
|
||
отчёт DICOM SR и веб-интерфейс, подписи отдаёт сервер, копий в JavaScript нет.
|
||
|
||
## 6. Результат разметки
|
||
|
||
`labels/labels_images.csv` (и XLSX) — по одной строке на уникальный снимок:
|
||
|
||
| | позвоночник | бедро R | бедро L | неопред. | всего |
|
||
|---|---|---|---|---|---|
|
||
| качественных | 66 | 58 | 51 | 0 | 175 |
|
||
| с нарушением | 33 | 21 | 22 | 1 | 77 |
|
||
| **итого** | **99** | **79** | **73** | **1** | **252** |
|
||
|
||
Помимо метки в CSV сохранено происхождение: `quality_from_excel` (вердикт
|
||
эксперта), `quality_from_filename` (пометка из имени файла), `sources_conflict`,
|
||
`label_rule`, `filename_fallback`, `laterality_mirrored`, `region_ambiguous`,
|
||
`expert_comment`. Поэтому правило можно переиграть без повторного разбора.
|
||
|
||
Рядом лежат варианты для воспроизведения сравнения:
|
||
`labels_images_table.csv`, `labels_images_union.csv`, `labels_images_expert.csv`
|
||
(эталон: только снимки с экспертной оценкой, 249 строк) и
|
||
`split_expert_seed42.json` (зафиксированное разбиение).
|
||
|
||
## 7. Гигиена данных: имена файлов
|
||
|
||
Имена проставлялись вручную и разошлись: `spine_1` и `spine_01`, `Spine_01`,
|
||
`r_spine_03`, `r_hip03`, `r_hop_02` (опечатка), `spine-1`. Они приведены к виду
|
||
`<область>_<NN>[_good|_bad].dcm` инструментом `src/dxa/rename_files.py`;
|
||
переименовано 344 файла из 548, карта отката — `labels/rename_map.csv`.
|
||
|
||
Переименование сделано **после** того, как разметка и метрики были посчитаны, и
|
||
проверено, что оно на них не влияет: набор из 252 пиксельных групп идентичен до и
|
||
после, разметка не изменилась ни в одной строке. Суффиксы `_good`/`_bad`
|
||
сохранены как были и в метках не участвуют — только как диагностический столбец.
|
||
|
||
## 8. Оценка качества модели
|
||
|
||
Разбиение по исследованиям (по умолчанию seed 42): обучение 199 снимков /
|
||
81 исследование, валидация 53 снимка / 19 исследований, 16 нарушений.
|
||
|
||
| Метрика | Значение | Как получено |
|
||
|---|---|---|
|
||
| ROC-AUC | **0.6764** [0.6309, 0.7218] | 5 seed'ов на фиксированном разбиении, эталон — вердикт эксперта |
|
||
| PR-AUC | 0.4759 [0.4141, 0.5377] | там же |
|
||
| F1 | 0.5676 [0.5270, 0.6082] | там же; порог подобран по F1 на валидации, поэтому смещён вверх |
|
||
| ROC-AUC по областям | позвоночник 0.943, бедро R 0.576, бедро L 0.550 | рабочий чекпоинт, его собственная валидация |
|
||
|
||
Рабочий чекпоинт — обычный прогон с seed по умолчанию (эпоха 39, порог логита
|
||
−0.4930 → вероятность 0.379), его собственная валидационная ROC-AUC 0.6706
|
||
близка к среднему по seed'ам, то есть результат не отобран по удачности.
|
||
|
||
Проверка, что модель смотрит на снимок, а не угадывает анатомию: внутри областей
|
||
она даёт AUC 0.85–0.93, правило «позвоночник значит нарушение» — ровно 0.50.
|
||
Числа считаются на всём наборе, включая обучающие снимки, поэтому смещены вверх и
|
||
отвечают на вопрос «есть ли вклад содержимого», а не «каково качество на новых
|
||
данных».
|
||
|
||
## 9. Ограничения
|
||
|
||
1. **Разметка унаследована от исследования.** Таблица оценивает исследование, а
|
||
не снимок; перенос однозначен, потому что область встречается один раз, но
|
||
исходная оценка всё равно не поштучная.
|
||
2. **Мало данных:** 252 снимка, 77 нарушений. Интервалы широкие.
|
||
3. **Эталон — та же таблица.** Независимой истины нет; вариант, обучавшийся на
|
||
таблице, в сравнении в выигрышном положении.
|
||
4. **Тип нарушения — эвристика**, а не вывод модели: 5 снимков имеют только
|
||
`unspecified`, у остальных тип приходит из критериев таблицы.
|
||
5. **Три снимка без экспертной оценки** размечены по пометке в имени файла и
|
||
помечены `filename_fallback`.
|
||
6. **Сторона бедра в 7 исследованиях не проверяема:** теги латеральности пусты.
|
||
7. **Корректность областей интереса наследуется из таблицы:** разметки ROI в
|
||
DICOM нет, сравнить её напрямую не с чем.
|
||
|
||
## 10. Отрицательный результат: локальная vision-модель
|
||
|
||
Планировалась визуальная разметка локальной vision-моделью (9 млрд параметров,
|
||
офлайн), чтобы не зависеть от таблицы. На калибровке по 14 снимкам, из которых 8
|
||
заведомо с нарушениями, модель вынесла «непригоден» всем 14, включая все
|
||
качественные, с шаблонными формулировками и выдуманными имплантами. Разделяющая
|
||
способность — на уровне случайной, поэтому как разметчик модель непригодна.
|
||
|
||
Вывод, который стоит зафиксировать: разделяющую способность инструмента нужно
|
||
проверять **до** того, как строить на нём пайплайн. Инструменты рендера снимков и
|
||
контактных листов остались в `src/dxa/render.py` — они полезны для выборочной
|
||
ручной проверки.
|
||
|
||
## 11. Воспроизведение
|
||
|
||
```bash
|
||
./run.sh label # разметка по экспертной таблице
|
||
./run.sh rename # имена файлов (план; --apply)
|
||
./run.sh split && ./run.sh compare # выбор правила метки, 5 seed'ов
|
||
python -m src.dxa.excel_labels --label-rule union --out-name labels_images_union
|
||
python -m src.dxa.render --by-region --out dataset_hack/_preview
|
||
```
|
||
|
||
## 12. Что дальше
|
||
|
||
- Поштучная разметка снимков специалистом — снимет ограничение №1.
|
||
- Мультилейбл по типам нарушений вместо эвристики.
|
||
- Больше исследований (500+), чтобы сузить интервалы.
|
||
- Калибровка порога определения области под конкретное оборудование.
|