Main Content

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

이 예제에서는 손으로 쓴 숫자의 회전 각도를 예측하는 컨벌루션 신경망을 훈련시키는 방법을 보여줍니다.

회귀 작업에는 이산적인 클래스 레이블이 아니라 연속적인 숫자형 값을 예측하는 작업이 포함됩니다. 이 예제에서는 회귀를 위한 컨벌루션 신경망 아키텍처를 구성하고 신경망을 훈련시킨 다음 훈련된 신경망을 사용하여 손으로 쓴 숫자의 회전 각도를 예측합니다.

다음 도식은 회귀 신경망을 통과하는 영상 데이터의 흐름을 보여줍니다.

데이터 불러오기

데이터 세트에는 손으로 쓴 숫자를 나타내는 합성 영상과 영상 각각의 회전 각도(단위: 도)가 포함되어 있습니다.

MAT 파일 DigitsDataTrain.matDigitsDataTest.mat에서 훈련 데이터와 테스트 데이터를 각각 불러옵니다. 변수 anglesTrainanglesTest는 회전 각도(단위: 도)입니다. 훈련 및 테스트 데이터 세트는 각각 5,000개의 영상을 포함합니다.

load DigitsDataTrain
load DigitsDataTest

훈련 영상 몇 개를 표시합니다.

numObservations = size(XTrain,4);
idx = randperm(numObservations,49);
I = imtile(XTrain(:,:,:,idx));
figure
imshow(I);

이 예제에 지원 파일로 첨부된 trainingPartitions 함수를 사용하여 XTrainanglesTrain을 훈련 파티션과 검증 파티션으로 분할합니다. 이 함수에 액세스하려면 예제를 라이브 스크립트로 여십시오. 검증을 위해 훈련 데이터의 15%를 남겨 둡니다.

[idxTrain,idxValidation] = trainingPartitions(numObservations,[0.85 0.15]);

XValidation = XTrain(:,:,:,idxValidation);
anglesValidaiton = anglesTrain(idxValidation);

XTrain = XTrain(:,:,:,idxTrain);
anglesTrain = anglesTrain(idxTrain);

데이터 정규화 확인하기

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

  • 입력 데이터. 예측 변수를 신경망에 입력하기 전에 먼저 정규화합니다. 이 예제에서는 입력 영상이 이미 범위 [0,1]로 정규화되어 있습니다.

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

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

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

figure
histogram(anglesTrain)
axis tight
ylabel("Counts")
xlabel("Rotation Angle")

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

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

신경망 아키텍처 정의하기

신경망 아키텍처를 정의합니다.

  • 영상 입력값으로 영상 입력 계층을 지정합니다.

  • 매번 필터 개수를 늘리면서 4개의 convolution-batchnorm-ReLU 블록을 지정합니다.

  • 각 블록 사이에 풀링 영역과 스트라이드 크기가 2인 평균값 풀링 계층을 지정합니다.

  • 신경망 끝부분에, 출력 크기가 응답 변수의 개수와 일치하는 완전 연결 계층을 추가합니다.

numResponses = 1;

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
    fullyConnectedLayer(numResponses)];

훈련 옵션 지정하기

훈련 옵션을 지정합니다. 옵션 중에서 선택하려면 경험적 분석이 필요합니다. 실험을 실행하여 다양한 훈련 옵션 구성을 살펴보려면 Experiment Manager 앱을 사용합니다.

  • 초기 학습률을 0.001로 설정하고, Epoch 20회가 지나면 학습률을 떨어뜨립니다.

  • 검증 데이터와 검증 빈도를 지정하여 훈련 중에 신경망 정확도를 모니터링합니다. 훈련 데이터에 대해 신경망이 훈련되고, 훈련 중에 규칙적인 간격으로 검증 데이터에 대한 정확도가 계산됩니다. 검증 데이터는 신경망 가중치를 업데이트하는 데 사용되지 않습니다.

  • 훈련 진행 상황을 플롯으로 표시하고 RMS 오차를 모니터링합니다.

  • 상세 출력값을 비활성화합니다.

miniBatchSize  = 128;
validationFrequency = floor(numel(anglesTrain)/miniBatchSize);

options = trainingOptions("sgdm", ...
    MiniBatchSize=miniBatchSize, ...
    InitialLearnRate=1e-3, ...
    LearnRateSchedule="piecewise", ...
    LearnRateDropFactor=0.1, ...
    LearnRateDropPeriod=20, ...
    Shuffle="every-epoch", ...
    ValidationData={XTest,anglesTest}, ...
    ValidationFrequency=validationFrequency, ...
    Plots="training-progress", ...
    Metrics="rmse", ...
    Verbose=false);

신경망 훈련시키기

trainnet 함수를 사용하여 신경망을 훈련시킵니다. 회귀의 경우 평균제곱오차 손실을 사용합니다. 기본적으로 trainnet 함수는 GPU를 사용할 수 있으면 GPU를 사용합니다. GPU를 사용하려면 Parallel Computing Toolbox™ 라이선스와 지원되는 GPU 장치가 필요합니다. 지원되는 장치에 대한 자세한 내용은 GPU 연산 요구 사항 (Parallel Computing Toolbox) 항목을 참조하십시오. GPU를 사용할 수 없는 경우, 함수는 CPU를 사용합니다. 실행 환경을 지정하려면 ExecutionEnvironment 훈련 옵션을 사용하십시오.

net = trainnet(XTrain,anglesTrain,layers,"mse",options);

신경망 테스트하기

테스트 데이터에 대한 정확도를 평가함으로써 신경망의 성능을 테스트합니다.

minibatchpredict 함수를 사용하여 예측을 수행합니다. 기본적으로 minibatchpredict 함수는 GPU를 사용할 수 있으면 GPU를 사용합니다.

YTest = minibatchpredict(net,XTest);

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

predictionError = anglesTest - YTest;
squares = predictionError.^2;
rmse = sqrt(mean(squares))
rmse = single
    4.7017

산점도 플롯에서 예측을 시각화합니다. 실제 값에 대해 예측된 값을 플로팅합니다.

figure
scatter(YTest,anglesTest,"+")
xlabel("Predicted Value")
ylabel("True Value")

hold on
plot([-60 60], [-60 60],"r--")

새 데이터를 사용하여 예측하기

신경망을 사용하여 첫 번째 테스트 영상으로 예측을 수행합니다. 하나의 영상을 사용하여 예측을 수행하기 위해 predict 함수를 사용합니다. GPU를 사용하려면 먼저 데이터를 gpuArray로 변환합니다.

X = XTest(:,:,:,1);
if canUseGPU
    X = gpuArray(X);
end
Y = predict(net,X)
Y = single
    35.1394

참고 항목

| |

관련 항목