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

심층 학습을 사용한 sequence-to-sequence 회귀

이 예제에서는 심층 학습을 사용하여 엔진의 잔여 수명(RUL)을 예측하는 방법을 보여줍니다.

시계열 또는 시퀀스 데이터로부터 숫자형 값을 예측하도록 심층 신경망을 훈련시키기 위해 장단기 기억(LSTM) 네트워크를 사용할 수 있습니다.

이 예제에서는 [1]에서 설명한 Turbofan Engine Degradation Simulation Data Set를 사용합니다. 이 예제에서는 엔진의 여러 센서를 나타내는 시계열 데이터를 준 다음, 예측 유지관리 관점에서 엔진의 잔여 수명(단위: 주기)을 예측하도록 LSTM 네트워크를 훈련시킵니다. 훈련 데이터는 엔진 100개의 시뮬레이션된 시계열 데이터를 포함합니다. 각 시퀀스는 17개의 특징을 가지고 길이가 다양하며, 하나의 완전한 RTF(run to failure) 인스턴스에 대응됩니다. 테스트 데이터는 100개의 부분 시퀀스를 포함합니다. 각 시퀀스의 마지막에는 잔여 수명에 대응되는 값이 포함됩니다.

데이터 세트는 100개의 훈련 관측값과 100개의 테스트 관측값을 포함합니다.

데이터 다운로드하기

https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/ [2]에서 Turbofan Engine Degradation Simulation Data Set를 다운로드하고 압축을 풉니다.

각 시계열은 서로 다른 엔진을 나타냅니다. 각 엔진은 알려지지 않은 초기 마모 및 제작 편차가 있는 상태에서 구동되기 시작합니다. 각 시계열의 시작 시에 엔진은 정상적으로 동작하며, 시계열의 어느 시점에서 결함이 발생합니다. 훈련 세트에서 결함의 크기는 시스템 결함이 발생할 때까지 커집니다.

데이터는 공백으로 구분된 26개 숫자 열의 형태로 압축 텍스트 파일에 들어 있습니다. 각 행은 1회의 동작 주기 동안 캡처한 데이터 스냅샷이고, 각 열은 다른 변수입니다. 열은 다음에 대응됩니다.

  • 1열: 유닛 번호

  • 2열: 시간(단위: 주기)

  • 3–5열: 동작 설정

  • 6–26열: 센서 측정값 1–17

filename = "CMAPSSData.zip";
dataFolder = "data";
unzip(filename,dataFolder)

훈련 데이터 준비하기

이 예제의 마지막에 표시된 함수 preprocessDataTrain을 사용하여 데이터를 불러옵니다. 함수 prepareDataTrainfilenamePredictors에서 데이터를 추출하고, 훈련 예측 변수 시퀀스와 응답 변수 시퀀스를 포함하는 셀형 배열 XTrainYTrain을 반환합니다.

filenamePredictors = fullfile(dataFolder,"train_FD001.txt");
[XTrain,YTrain] = prepareDataTrain(filenamePredictors);

상수 값을 갖는 특징 제거하기

모든 시간 스텝에 대해 변하지 않는 특징은 훈련의 성능을 저하할 수 있습니다. 동일한 최솟값과 최댓값을 갖는 데이터 행을 찾아서 제거합니다.

m = min([XTrain{:}],[],2);
M = max([XTrain{:}],[],2);
idxConstant = M == m;

for i = 1:numel(XTrain)
    XTrain{i}(idxConstant,:) = [];
end

훈련 예측 변수 정규화하기

훈련 예측 변수가 평균 0과 단위 분산을 갖도록 정규화합니다. 모든 관측값에 대해 평균과 표준편차를 계산하려면 시퀀스 데이터를 가로로 결합하십시오.

mu = mean([XTrain{:}],2);
sig = std([XTrain{:}],0,2);

for i = 1:numel(XTrain)
    XTrain{i} = (XTrain{i} - mu) ./ sig;
end

응답 변수 자르기

엔진 결함이 임박했을 때 시퀀스 데이터로부터 더 많이 학습할 수 있도록 응답 변수를 임계값 150에서 자르십시오. 이렇게 하면 네트워크가 이보다 더 높은 RUL 값을 갖는 인스턴스들을 동일하게 처리합니다.

thr = 150;
for i = 1:numel(YTrain)
    YTrain{i}(YTrain{i} > thr) = thr;
end

이 그림에서는 첫 번째 관측값과 여기에 대응하는 잘린 응답 변수를 보여줍니다.

채우기를 위해 데이터 준비하기

