В этом примере показано, как подготовить datastore для настройки сети регрессии изображение-изображение с помощью transform
и combine
функции ImageDatastore
.
Этот пример показывает, как обработать данные предварительно с помощью конвейера, подходящего для настройки обесценивающей сети. Этот пример затем использует предварительно обработанные данные шума, чтобы обучить простую сверточную сеть автоэнкодера для удаления шума изображения.
Этот пример использует модель шума соли и перца, в которой часть входных пикселей изображения заданы как 0
или 1
(черный и белый, соответственно). Шумные изображения выступают в качестве входов сети. Первозданные изображения действуют как ожидаемый сетевой ответ. Сеть учится обнаруживать и удалять шум от соли и перца.
Загрузите первозданные изображения в набор данных как imageDatastore
. datastore содержит 10 000 синтетических изображений цифр от 0 до 9. Изображения генерируются путем применения случайных преобразований к цифровым изображениям, созданным различными шрифтами. Каждое цифровое изображение составляет 28 на 28 пикселей. datastore содержит равное количество изображений в категории.
digitDatasetPath = fullfile(matlabroot,'toolbox','nnet', ... 'nndemos','nndatasets','DigitDataset'); imds = imageDatastore(digitDatasetPath, ... 'IncludeSubfolders',true, ... 'LabelSource','foldernames');
Задайте большой размер чтения, чтобы минимизировать стоимость ввода-вывода файлов.
imds.ReadSize = 500;
Установите seed глобального генератора случайных чисел, чтобы помочь в воспроизводимости результатов.
rng(0)
Используйте shuffle
функция для тасования данных цифр перед обучением.
imds = shuffle(imds);
Используйте splitEachLabel
функция для деления imds
в три хранилища изображений, содержащих первозданные изображения для обучения, валидации и проверки.
[imdsTrain,imdsVal,imdsTest] = splitEachLabel(imds,0.95,0.025);
Используйте transform
функция для создания шумных версий каждого входного изображения, которое будет служить входом сети. The transform
функция считывает данные из базового datastore и обрабатывает данные с помощью операций, заданных в вспомогательной функции addNoise
(определено в конце этого примера). Выходные выходы transform
функция является TransformedDatastore
.
dsTrainNoisy = transform(imdsTrain,@addNoise); dsValNoisy = transform(imdsVal,@addNoise); dsTestNoisy = transform(imdsTest,@addNoise);
Используйте combine
функция для объединения шумных изображений и нетронутых изображений в один datastore, который передает данные в trainNetwork
. Этот комбинированный datastore считывает пакеты данных в массив ячеек с двумя столбцами, как ожидалось trainNetwork
. Выходные выходы combine
функция является CombinedDatastore
.
dsTrain = combine(dsTrainNoisy,imdsTrain); dsVal = combine(dsValNoisy,imdsVal); dsTest = combine(dsTestNoisy,imdsTest);
Используйте transform
функция для выполнения дополнительных операций предварительной обработки, которые являются общими для входов входных и ответных данных. The commonPreprocessing
функция помощника (определенный в конце этого примера) изменяет размеры входа и изображений ответа к 32 на 32 пикселя, чтобы соответствовать размеру входа сети, и нормализует данные в каждом изображении к области значений [0, 1].
dsTrain = transform(dsTrain,@commonPreprocessing); dsVal = transform(dsVal,@commonPreprocessing); dsTest = transform(dsTest,@commonPreprocessing);
Наконец, используйте transform
функция для добавления рандомизированного увеличения к набору обучающих данных. The augmentImages
вспомогательная функция (заданная в конце этого примера) применяет рандомизированные повороты на 90 степени к данным. Идентичные повороты применяются к входу сети и соответствующим ожидаемым откликам.
dsTrain = transform(dsTrain,@augmentImages);
Увеличение уменьшает сверхподбор кривой и добавляет робастности наличию вращений в обученной сети. Рандомизированное увеличение не требуется для наборов валидационных или тестовых данных.
Поскольку для подготовки обучающих данных необходимо выполнить несколько операций предварительной обработки, предварительно просмотрите предварительно обработанные данные, чтобы подтвердить, что они выглядят правильными перед обучением. Используйте preview
функция для предварительного просмотра данных.
Визуализируйте примеры парных шумных и первозданных изображений с помощью montage
(Image Processing Toolbox) функция. Обучающие данные выглядят правильно. Шум от соли и перца появляется на входных изображениях в левом столбце. Кроме сложения шума, входа изображение и изображение отклика одинаковы. Рандомизированное вращение на 90 степени применяется как к входному, так и к ответному изображениям одинаковым образом.
exampleData = preview(dsTrain); inputs = exampleData(:,1); responses = exampleData(:,2); minibatch = cat(2,inputs,responses); montage(minibatch','Size',[8 2]) title('Inputs (Left) and Responses (Right)')
Сверточные автоэнкодеры являются общей архитектурой для шумоподавления изображений. Сверточные автоэнкодеры состоят из двух этапов: энкодера и декодера. Энкодер сжимает исходное входное изображение в латентное представление, которое меньше по ширине и высоте, но глубже в том смысле, что существует много карт функций на пространственное расположение, чем исходное входное изображение. Сжатое латентное представление теряет некоторое пространственное разрешение в своей способности восстанавливать высокую частоту функций в оригинальное изображение, но также учится не включать шумные программные продукты в кодировку оригинального изображения. Декодер неоднократно увеличивает дискретизированный сигнал, чтобы переместить его назад на его исходную ширину, высоту и количество каналов. Поскольку энкодер удаляет шум, декодированное окончательное изображение имеет меньше программные продукты шума.
Этот пример определяет сверточную сеть автоэнкодера с использованием слоев из Deep Learning Toolbox™, включая:
imageInputLayer
- Входной слой изображения
convolution2dLayer
- Слой свертки для сверточных нейронных сетей
reluLayer
- Выпрямленный слой линейного модуля
maxPooling2dLayer
- 2-D максимального слоя объединения
transposedConv2dLayer
- Транспонированный слой свертки
clippedReluLayer
- Обрезанный выпрямленный слой линейного модуля
regressionLayer
- Выходной слой регрессии
Создайте входной слой изображения. Чтобы упростить проблемы заполнения, связанные с понижающей дискретизацией и увеличением дискретизации на два фактора, выберите размер входа 32 на 32, потому что 32 чисто делится на 2, 4 и 8.
imageLayer = imageInputLayer([32,32,1]);
Создайте слои кодирования. Понижающая дискретизация в энкодере достигается за счет максимального объединения с размером пула 2 и полосой 2.
encodingLayers = [ ... convolution2dLayer(3,16,'Padding','same'), ... reluLayer, ... maxPooling2dLayer(2,'Padding','same','Stride',2), ... convolution2dLayer(3,8,'Padding','same'), ... reluLayer, ... maxPooling2dLayer(2,'Padding','same','Stride',2), ... convolution2dLayer(3,8,'Padding','same'), ... reluLayer, ... maxPooling2dLayer(2,'Padding','same','Stride',2)];
Создайте слои декодирования. Декодер увеличивает амплитуду закодированного сигнала, используя транспонированный слой свертки. Создайте транспонированный слой свертки с правильным коэффициентом повышающей дискретизации при помощи createUpsampleTransponseConvLayer
вспомогательная функция. Эта функция определяется в конце этого примера.
Сеть использует clippedReluLayer
как конечный слой активации, чтобы заставить выходы находиться в области значений [0, 1].
decodingLayers = [ ... createUpsampleTransponseConvLayer(2,8), ... reluLayer, ... createUpsampleTransponseConvLayer(2,8), ... reluLayer, ... createUpsampleTransponseConvLayer(2,16), ... reluLayer, ... convolution2dLayer(3,1,'Padding','same'), ... clippedReluLayer(1.0), ... regressionLayer];
Объедините входной слой изображений, слои кодирования и слои декодирования, чтобы сформировать сверточную сетевую архитектуру автоэнкодера.
layers = [imageLayer,encodingLayers,decodingLayers];
Обучите сеть с помощью оптимизатора Adam. Задайте установки гиперпараметров при помощи trainingOptions
функция. Тренируйтесь на 100 эпох.
options = trainingOptions('adam', ... 'MaxEpochs',100, ... 'MiniBatchSize',imds.ReadSize, ... 'ValidationData',dsVal, ... 'Plots','training-progress', ... 'Verbose',false);
Теперь, когда источник данных и опции обучения сконфигурированы, обучите сверточную сеть автоэнкодера с помощью trainNetwork
функция.
Обучите на графическом процессоре, если он доступен. Для использования GPU требуется Parallel Computing Toolbox™ и графический процессор с поддержкой CUDA ® NVIDIA ®. Для получения дополнительной информации смотрите Поддержку GPU by Release (Parallel Computing Toolbox). Обучение занимает около 25 минут на NVIDIA Titan XP.
net = trainNetwork(dsTrain,layers,options);
modelDateTime = string(datetime('now','Format',"yyyy-MM-dd-HH-mm-ss")); save(strcat("trainedImageToImageRegressionNet-",modelDateTime,".mat"),'net');
Получите выходные изображения из тестового набора при помощи predict
функция.
ypred = predict(net,dsTest);
Визуализируйте выборку входного изображения и связанный с ним выход предсказания из сети, чтобы получить представление о том, насколько хорошо работает денуазация. Как ожидалось, выходное изображение из сети удалило большую часть программных продуктов шума с входом изображения. Деноминированное изображение слегка размыто в результате процесса кодирования и декодирования.
inputImageExamples = preview(dsTest); montage({inputImageExamples{1},ypred(:,:,:,1)});
Оцените эффективность сети путем анализа пикового отношения сигнал/шум (PSNR).
ref = inputImageExamples{1,2}; originalNoisyImage = inputImageExamples{1,1}; psnrNoisy = psnr(originalNoisyImage,ref)
psnrNoisy = single
17.8455
psnrDenoised = psnr(ypred(:,:,:,1),ref)
psnrDenoised = single
21.8439
PSNR выходного изображения выше шумного входного изображения, как и ожидалось.
The addNoise
функция helper добавляет соль и перец шум к изображениям при помощи imnoise
(Image Processing Toolbox) функция. The addNoise
функция требует, чтобы формат входных данных представлял собой массив ячеек с данными изображений, который соответствует формату данных, возвращаемых read
функция ImageDatastore
.
function dataOut = addNoise(data) dataOut = data; for idx = 1:size(data,1) dataOut{idx} = imnoise(data{idx},'salt & pepper'); end end
The commonPreprocessing
Функция helper задает предварительную обработку, которая является общей для наборов обучения, валидации и тестов. Функция helper выполняет эти шаги предварительной обработки.
Функция helper требует, чтобы формат входных данных был двухколоночным массивом ячеек данных изображения, который соответствует формату данных, возвращаемых read
функция CombinedDatastore
.
function dataOut = commonPreprocessing(data) dataOut = cell(size(data)); for col = 1:size(data,2) for idx = 1:size(data,1) temp = single(data{idx,col}); temp = imresize(temp,[32,32]); temp = rescale(temp); dataOut{idx,col} = temp; end end end
The augmentImages
вспомогательная функция добавляет рандомизированные повороты на 90 степени к данным при помощи rot90
функция. Идентичные повороты применяются к входу сети и соответствующим ожидаемым откликам. Функция требует, чтобы формат входных данных был двухколоночным массивом ячеек данных изображения, который соответствует формату данных, возвращенных read
функция CombinedDatastore
.
function dataOut = augmentImages(data) dataOut = cell(size(data)); for idx = 1:size(data,1) rot90Val = randi(4,1,1)-1; dataOut(idx,:) = {rot90(data{idx,1},rot90Val),rot90(data{idx,2},rot90Val)}; end end
The createUpsampleTransposeConvLayer
Функция helper задает транспонированный слой свертки, который увеличивает входной параметр слоя на заданный коэффициент.
function out = createUpsampleTransponseConvLayer(factor,numFilters) filterSize = 2*factor - mod(factor,2); cropping = (factor-mod(factor,2))/2; numChannels = 1; out = transposedConv2dLayer(filterSize,numFilters, ... 'NumChannels',numChannels,'Stride',factor,'Cropping',cropping); end
combine
| imageDatastore
| trainingOptions
| trainNetwork
| transform