이 페이지의 최신 내용은 아직 번역되지 않았습니다. 최신 내용은 영문으로 볼 수 있습니다.

회귀를 위해 컨벌루션 신경망 훈련시키기

이 예제에서는 컨벌루션 신경망을 사용하여 손으로 쓴 숫자의 회전 각도를 예측하는 회귀 모델을 피팅하는 방법을 보여줍니다.

컨벌루션 신경망(CNN 또는 ConvNet)은 심층 학습(딥 러닝)의 필수 툴로서, 특히 이미지 데이터 분석에 적합합니다. 예를 들어, CNN을 사용하여 이미지를 분류할 수 있습니다. 각도나 거리와 같은 연속 데이터를 예측하려면 네트워크 끝부분에 회귀 계층을 포함시킬 수 있습니다.

이 예제에서는 컨벌루션 신경망 아키텍처를 구성하고 네트워크를 훈련시킨 다음 훈련된 네트워크를 사용하여 손으로 쓴 숫자의 회전 각도를 예측합니다. 이러한 예측은 광학 문자 인식 분야에 유용합니다.

선택적으로 imrotate(Image Processing Toolbox™)를 사용하여 이미지를 회전하고 boxplot(Statistics and Machine Learning Toolbox™)을 사용하여 잔차 상자 플롯을 만들 수 있습니다.

데이터 불러오기

데이터 세트에는 손으로 쓴 숫자의 합성 이미지와 이미지 각각의 회전 각도(단위: 도)가 포함되어 있습니다.

digitTrain4DArrayDatadigitTest4DArrayData를 사용하여 훈련 및 검증 이미지를 4차원 배열로 불러옵니다. 출력값 YTrain YValidation은 회전 각도(단위: 도)입니다. 훈련 및 검증 데이터 세트는 각각 5,000개의 이미지를 포함합니다.

[XTrain,~,YTrain] = digitTrain4DArrayData;
[XValidation,~,YValidation] = digitTest4DArrayData;

imshow를 사용하여 임의의 훈련 이미지 20개를 표시합니다.

numTrainImages = numel(YTrain);
figure
idx = randperm(numTrainImages,20);
for i = 1:numel(idx)
    subplot(4,5,i)    
    imshow(XTrain(:,:,:,idx(i)))
    drawnow
end

데이터 정규화 확인하기

신경망을 훈련시킬 때 네트워크의 모든 단계에서 정규화된 데이터를 사용하면 유용한 경우가 종종 있습니다. 정규화는 경사하강법을 사용하여 네트워크 훈련을 안정화하고 속도를 높이는 데 도움이 됩니다. 데이터가 제대로 스케일링되지 않은 경우에는 손실이 NaN이 되어 훈련 중에 네트워크 파라미터가 발산할 수 있습니다. 데이터를 정규화하는 일반적인 방법에는 범위가 [0,1]이 되도록 데이터를 다시 스케일링하는 방법과 평균 0, 표준편차 1이 되도록 다시 스케일링하는 방법이 있습니다. 정규화할 수 있는 데이터는 다음과 같습니다.

  • 입력 데이터. 예측 변수를 네트워크에 입력하기 전에 먼저 정규화합니다. 이 예제에서는 입력 이미지가 이미 범위 [0,1]로 정규화되어 있습니다.

  • 계층 출력값. 배치 정규화 계층을 사용하여 각 컨벌루션 계층과 완전 연결 계층의 출력값을 정규화할 수 있습니다.

  • 응답 변수. 네트워크의 끝부분에서 배치 정규화 계층을 사용하여 계층 출력값을 정규화하는 경우, 훈련이 시작될 때 네트워크의 예측값이 정규화됩니다. 응답 변수의 스케일이 이러한 예측값의 스케일과 크게 다르면 네트워크 훈련이 수렴하지 못할 수 있습니다. 응답 변수가 제대로 스케일링되지 않았다면 정규화를 수행한 다음 네트워크 훈련이 개선되는지 확인하십시오. 훈련을 진행하기 전에 응답 변수를 정규화한 경우에는 훈련된 네트워크의 예측값을 변환해야만 원래 응답 변수에 대한 예측값을 얻을 수 있습니다.

응답 변수의 분포를 플로팅합니다. 응답 변수(도 단위의 회전 각도)는 -45와 45 사이에서 대략 균등분포되어 있으므로 정규화할 필요가 없습니다. 분류 문제에서는 출력값이 클래스 확률입니다. 클래스 확률은 항상 정규화됩니다.

figure
histogram(YTrain)
axis tight
ylabel('Counts')
xlabel('Rotation Angle')

