Main Content

영상 분류를 위해 적층 오토인코더 훈련시키기

이 예제에서는 숫자 영상을 분류하기 위해 적층 오토인코더를 훈련시키는 방법을 보여줍니다.

은닉 계층이 여러 개 있는 신경망은 영상과 같은 복잡한 데이터의 분류 문제를 해결하는 데 유용합니다. 각 계층은 서로 다른 추상화 수준에서 특징을 학습할 수 있습니다. 그러나 은닉 계층이 여러 개인 신경망을 실제로 훈련시키기란 쉽지 않을 수 있습니다.

계층이 여러 개인 신경망을 효율적으로 훈련시키는 한 가지 방법은 한 번에 한 계층씩 훈련시키는 것입니다. 이렇게 하려면 원하는 은닉 계층 각각에 대해 오토인코더라고 알려진 특수한 유형의 신경망을 훈련시키면 됩니다.

이 예제에서는 은닉 계층이 2개인 신경망이 영상 속 숫자를 분류하도록 훈련시키는 방법을 보여줍니다. 먼저 은닉 계층을 오토인코더를 사용하여 비지도 방식으로 개별적으로 훈련시킵니다. 그런 다음 마지막 소프트맥스 계층을 훈련시킨 후 계층들을 하나로 결합하여 적층 신경망을 만듭니다. 이 적층 신경망을 마지막으로 한 번 더 지도 방식으로 훈련시킵니다.

데이터 세트

이 예제에서는 훈련과 테스트 모두 처음부터 끝까지 합성 데이터를 사용합니다. 합성 영상은 여러 다른 글꼴의 숫자 영상에 무작위 아핀 변환을 적용하여 생성되었습니다.

각 숫자 영상은 28×28 픽셀이며 5,000개의 훈련 표본이 있습니다. 훈련 데이터를 불러온 다음 영상 일부를 표시할 수 있습니다.

% Load the training data into memory
[xTrainImages,tTrain] = digitTrainCellArrayData;

% Display some of the training images
clf
for i = 1:20
    subplot(4,5,i);
    imshow(xTrainImages{i});
end

영상에 대한 레이블은 10×5,000 행렬에 저장됩니다. 각 열마다 단 한 개의 요소만 숫자가 속한 클래스를 나타내기 위해 1을 가지고 다른 모든 요소는 0입니다. 10번째 요소가 1이면 그 숫자 영상은 0이라는 점에 유의하십시오.

첫 번째 오토인코더 훈련시키기

먼저 레이블을 사용하지 않고 훈련 데이터에 대해 희소 오토인코더를 훈련시킵니다.

오토인코더는 입력값을 출력값에 복제하려고 시도하는 신경망입니다. 따라서 입력값의 크기는 출력값의 크기와 같습니다. 은닉 계층의 뉴런의 개수가 입력값의 크기보다 작은 경우, 오토인코더는 입력값의 압축된 표현을 학습합니다.

신경망은 훈련이 시작되기 전에 무작위로 초기화되는 가중치를 갖습니다. 따라서 훈련의 결과는 매번 달라집니다. 이를 방지하려면 난수 생성기 시드값을 명시적으로 설정하십시오.

rng('default')

오토인코더의 은닉 계층의 크기를 설정합니다. 여기서 훈련할 오토인코더는 은닉 계층의 크기를 입력값 크기보다 작게 설정하는 것이 좋습니다.

hiddenSize1 = 100;

