blockedImage
и глубокое обучениеВ этом примере показано, как классифицировать мультиразрешение целых изображения (WSIs), которые не помещаются в памяти, используя Inception-v3 глубокую нейронную сеть.
Единственным окончательным способом диагностики рака молочной железы является исследование выборок тканей, собранных при биопсии или хирургии. Выборки обычно готовят с окрашиванием гематоксилином и эозином (H&E) для повышения контрастности структур в ткани. Традиционно патологоанатомы исследуют ткани на стеклянных слайдах под микроскопом, чтобы обнаружить опухолевую ткань. Диагностика занимает время, поскольку патологоанатомы должны тщательно осмотреть целый слайд при близком увеличении. Кроме того, патологоанатомы могут не замечать мелких опухолей. Методы глубокого обучения направлены на автоматизацию обнаружения опухолевой ткани, экономию времени и улучшение скорости обнаружения небольших опухолей.
Методы глубокого обучения для классификации опухолей полагаются на цифровую патологию, при которой скольжения всей ткани визуализируются и оцифровываются. Получившиеся WSI имеют чрезвычайно высокое разрешение. WSI часто хранятся в файле мультиразрешения, чтобы облегчить отображение, навигацию и обработку изображений.
Чтение WSI является проблемой, потому что изображения не могут быть загружены как единое целое в память и, следовательно, требуют неядерных методов обработки изображений. Вы можете хранить и обрабатывать этот тип большого мультирезолюционного изображения при помощи blockedImage
(Image Processing Toolbox) объекты. Можно извлечь пакеты данных из blockedImage
объекты, использующие blockedImageDatastore
(Image Processing Toolbox) объекты.
Этот пример показов, как обучить нейронную сеть для глубокого обучения классифицировать опухоли на очень больших мультиразрешениях изображениях с помощью blockedImage
и blockedImageDatastore
. Пример представляет результаты классификации как тепловые карты, которые изображают вероятность того, что локальная ткань является опухолевой. Локализация опухолевых областей позволяет медицинским патологоанатомам исследовать определенные области и быстро идентифицировать опухоли любого размера на изображении.
В этом примере используются WSI из Camelyon16 задачи [1]. Данные этой проблемы содержат в общей сложности 400 WSI лимфатических узлов из двух независимых источников, разделенных на 270 обучающих изображений и 130 тестовых изображений. WSI хранятся как файлы TIF в обрезанном формате с 11-уровневой структурой пирамиды.
Обучающие данные состоят из 159 WSI нормальных лимфатических узлов и 111 WSI лимфатических узлов с опухолью и здоровой тканью. Обычно опухолевая ткань является небольшой частью здоровой ткани. Основные истины контуров поражения сопровождают изображения опухоли.
Размер каждого обучающего файла составляет приблизительно 2 ГБ. Если вы не хотите загружать обучающие данные или обучать сеть, перейдите непосредственно в раздел Train или Download the Network в этом примере.
Создайте директорию для хранения обучающих данных.
trainingImageDir = fullfile(tempdir,'Camelyon16','training'); if ~exist(trainingImageDir,'dir') mkdir(trainingImageDir); mkdir(fullfile(trainingImageDir,'normal')); mkdir(fullfile(trainingImageDir,'tumor')); mkdir(fullfile(trainingImageDir,'lesion_annotations')); end trainNormalDataDir = fullfile(trainingImageDir,'normal'); trainTumorDataDir = fullfile(trainingImageDir,'tumor'); trainTumorAnnotationDir = fullfile(trainingImageDir,'lesion_annotations');
Чтобы загрузить обучающие данные, перейдите на веб-сайт Camelyon17 и щелкните первую ссылку «CAMELYON16 data set». Откройте директорию «обучение», а затем выполните следующие действия.
Загрузите файл «lesion_annotations.zip». Извлеките файлы в директорию, заданный trainTumorAnnotationDir
переменная.
Откройте «нормальную » директорию. Загрузите изображения в директорию, заданный trainNormalDataDir
переменная.
Откройте директорию «опухоль». Загрузите изображения в директорию, заданный trainTumorDataDir
переменная.
Укажите количество обучающих изображений. Обратите внимание, что одно из обучающих изображений нормальной ткани, 'normal _ 144.tif', имеет метаданные, которые не могут быть считаны blockedImage
объект. Этот пример использует оставшиеся 158 файлов обучения.
numNormalFiles = 158; numTumorFiles = 111;
Чтобы лучше изучить обучающие данные, отобразите одно обучающее изображение. Поскольку загрузка всего изображения в память в самом высоком разрешении невозможна, вы не можете использовать традиционные функции отображения изображений, такие как imshow
. Чтобы отобразить и обработать данные изображения, используйте blockedImage
(Image Processing Toolbox) объект.
Создайте blockedImage
объект из обучающего изображения опухоли.
tumorFileName = fullfile(trainTumorDataDir,'tumor_001.tif');
tumorImage = blockedImage(tumorFileName);
Осмотрите размерности blockedImage
на каждом уровне разрешения. Уровень 1 имеет больше всего пикселей и является лучшим уровнем разрешения. Уровень 10 имеет наименьшее количество пикселей и является самым грубым уровнем разрешения. Соотношение сторон не является последовательным, что указывает на то, что уровни не все охватывают одну и ту же мировую площадь.
levelSizeInfo = table((1:length(tumorImage.Size))', ... tumorImage.Size(:,1), ... tumorImage.Size(:,2), ... tumorImage.Size(:,1)./tumorImage.Size(:,2), ... 'VariableNames',["Resolution Level" "Image Width" "Image Height" "Aspect Ratio"])
levelSizeInfo=11×4 table
Resolution Level Image Width Image Height Aspect Ratio
________________ ___________ ____________ ____________
1 2.2118e+05 97792 2.2618
2 1.1059e+05 49152 2.25
3 55296 24576 2.25
4 27648 12288 2.25
5 13824 6144 2.25
6 7168 3072 2.3333
7 1577 3629 0.43455
8 3584 1536 2.3333
9 2048 1024 2
10 1024 512 2
11 512 512 1
Отобразите blockedImage
на уровне грубого разрешения при помощи bigimageshow
(Image Processing Toolbox) функция. Верните указатель на bigimageshow
объект. Для настройки отображения можно использовать указатель. Изображение содержит много пустого белого пространства. Ткань занимает лишь небольшой фрагмент изображения.
h = bigimageshow(tumorImage,'ResolutionLevel',8);
Масштабирование одной части изображения путем установки горизонтального и вертикального пространственных границ относительно уровня наименьшего разрешения. Изображение выглядит размытым, потому что этот уровень разрешения очень грубый.
xlim([29471,29763]); ylim([117450,118110]);
Для получения дополнительной информации измените уровень разрешения на более мелкий.
h.ResolutionLevel = 1;
Вы можете уменьшить количество расчета, обрабатывая только видимые области (ROIs). Используйте маску для определения ROIs. Маска является логическим изображением, в котором true
пиксели представляют информация только для чтения.
Чтобы дополнительно уменьшить количество расчетов, создайте маски на уровне грубого разрешения, который может быть полностью обработан в памяти, а не на базисе. Если пространственная привязка уровня грубого разрешения совпадает с пространственной привязкой более мелких уровней разрешения, то местоположения на грубом уровне соответствуют местоположениям на более мелких уровнях. В этом случае можно использовать грубую маску, чтобы выбрать, какие блоки обрабатывать на более мелких уровнях. Для получения дополнительной информации смотрите Настройка пространственных ссылок для заблокированных изображений (Image Processing Toolbox) и Эффективно обрабатывать заблокированные изображения с помощью маски (Image Processing Toolbox).
Задает уровень разрешения для создания маски. Этот пример использует уровень разрешения 7, который является грубым и помещается в памяти. Обратите внимание, что blockedImage
объект автоматически сортирует уровни в мультиразрешение изображении от мельчайших до грубейших на основе количества пикселей на каждом уровне. Несколько Camelyon16 файлов изображений содержат маску промежуточного разрешения. Этот пример игнорирует маску при определении и считывании седьмого уровня данных изображения.
resolutionLevel = 7;
На нормальных изображениях информация только для чтения состоит из здоровой ткани. Цвет здоровой ткани отличается от цвета фона, поэтому используйте порог цвета, чтобы сегментировать изображение и создать информация только для чтения. Цветовое пространство L * a * b * обеспечивает лучшее цветоделение для сегментации. Преобразуйте изображение в цветовое пространство L * a * b *, затем пороговите канал a *, чтобы создать тканевую маску.
Можно использовать функцию helper createMaskForNormalTissue
чтобы создать маски с помощью порога цвета. Эта вспомогательная функция присоединена к примеру как вспомогательный файл.
Вспомогательная функция выполняет эти операции на каждом обучающем изображении нормальной ткани:
Создайте blockedImage
объект из файла изображений TIF.
Установите пространственные ссылки на все уровни разрешения из метаданных изображения.
Получите изображение на уровне грубого разрешения.
Преобразуйте грубое изображение в цветовое пространство L * a * b *, затем извлеките канал a *.
Создайте бинарное изображение путем порога изображения с помощью метода Otsu, который минимизирует внутриклассовое отклонение между черным и белым пикселями.
Создайте одно разрешение blockedImage
объект из маски и установите пространственную ссылку маски так, чтобы она совпадала с пространственной привязкой входного изображения.
Напишите маску blockedImage
в память. Только blockedImage
объект находится в памяти. Отдельные блоки изображений, соответствующие логическому изображению маски, находятся во временной директории. Запись в директорию сохраняет пользовательские пространственные ссылки, что гарантирует, что обычные изображения и соответствующие им маскировочные изображения имеют одинаковые пространственные ссылки.
trainNormalMaskDir = fullfile(trainNormalDataDir,['normal_mask_level' num2str(resolutionLevel)]);
createMaskForNormalTissue(trainNormalDataDir,trainNormalMaskDir,resolutionLevel)
Теперь, когда и обычные изображения, и маски находятся на диске, создайте blockedImage
объекты для управления данными с помощью вспомогательной функции createBlockedImageAndMaskArrays
. Эта функция создает массив blockedImage
объекты из нормальных изображений и соответствующий массив blockedImage
объекты из изображений обычной маски. Функция helper присоединена к примеру как вспомогательный файл.
[normalImages,normalMasks] = createBlockedImageAndMaskArrays(trainNormalDataDir,trainNormalMaskDir);
Выберите выборку обычного изображения и маски. Подтвердите, что пространственные границы мира маски совпадают с границами изображения на самом высоком уровне разрешения. Пространственные границы мира заданы WorldStart
и WorldEnd
свойства.
idx = 2; [normalImages(idx).WorldStart normalImages(idx).WorldEnd]
ans = 11×6
105 ×
0 0 0.0000 2.2118 0.9779 0.0000
0 0 0.0000 2.2118 0.9830 0.0000
0 0 0.0000 2.2118 0.9830 0.0000
0 0 0.0000 2.2118 0.9830 0.0000
0 0 0.0000 2.2118 0.9830 0.0000
0 0 0.0000 2.2938 0.9830 0.0000
0.0000 0.0000 0.0000 2.2118 0.9779 0.0000
0 0 0.0000 2.2938 0.9830 0.0000
0 0 0.0000 2.6214 1.3107 0.0000
0 0 0.0000 2.6214 1.3107 0.0000
⋮
[normalMasks(idx).WorldStart normalMasks(idx).WorldEnd]
ans = 1×4
0 0 221184 97792
Проверьте, что маска содержит правильные ROI и пространственные ссылки. Отобразите образец изображения при помощи bigimageshow
функция. Получите оси, содержащие отображение.
figure hNormal = bigimageshow(normalImages(idx)); hNormalAxes = hNormal.Parent;
Создайте новые оси поверх отображаемой blockedImage
. В новых осях отобразите соответствующее изображение маски с частичной прозрачностью. Маска подсвечивает области, содержащие нормальную ткань.
hMaskAxes = axes; hMask = bigimageshow(normalMasks(idx),'Parent',hMaskAxes, ... 'Interpolation','nearest','AlphaData',0.5); hMaskAxes.Visible = 'off';
Соедините оси изображения с осями маски. При масштабировании и панорамировании обе оси обновляются идентично.
linkaxes([hNormalAxes,hMaskAxes]);
Масштабирование одной части изображения путем установки горизонтального и вертикального пространственных границ. Маска правильно перекрывает нормальную ткань.
xlim([45000 80000]); ylim([130000 165000]);
На опухолевых изображениях информация только для чтения состоит из опухолевой ткани. Цвет опухолевой ткани похож на цвет здоровой ткани, поэтому вы не можете использовать методы сегментации цвета. Вместо этого создайте ROIs с помощью основной истины координат контуров поражения, которые сопровождают изображения опухоли.
Можно использовать функцию helper createMaskForTumorTissue
чтобы создать маску с помощью ROIs. Эта вспомогательная функция присоединена к примеру как вспомогательный файл.
Вспомогательная функция выполняет эти операции на каждом обучающем изображении опухолевой ткани:
Создайте blockedImage
объект из файла изображений TIF.
Установите пространственные ссылки из метаданных изображения.
Прочитайте соответствующие аннотации поражения в XML- файлах и преобразуйте аннотации в многоугольники (Polygon
(Image Processing Toolbox) объекты).
Для каждого блока изображений используйте многоугольники, чтобы создать маску для соответствующего блока. Изображения с опухолевыми областями могут содержать в себе некоторые нормальные области. Используйте аннотации нормальной ткани, чтобы исключить эти области.
Создайте выход логическую маску blockedImage
объект на более грубом уровне разрешения. Запишите изображение маски на блок-за- базис при помощи setBlock
функция.
Напишите маску blockedImage
объект в директорию в памяти. Только blockedImage
объект находится в памяти. Отдельные блоки изображений, соответствующие логическому изображению маски, находятся во временной директории. Запись в директорию сохраняет пользовательскую пространственную ссылку, которая гарантирует, что опухолевые изображения и соответствующие им масковые изображения имеют одинаковую пространственную ссылку.
trainTumorMaskDir = fullfile(trainTumorDataDir,['tumor_mask_level' num2str(resolutionLevel)]); createMaskForTumorTissue(trainTumorDataDir,trainTumorAnnotationDir, ... trainTumorMaskDir,resolutionLevel);
Теперь, когда и изображения опухоли, и маски находятся на диске, создайте blockedImage
объекты для управления данными с помощью вспомогательной функции createBlockedImageAndMaskArrays
. Эта функция создает массив blockedImage
объекты из изображений опухоли и соответствующий массив blockedImage
объекты из изображений маски опухоли. Функция helper присоединена к примеру как вспомогательный файл.
[tumorImages,tumorMasks] = createBlockedImageAndMaskArrays(trainTumorDataDir,trainTumorMaskDir);
Выберите образец изображения опухоли и маски. Подтвердите, что пространственные границы мира маски совпадают с границами изображения на самом высоком уровне разрешения. Пространственные границы мира заданы XWorldLimits
и YWorldLimits
свойства.
idx = 5; [tumorImages(idx).WorldStart tumorImages(idx).WorldEnd]
ans = 11×6
105 ×
0 0 0.0000 2.1965 0.9779 0.0000
0 0 0.0000 2.2016 0.9830 0.0000
0 0 0.0000 2.2118 0.9830 0.0000
0 0 0.0000 2.2118 0.9830 0.0000
0 0 0.0000 2.2118 0.9830 0.0000
0 0 0.0000 2.2938 0.9830 0.0000
0.0000 0.0000 0.0000 2.1965 0.9779 0.0000
0 0 0.0000 2.2938 0.9830 0.0000
0 0 0.0000 2.6214 1.3107 0.0000
0 0 0.0000 2.6214 1.3107 0.0000
⋮
[tumorMasks(idx).WorldStart tumorMasks(idx).WorldEnd]
ans = 1×4
0 0 219648 97792
Проверьте, что маска содержит правильные ROI и пространственные ссылки. Отобразите образец изображения при помощи bigimageshow
функция. Получите оси, содержащие отображение.
figure hTumor = bigimageshow(tumorImages(idx)); hTumorAxes = hTumor.Parent;
Создайте новые оси поверх отображаемой blockedImage
. В новых осях отобразите соответствующее изображение маски с частичной прозрачностью. Маска подсвечивает области, содержащие нормальную ткань.
hMaskAxes = axes; hMask = bigimageshow(tumorMasks(idx),'Parent',hMaskAxes, ... 'Interpolation','nearest','AlphaData',0.5); hMaskAxes.Visible = 'off';
Соедините оси изображения с осями маски. При масштабировании и панорамировании обе оси обновляются идентично.
linkaxes([hTumorAxes,hMaskAxes]);
Масштабирование одной части изображения путем установки горизонтального и вертикального пространственных границ. Маска перекрывает опухолевую ткань правильно.
xlim([45000 65000]); ylim([130000 150000]);
Чтобы извлечь закрашенные фигуры обучающих данных из blockedImage
объекты, используйте blockedImageDatastore
(Image Processing Toolbox). Этот datastore считывает закрашенные фигуры blockedImage
данные на одном уровне разрешения.
Цветовой дисбаланс и классовый дисбаланс в необработанных обучающих закрашенных фигурах могут потенциально смещать сеть. Цветовой дисбаланс является результатом неоднородного окрашивания ткани. Классовый дисбаланс возникает из-за неравного количества опухоли и нормальной ткани в данных. Чтобы исправить эти дисбалансы, можно предварительно обработать и увеличить datastore.
В этом примере показано, как создать blockedImageDatastore
который извлекает опухоль и нормальные закрашенные фигуры для обучения сети. Пример также показывает, как предварительно обработать и увеличить хранилища данных, чтобы избежать смещения сети.
Случайным образом разделите нормальные изображения и соответствующие маски на два набора. Набор валидации содержит два случайным образом выбранных изображения и соответствующие маски. Этот набор обучающих данных содержит оставшиеся изображения и маски.
normalValnIdx = randi(numNormalFiles,[1 2]); normalTrainIdx = setdiff(1:numNormalFiles,normalValnIdx);
Размер закрашенной фигуры невелик по сравнению с размером функций на изображении. По умолчанию a blockedImageDatastore
извлекает закрашенные фигуры без перекрытия и без зазора, что генерирует огромное количество обучающих закрашенных фигур. Можно уменьшить объем обучающих данных, задав подмножество закрашенных фигур. Задайте координаты закрашенных фигур с помощью selectBlockLocations
(Image Processing Toolbox) функция. Добавьте погрешность между выборочными закрашенными фигурами для обучения с помощью BlockOffsets
аргумент имя-значение. Задайте смещение, больше, чем размер закрашенной фигуры. Увеличьте порог включения от значения по умолчанию 0,5, чтобы сеть обучалась на относительно однородных закрашенных фигурах.
patchSize = [299,299,3]; normalStrideFactor = 10; blsNormalData = selectBlockLocations(normalImages(normalTrainIdx), ... "BlockSize",patchSize(1:2),"BlockOffsets",patchSize(1:2)*normalStrideFactor, ... "Masks",normalMasks(normalTrainIdx),"InclusionThreshold",0.75,"ExcludeIncompleteBlocks",true);
Выберите местоположение закрашенных фигур для валидации. Поскольку изображений валидации меньше, вам не нужно добавлять зазор между закрашенными фигурами.
blsNormalDataVal = selectBlockLocations(normalImages(normalValnIdx), ... "BlockSize",patchSize(1:2), ... "Masks",normalMasks(normalValnIdx),"InclusionThreshold",0.75,"ExcludeIncompleteBlocks",true);
Создайте хранилища данных dsNormalData
и dsNormalDataVal
которые считывают закрашенные фигуры изображений от нормальных изображений на самом высоком уровне разрешения для обучения и валидации, соответственно. Задайте координаты закрашенных фигур с помощью BlockLocationSet
аргумент пары "имя-значение".
dsNormalData = blockedImageDatastore(normalImages(normalTrainIdx), ... "BlockLocationSet",blsNormalData); dsNormalDataVal = blockedImageDatastore(normalImages(normalValnIdx), ... "BlockLocationSet",blsNormalDataVal);
Предварительный просмотр закрашенных фигур из datastore, содержащих нормальные обучающие изображения.
imagesToPreview = zeros([patchSize 10],'uint8'); for n = 1:10 im = read(dsNormalData); imagesToPreview(:,:,:,n) = im{1}; end figure montage(imagesToPreview,'Size',[2 5],'BorderSize',10,'BackgroundColor','k');
title("Training Patches of Normal Tissue")
Случайным образом разделите изображения опухоли и соответствующие маски на два набора. Набор валидации содержит два случайным образом выбранных изображения и соответствующие маски. Этот набор обучающих данных содержит оставшиеся изображения и маски.
tumorValIdx = randi(numTumorFiles,[1 2]); tumorTrainIdx = setdiff(1:numTumorFiles,tumorValIdx);
Задайте координаты закрашенных фигур для чтения с помощью selectBlockLocations
функция. Опухолевая ткань является более разреженной, чем нормальная ткань, поэтому увеличение плотности дискретизации путем определения меньшего смещения блока, чем для нормальной ткани. Обратите внимание, что если вы хотите обучаться с использованием меньшего количества обучающих изображений, то, возможно, вам потребуется увеличить размер набора обучающих данных, уменьшив смещение блока еще больше.
tumorStrideFactor = 3; blsTumorData = selectBlockLocations(tumorImages(tumorTrainIdx), ... "BlockSize",patchSize(1:2),"BlockOffsets",patchSize(1:2)*tumorStrideFactor, ... "Masks",tumorMasks(tumorTrainIdx),"InclusionThreshold",0.75,"ExcludeIncompleteBlocks",true);
Выберите местоположение закрашенных фигур для валидации. Поскольку изображений валидации меньше, вам не нужно добавлять зазор между закрашенными фигурами.
blsTumorDataVal = selectBlockLocations(tumorImages(tumorValIdx), ... "BlockSize",patchSize(1:2), ... "Masks",tumorMasks(tumorValIdx),"InclusionThreshold",0.75,"ExcludeIncompleteBlocks",true);
Создайте blockedImageDatastore
из обучающих изображений опухоли и масок. Хранилища данных dsTumorData
и dsTumorDataVal
считывайте закрашенные фигуры с изображений опухоли на самом высоком уровне разрешения для обучения и валидации, соответственно.
dsTumorData = blockedImageDatastore(tumorImages(tumorTrainIdx), ... "BlockLocationSet",blsTumorData); dsTumorDataVal = blockedImageDatastore(tumorImages(tumorValIdx), ... "BlockLocationSet",blsTumorDataVal);
Предварительный просмотр закрашенных фигур из datastore, содержащих обучающие изображения опухоли.
imagesToPreview = zeros([patchSize 10],'uint8'); for n = 1:10 im = read(dsTumorData); imagesToPreview(:,:,:,n) = im{1}; end montage(imagesToPreview,'Size',[2 5],'BorderSize',10,'BackgroundColor','k'); title("Training Patches of Tumor Tissue")
Обучающие изображения имеют различные цветовые распределения, потому что набор данных пришел из разных источников, и окрашивание ткани цветом не приводит к одинаково окрашенным изображениям. Дополнительная предварительная обработка необходима, чтобы избежать смещения сети.
Чтобы предотвратить изменчивость цвета, этот пример предварительно обрабатывает данные стандартными методами нормализации окрашивания. Примените нормализацию и увеличение пятна при помощи transform
функция с пользовательскими операциями предварительной обработки, заданными функцией helper augmentAndLabelCamelyon16
. Эта функция присоединена к примеру как вспомогательный файл.
The augmentAndLabelCamelyon16
функция выполняет следующие операции:
Нормализуйте окрашивание при помощи normalizeStaining.m
функция [4]. Нормализацию окрашивания осуществляют методом Маченко, который разделяет цветовые каналы H&E цветом деконволюции с помощью фиксированной матрицы и затем воссоздает нормализованные изображения с индивидуальным исправленным смешиванием. Функция возвращает нормированное изображение, а также изображения H & E.
Добавьте цветовой джиттер при помощи jitterColorHSV
(Image Processing Toolbox) функция. Цветовой джиттер изменяет цвет каждой закрашенной фигуры, возмущая контрастность изображения, оттенок, насыщение и яркость. Дрожание цвета выполняется в цветовом пространстве HSV, чтобы избежать нежелательных программных продуктов цвета в изображении RGB.
Применить случайные комбинации поворотов на 90 степени и вертикального и горизонтального отражения. Рандомизированные аффинные преобразования делают сеть агностической к ориентации входных данных изображения.
Пометьте закрашенную фигуру следующим 'normal'
или 'tumor'
.
Каждая закрашенная фигура изображения генерирует пять дополненных и маркированные закрашенные фигуры: окрашенно-нормализованный закрашенная фигура, окрашенно-нормализованный закрашенная фигура с цветным дрожанием, окрашенно-нормализованный закрашенная фигура с цветным дрожанием и случайным аффинным преобразованием, гематоксилиновое изображение со случайным аффинным преобразованием и эозиновое изображение со случайным аффинным преобразованием.
Создайте хранилища данных, которые преобразуют нормальные изображения для обучения и валидации и пометьте сгенерированные закрашенные фигуры как 'normal'
.
dsLabeledNormalData = transform(dsNormalData, ... @(x,info)augmentAndLabelCamelyon16(x,info,'normal'),'IncludeInfo',true); dsLabeledNormalDataVal = transform(dsNormalDataVal, ... @(x,info)augmentAndLabelCamelyon16(x,info,'normal'),'IncludeInfo',true);
Создайте хранилища данных, которые преобразуют изображения обучения и валидации опухоли и пометьте сгенерированные закрашенные фигуры как 'tumor'
.
dsLabeledTumorData = transform(dsTumorData, ... @(x,info)augmentAndLabelCamelyon16(x,info,'tumor'),'IncludeInfo',true); dsLabeledTumorDataVal = transform(dsTumorDataVal, ... @(x,info)augmentAndLabelCamelyon16(x,info,'tumor'),'IncludeInfo',true);
Количество раковой ткани в изображениях опухоли очень мало по сравнению с количеством нормальной ткани. Дополнительная предварительная обработка необходима, чтобы избежать настройки сети на несбалансированных по классам данных, содержащих большое количество нормальной ткани и очень небольшое количество опухолевой ткани.
Чтобы предотвратить дисбаланс классов, этот пример задает пользовательский datastore, называемый randomSamplingDatastore
который случайным образом выбирает нормальные и опухолевые обучающие закрашенные фигуры сбалансированным образом. Скрипт для определения этого пользовательского datastore присоединен к примеру как вспомогательный файл. Для получения дополнительной информации см. Раздел «Разработка пользовательского Datastore».
Создайте пользовательскую randomSamplingDatastore
из нормальных и опухолевых обучающих хранилищ данных. datastore случайной выборки dsTrain
предоставляет мини-пакеты обучающих данных в сеть при каждой итерации эпохи.
dsTrain = randomSamplingDatastore(dsLabeledTumorData,dsLabeledNormalData);
Чтобы ограничить количество закрашенных фигур, используемых во время валидации, этот пример задает пользовательский datastore, называемое validationDatastore
который возвращает пять закрашенных фигур валидации из каждого класса. Скрипт для определения этого пользовательского datastore присоединен к примеру как вспомогательный файл.
Создайте пользовательскую validationDatastore
из хранилищ данных нормальной и опухолевой валидации.
numValidationPatchesPerClass = 5;
dsVal = validationDatastore(dsLabeledTumorDataVal, ...
dsLabeledNormalDataVal,numValidationPatchesPerClass);
Этот пример использует Inception-v3 сеть, сверточную нейронную сеть, которая обучена более чем на миллионе изображений из базы данных ImageNet [3]. Сеть имеет глубину 48 слоев и может классифицировать изображения в 1000 категорий объектов, таких как клавиатура, мышь, карандаш и многие животные. Сеть ожидает размер входа изображения 299 на 299 с 3 каналами.
The inceptionv3
функция возвращает предварительно обученную Inception-v3 сеть. Inception-v3 требуется модель Deep Learning Toolbox™ для пакета поддержки Inception-v3 Network. Если этот пакет поддержки не установлен, то функция предоставляет ссылку на загрузку.
net = inceptionv3;
Сверточные слои сети извлекают изображение, функции последний выучиваемый слой и конечный слой классификации используют для классификации входа изображения. Эти два слоя содержат информацию о том, как объединить функции, которые сеть извлекает в вероятности класса, значение потерь и предсказанные метки. Чтобы переобучить предварительно обученную сеть для классификации новых изображений, замените эти два слоя новыми слоями, адаптированными к новому набору данных. Для получения дополнительной информации смотрите Обучите нейронную сеть для глубокого обучения для классификации новых изображений.
Извлеките график слоев из обученной сети.
lgraph = layerGraph(net);
Найдите имена двух слоев, которые нужно заменить с помощью вспомогательной функции findLayersToReplace
. Эта функция присоединена к примеру как вспомогательный файл. В Inception-v3 эти два слоя названы 'predictions'
и 'ClassificationLayer_predictions'
.
[learnableLayer,classLayer] = findLayersToReplace(lgraph)
learnableLayer = FullyConnectedLayer with properties: Name: 'predictions' Hyperparameters InputSize: 2048 OutputSize: 1000 Learnable Parameters Weights: [1000×2048 single] Bias: [1000×1 single] Show all properties
classLayer = ClassificationOutputLayer with properties: Name: 'ClassificationLayer_predictions' Classes: [1000×1 categorical] ClassWeights: 'none' OutputSize: 1000 Hyperparameters LossFunction: 'crossentropyex'
Цель этого примера состоит в том, чтобы выполнить двоичную сегментацию между двумя классами, опухолевыми и нетуморными областями. Создайте новый полносвязный слой для двух классов. Замените исходный конечный полносвязный слой новым слоем.
numClasses = 2; newLearnableLayer = fullyConnectedLayer(numClasses,'Name','predictions'); lgraph = replaceLayer(lgraph,learnableLayer.Name,newLearnableLayer);
Создайте новый слой классификации для двух классов. Замените исходный слой окончательной классификации новым слоем.
newClassLayer = classificationLayer('Name','ClassificationLayer_predictions'); lgraph = replaceLayer(lgraph,classLayer.Name,newClassLayer);
Обучите сеть с помощью rmsprop
решатель оптимизации. Этот решатель автоматически настраивает скорость и импульс обучения для более быстрого сходимости. Задайте другие установки гиперпараметров при помощи trainingOptions
функция. Уменьшите MaxEpochs
в небольшом количестве, потому что большой объем обучающих данных позволяет сети достичь сходимости раньше.
checkpointsDir = fullfile(trainingImageDir,'checkpoints'); if ~exist(checkpointsDir,'dir') mkdir(checkpointsDir); end options = trainingOptions('rmsprop', ... 'InitialLearnRate',1e-5, ... 'SquaredGradientDecayFactor',0.99, ... 'MaxEpochs',3, ... 'MiniBatchSize',32, ... 'Plots','training-progress', ... 'CheckpointPath',checkpointsDir, ... 'ValidationData',dsVal, ... 'ExecutionEnvironment','auto', ... 'Shuffle','every-epoch');
По умолчанию пример загружает предварительно обученную версию обученной Inception-v3 сети с помощью функции helper downloadTrainedCamelyonNet
. Функция helper присоединена к примеру как вспомогательный файл. Предварительно обученная сеть позволяет запускать весь пример, не дожидаясь завершения обучения.
Чтобы обучить сеть, установите doTraining
переменная в следующем коде, для true
. Обучите сеть с помощью trainNetwork
функция.
Обучите на графическом процессоре, если он доступен. Для использования GPU требуется Parallel Computing Toolbox™ и графический процессор с поддержкой CUDA ® NVIDIA ®. Для получения дополнительной информации смотрите Поддержку GPU by Release (Parallel Computing Toolbox). Обучение занимает около 20 часов на NVIDIA Titan X.
doTraining = false; if doTraining trainedNet = trainNetwork(dsTrain,lgraph,options); modelDateTime = string(datetime('now','Format',"yyyy-MM-dd-HH-mm-ss")); save(strcat("trainedCamelyonNet-",modelDateTime,".mat"),'trainedNet'); else trainedCamelyonNet_url = 'https://www.mathworks.com/supportfiles/vision/data/trainedCamelyonNet.mat'; netDir = fullfile(tempdir,'Camelyon16'); downloadTrainedCamelyonNet(trainedCamelyonNet_url,netDir); load(fullfile(netDir,'trainedCamelyonNet.mat')); end
Pretrained Inception-v3 network for Cameylon16 data set already exists.
Набор Camelyon16 тестовых данных состоит из 130 WSI. Эти изображения имеют как нормальную, так и опухолевую ткань. Этот пример использует два тестовых изображения из Camelyon16 тестовых данных. Размер каждого файла составляет приблизительно 2 ГБ.
Создайте директорию для хранения тестовых данных.
testingImageDir = fullfile(tempdir,'Camelyon16','testing'); if ~exist(testingImageDir,'dir') mkdir(testingImageDir); mkdir(fullfile(testingImageDir,'images')); mkdir(fullfile(testingImageDir,'lesion_annotations')); end testDataDir = fullfile(testingImageDir,'images'); testTumorAnnotationDir = fullfile(testingImageDir,'lesion_annotations');
Чтобы загрузить тестовые данные, перейдите на веб-сайт Camelyon17 и щелкните первую ссылку «CAMELYON16 data set». Откройте директорию « проверку», а затем выполните следующие действия.
Загрузите файл «lesion_annotations.zip». Извлечь все файлы в директорию, заданный testTumorAnnotationDir
переменная.
Откройте директорию « изображения». Загрузите первые два файла, «test_001.tif» и «test_002.tif.» Переместите файлы в директорию, заданный testDataDir
переменная.
Укажите количество тестовых изображений.
numTestFiles = 2;
Тестовые изображения содержат смесь нормальных и опухолевых изображений. Чтобы уменьшить количество расчетов во время классификации, задайте ROIs путем создания масок.
Задает уровень разрешения для создания маски. Этот пример использует уровень разрешения 7, который является грубым и помещается в памяти.
resolutionLevel = 7;
Создайте маски для областей, содержащих ткани. Можно использовать функцию helper createMaskForNormalTissue
чтобы создать маски с помощью порога цвета. Эта вспомогательная функция присоединена к примеру как вспомогательный файл. Для получения дополнительной информации об этой вспомогательной функции см. Раздел «Создание масок для нормальных изображений».
testTissueMaskDir = fullfile(testDataDir,['test_tissuemask_level' num2str(resolutionLevel)]);
createMaskForNormalTissue(testDataDir,testTissueMaskDir,resolutionLevel);
Создайте маски для изображений, которые содержат опухолевую ткань. Пропустите изображения, которые не содержат опухолевую ткань. Можно использовать функцию helper createMaskForTumorTissue
создание масок с использованием объектов информация только для чтения. Эта вспомогательная функция присоединена к примеру как вспомогательный файл. Для получения дополнительной информации об этой вспомогательной функции см. Раздел «Создание масок для изображений опухоли».
testTumorMaskDir = fullfile(testDataDir,['test_tumormask_level' num2str(resolutionLevel)]);
createMaskForTumorTissue(testDataDir,testTumorAnnotationDir,testTumorMaskDir,resolutionLevel);
Каждое тестовое изображение имеет две маски, одну, указывающую на нормальную ткань, и одну, указывающую на опухолевую ткань. Создание blockedImage
объекты для управления тестовыми данными и масками с помощью функции helper createBlockedImageAndMaskArrays
. Функция helper присоединена к примеру как вспомогательный файл.
[testImages,testTissueMasks] = createBlockedImageAndMaskArrays(testDataDir,testTissueMaskDir); [~,testTumorMasks] = createBlockedImageAndMaskArrays(testDataDir,testTumorMaskDir);
Используйте обученную Inception-v3 сеть для идентификации опухолевых закрашенных фигур на тестовых изображениях, testImages
. Классифицируйте тестовые изображения по блокам базиса при помощи apply
(Image Processing Toolbox) с пользовательским конвейером обработки, заданным функцией helper tumorProbabilityHeatMap
. Эта вспомогательная функция присоединена к примеру как вспомогательный файл. Чтобы уменьшить количество необходимых расчетов, укажите тканевую маску testTissueMask
так что apply
функция обрабатывает только закрашенные фигуры, которые содержат ткани. Задайте 'UseParallel'
Аргумент пары "имя-значение" как логическое значение, возвращаемое canUseGPU
. Если поддерживаемый графический процессор доступен для расчетов, то apply
функция оценивает блоки параллельно.
The tumorProbabilityHeatMap
функция выполняет эти операции над каждым тканевым блоком:
Вычислите счет вероятности опухоли при помощи predict
функция.
Создайте закрашенную фигуру изображения тепловой карты с пиксельными значениями, равными счету вероятности опухоли.
The apply
функция сшивает тепловую карту каждого блока в одну тепловую карту для тестового изображения. Тепловая карта показывает, где сеть обнаруживает области, содержащие опухоли.
Чтобы визуализировать тепловую карту, наложите тепловую карту на оригинальное изображение и установите 'AlphaData' прозрачности
свойство как тканевая маска. Оверлей показывает, насколько хорошо опухоль локализована на изображении. Области с высокой вероятностью опухолей отображаются с красными пикселями. Области с низкой вероятностью опухолей отображаются в виде синих пикселей.
outputHeatmapsDir = fullfile(testingImageDir,'heatmaps'); if ~exist(outputHeatmapsDir,'dir') mkdir(outputHeatmapsDir); end patchSize = [299,299,3]; for idx = 1:numTestFiles bls = selectBlockLocations(testImages(idx),'BlockSize',patchSize(1:2),'Mask',testTissueMasks(idx),... 'InclusionThreshold',0,'Levels',1); testHeatMaps(idx) = apply(testImages(idx),@(x)tumorProbabilityHeatMap(x,trainedNet), ... 'Level',1,'BlockLocationSet',bls,'UseParallel',canUseGPU,'OutputLocation',outputHeatmapsDir); figure hTest = bigimageshow(testImages(idx)); hTestAxes = hTest.Parent; hTestAxes.Visible = 'off'; hMaskAxes = axes; hMask = bigimageshow(testHeatMaps(idx),'Parent',hMaskAxes, ... "Interpolation","nearest","AlphaData",testTissueMasks(idx)); colormap(jet(255)); hMaskAxes.Visible = 'off'; linkaxes([hTestAxes,hMaskAxes]); title(['Tumor Heatmap of Test Image ',num2str(idx)]); end
[1] Ehteshami B. B., et al. «Диагностическая оценка алгоритмов глубокого обучения для обнаружения метастазов в лимфатических узлах у женщин с раком молочной железы». Журнал Американской медицинской ассоциации. Том 318, № 22, 2017, с. 2199-2210. doi: 10.1001/jama.2017.14585
[2] Szegedy, C., V. Vanhoucke, S. Ioffe, J. Shlens, and Z. Wojna. «Переосмысление архитектуры создания компьютерного зрения». В работе Конференции IEEE по компьютерному зрению и распознаванию шаблона, 2818-2826. Лас-Вегас, NV: IEEE, 2016.
[3] ImageNet. http://www.image-net.org.
[4] Macenko, M. et al. Метод нормализации гистологических слайдов для количественного анализа. В 2009 году IEEE International Symposium on Biomedical Imaging: From Nano to Macro, 1107-1110. Бостон, Массачусетс: IEEE, 2009.
[5] xml2struct https://www.mathworks.com/matlabcentral/fileexchange/28518-xml2struct.
trainingOptions
| trainNetwork
| transform
| bigimageshow
(Image Processing Toolbox) | blockedImage
(Image Processing Toolbox) | blockedImageDatastore
(Набор Image Processing Toolbox) | blockLocationSet
(Набор Image Processing Toolbox) | selectBlockLocations
(Набор Image Processing Toolbox)