AI endoscopy: how to train the network
ИИ-эндоскопия: как обучить нейросеть
Методика для команды проекта и специалистов больницы: какие снимки собрать, как их обезличить и разметить, как обучить сеть, проверить её и выпустить модель для модуля «ИИ-эндоскопия». Все шаги выполняются программами из modules/or_endo/training/ (Python 3.10+, pip install -r training/requirements.txt). Как пользоваться модулем на Vidicap — в инструкции «ИИ-эндоскопия (доп. модуль)».
Главное правило данных. Снимки и видео эндоскопий — персональные данные пациентов. Они не покидают больницу: сбор, обезличивание, разметка и обучение идут на сервере больницы (или на рабочей станции в её сети). Таблица «пациент ↔ псевдоним» хранится только у больницы. Наружу (в том числе нам) может уйти только готовая модель — файл с весами сети, в котором снимков нет.
Два пути к данным. (1) В больнице — всё ниже: записи, обезличивание и разметка на сервере больницы. (2) На платформе — раздел «Обучение ИИ» на vidicap.cloud (инструкция «Обучение ИИ на платформе»): врач-участник программы, с разрешения своей клиники, открывает свои видео и фото в браузере, обрезает и закрашивает всё, что может указать на пациента, и отправляет только эти обезличенные кадры; эксперт проверяет разметку, а компьютер обучения (training/worker.py) собирает тестовую модель теми же программами, что описаны здесь. Видео и фото целиком на платформу не попадают.
Весь путь одной строкой: запись → кадры → обезличивание → разметка в CVAT → проверка и разбиение по пациентам → обучение → выбор порогов на val → итоговая проверка на test → пакет модели → установка на Vidicap → сбор ошибок кнопкой «Сохранить кадр» → следующая версия.
1. Что сеть должна находить
| Класс | Что размечаем | Что НЕ размечаем |
|---|---|---|
polyp — полип |
любой полип толстой кишки (и желудка) по Парижской классификации: на ножке (0-Ip), на широком основании (0-Is), плоские (0-IIa/b/c), латерально стелющиеся (LST) | складки, остатки кала, пузыри, лимфоидные фолликулы, основание удалённого полипа |
neoplasm — новообразование |
подозрение на рак, изъязвлённая или деформирующая опухоль, подслизистое образование | доброкачественные полипы (это polyp), рубцы, анастомоз |
bleeding — кровотечение |
активное кровотечение (струя, подтекание, Forrest Ia/Ib), свежая кровь в просвете, сосуд или сгусток на дне язвы (IIa/IIb) | окрашивание слизистой, старая гематин-кровь без источника, блики, красное освещение |
ulcer — язва, эрозия |
дефекты слизистой: язвы и эрозии | следы биопсии и полипэктомии (если это не цель разметки), повреждения от инструмента |
Классы и их порядок закреплены в training/common.py и в модуле: менять их можно только вместе с новой версией модуля. Один объект — один класс; если врач сомневается между polyp и neoplasm, решает гистология (атрибут histology), а до неё — эксперт-арбитр.
2. Какие снимки нужны и сколько
Сеть узнаёт только то, что видела. Поэтому важно не только количество, но и разнообразие:
- Оборудование: видеопроцессоры и эндоскопы всех производителей, которые есть в больницах проекта (Olympus, Pentax, Fujifilm…), разных поколений; разное разрешение и сжатие записи.
- Режимы света: белый свет (WLI) — основной; NBI, BLI, LCI, хромоскопия — отдельными записями с пометкой
light. - Органы: толстая кишка (основной), желудок, двенадцатиперстная кишка, пищевод — с пометкой
organ. - Находки: полипы всех размеров, особенно мелкие (≤ 5 мм) и плоские — их чаще всего пропускают люди и сети; кровотечения разной силы; язвы и эрозии.
- Трудные «пустые» кадры (не меньше трети набора): нормальная слизистая, пузыри, пена, остатки содержимого, плохая подготовка, блики, размытие при движении, инструменты (щипцы, петля, клипсы), вода при промывании, дивертикулы, баугиниева заслонка, аппендикулярное отверстие, анастомозы. Без них сеть отмечает всё подряд.
- Целые процедуры, а не только кадры с находками: по ним меряется главное для врача — сколько ложных отметок в минуту.
Ориентиры объёма (по опыту опубликованных систем CADe; уточняются по результатам каждой версии):
| Этап | Процедур (пациентов) | Находок | Размеченных кадров | Статус модели |
|---|---|---|---|---|
| Пилот | 150–300 | от 500 полипов, от 100 кровотечений и язв | 10–20 тыс. с находками + столько же «пустых» | исследовательская |
| Первая клиническая версия | 1 000+ из 3+ больниц | от 3 000 полипов | 50–100 тыс. | после регистрации — для клиники |
Внешний тест — записи другой больницы, которая не дала ни одного кадра для обучения. Только он показывает, как модель поведёт себя на новом месте.
Откуда брать снимки
- Записи Vidicap и архив больницы — основной источник:
training/frames.pyдостаёт кадры из MP4. - Кнопка «Сохранить кадр для обучения» на экране модуля: кадр с отметками сети и вердиктом врача («ИИ прав», «Ложная отметка», «ИИ пропустил»). Это самые ценные кадры — ошибки текущей модели.
- Открытые наборы — для первой модели и для сравнения, после проверки лицензии на странице набора и в файле лицензии внутри него. Проверено в октябре 2026: - можно в продаваемой модели (CC BY 4.0, с указанием авторов): HyperKvasir, PolypGen, GastroVision, Kvasir-Capsule; - только проверка, не обучение: REAL-Colon. На странице figshare и в статье указано CC BY 4.0, но в описании внутри самого набора стоит CC BY-NC-SA 4.0 (без коммерческого использования). До письменного разрешения авторов он используется только как тестовая часть; - только исследования: SUN Colonoscopy (коммерческое использование по разрешению лаборатории Mori), CVC-ClinicDB и CVC-ColonDB (по договору). У LDPolypVideo лицензия на видео не указана.
training/public.py переносит HyperKvasir, PolypGen и REAL-Colon в наш набор (раздел «Первая модель на открытых данных»). Каждый кадр помечается "source": "public:<имя набора>", а в dataset.json записывается список наборов с лицензиями и ссылками для цитирования. Этот список попадает в карточку модели.
3. Право и этика
До начала сбора:
- договор с больницей о совместной работе с данными и решение этического комитета больницы (протокол исследования, цель — разработка системы поддержки врача);
- информированное согласие пациентов или основание для использования обезличенных данных по закону страны (Беларусь, Россия, Казахстан, страны ЕС — правила разные, решает юрист больницы);
- назначенный в больнице ответственный за ключи псевдонимов и за удаление данных пациента по его просьбе.
4. Кадры из записей
python3 training/frames.py запись.mp4 raw/<номер-истории>/<номер-исследования>/ --fps 1
python3 training/frames.py запись.mp4 raw/<номер-истории>/<номер-исследования>/ --fps 25 --from 00:12:30 --to 00:13:10
- Вся процедура — 1–2 кадра в секунду: это «пустые» кадры и общий фон.
- Отрезки с находками — каждый кадр (25–30 в секунду), от первого появления находки до последнего: так находка размечается как трек, и проверка меряет время до отметки.
- Кадры называются
f<номер кадра>.jpg, папки — как принято в больнице (номер истории, номер исследования). Эти названия заменятся псевдонимами на следующем шаге.
5. Обезличивание
python3 training/deid.py --in raw/ --out dataset/ --keys /защищённая/папка/endo-keys/ --crop auto
Что делает программа:
- Обрезает кадр по изображению эндоскопа (
--crop autoнаходит освещённую область, как кнопка «Найти автоматически» в модуле). Поля видеопроцессора с именем, датой, номером истории отрезаются. - Перекодирует кадр в JPEG без EXIF и любых метаданных, под случайным именем.
- Заменяет номер истории и исследования псевдонимами (
P0042,E0107); таблица соответствия пишется только в--keys. Программа откажется писать ключи внутрь набора. - Не добавляет второй раз уже обезличенный кадр.
После программы — ручная проверка: человек просматривает не меньше 5 % кадров каждой записи (и все кадры, где видна часть экрана видеопроцессора) — нет ли текста, лиц, бейджей, наклеек. Кадр с идентификатором удаляется, запись проверяется целиком.
Ключи нужны, чтобы позже добавить гистологию и удалить кадры пациента по его просьбе. Без ключей набор уже не связан с людьми.
6. Разметка в CVAT
CVAT (открытая программа разметки, лицензия MIT) ставится на сервер больницы в Docker и доступен только из её сети.
- Создайте проект «Vidicap endoscopy», вкладка Constructor → Raw, вставьте содержимое
training/cvat-labels.json: четыре класса с цветами модуля и атрибутами (Paris, размер, гистология, Forrest, «видна частично»). - Задачи — по одной процедуре (папка кадров из
dataset/imagesодногоprocedure). Отрезки с находками — задачей «видео» (кадры по порядку), чтобы размечать треками: одна находка — один трек через все кадры, где она видна. - Экспорт — COCO 1.0; импорт в набор:
python3 training/dataset.py import-cvat dataset/ export.json(номера треков становятсяlesion_id).
Правила рамки
- Рамка — по границе видимой части находки, плотно, без запаса. Полип на ножке — головка и видимая ножка.
- Находка видна меньше чем на четверть, закрыта складкой или в сильном размытии — рамку ставим, атрибут «видна частично». Такие кадры сеть учит, а проверка их не считает обязательными.
- Несколько рядом стоящих полипов — каждый своей рамкой. Кровотечение — рамка по источнику и свежей крови рядом с ним, не по всей луже в просвете.
- Сомнение — не угадывать: пометка «на арбитраж» (комментарий в CVAT).
- Атрибуты, которые известны (размер по оценке эндоскописта, Paris, Forrest), заполняются; гистология — после ответа патоморфолога, по ключам псевдонимов.
Кто размечает и как проверяется
- Разметчики — врачи-эндоскописты (не меньше двух), перед началом — обучение на 50 эталонных кадрах с разбором ошибок.
- Двойная разметка не меньше 20 % процедур: два врача независимо. Согласие считается по находкам (рамки совпали при IoU ≥ 0,5); ниже 80 % — разбор правил и повторная разметка.
- Расхождения решает эксперт-арбитр (эндоскопист с большим опытом). Его решение — окончательное.
- Каждая партия:
python3 training/dataset.py check dataset/— пустые рамки, рамки за краем кадра, неизвестные классы, кадры без файла.
7. Набор: разбиение и проверка
python3 training/dataset.py split dataset/ --val 0.15 --test 0.15 --seed 1
python3 training/dataset.py check dataset/
python3 training/dataset.py stats dataset/
- Разбиение только по пациентам. Все кадры одного пациента — в одной части. Соседние кадры одной процедуры почти одинаковы: сеть, проверенная на соседях своих обучающих кадров, кажется намного лучше, чем есть.
train— обучение,val— выбор эпохи и порогов,test— один раз, для итогового отчёта. Если по test что-то подкручивали, он перестаёт быть проверкой: нужен новый test.- Редкие классы распределяются по частям поровну (разбиение учитывает их сам).
statsпоказывает, сколько кадров, рамок и находок каждого класса в каждой части, по органам, режимам света и источникам. Перекос (например, кровотечения только из одной больницы) — сигнал добрать данные.
8. Обучение
Оборудование: сервер больницы или рабочая станция с видеокартой NVIDIA 12–24 ГБ. На процессоре обучение тоже идёт, но в десятки раз медленнее (годится для проверки цепочки).
python3 training/train.py dataset/ runs/colon-v1 --arch frcnn-mobilenet --size 640 --epochs 40
python3 training/train.py --export runs/colon-v1/best.pt runs/colon-v1/model.onnx
- Архитектура. Начальные модели — Faster R-CNN на MobileNetV3 (
frcnn-mobilenet, быстрая, работает на процессоре Vidicap Touch 2.0) или ResNet-50 (frcnn-resnet50, точнее, для Vidicap AI Server с ускорителем); библиотека torchvision, лицензия BSD. С ~20 тыс. размеченных кадров — трансформеры реального времени D-FINE или RT-DETRv2 (Apache 2.0) их собственными программами обучения; экспорт с теми же тремя выходами (boxes,labels,scores) — и модуль работает с ними без изменений. Ultralytics YOLO распространяется под AGPL-3.0: для закрытого продукта без коммерческой лицензии не используется. - Предобучение. Веса COCO (
--weights coco, по умолчанию): сеть уже умеет видеть края и формы, ей нужно меньше снимков. - Подготовка кадра такая же, как на Vidicap: вписывание в квадрат с серыми полями (114).
- Аугментации — только то, что бывает у эндоскопа: повороты на 90° и зеркало (эндоскоп вращается), яркость, контраст и цвет в пределах разных процессоров, масштаб 0,7–1,3, смаз при движении.
- Баланс. Кадры с редкими классами показываются чаще, но треть каждой партии — кадры без находок.
- Ход обучения. После каждой эпохи — AP50 на val; сохраняется лучшая эпоха (
best.pt). Отдельную партию с потерямиnan/infпрограмма пропускает; если таких больше 20, она остановится: уменьшите--lrвдвое. - Ошибки прошлой версии. Кадры «Ложная отметка» с Vidicap размечаются как «пустые» (или с правильной находкой) и добавляются в train: это самый быстрый способ снизить ложные отметки.
9. Проверка
python3 training/evaluate.py dataset/ runs/colon-v1 --split val --choose --target 0.90
python3 training/evaluate.py dataset/ runs/colon-v1 --split test --thresholds runs/colon-v1/thresholds.json --report runs/colon-v1/test-report.json
Модель запускается тем же кодом, что на Vidicap, и находки проходят через тот же трекер, поэтому цифры — те, что увидит врач.
| Показатель | Что значит | Цель для исследовательской версии |
|---|---|---|
| Чувствительность по находкам | доля находок (lesion_id), отмеченных хотя бы раз, пока они в кадре |
полипы ≥ 90 %, кровотечение ≥ 90 % |
| Специфичность | доля кадров без находок, на которых модель (через трекер) не поставила ни одной отметки | ≥ 95 % |
| Ложные отметки в минуту | рамки, показанные там, где находки нет, на целых процедурах | ≤ 1 в минуту |
| Время до отметки | медиана секунд от появления находки до рамки | ≤ 1 с |
| AP50, чувствительность и точность по кадрам | обычные метрики детекции, по классам | для сравнения версий |
- Пороги выбираются на val (
--choose): для каждого класса — самый высокий порог, при котором чувствительность по кадрам не ниже цели, и затем ниже, пока это не добавляет ложных отметок. Они записываются в модель и работают как «Обычная» чувствительность на экране. - Подгруппы в отчёте обязательно: мелкие полипы (≤ 5 мм), плоские (0-II, LST), каждый режим света, каждый процессор, плохая подготовка. Модель, хорошая «в среднем» и слепая к плоским полипам, не выпускается.
- Внешний тест — набор другой больницы, тем же
evaluate.py. - Скорость:
vidicap-endo bench --model <имя>на Vidicap Touch 2.0 и на Vidicap AI Server — не меньше 10 кадров в секунду.
Классификация: изображение целиком
Для направлений «оценить изображение целиком» (например, УЗИ печени: норма, стеатоз, фиброз) — train_cls.py: MobileNetV3 с весами ImageNet, классы берутся из набора.
python3 training/train_cls.py dataset/ runs/liver-v1 --epochs 30 --size 224
Отчёт test-report.json: точность, чувствительность и специфичность каждого класса, матрица ошибок. Модель экспортируется в ONNX с выходом scores (вероятности классов).
10. Выпуск модели
python3 training/package.py runs/colon-v1/model.onnx --name vidicap-colon --version 1.0.0 \
--title "Колоноскопия: полипы, кровотечение" --status research \
--thresholds runs/colon-v1/thresholds.json --report runs/colon-v1/test-report.json --out dist/
Получается dist/vidicap-endo-model-vidicap-colon-1.0.0.zip: модель, model.json (классы, вход, пороги, результаты проверки, контрольная сумма) и REPORT.md — отчёт для врачей. На Vidicap модель ставится с флешки («Настройки» → «Установить с флешки») или sudo vidicap-endo model-install. Модуль проверяет контрольную сумму: изменённый файл не установится.
Статусы: demo — никогда для пациентов; research — исследования по протоколу, на экране «не для диагностики»; clinical — только после регистрации (раздел 11), с отчётом о проверке (без отчёта программа не соберёт такой пакет).
Версии: новая версия — новые данные или обучение; номер растёт, старые пакеты хранятся вместе с отчётами и списком процедур (псевдонимов), на которых обучались. Так любую отметку на любом Vidicap можно связать с моделью и её проверкой.
С платформы на Vidicap. Пакет загружается на платформу («Выпуски для устройств», тип «Модель ИИ») или приходит от компьютера обучения («Обучение ИИ» → «Тестовые модели»); кнопка «Отправить на Vidicap» делает его доступным. Vidicap показывает его в «Новые модели с платформы» с чувствительностью, специфичностью и ложными в минуту; врач скачивает и включает его, прежняя версия остаётся.
Компьютер обучения (training/worker.py --server https://vidicap.cloud --token vw_…) берёт задания «Собрать тестовую модель», скачивает одобренный набор, делит его по пациентам (dataset.py split), обучает (train.py или train_cls.py), выбирает пороги на val, проверяет на test, собирает пакет (package.py, статус research) и отправляет его на платформу; журнал обучения виден на платформе. Набор удаляется после сборки. Ключ vw_… выдаёт администратор: «Обучение ИИ» → «Участники и приглашения» → «Компьютеры обучения».
После выпуска — цикл: врачи нажимают «Сохранить кадр» на ошибках, специалист больницы раз в месяц забирает кадры (~/endo-dataset/ на Vidicap), обезличивает (deid.py понимает их формат сам), размечает, и они идут в следующую версию.
11. Регистрация как медицинского изделия
Программа, которая отмечает находки при эндоскопии (CADe — computer-aided detection), — медицинское изделие. Для работы с пациентами вне исследований нужна регистрация:
- Беларусь, Россия, ЕАЭС: регистрация медицинского изделия (программное обеспечение) — в Беларуси через Минздрав (РУП «Центр экспертиз и испытаний в здравоохранении»), в России — Росздравнадзор, по правилам ЕАЭС; ожидаемый класс риска 2а–2б; клинические испытания на данных больниц.
- Европейский союз: MDR 2017/745, правило 11 — как правило, класс IIa, оценка нотифицированным органом; кроме того, требования Регламента об ИИ (AI Act) к системам высокого риска.
- Стандарты, по которым строится разработка с самого начала: IEC 62304 (жизненный цикл ПО медицинского изделия), ISO 14971 (управление рисками), ISO 13485 (система менеджмента качества), IEC 62366-1 (юзабилити), IEC 82304-1 (медицинское ПО), принципы надлежащей практики машинного обучения (GMLP).
- Что для этого уже заложено: версии и контрольные суммы моделей, отчёты о проверке на независимых данных, разбиение по пациентам, двойная разметка, журнал происхождения данных (
source, псевдонимы), явные статусы модели на экране, отметка — подсказка, решение — за врачом.
Этот раздел — план, а не юридическая консультация: конкретный путь регистрации определяет регуляторный консультант до начала клинических испытаний.
12. Проверить всю цепочку без данных пациентов
Пока снимков нет, цепочку проверяют на синтетическом наборе из имитатора эндоскопа (тот же, что «Имитатор эндоскопа» в модуле):
python3 training/synth.py dataset-synth/ --videos 12 --seconds 32 --fps 4
python3 training/dataset.py split dataset-synth/
python3 training/train.py dataset-synth/ runs/synth --size 320 --epochs 6 --lr 0.005
python3 training/train.py --export runs/synth/best.pt runs/synth/model.onnx
python3 training/evaluate.py dataset-synth/ runs/synth --split val --choose
python3 training/package.py runs/synth/model.onnx --name sim-colon --version 0.1.0 --title "Имитатор" --status demo \
--thresholds runs/synth/thresholds.json --out dist/
Так проверены все программы этой методики: сеть, обученная на имитаторе за 6 эпох на процессоре, на проверке нашла 100 % находок без ложных отметок и на Vidicap работает со скоростью около 60 кадров в секунду (вход 320×320). Такая сеть знает только имитатор: на настоящий эндоскоп её не ставят.
13. Первая модель на открытых данных
Чтобы проверить всю цепочку на настоящих колоноскопиях, первая модель полипов обучена только на открытых наборах, без данных наших больниц. Она называется «Полипы (открытые данные, тестовая)» 0.1.0, статус «исследовательская».
| Что | Значение |
|---|---|
| Обучение | PolypGen (6 центров, CC BY 4.0) и HyperKvasir (CC BY 4.0): 7706 кадров для обучения, 1331 для выбора порога |
| Сеть | Faster R-CNN MobileNetV3 (frcnn-mobilenet), вход 512×512, 8 эпох на процессоре |
| Порог рамки | 21 % (выбран на проверочной части) |
| На проверочной части (1331 кадр) | находит 90,1 % полипов, из рамок верны 72,7 % |
| На видео колоноскопий другого центра (REAL-Colon, 2 видео, 39 минут) | найдено 7 полипов из 8, первая рамка в среднем через 2,8 с, ложных рамок 7,3 в минуту, кадров без полипа без рамки 87 % |
Как её собрать заново:
cd modules/or_endo/training
python3 public.py hyperkvasir ds/ hyper-kvasir-segmented-images.zip
python3 public.py polypgen ds/ PolypGen2021/
python3 public.py real-colon rc/ 001-007 002-002 --every 10 --test-only # только для проверки
python3 train.py ds/ out/ --epochs 8 --size 512 --batch 4 --lr 0.0025 --per-epoch 1500
python3 evaluate.py ds/ out/ --split val --choose
python3 evaluate.py rc/ out/ --split test --thresholds out/thresholds.json --report out/report.json
python3 package.py out/model.onnx --name polyp-open --version 0.1.0 --title "Полипы (открытые данные, тестовая)" \
--thresholds out/thresholds.json --report out/report.json
Главное, что нужно улучшить, — ложные рамки на бликах и засветке: на видео их около 7 в минуту. Это лечится только кадрами с ваших эндоскопов: отмечайте ложные рамки кнопкой «Сохранить кадр для обучения» → «ложная», и они попадут в следующее обучение. До тех пор техник может поднять порог в настройках модуля («Когда рисовать рамку»).
REAL-Colon в описании набора помечен некоммерческой лицензией (CC BY-NC-SA 4.0). Поэтому он используется только для проверки (
--test-only), в обучение не попадает, а его кадры и видео не публикуются на платформе.
← ИИ-лапароскопия (доп. модуль) AI training on the platform: doctors, experts, administrators →