훈련할 오토인코더의 유형은 희소 오토인코더입니다. 이 오토인코더는 정규화 함수를 사용하여 첫 번째 계층의 희소 표현을 학습합니다. 다음과 같이 여러 파라미터를 설정하여 정규화 함수의 영향을 제어할 수 있습니다.

  • L2WeightRegularization은 L2 정규화 함수가 신경망에서 편향(bias)이 아닌 가중치에 미치는 영향을 제어합니다. 이 값은 일반적으로 상당히 작습니다.

  • SparsityRegularization은 은닉 계층의 출력값에 희소 제약을 가하려고 시도하는 희소 정규화 함수의 영향을 제어합니다. 이는 가중치에 희소 정규화 함수를 적용하는 것과는 다르다는 점에 유의하십시오.

  • SparsityProportion은 희소 정규화 함수의 파라미터입니다. 은닉 계층의 출력값의 희소 정도를 제어합니다. 일반적으로 SparsityProportion의 값이 작으면 은닉 계층의 각 뉴런이 적은 수의 훈련 표본에 대해서만 높은 출력값을 부여함으로써 "특화"됩니다. 예를 들어, SparsityProportion이 0.1로 설정되면, 이는 은닉 계층의 각 뉴런이 훈련 표본에 대해 평균 출력값 0.1을 가져야 한다고 지정하는 것과 같습니다. 이 값은 0에서 1 사이여야 합니다. 어떤 값이 이상적일지는 문제의 특성에 따라 달라집니다.

이제 위에서 설명한 정규화 함수의 값을 지정하여 오토인코더를 훈련시킵니다.

autoenc1 = trainAutoencoder(xTrainImages,hiddenSize1, ...
    'MaxEpochs',400, ...
    'L2WeightRegularization',0.004, ...
    'SparsityRegularization',4, ...
    'SparsityProportion',0.15, ...
    'ScaleData', false);

오토인코더의 도식을 표시할 수 있습니다. 오토인코더는 인코더와 그 뒤에 오는 디코더로 이루어져 있습니다. 인코더는 입력값을 은닉 표현으로 매핑하고, 디코더는 이 매핑에서 역으로 원본 입력값을 재구성하려고 시도합니다.

view(autoenc1)

첫 번째 오토인코더의 가중치 시각화하기

오토인코더의 인코더 부분이 학습한 매핑은 데이터에서 특징을 추출할 때 유용할 수 있습니다. 인코더의 각 뉴런은 연관된 가중치 벡터를 가지는데, 이 벡터를 특정한 시각적 특징에 반응하도록 조정할 수 있습니다. 이러한 특징의 표현을 표시할 수 있습니다.

figure()
plotWeights(autoenc1);

이 오토인코더가 학습한 특징들은 숫자 영상에서 말린 패턴과 획 패턴을 표현하고 있음을 확인할 수 있습니다.

오토인코더의 은닉 계층의 100차원 출력값은 위에서 시각화한 특징들에 대한 응답을 요약한 값, 즉 입력값의 압축된 버전입니다. 훈련 데이터에서 추출한 이러한 벡터 세트에 대해 다음 오토인코더를 훈련시킵니다. 먼저 훈련된 오토인코더의 인코더를 사용하여 특징들을 생성해야 합니다.

feat1 = encode(autoenc1,xTrainImages);

두 번째 오토인코더 훈련시키기

첫 번째 오토인코더를 훈련시킨 뒤에 비슷한 방식으로 두 번째 오토인코더를 훈련시킵니다. 주된 차이는 첫 번째 오토인코더에서 생성된 특징들을 두 번째 오토인코더의 훈련 데이터로 사용한다는 것입니다. 또한, 은닉 표현의 크기를 50으로 줄여서 두 번째 오토인코더의 인코더가 입력 데이터의 더 작은 표현을 학습하도록 합니다.

hiddenSize2 = 50;
autoenc2 = trainAutoencoder(feat1,hiddenSize2, ...
    'MaxEpochs',100, ...
    'L2WeightRegularization',0.002, ...
    'SparsityRegularization',4, ...
    'SparsityProportion',0.1, ...
    'ScaleData', false);

이번에도 view 함수를 사용하여 오토인코더의 도식을 표시할 수 있습니다.

view(autoenc2)

두 번째 오토인코더의 인코더에 직전 세트를 통과시켜서 두 번째 특징 세트를 추출할 수 있습니다.

feat2 = encode(autoenc2,feat1);

