이 페이지의 내용은 이전 릴리스에 관한 것입니다. 해당 영문 페이지는 최신 릴리스에서 제거되었습니다.

image-to-image 회귀를 위해 데이터저장소 준비하기

이 예제에서는 image-to-image 회귀 네트워크를 훈련시키기 위해 ImageDatastoretransform 함수와 combine 함수를 사용하여 데이터저장소를 준비하는 방법을 보여줍니다.

이 예제에서는 잡음 제거 네트워크 훈련에 적합한 파이프라인을 사용하여 데이터를 전처리하는 방법을 보여줍니다. 그런 다음 전처리된 잡음 데이터를 사용하여 영상 잡음을 제거하도록 간단한 컨벌루션 오토인코더 네트워크를 훈련시킵니다.

전처리 파이프라인을 사용하여 데이터 준비하기

이 예제에서는 입력 영상 픽셀 중 일부가 0 또는 1(각각 검은색과 흰색)로 설정된 점잡음 모델을 사용합니다. 잡음이 있는 영상은 네트워크 입력값으로 기능합니다. 잡음이 빠진 원본 영상은 예상 네트워크 응답 변수로 기능합니다. 네트워크는 점잡음을 검출하고 제거하는 것을 학습합니다.

숫자 데이터 세트에 있는 원본 영상을 imageDatastore로서 불러옵니다. 이 데이터저장소에는 0부터 9까지 숫자를 나타내는 합성 영상 10,000개가 있습니다. 이 영상은 서로 다른 글꼴로 만들어진 숫자 영상에 무작위 변환을 적용하여 생성됩니다. 각 숫자 영상은 28x28픽셀입니다. 이 데이터저장소에는 범주당 동일한 개수의 영상이 포함되어 있습니다.

digitDatasetPath = fullfile(matlabroot,'toolbox','nnet', ...
    'nndemos','nndatasets','DigitDataset');
imds = imageDatastore(digitDatasetPath, ...
    'IncludeSubfolders',true, ...
    'LabelSource','foldernames');

파일 I/O 비용을 최소화할 수 있도록 읽기 크기를 큰 값으로 지정하십시오.

imds.ReadSize = 500;

결과의 재현성을 높이기 위해 전역 난수 생성기의 시드값을 설정합니다.

rng(0)

훈련에 앞서 shuffle 함수를 사용하여 숫자 데이터를 섞습니다.

imds = shuffle(imds);

splitEachLabel 함수를 사용하여 imds를 훈련, 검증 및 테스트를 위한 원래 그대로의 영상을 포함하는 세 개의 영상 데이터저장소로 나눕니다.

[imdsTrain,imdsVal,imdsTest] = splitEachLabel(imds,0.95,0.025);

transform 함수를 사용하여 각 입력 영상에 잡음을 추가한 영상을 만듭니다. 이 영상은 네트워크 입력값이 됩니다. transform 함수는 기본 데이터저장소에서 데이터를 읽어 들인 후 (이 예제의 끝부분에 정의된) 헬퍼 함수 addNoise에 정의된 연산을 사용하여 데이터를 처리합니다. transform 함수의 출력값은 TransformedDatastore입니다.

dsTrainNoisy = transform(imdsTrain,@addNoise);
dsValNoisy = transform(imdsVal,@addNoise);
dsTestNoisy = transform(imdsTest,@addNoise);

combine 함수를 사용하여 잡음이 있는 영상과 원래 그대로의 영상을 단일 데이터저장소로 결합하는데, 이 데이터저장소가 trainNetwork에 데이터를 입력하게 됩니다. 이 결합된 데이터저장소는 데이터 배치를 trainNetwork에 필요한 것과 같이 2열 셀형 배열로 읽어 들입니다. combine 함수의 출력값은 CombinedDatastore입니다.

dsTrain = combine(dsTrainNoisy,imdsTrain);
dsVal = combine(dsValNoisy,imdsVal);
dsTest = combine(dsTestNoisy,imdsTest);

transform 함수를 사용하여 입력 데이터저장소와 응답 데이터저장소 양쪽에 공통적인 전처리 연산을 추가로 수행합니다. 이 예제의 끝부분에 정의된 commonPreprocessing 헬퍼 함수는 입력 영상과 응답 영상을 네트워크의 입력 크기와 일치하도록 32x32 픽셀로 크기 조정한 후 각 영상의 데이터를 [0, 1] 범위로 정규화합니다.

dsTrain = transform(dsTrain,@commonPreprocessing);
dsVal = transform(dsVal,@commonPreprocessing);
dsTest = transform(dsTest,@commonPreprocessing);

마지막으로, transform 함수를 사용하여 훈련 세트에 무작위 증대를 적용합니다. 이 예제의 끝부분에 정의된 augmentImages 헬퍼 함수는 데이터에 무작위로 90도 회전을 적용합니다. 네트워크 입력값과 이에 대응하는 예상 응답 변수에 동일한 회전이 적용됩니다.