미니 배치에 추가되는 채우기의 양을 최소화하려면 시퀀스 길이를 기준으로 훈련 데이터를 정렬하십시오. 그런 다음 훈련 데이터를 균등하게 나누고 미니 배치의 채우기 양을 줄이는 미니 배치 크기를 선택합니다.

시퀀스 길이를 기준으로 훈련 데이터를 정렬합니다.

for i=1:numel(XTrain)
    sequence = XTrain{i};
    sequenceLengths(i) = size(sequence,2);
end

[sequenceLengths,idx] = sort(sequenceLengths,'descend');
XTrain = XTrain(idx);
YTrain = YTrain(idx);

정렬된 시퀀스 길이를 막대 차트로 표시합니다.

figure
bar(sequenceLengths)
xlabel("Sequence")
ylabel("Length")
title("Sorted Data")

훈련 데이터를 균등하게 나누고 미니 배치의 채우기 양을 줄이는 미니 배치 크기를 선택합니다. 미니 배치 크기를 20으로 지정합니다. 이 그림에서는 정렬된 시퀀스와 정렬되지 않은 시퀀스에 더해진 채우기를 보여줍니다.

miniBatchSize = 20;

네트워크 아키텍처 정의하기

네트워크 아키텍처를 정의합니다. 은닉 유닛 200개를 갖는 LSTM 계층, 크기가 50인 완전 연결 계층, 드롭아웃 확률이 0.5인 드롭아웃 계층으로 구성된 LSTM 네트워크를 만듭니다.

numResponses = size(YTrain{1},1);
featureDimension = size(XTrain{1},1);
numHiddenUnits = 200;

layers = [ ...
    sequenceInputLayer(featureDimension)
    lstmLayer(numHiddenUnits,'OutputMode','sequence')
    fullyConnectedLayer(50)
    dropoutLayer(0.5)
    fullyConnectedLayer(numResponses)
    regressionLayer];

훈련 옵션을 지정합니다. 솔버 'adam'을 사용하여 크기가 20인 미니 배치로 구성된 Epoch 60회에 대해 훈련을 진행합니다. 학습률을 0.01로 지정합니다. 기울기가 한없이 증가하지 않도록 하려면 기울기 임계값을 1로 설정하십시오. 시퀀스가 길이를 기준으로 정렬된 상태를 유지하도록 하려면 'Shuffle''never'로 설정하십시오.

maxEpochs = 60;
miniBatchSize = 20;

options = trainingOptions('adam', ...
    'MaxEpochs',maxEpochs, ...
    'MiniBatchSize',miniBatchSize, ...
    'InitialLearnRate',0.01, ...
    'GradientThreshold',1, ...
    'Shuffle','never', ...
    'Plots','training-progress',...
    'Verbose',0);

네트워크 훈련시키기

trainNetwork를 사용하여 네트워크를 훈련시킵니다.

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

네트워크 테스트하기

이 예제의 마지막에 나오는 함수 prepareDataTest를 사용하여 테스트 데이터를 준비합니다. 함수 prepareDataTestfilenamePredictorsfilenameResponses에서 데이터를 추출하고, 각각 훈련 예측 변수 시퀀스와 응답 변수 시퀀스를 포함하는 셀형 배열 XTestYTest를 반환합니다.

filenamePredictors = fullfile(dataFolder,"test_FD001.txt");
filenameResponses = fullfile(dataFolder,"RUL_FD001.txt");
[XTest,YTest] = prepareDataTest(filenamePredictors,filenameResponses);

훈련 데이터로부터 계산한 idxConstant를 사용하여 상수 값을 갖는 특징을 제거합니다. 훈련 데이터와 동일한 파라미터를 사용하여 테스트 예측 변수를 정규화합니다. 훈련 데이터에 사용된 임계값과 동일한 임계값에서 테스트 응답 변수를 자릅니다.

for i = 1:numel(XTest)
    XTest{i}(idxConstant,:) = [];
    XTest{i} = (XTest{i} - mu) ./ sig;
    YTest{i}(YTest{i} > thr) = thr;
end

predict를 사용하여 테스트 데이터에 대해 예측을 수행합니다. 함수가 데이터에 채우기를 추가하지 않도록 하려면 미니 배치 크기를 1로 지정하십시오.

YPred = predict(net,XTest,'MiniBatchSize',1);

LSTM 네트워크는 한 번에 시간 스텝 하나씩 부분 시퀀스에 대해 예측을 수행합니다. 각 시간 스텝마다 네트워크는 이번 시간 스텝의 값과 이전 시간 스텝들로부터 계산한 네트워크 상태만을 사용하여 예측을 수행합니다. 네트워크는 각 예측 사이에 네트워크 상태를 업데이트합니다. predict 함수는 이러한 예측으로 구성된 시퀀스를 반환합니다. 예측의 마지막 요소는 해당 부분 시퀀스에 대해 예측된 RUL에 대응합니다.

