주요 콘텐츠

거리 척도로서의 정규화된 평균제곱오차

R2025a 이후

이 예제에서는 무선 통신 응용 분야에서 신경망 훈련을 위해 NMSE(정규화된 평균제곱오차)를 손실 함수로 사용하는 방법을 보여줍니다.

소개

무선 통신에서 신호의 동작과 성능을 정확하게 예측하는 것은 시스템 설계 및 동작을 최적화하는 데 매우 중요합니다. 신경망은 통신 시스템에서 복잡한 관계를 모델링하고 예측하기 위한 강력한 도구로 부상했습니다. 신경망 훈련에서 중요한 측면 중 하나는 손실 함수의 선택이며, 이는 예측 오차를 최소화하도록 최적화 과정을 안내합니다.

NMSE는 MSE(평균제곱오차)와 유사한 유클리드 거리 척도입니다. NMSE는 데이터의 스케일이 변하는 시나리오에서 특히 유용한데, 이는 타깃 데이터의 분산으로 MSE를 정규화하여 예측 정확도에 대해 스케일 독립적인 척도를 제공하기 때문입니다.

이 예제에서는 helperNNDPDTrainingData 함수를 사용하여 통신 링크에 대한 데이터를 생성합니다. 신호 x와 y는 PA(전력 증폭기)의 입력과 출력입니다. 이상적으로는 증폭기 이득을 제거하면 신호 x와 y는 동일해야 합니다. 자세한 내용은 Neural Network for Digital Predistortion Design-Offline Training 예제를 참조하십시오.

dpdData = helperNNDPDTrainingData;
x = dpdData.txWaveTrain;
y = dpdData.paOutputTrain;

신호를 검토합니다.

plotSignals(x,y);

Figure contains 2 axes objects. Axes object 1 with xlabel Samples, ylabel Amplitude contains 2 objects of type line. These objects represent x, y. Axes object 2 with xlabel Samples, ylabel |x-y| contains a line object which displays its values using only markers.

fprintf("The maximum amplitude of the signals is %f",max(max(abs(x)),max(abs(y))))
The maximum amplitude of the signals is 0.020772
fprintf("The maximum absolute error between the two signals is %e",max(abs(x-y)))
The maximum absolute error between the two signals is 2.052652e-03
fprintf("The average power of signal x is %e",mean(abs(x).^2))
The average power of signal x is 7.787301e-05

유클리드 거리를 기준으로 한 유사성 척도

MSE(평균제곱오차)와 NMSE(정규화된 평균제곱오차)를 사용하여 두 신호의 유사성을 측정합니다.

두 신호 간의 MSE

MSE는 다음으로 정의됩니다.

MSE=1Nn=1N|xn-yn|2

mse = mean(abs(x-y).^2)
mse = single

5.6925e-07

dB 스케일에서 MSE는 다음과 같습니다.

mse_dB = 10*log10(mse)
mse_dB = single

-62.4470

신호 x의 진폭과 평균 전력이 작기 때문에 MSE도 매우 작은 수입니다.

두 신호 간의 NMSE

훈련 중에 값이 작은 신호는 값이 큰 신호만큼 고려되지 않을 수 있습니다. NMSE 손실 함수는 신호 전력으로 손실 함수를 스케일링하여 이 문제를 해결합니다. helperNMSE 함수는 다음 방정식을 구현하고 NMSE를 dB 단위로 출력합니다.

Norm=1Nn=1N|xn|2

NMSE=MSENorm

nmse = helperNMSE(x,y)
nmse = single

-21.3609

NMSE 및 MSE를 사용하여 훈련시키기

MSE와 NMSE를 손실 함수로 사용하여 신경망 DPD를 훈련시킵니다. 내장 mse 손실 함수와 사용자 지정 helperNMSE 함수를 사용합니다. 먼저 helperNNDPDTrainingOptions 함수를 사용하여 훈련 옵션과 신경망을 가져옵니다.

[net,options] = helperNNDPDTrainingOptions;

두 경우 모두에 대해 동일한 초기 조건에서 훈련을 시작하기 위해 난수 생성기를 알려진 값으로 설정합니다.

