Main Content

사전 훈련된 신경망을 사용하여 영상 특징 추출하기

이 예제에서는 사전 훈련된 컨벌루션 신경망에서 학습된 영상 특징을 추출한 다음 추출한 특징을 사용하여 영상 분류기를 훈련시키는 방법을 보여줍니다. 특징 추출은 사전 훈련된 심층 신경망의 강력한 표현 기능을 가장 쉽고 빠르게 사용하는 방법입니다. 예를 들어, 추출된 특징에 대해 fitcecoc(Statistics and Machine Learning Toolbox™)를 사용하여 서포트 벡터 머신(SVM)을 훈련시킬 수 있습니다. 특징 추출은 데이터를 한 번만 통과하면 되기 때문에 신경망 훈련을 가속할 GPU가 없을 때 시도할 수 있는 좋은 시작점이 됩니다.

데이터 불러오기

샘플 영상의 압축을 풀고 영상 데이터저장소로서 불러옵니다. imageDatastore는 폴더 이름을 기준으로 영상에 자동으로 레이블을 지정하고 데이터를 ImageDatastore 객체로 저장합니다. 영상 데이터저장소를 사용하면 메모리에 담을 수 없는 데이터를 포함하여 다량의 영상 데이터를 저장할 수 있습니다. 데이터를 훈련 데이터 70%와 테스트 데이터 30%로 분할합니다.

unzip('MerchData.zip');
imds = imageDatastore('MerchData','IncludeSubfolders',true,'LabelSource','foldernames');
[imdsTrain,imdsTest] = splitEachLabel(imds,0.7,'randomized');

이 매우 작은 데이터 세트에는 이제 55개의 훈련 영상과 20개의 검증 영상이 있습니다. 샘플 영상 몇 개를 표시합니다.

numTrainImages = numel(imdsTrain.Labels);
idx = randperm(numTrainImages,16);
figure
for i = 1:16
    subplot(4,4,i)
    I = readimage(imdsTrain,idx(i));
    imshow(I)
end

사전 훈련된 신경망 불러오기

사전 훈련된 ResNet-18 신경망을 불러옵니다. Deep Learning Toolbox Model for ResNet-18 Network 지원 패키지가 설치되어 있지 않으면 이를 다운로드할 수 있는 링크가 제공됩니다. 1백만 개가 넘는 영상에 대해 훈련된 ResNet-18은 영상을 키보드, 마우스, 연필, 각종 동물 등 1,000가지 사물 범주로 분류할 수 있습니다. 그 결과 이 모델은 다양한 영상을 대표하는 다양한 특징을 학습했습니다.

net = resnet18
net = 
  DAGNetwork with properties:

         Layers: [71×1 nnet.cnn.layer.Layer]
    Connections: [78×2 table]
     InputNames: {'data'}
    OutputNames: {'ClassificationLayer_predictions'}

신경망 아키텍처를 분석합니다. 첫 번째 계층인 영상 입력 계층에 입력되는 영상은 크기가 224x224x3이어야 합니다. 여기서 3은 색 채널의 개수입니다.

inputSize = net.Layers(1).InputSize;
analyzeNetwork(net)

영상 특징 추출하기

이 신경망의 입력 영상은 크기가 224x224x3이어야 하는데 영상 데이터저장소의 영상은 이와 크기가 다릅니다. 신경망에 입력하기 전에 훈련 영상과 테스트 영상의 크기를 자동으로 조정하려면 증대 영상 데이터저장소를 만들고 원하는 영상 크기를 지정한 다음 이러한 데이터저장소를 activations에 대한 입력 인수로 사용하십시오.

augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain);
augimdsTest = augmentedImageDatastore(inputSize(1:2),imdsTest);

신경망은 입력 영상에 대한 계층 표현을 생성합니다. 보다 심층의 계층에는 앞쪽 계층의 하위 수준 특징을 사용하여 생성한 상위 수준의 특징이 포함됩니다. 훈련 영상과 테스트 영상의 특징 표현을 가져오려면 신경망의 끝부분에 있는 전역 풀링 계층 'pool5', 에 대해 activations를 사용하십시오. 전역 풀링 계층은 모든 공간 위치에 대해 입력 특징을 풀링하여 총 512개의 특징을 제공합니다.