dsTrain = transform(dsTrain,@augmentImages);

증대는 과적합을 줄이고 훈련된 네트워크에 존재하는 회전에 강인성을 더해 줍니다. 검증 데이터 세트나 테스트 데이터 세트에는 무작위 증대가 필요하지 않습니다.

전처리된 데이터 미리 보기

훈련 데이터를 준비하려면 몇 가지 전처리 연산이 필요하므로 전처리된 데이터를 미리 봄으로써 훈련에 앞서 데이터가 올바른지 확인합니다. preview 함수를 사용하여 데이터를 미리 봅니다.

잡음이 있는 영상과 원래 그대로의 영상으로 이루어진 쌍의 예를 montage 함수를 사용하여 시각화합니다. 훈련 데이터가 올바르게 보입니다. 왼쪽 열에 있는 입력 영상에서 점잡음이 보입니다. 잡음이 더해진 것 외에는 입력 영상과 응답 영상이 동일합니다. 입력 영상과 응답 영상 양쪽에 모두 무작위 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™의 계층을 사용하여 컨벌루션 오토인코더 네트워크를 정의합니다.

영상 입력 계층을 만듭니다. 2배로 다운샘플링 및 업샘플링을 하면서 생기는 채우기 문제를 단순화하기 위해 입력 크기를 32x32로 선택합니다. 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 함수를 사용하여 하이퍼파라미터 설정을 지정합니다. 훈련을 Epoch 100회 수행합니다. (combine 함수를 사용하여 만든) 결합된 데이터저장소는 섞을 수 없으므로 Shuffle 파라미터를 'never'로 지정합니다.

options = trainingOptions('adam', ...
    'MaxEpochs',100, ...
    'MiniBatchSize',imds.ReadSize, ...
    'ValidationData',dsVal, ...
    'Shuffle','never', ...
    'Plots','training-progress', ...
    'Verbose',false);

네트워크 훈련시키기

이제 데이터 소스와 훈련 옵션이 구성되었으니 trainNetwork 함수를 사용하여 컨벌루션 오토인코더 네트워크를 훈련시킵니다. 훈련을 수행할 때는 CUDA 지원 NVIDIA™ GPU(Compute Capability 3.0 이상)를 사용하는 것이 권장됩니다.

참고: 훈련은 NVIDIA™ Titan XP GPU에서 약 25분 정도 소요됩니다.

net = trainNetwork(dsTrain,layers,options);

잡음 제거 네트워크의 성능 평가하기

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
    18.6498
psnrDenoised = psnr(ypred(:,:,:,1),ref)
psnrDenoised = single
    21.8640

예상과 같이 출력 영상의 PSNR이 잡음이 있는 입력 영상보다 높습니다.

요약

이 예제에서는 ImageDatastoretransform 함수와 combine 함수를 사용하여 숫자 데이터 세트에 대한 컨벌루션 오토인코더를 훈련시키고 평가하는 데 필요한 데이터 전처리를 설정하는 방법을 알아보았습니다.

지원 함수

addNoise 헬퍼 함수는 imnoise 함수를 사용하여 영상에 점잡음을 추가합니다. addNoise 함수를 사용하려면 입력 데이터의 형식이 영상 데이터로 구성된 셀형 배열이어야 합니다. 이는 ImageDatastoreread 함수가 반환하는 데이터의 형식과 일치합니다.

function dataOut = addNoise(data)

dataOut = data;
for idx = 1:size(data,1)
   dataOut{idx} = imnoise(data{idx},'salt & pepper');
end

end

commonPreprocessing 헬퍼 함수는 훈련, 검증 및 테스트 세트에 공통적인 전처리를 정의합니다. 헬퍼 함수는 다음의 전처리 단계를 수행합니다.

  1. 영상 데이터를 single 데이터형으로 변환합니다.

  2. imresize 함수를 사용하여 영상 데이터의 크기가 입력 계층의 크기와 일치하도록 조정합니다.

  3. rescale 함수를 사용하여 데이터를 [0, 1] 범위로 정규화합니다.

헬퍼 함수를 사용하려면 입력 데이터의 형식이 영상 데이터로 구성된 2열 셀형 배열이어야 합니다. 이는 CombinedDatastoreread 함수가 반환하는 데이터의 형식과 일치합니다.

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

augmentImages 헬퍼 함수는 rot90 함수를 사용하여 데이터에 무작위로 90도 회전을 적용합니다. 네트워크 입력값과 이에 대응하는 예상 응답 변수에 동일한 회전이 적용됩니다. 이 함수를 사용하려면 입력 데이터의 형식이 영상 데이터로 구성된 2열 셀형 배열이어야 합니다. 이는 CombinedDatastoreread 함수가 반환하는 데이터의 형식과 일치합니다.

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

createUpsampleTransposeConvLayer 헬퍼 함수는 계층 입력값을 지정된 인자를 사용해 업샘플링하는 전치된 컨벌루션 계층을 정의합니다.

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

참고 항목

| | | |

관련 예제

세부 정보