rng(123)
netDPDMSE = trainnet(dpdData.trainingInput,dpdData.trainingOutput, ...
  net,"mse",options);
    Iteration    Epoch    TimeElapsed    LearnRate    TrainingLoss
    _________    _____    ___________    _________    ____________
            1        1       00:00:00        0.001          3.4093
          256        2       00:00:02        0.001        0.015105
          512        4       00:00:02        0.001       0.0069223
          768        6       00:00:03      0.00095       0.0043773
         1024        8       00:00:04      0.00095       0.0025694
         1280       10       00:00:05      0.00095       0.0014847
         1536       12       00:00:06    0.0009025       0.0012758
         1792       14       00:00:07    0.0009025       0.0010268
         2048       16       00:00:07   0.00085737      0.00078196
         2304       18       00:00:08   0.00085737       0.0007438
         2560       20       00:00:09   0.00085737      0.00069718
Training stopped: Max epochs completed
rng(123)
netDPDNMSE = trainnet(dpdData.trainingInput,dpdData.trainingOutput, ...
  net,@(Y,T)helperNMSE(Y,T,"linear"),options);
    Iteration    Epoch    TimeElapsed    LearnRate    TrainingLoss
    _________    _____    ___________    _________    ____________
            1        1       00:00:00        0.001          1.0841
          256        2       00:00:03        0.001        0.014231
          512        4       00:00:06        0.001       0.0053596
          768        6       00:00:08      0.00095       0.0035835
         1024        8       00:00:11      0.00095       0.0035037
         1280       10       00:00:14      0.00095       0.0016687
         1536       12       00:00:16    0.0009025       0.0014887
         1792       14       00:00:18    0.0009025       0.0021333
         2048       16       00:00:21   0.00085737        0.001189
         2304       18       00:00:23   0.00085737       0.0014467
         2560       20       00:00:26   0.00085737       0.0010198
Training stopped: Max epochs completed

훈련된 신경망의 EVM, ACPR, MSE 및 NMSE 값을 비교합니다.

dpdOutNMSE = predict(netDPDNMSE,dpdData.inputMtxTest);
dpdOutNMSE = complex(dpdOutNMSE(:,1),dpdOutNMSE(:,2));
dpdOutNMSE = dpdOutNMSE/dpdData.scalingFactor;
pa = helperNNDPDPowerAmplifier(DataSource="Simulated PA",SampleRate=dpdData.ofdmParams.SampleRate);
paOutputNN = pa(dpdOutNMSE);
% Evaluate performance with MSE loss function
acprNMSE = helperACPR(paOutputNN,dpdData.ofdmParams.SampleRate,dpdData.ofdmParams.Bandwidth);
nmseNMSE = helperNMSE(dpdData.txWaveTest,paOutputNN);
mseNMSE = helperMSE(dpdData.txWaveTest,paOutputNN);
evmNMSE = helperEVM(paOutputNN,dpdData.qamRefSymTest,dpdData.ofdmParams);

dpdOutMSE = predict(netDPDMSE,dpdData.inputMtxTest);
dpdOutMSE = complex(dpdOutMSE(:,1),dpdOutMSE(:,2));
dpdOutMSE = dpdOutMSE/dpdData.scalingFactor;
paOutputNN = pa(dpdOutMSE);
% Evaluate performance with NMSE loss function
acprMSE = helperACPR(paOutputNN,dpdData.ofdmParams.SampleRate,dpdData.ofdmParams.Bandwidth);
nmseMSE = helperNMSE(dpdData.txWaveTest,paOutputNN);
mseMSE = helperMSE(dpdData.txWaveTest,paOutputNN);
evmMSE = helperEVM(paOutputNN,dpdData.qamRefSymTest,dpdData.ofdmParams);

results = table([evmMSE;evmNMSE],[acprMSE;acprNMSE],[mseMSE;mseNMSE],[nmseMSE;nmseNMSE], ...
  VariableNames=["EVM_percent","ACPR_dB","MSE_dB","NMSE_dB"],RowNames=["MSE Trained","NMSE Trained"])
results=2×4 table
                    EVM_percent    ACPR_dB    MSE_dB     NMSE_dB
                    ___________    _______    _______    _______

    MSE Trained       2.0842       -33.802     -69.27    -28.159
    NMSE Trained      1.7407       -35.389    -70.921     -29.81

로컬 함수

function plotSignals(x,y)
tiledlayout(2,1)
nexttile
plot(real(x(1:1000,1)))
hold on
plot(real(y(1:1000,1)))
hold off
grid on
xlabel("Samples")
ylabel("Amplitude")
legend("x","y")
nexttile
plot(abs(x-y),'.')
grid on
xlabel("Samples")
ylabel("|x-y|")
end

참고 항목

도움말 항목