Разработка AI-системы анализа медицинских изображений

AI-система анализа медицинских изображений

Направления AI-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1302
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    998
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1267
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    714
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1006

AI-система анализа медицинских изображений

Представьте: рентгенолог просматривает 100 снимков в день, усталость нарастает, а пропущенный узелок в лёгком — это уже клинический случай. Мы сталкивались с ситуацией, когда модель даёт 99% accuracy, но на редкой патологии ошибается с катастрофической уверенностью. Именно поэтому мы строим медицинские CV-системы, которые не просто детектируют аномалии, но и честно сообщают о неуверенности, а врач остаётся в контуре принятия решений.

Медицинский CV требует не только высокой accuracy, но и калиброванной уверенности, интерпретируемости (Grad-CAM, SHAP), соответствия регуляторам (MDR, FDA 510(k)) и обязательного human-in-the-loop для высокорисковых решений. Наш опыт — 7+ лет в ML для здравоохранения, 12+ коммерческих проектов, включая сертифицированные системы. Гарантируем прозрачность каждого этапа — от прототипа до клинического применения.

Какие архитектуры оптимальны для медицинской CV?

Выбор backbone зависит от модальности. DenseNet121 показывает лучшее соотношение качество/скорость для рентгена — на 15% выше AUC по сравнению с ResNet50 на CheXpert. Для КТ используем 3D ResNet или 2.5D ensemble (3 ортогональных среза). В гистологии эффективна EfficientNet с патч-стратегией (слайд разбивается на 512x512 тайлы). По нашим тестам, EfficientNet-B3 превосходит DenseNet121 по F1 на 0.03 при равной скорости вывода, но требует больше GPU памяти.

Почему объяснимость критична в медицинском AI?

Врач никогда не поверит "чёрному ящику". Grad-CAM показывает, на каком регионе модель фокусируется: затемнение в лёгком, утолщение плевры. Исследование Rajpurkar et al. (2017) показало, что CheXNet достигает AUC 0.92, но без объяснения модель бесполезна в клинике. Мы всегда поставляем heatmap вместе с предсказанием, а для критических случаев добавляем SHAP-значения. Больше о Grad-CAM.

Как мы строим надёжный пайплайн предобработки?

Предобработка — основа любой медицинской CV-системы. DICOM-файлы содержат метаданные (RescaleSlope, WindowCenter) и пиксельные массивы в Hounsfield units для КТ. Без правильного windowing модель будет видеть «шум» вместо патологии. Мы используем pydicom (официальная документация) для чтения и преобразования. Для рентгена — перцентильное масштабирование (1-99%), для КТ — оконное с настраиваемыми параметрами.

Также обязательна аугментация: RandomRotation, ElasticTransform, но с осторожностью — медицинские данные чувствительны к геометрическим искажениям.

import pydicom import numpy as np import cv2 def dicom_to_array( dcm_path: str, target_modality: str = 'xray', window_center: float = None, window_width: float = None ) -> np.ndarray: """ Нормализация DICOM в диапазон [0, 255] uint8. Для КТ обязательно windowing по HU. """ dcm = pydicom.dcmread(dcm_path) array = dcm.pixel_array.astype(np.float32) slope = float(getattr(dcm, 'RescaleSlope', 1)) intercept = float(getattr(dcm, 'RescaleIntercept', 0)) array = array * slope + intercept if target_modality == 'ct': wc = window_center or float(getattr(dcm, 'WindowCenter', -600)) ww = window_width or float(getattr(dcm, 'WindowWidth', 1500)) lower = wc - ww / 2 upper = wc + ww / 2 array = np.clip(array, lower, upper) elif target_modality == 'xray': p1, p99 = np.percentile(array, [1, 99]) array = np.clip(array, p1, p99) arr_min, arr_max = array.min(), array.max() if arr_max > arr_min: array = (array - arr_min) / (arr_max - arr_min) * 255 return array.astype(np.uint8) 

Детекция патологий на рентгене: CheXNet-подход