이러한 데이터는 일반적으로 정확하게 정규화할 필요가 없습니다. 그러나 이 예제의 경우 YTrain 대신 100*YTrain이나 YTrain+500을 예측하도록 네트워크를 훈련시키면 손실이 NaN이 되어 훈련을 시작하면 네트워크 파라미터가 발산합니다. aY + b를 예측하는 네트워크와 Y를 예측하는 네트워크의 유일한 차이가 마지막 완전 연결 계층의 가중치와 편향을 다시 스케일링한 것뿐임에도 불구하고 이러한 결과가 발생합니다.

입력값이나 응답 변수의 분포가 매우 고르지 않거나 편중되었다면 네트워크를 훈련시키기 전에 데이터에 대해 비선형 변환(예: 로그 적용)을 수행할 수도 있습니다.

네트워크 계층 만들기

회귀 문제를 풀려면 네트워크 계층을 만들고 네트워크 끝부분에 회귀 계층을 포함시키십시오.

첫 번째 계층은 입력 데이터의 크기와 유형을 정의합니다. 입력 이미지는 28x28x1입니다. 훈련 이미지와 크기가 같은 이미지 입력 계층을 만듭니다.

네트워크의 중간 계층은 대부분의 연산과 학습이 이루어지는 네트워크의 핵심 아키텍처를 정의합니다.

마지막 계층은 출력 데이터의 크기와 유형을 정의합니다. 회귀 문제인 경우에는 네트워크의 끝부분에서 완전 연결 계층이 회귀 계층 앞에 와야 합니다. 크기가 1인 완전 연결된 출력 계층을 만들고 회귀 계층을 만듭니다.

모든 계층을 Layer 배열에서 결합합니다.