또는 predictAndUpdateState를 사용하여 한 번에 시간 스텝 하나씩 예측을 수행할 수도 있습니다. 이 방법은 시간 스텝의 값이 스트림으로 수신되는 경우에 유용합니다. 일반적으로 한 번에 시간 스텝 하나씩 예측을 수행하는 것보다 전체 시퀀스에 대해 예측을 수행하는 것이 빠릅니다. 단일 시간 스텝 예측들 사이에서 네트워크를 업데이트하여 미래의 시간 스텝을 예측하는 방법에 대한 예제는 심층 학습을 사용한 시계열 예측 항목을 참조하십시오.

예측 중 일부를 플롯으로 시각화합니다.

idx = randperm(numel(YPred),4);
figure
for i = 1:numel(idx)
    subplot(2,2,i)
    
    plot(YTest{idx(i)},'--')
    hold on
    plot(YPred{idx(i)},'.-')
    hold off
    
    ylim([0 thr + 25])
    title("Test Observation " + idx(i))
    xlabel("Time Step")
    ylabel("RUL")
end
legend(["Test Data" "Predicted"],'Location','southeast')

주어진 부분 시퀀스에서 예측된 현재 RUL은 예측된 시퀀스의 마지막 요소입니다. 예측의 RMSE(제곱평균제곱근 오차)를 계산하고, 예측 오차를 히스토그램으로 시각화합니다.

for i = 1:numel(YTest)
    YTestLast(i) = YTest{i}(end);
    YPredLast(i) = YPred{i}(end);
end
figure
rmse = sqrt(mean((YPredLast - YTestLast).^2))
rmse = single
    21.1878
histogram(YPredLast - YTestLast)
title("RMSE = " + rmse)
ylabel("Frequency")
xlabel("Error")

예제 함수

함수 prepareDataTrainfilenamePredictors에서 데이터를 추출하고, 각각 훈련 예측 변수 시퀀스와 응답 변수 시퀀스를 포함하는 셀형 배열 XTrainYTrain을 반환합니다.

데이터는 공백으로 구분된 26개 숫자 열의 형태로 압축 텍스트 파일에 들어 있습니다. 각 행은 1회의 동작 주기 동안 캡처한 데이터 스냅샷이고, 각 열은 다른 변수입니다. 열은 다음에 대응됩니다.

  • 1: 유닛 번호

  • 2: 시간(단위: 주기)

  • 3–5: 동작 설정

  • 6–26: 센서 측정값 1–17

function [XTrain,YTrain] = prepareDataTrain(filenamePredictors)

dataTrain = dlmread(filenamePredictors);

numObservations = max(dataTrain(:,1));

XTrain = cell(numObservations,1);
YTrain = cell(numObservations,1);
for i = 1:numObservations
    idx = dataTrain(:,1) == i;
    
    X = dataTrain(idx,3:end)';
    XTrain{i} = X;
    
    timeSteps = dataTrain(idx,2)';
    Y = fliplr(timeSteps);
    YTrain{i} = Y;
end

end

함수 prepareDataTestfilenamePredictorsfilenameResponses에서 데이터를 추출하고, 훈련 예측 변수 시퀀스와 응답 변수 시퀀스를 포함하는 셀형 배열 XTestYTest를 반환합니다. filenamePredictors에서 시계열은 시스템 결함이 발생하기 조금 전에 종료됩니다. filenameResponses의 데이터는 테스트 데이터에 대한 진짜 RUL 값으로 구성된 벡터를 제공합니다.

function [XTest,YTest] = prepareDataTest(filenamePredictors,filenameResponses)

XTest = prepareDataTrain(filenamePredictors);

RULTest = dlmread(filenameResponses);

numObservations = numel(RULTest);

YTest = cell(numObservations,1);
for i = 1:numObservations
    X = XTest{i};
    sequenceLength = size(X,2);
    
    rul = RULTest(i);
    YTest{i} = rul+sequenceLength-1:-1:rul;
end

end

참고 항목

| | | |

참고 문헌

[1] Saxena, Abhinav, Kai Goebel, Don Simon, and Neil Eklund. "Damage propagation modeling for aircraft engine run-to-failure simulation." In Prognostics and Health Management, 2008. PHM 2008. International Conference on, pp. 1-9. IEEE, 2008.

[2] Saxena, Abhinav, Kai Goebel. "Turbofan Engine Degradation Simulation Data Set." NASA Ames Prognostics Data Repository https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/, NASA Ames Research Center, Moffett Field, CA

관련 항목