layer = 'pool5';
featuresTrain = activations(net,augimdsTrain,layer,'OutputAs','rows');
featuresTest = activations(net,augimdsTest,layer,'OutputAs','rows');

whos featuresTrain
  Name                Size              Bytes  Class     Attributes

  featuresTrain      55x512            112640  single              

훈련 데이터와 테스트 데이터로부터 클래스 레이블을 추출합니다.

YTrain = imdsTrain.Labels;
YTest = imdsTest.Labels;

영상 분류기 피팅하기

훈련 영상으로부터 추출한 특징을 예측 변수로 사용하고 fitcecoc(Statistics and Machine Learning Toolbox)를 사용하여 다중클래스 서포트 벡터 머신(SVM)을 피팅합니다.

classifier = fitcecoc(featuresTrain,YTrain);

테스트 영상 분류하기

훈련된 SVM 모델과 테스트 영상으로부터 추출한 특징을 사용하여 테스트 영상을 분류합니다.

YPred = predict(classifier,featuresTest);

4개의 샘플 테스트 영상을 예측된 레이블과 함께 표시합니다.

idx = [1 5 10 15];
figure
for i = 1:numel(idx)
    subplot(2,2,i)
    I = readimage(imdsTest,idx(i));
    label = YPred(idx(i));
    imshow(I)
    title(char(label))
end

테스트 세트에 대한 분류 정확도를 계산합니다. 정확도는 신경망이 올바르게 예측하는 레이블의 비율입니다.

accuracy = mean(YPred == YTest)
accuracy = 1

더 얕은 특징을 대상으로 분류기 훈련시키기

신경망의 앞쪽에 있는 계층에서 특징을 추출하여 이 특징을 대상으로 분류기를 훈련시킬 수도 있습니다. 앞쪽 계층은 통상적으로 더 적고 더 얕은 특징을 추출하고, 공간 분해능이 더 높으며, 총 활성화 개수가 더 많습니다. 'res3b_relu' 계층에서 특징을 추출합니다. 이것은 128개의 특징을 출력하는 마지막 계층으로, 활성화 값의 공간 크기는 28x28입니다.

layer = 'res3b_relu';
featuresTrain = activations(net,augimdsTrain,layer);
featuresTest = activations(net,augimdsTest,layer);
whos featuresTrain
  Name                Size                      Bytes  Class     Attributes

  featuresTrain      28x28x128x55            22077440  single              

이 예제의 첫 번째 부분에서 사용되었던 추출된 특징은 전역 풀링 계층에 의해 모든 공간 위치에 대해 풀링되었습니다. 앞쪽 계층에서 특징을 추출할 때도 동일한 결과를 달성하려면 모든 공간 위치에 대해 활성화 값의 평균을 직접 구하십시오. N이 관측값의 개수이고 C가 특징의 개수일 때 N-by-C 형식을 대상으로 특징을 얻으려면 한원소 차원을 제거하고 전치하십시오.

featuresTrain = squeeze(mean(featuresTrain,[1 2]))';
featuresTest = squeeze(mean(featuresTest,[1 2]))';
whos featuresTrain
  Name                Size             Bytes  Class     Attributes

  featuresTrain      55x128            28160  single              

더 얕은 특징을 대상으로 SVM 분류기를 훈련시킵니다. 테스트 정확도를 계산합니다.

classifier = fitcecoc(featuresTrain,YTrain);
YPred = predict(classifier,featuresTest);
accuracy = mean(YPred == YTest)
accuracy = 0.9500

훈련된 SVM 두 개 모두 높은 정확도를 갖습니다. 특징 추출을 사용했을 때의 정확도가 충분히 높지 않다면 그 대신 전이 학습을 사용해 보십시오. 예제는 새로운 영상을 분류하도록 딥러닝 신경망 훈련시키기 항목을 참조하십시오. 사전 훈련된 신경망의 목록 및 비교한 내용을 보려면 사전 훈련된 심층 신경망 항목을 참조하십시오.

참고 항목

| (Statistics and Machine Learning Toolbox)

관련 항목