layers = [
    imageInputLayer([28 28 1])

    convolution2dLayer(3,8,'Padding','same')
    batchNormalizationLayer
    reluLayer
    
    averagePooling2dLayer(2,'Stride',2)

    convolution2dLayer(3,16,'Padding','same')
    batchNormalizationLayer
    reluLayer
    
    averagePooling2dLayer(2,'Stride',2)
  
    convolution2dLayer(3,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    
    convolution2dLayer(3,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    
    dropoutLayer(0.2)
    fullyConnectedLayer(1)
    regressionLayer];

네트워크 훈련시키기

네트워크 훈련 옵션을 만듭니다. 훈련을 Epoch 30회 수행합니다. 초기 학습률을 0.001로 설정하고, Epoch 20회가 지나면 학습률을 떨어뜨립니다. 검증 데이터와 검증 빈도를 지정하여 훈련 중에 네트워크 정확도를 모니터링합니다. 훈련 데이터에 대해 네트워크가 훈련되고, 훈련 중에 규칙적인 간격으로 검증 데이터에 대한 정확도가 계산됩니다. 검증 데이터는 네트워크 가중치를 업데이트하는 데 사용되지 않습니다. 훈련 진행 상황 플롯을 켜고 명령 창 출력을 끕니다.

miniBatchSize  = 128;
validationFrequency = floor(numel(YTrain)/miniBatchSize);
options = trainingOptions('sgdm', ...
    'MiniBatchSize',miniBatchSize, ...
    'MaxEpochs',30, ...
    'InitialLearnRate',1e-3, ...
    'LearnRateSchedule','piecewise', ...
    'LearnRateDropFactor',0.1, ...
    'LearnRateDropPeriod',20, ...
    'Shuffle','every-epoch', ...
    'ValidationData',{XValidation,YValidation}, ...
    'ValidationFrequency',validationFrequency, ...
    'Plots','training-progress', ...
    'Verbose',false);

trainNetwork를 사용하여 네트워크를 만듭니다. 이 명령은 사용 가능한 경우 호환되는 GPU를 사용합니다. 사용 가능하지 않은 경우 trainNetwork는 CPU를 사용합니다. GPU에서 훈련시키려면 CUDA® 지원 NVIDIA® GPU(Compute Capability 3.0 이상)가 필요합니다.

net = trainNetwork(XTrain,YTrain,layers,options);

netLayers 속성에 포함된 네트워크 아키텍처의 세부 정보를 살펴봅니다.

net.Layers
ans = 
  18x1 Layer array with layers:

     1   'imageinput'         Image Input           28x28x1 images with 'zerocenter' normalization
     2   'conv_1'             Convolution           8 3x3x1 convolutions with stride [1  1] and padding 'same'
     3   'batchnorm_1'        Batch Normalization   Batch normalization with 8 channels
     4   'relu_1'             ReLU                  ReLU
     5   'avgpool2d_1'        Average Pooling       2x2 average pooling with stride [2  2] and padding [0  0  0  0]
     6   'conv_2'             Convolution           16 3x3x8 convolutions with stride [1  1] and padding 'same'
     7   'batchnorm_2'        Batch Normalization   Batch normalization with 16 channels
     8   'relu_2'             ReLU                  ReLU
     9   'avgpool2d_2'        Average Pooling       2x2 average pooling with stride [2  2] and padding [0  0  0  0]
    10   'conv_3'             Convolution           32 3x3x16 convolutions with stride [1  1] and padding 'same'
    11   'batchnorm_3'        Batch Normalization   Batch normalization with 32 channels
    12   'relu_3'             ReLU                  ReLU
    13   'conv_4'             Convolution           32 3x3x32 convolutions with stride [1  1] and padding 'same'
    14   'batchnorm_4'        Batch Normalization   Batch normalization with 32 channels
    15   'relu_4'             ReLU                  ReLU
    16   'dropout'            Dropout               20% dropout
    17   'fc'                 Fully Connected       1 fully connected layer
    18   'regressionoutput'   Regression Output     mean-squared-error with response 'Response'

네트워크 테스트하기

검증 데이터에 대한 정확도를 평가함으로써 네트워크의 성능을 테스트합니다.

predict를 사용하여 검증 이미지의 회전 각도를 예측합니다.

YPredicted = predict(net,XValidation);

성능 평가하기

다음을 계산하여 모델의 성능을 평가합니다.

  1. 허용 가능한 오차 범위 내에 있는 예측값의 비율

  2. 예측된 회전 각도와 실제 회전 각도 사이의 RMSE(제곱평균제곱근 오차)

예측된 회전 각도와 실제 회전 각도 사이의 예측 오차를 계산합니다.

predictionError = YValidation - YPredicted;

실제 각도로부터 허용 가능한 오차 범위 내에 있는 예측값의 개수를 계산합니다. 임계값을 10도로 설정합니다. 이 임계값 내에 있는 예측값의 비율을 계산합니다.

thr = 10;
numCorrect = sum(abs(predictionError) < thr);
numValidationImages = numel(YValidation);

accuracy = numCorrect/numValidationImages
accuracy = 0.9684

RMSE(제곱평균제곱근 오차)를 사용하여 예측된 회전 각도와 실제 회전 각도 사이의 차이를 측정합니다.

squares = predictionError.^2;
rmse = sqrt(mean(squares))
rmse = single
    4.5157

각 숫자 클래스에 대해 잔차 상자 플롯 표시하기

boxplot 함수에는 각 열이 각 숫자 클래스의 잔차에 대응하는 행렬이 필요합니다.

검증 데이터는 이미지를 0–9 숫자 클래스별로 표본 500개씩 그룹화합니다. reshape를 사용하여 숫자 클래스별로 잔차를 그룹화합니다.

residualMatrix = reshape(predictionError,500,10);

residualMatrix의 각 열은 각 숫자의 잔차에 대응됩니다. boxplot(Statistics and Machine Learning Toolbox)을 사용하여 각 숫자에 대해 잔차 상자 플롯을 만듭니다.

figure
boxplot(residualMatrix,...
    'Labels',{'0','1','2','3','4','5','6','7','8','9'})
xlabel('Digit Class')
ylabel('Degrees Error')
title('Residuals')

정확도가 가장 높은 숫자 클래스는 평균이 0에 가깝고 분산이 작습니다.

숫자 회전 정정하기

Image Processing Toolbox의 함수를 사용하여 숫자를 바로 세우고 함께 표시할 수 있습니다. imrotate(Image Processing Toolbox)를 사용하여 49개의 샘플 숫자를 예측한 회전 각도에 따라 회전합니다.

idx = randperm(numValidationImages,49);
for i = 1:numel(idx)
    image = XValidation(:,:,:,idx(i));
    predictedAngle = YPredicted(idx(i));  
    imagesRotated(:,:,:,i) = imrotate(image,predictedAngle,'bicubic','crop');
end

원래 숫자와 회전을 정정한 숫자를 함께 표시합니다. montage(Image Processing Toolbox)를 사용하여 숫자들을 이미지 하나에 한꺼번에 표시할 수 있습니다.

figure
subplot(1,2,1)
montage(XValidation(:,:,:,idx))
title('Original')

subplot(1,2,2)
montage(imagesRotated)
title('Corrected')

참고 항목

|

관련 항목