훈련 데이터의 원래 벡터는 784개의 차원을 가졌습니다. 첫 번째 인코더를 통과시킨 뒤에는 100개의 차원으로 줄어들었습니다. 두 번째 인코더를 사용한 뒤에는 또다시 50개의 차원으로 줄어들었습니다. 이제 이러한 50차원 벡터를 여러 숫자 클래스로 분류하도록 마지막 계층을 훈련시킬 수 있습니다.

마지막 소프트맥스 계층 훈련시키기

50차원 특징 벡터를 분류하도록 소프트맥스 계층을 훈련시킵니다. 소프트맥스 계층은 오토인코더와 달리 훈련 데이터에 대한 레이블을 사용하여 지도 방식으로 훈련시킵니다.

softnet = trainSoftmaxLayer(feat2,tTrain,'MaxEpochs',400);

view 함수를 사용하여 소프트맥스 계층의 도식을 표시할 수 있습니다.

view(softnet)

적층 신경망 형성하기

지금까지 적층 신경망을 구성하는 3개의 컴포넌트를 각각 따로 훈련했습니다. 이 시점에서 이 3개의 신경망을 살펴보면 좋을 것 같습니다. 이들 신경망은 autoenc1, autoenc2, softnet입니다.

view(autoenc1)

view(autoenc2)

view(softnet)

앞에서 설명했듯이 특징 추출을 위해 오토인코더의 인코더가 사용되었습니다. 오토인코더의 인코더에 소프트맥스 계층을 쌓아서 분류를 위한 적층 신경망을 형성할 수 있습니다.

stackednet = stack(autoenc1,autoenc2,softnet);

view 함수를 사용하여 적층 신경망의 도식을 표시할 수 있습니다. 이 신경망은 오토인코더의 인코더와 소프트맥스 계층으로 이루어집니다.

view(stackednet)

이렇게 형성된 전체 신경망을 사용하여 테스트 세트에 대해 결과를 계산할 수 있습니다. 적층 신경망에서 영상을 사용하려면 테스트 영상을 행렬로 형태 변경해야 합니다. 영상의 열을 쌓아 벡터로 만든 다음 이 벡터들로부터 행렬을 만들면 됩니다.

% Get the number of pixels in each image
imageWidth = 28;
imageHeight = 28;
inputSize = imageWidth*imageHeight;

% Load the test images
[xTestImages,tTest] = digitTestCellArrayData;

% Turn the test images into vectors and put them in a matrix
xTest = zeros(inputSize,numel(xTestImages));
for i = 1:numel(xTestImages)
    xTest(:,i) = xTestImages{i}(:);
end

결과는 혼동행렬로 시각화할 수 있습니다. 행렬의 오른쪽 아래 정사각형에 있는 숫자들이 전반적인 정확도를 나타냅니다.

y = stackednet(xTest);
plotconfusion(tTest,y);

적층 신경망 미세 조정하기

전체 다층 신경망에 대해 역전파를 수행하여 적층 신경망의 결과를 향상시킬 수 있습니다. 이 과정을 종종 미세 조정이라고 합니다.

신경망을 훈련 데이터에 대해 지도 방식으로 다시 훈련시킴으로써 미세 조정합니다. 이 작업을 하려면, 테스트 영상에 했던 것과 마찬가지로, 먼저 훈련 영상을 행렬로 형태 변경해야 합니다.

% Turn the training images into vectors and put them in a matrix
xTrain = zeros(inputSize,numel(xTrainImages));
for i = 1:numel(xTrainImages)
    xTrain(:,i) = xTrainImages{i}(:);
end

% Perform fine tuning
stackednet = train(stackednet,xTrain,tTrain);

그런 다음 혼동행렬을 사용하여 결과를 다시 표시합니다.

y = stackednet(xTest);
plotconfusion(tTest,y);

요약

이 예제에서는 오토인코더를 사용하여 영상의 숫자를 분류하도록 적층 신경망을 훈련시키는 방법을 살펴보았습니다. 이 예제에서 설명한 단계는 문자 영상 분류나 특정 범주에 속한 사물의 더 작은 영상 분류처럼 다른 비슷한 문제에 적용할 수 있습니다.