import torch import torch.nn as nn import timm from torch.cuda.amp import autocast PATHOLOGY_CLASSES = [ 'Atelectasis', 'Cardiomegaly', 'Consolidation', 'Edema', 'Enlarged Cardiomediastinum', 'Fracture', 'Lung Lesion', 'Lung Opacity', 'No Finding', 'Pleural Effusion', 'Pleural Other', 'Pneumonia', 'Pneumothorax', 'Support Devices' ] class ChestXRayClassifier(nn.Module): def __init__( self, backbone: str = 'densenet121', num_classes: int = 14, pretrained: bool = True ): super().__init__() self.backbone = timm.create_model( backbone, pretrained=pretrained, num_classes=0, global_pool='avg' ) feat_dim = self.backbone.num_features self.classifier = nn.Sequential( nn.Linear(feat_dim, 512), nn.ReLU(), nn.Dropout(0.3), nn.Linear(512, num_classes) ) def forward(self, x: torch.Tensor) -> torch.Tensor: features = self.backbone(x) return self.classifier(features) class WeightedBCEWithLogitsLoss(nn.Module): def __init__(self, pos_weights: torch.Tensor): """ pos_weights[i] = n_neg[i] / n_pos[i] для класса i. CheXpert: типичный дисбаланс 15:1 - 100:1. """ super().__init__() self.loss_fn = nn.BCEWithLogitsLoss(pos_weight=pos_weights) def forward(self, logits, targets): return self.loss_fn(logits, targets) 

Grad-CAM для объяснимости

Интерпретируемость обязательна — врач видит, где модель ошибается или права. Grad-CAM генерирует тепловую карту, накладываемую на оригинал.

import torch import numpy as np import cv2 class GradCAM: def __init__(self, model: nn.Module, target_layer: nn.Module): self.model = model self.gradients = None self.activations = None target_layer.register_forward_hook( lambda m, i, o: setattr(self, 'activations', o) ) target_layer.register_backward_hook( lambda m, gi, go: setattr(self, 'gradients', go[0]) ) def generate( self, image_tensor: torch.Tensor, target_class: int, original_size: tuple ) -> np.ndarray: self.model.eval() output = self.model(image_tensor) self.model.zero_grad() output[0, target_class].backward() weights = self.gradients.mean(dim=[2, 3], keepdim=True) cam = (weights * self.activations).sum(dim=1, keepdim=True) cam = torch.relu(cam).squeeze().cpu().numpy() cam = (cam - cam.min()) / (cam.max() - cam.min() + 1e-8) cam = cv2.resize(cam, (original_size[1], original_size[0])) return cam 

Как мы тестируем модель на редких патологиях?

Для редких заболеваний (распространённость < 1%) стандартное train/test разделение не подходит. Мы используем few-shot learning (модель обучается на 5-10 примерах) и реалистичную симуляцию: подкладываем редкие патологии в тестовый набор с разными дозами. Метрики считаем отдельно для частых и редких классов. Если recall на редком классе < 0.7 — включаем дополнительный детектор или rule-based фильтр. Такой подход уже применялся в проекте по выявлению интерстициальных заболеваний лёгких: recall вырос с 0.4 до 0.85.

Метрики для медицинской классификации

Метрика Использование Почему не accuracy
AUC-ROC Основная метрика Устойчива к дисбалансу
Sensitivity (Recall) Критична для скрининга Пропустить болезнь — хуже
Specificity Баланс с sensitivity Ложные тревоги — нагрузка
F1 (micro/macro) Multi-label задачи Баланс P/R
Calibration (ECE) Уверенность модели Для клинического доверия

Процесс работы

  1. Аналитика и аудит данных: сбор требований, оценка качества датасета, распределение классов.
  2. Проектирование архитектуры: выбор backbone (DenseNet, 3D ResNet, EfficientNet), стратегия fine-tuning (LoRA, full fine-tune).
  3. Обучение и валидация: кросс-валидация, мониторинг метрик (AUC, sensitivity, ECE), тестирование на редких классах.
  4. Интеграция объяснимости: Grad-CAM, SHAP для каждого предсказания.
  5. Деплой и MLOps: Triton Inference Server, ONNX Runtime, A/B тестирование, логирование дрейфа.
  6. Документация и сертификация: model card, отчёт по валидации, поддержка при подготовке к CE/FDA.

Сроки

Задача Срок
Классификатор патологий рентгена (fine-tuning) 4–6 недель
Детекция/сегментация на КТ/МРТ 8–14 недель
Медицинская система с CE/FDA-документацией 20–40 недель

Готовы оценить ваш датасет и посчитать метрики на пилотном проекте? Свяжитесь с нами — проведём аудит за 2 дня и предложим архитектуру. Реализуем систему под ключ: от сбора требований до развёртывания в клинике.