cycleGANにお​けるGPUに連携する​minibatchの​設定について

조회 수: 3 (최근 30일)
祐矢 関川
祐矢 関川 2024년 10월 7일
댓글: 祐矢 関川 2024년 10월 8일
以下のエラーが出ており、先に進めないので、ご教示頂けると幸いです。
次を使用中のエラー: minibatchqueue (行 188)
'MiniBatchFcn' の値で指定された関数を適用できません。
エラー: trainCycleGAN (行 39)
mbqTrain = minibatchqueue(dsTrain, ...
^^^^^^^^^^^^^^^^^^^^^^^^^^^
原因:
次を使用中のエラー: gpuArray
CUDA 実行中に予期しないエラーが発生しました。CUDA エラー:
an illegal memory access was encountered
本文は以下です。
% =========================================================================
% CycleGAN Training
% =========================================================================
clc
clear
close
% モデルをトレーニングするか、ロードするかを定義
doTraining = true; % トレーニングする場合はtrue、モデルをロードする場合はfalse
% データセットのパス
DataDirCT = "C:\Users\sekikawa\Desktop\研究\MRAC\研究データ\Current teaching data\CT"; % CT
DataDirMR = "C:\Users\sekikawa\Desktop\研究\MRAC\研究データ\Current teaching data\T2"; % MR
% トレーニングデータの画像データストア (DICOMファイル)
imdsTrainCT = imageDatastore(DataDirCT, 'FileExtensions', '.dcm', 'ReadFcn', @(x) dicomread(x), 'IncludeSubfolders', true);
imdsTrainMR = imageDatastore(DataDirMR, 'FileExtensions', '.dcm', 'ReadFcn', @(x) dicomread(x), 'IncludeSubfolders', true);
% テストデータのフォルダパス
FolderTestCT = "C:\Users\sekikawa\Desktop\研究\MRAC\研究データ\Current test data\CT"; % テスト用CTフォルダ
FolderTestMR = "C:\Users\sekikawa\Desktop\研究\MRAC\研究データ\Current test data\T2"; % テスト用MRフォルダ
% テストデータの画像データストア (DICOMファイル)
imdsTestCT = imageDatastore(FolderTestCT, 'FileExtensions', '.dcm', 'ReadFcn', @(x) dicomread(x), 'IncludeSubfolders', true);
imdsTestMR = imageDatastore(FolderTestMR, 'FileExtensions', '.dcm', 'ReadFcn', @(x) dicomread(x), 'IncludeSubfolders', true);
% randomPatchExtractionDatastoreを使用して、低線量と高線量のトレーニングデータを組み合わせる。
inputSize = [512, 512, 1];
patchesPerImage = 128;
dsTrain = randomPatchExtractionDatastore(shuffle(imdsTrainMR), shuffle(imdsTrainCT), ...
inputSize(1:2), PatchesPerImage=patchesPerImage);
% minibatchqueue オブジェクトを作成し、ミニバッチ前処理関数を concatenateMiniBatch と指定する。
miniBatchSize = 8; % バッチサイズの調整
mbqTrain = minibatchqueue(dsTrain, ...
MiniBatchSize=miniBatchSize, ...
MiniBatchFcn=@concatenateMiniBatch, ...
PartialMiniBatch="discard", ...
MiniBatchFormat="SSCB", ...
OutputEnvironment="gpu"); % 出力環境をGPUに設定
% 生成器と識別器の定義
numResiduals = 6;
genCT2MR = cycleGANGenerator(inputSize, NumResidualBlocks=numResiduals, NumOutputChannels=1);
genMR2CT = cycleGANGenerator(inputSize, NumResidualBlocks=numResiduals, NumOutputChannels=1);
discCT = patchGANDiscriminator(inputSize); % CT識別器
discMR = patchGANDiscriminator(inputSize); % MR識別器
% オプティマイザーの設定
lambda = 10; % サイクル一貫性損失の係数
numEpochs = 5;
learningRate = 0.0002;
gradientDecay = 0.5;
sqGradientDecayFactor = 0.999;
% ジェネレーターとディスクリミネーターのアダム・パラメーターを初期化する。
avgGradgenMR2CT = [];
avgSqGradgenMR2CT = [];
avgGradgenCT2MR = [];
avgSqGradgenCT2MR = [];
avgGraddiscMR = [];
avgSqGraddiscMR = [];
avgGraddiscCT = [];
avgSqGraddiscCT = [];
% 生成された訓練画像パッチを250反復ごとに表示し、250反復ごとに訓練モニタを更新する。
displayImageFrequency = 250;
updateTrainingMonitorFrequency = 250;
% 学習モニターを定期的に更新するための反復回数を計算する。%
numObservationsTrain = numel(imdsTrainCT.Files) * patchesPerImage;
numIterationsPerEpoch = floor(numObservationsTrain / miniBatchSize);
numIterations = numEpochs * numIterationsPerEpoch;
psnrTrain = zeros(1, numIterations); % 1行numIterations列のゼロ配列
ssimTrain = zeros(1, numIterations); % 1行numIterations列のゼロ配列
% トレーニング監視モニターの設定
if doTraining
monitor = trainingProgressMonitor;
monitor.Metrics = ["PSNRCT", "PSNRMR", "SSIMCT", "SSIMMR"];
monitor.Info = ["Epoch", "Iteration", "LearnRate", "ExecutionEnvironment"];
groupSubPlot(monitor, "PSNR", ["PSNRCT", "PSNRMR"]);
groupSubPlot(monitor, "SSIM", ["SSIMCT", "SSIMMR"]);
monitor.XLabel = "Iteration";
monitor.Status = "Configuring";
monitor.Progress = 0;
% 実行環境の確認
if canUseGPU
updateInfo(monitor, ExecutionEnvironment = "GPU");
else
updateInfo(monitor, ExecutionEnvironment = "CPU");
end
% チェックポイント保存ディレクトリ
checkpointDir = fullfile("checkpoints/");
if ~exist(checkpointDir, "dir")
mkdir(checkpointDir);
end
% trainingProgressMonitorのトレーニングステータスを更新する。
monitor.Status = "Running";
epoch = 0;
iteration = 0;
metricsForMonitoring = {[], [], [], []};
while epoch < numEpochs && ~monitor.Stop
epoch = epoch + 1;
shuffle(mbqTrain);
% ミニバッチのループ
while hasdata(mbqTrain) && ~monitor.Stop
iteration = iteration + 1;
% データ取得
[dataCT, dataMR] = next(mbqTrain);
% 画像データを4次元に結合
dataCT = cat(4, dataCT{:});
dataMR = cat(4, dataMR{:});
% データをGPUに転送
dataCT = dlarray(single(dataCT) / 255, 'SSCB');
dataMR = dlarray(single(dataMR) / 255, 'SSCB');
if canUseGPU
dataCT = gpuArray(dataCT);
dataMR = gpuArray(dataMR);
end
% 勾配計算
[genCT2MRGrad, genMR2CTGrad, discrXGrad, discYGrad, ...
genCT2MRState, genMR2CTState, scores, metrics, imagesOutMR2CT, imagesOutCT2MR] = ...
dlfeval(@modelGradients, genMR2CT, genCT2MR, ...
discMR, discCT, dataCT, dataMR, lambda);
genCT2MR.State = genCT2MRState;
genMR2CT.State = genMR2CTState;
% メトリクスの記録
metricsForMonitoring{1} = [metricsForMonitoring{1}, metrics{1}];
metricsForMonitoring{2} = [metricsForMonitoring{2}, metrics{2}];
metricsForMonitoring{3} = [metricsForMonitoring{3}, metrics{3}];
metricsForMonitoring{4} = [metricsForMonitoring{4}, metrics{4}];
% discMRのパラメータを更新
[discMR.Learnables, avgGraddiscMR, avgSqGraddiscMR] = ...
adamupdate(discMR.Learnables, discrXGrad, avgGraddiscMR, ...
avgSqGraddiscMR, iteration, learningRate, gradientDecay, sqGradientDecayFactor);
% discCTのパラメータを更新
[discCT.Learnables, avgGraddiscCT, avgSqGraddiscCT] = ...
adamupdate(discCT.Learnables, discYGrad, avgGraddiscCT, ...
avgSqGraddiscCT, iteration, learningRate, gradientDecay, sqGradientDecayFactor);
% genCT2MRのパラメータを更新
[genCT2MR.Learnables, avgGradgenCT2MR, avgSqGradgenCT2MR] = ...
adamupdate(genCT2MR.Learnables, genCT2MRGrad, avgGradgenCT2MR, ...
avgSqGradgenCT2MR, iteration, learningRate, gradientDecay, sqGradientDecayFactor);
% genMR2CTのパラメータを更新
[genMR2CT.Learnables, avgGradgenMR2CT, avgSqGradgenMR2CT] = ...
adamupdate(genMR2CT.Learnables, genMR2CTGrad, avgGradgenMR2CT, ...
avgSqGradgenMR2CT, iteration, learningRate, gradientDecay, sqGradientDecayFactor);
% メトリクス更新
if mod(iteration, updateTrainingMonitorFrequency) == 0 || iteration == 1
recordMetrics(monitor, iteration, ...
PSNRCT = mean(metricsForMonitoring{1}), ...
PSNRMR = mean(metricsForMonitoring{2}), ...
SSIMCT = mean(metricsForMonitoring{3}), ...
SSIMMR = mean(metricsForMonitoring{4}));
metricsForMonitoring = {[], [], [], []};
end
recordMetrics(monitor, iteration);
updateInfo(monitor, ...
Epoch = epoch + " of " + numEpochs, ...
LearnRate = learningRate, ...
Iteration = iteration + " of " + numIterations);
monitor.Progress = 100 * iteration / numIterations;
end
% エポック終了後のメトリクス計算
% MR画像をCT画像に変換
generatedCT = forward(genMR2CT, dataMR);
% PSNRとSSIMを計算
psnrEpoch = mean(psnr(generatedCT, dataCT), 'all');
ssimEpoch = mean(multissim(generatedCT, dataCT), 'all');
% トレーニングメトリクスに追加
psnrTrain = psnrEpoch;
ssimTrain = ssimEpoch;
% 各モデルの保存
save(fullfile(checkpointDir, "CycleGAN-Epoch-" + epoch + ".mat"), ...
"genMR2CT", "genCT2MR", "discCT", "discMR");
end
% 最終モデルを保存
save('cycleGANModels.mat', "genMR2CT", "genCT2MR", "discCT", "discMR");
monitor.Status = "Training complete";
% モニタの状態を更新
if monitor.Stop == 1
monitor.Status = "Training stopped";
else
monitor.Status = "Training complete";
end
end
% モデル勾配関数
function [genCT2MRGrad, genMR2CTGrad, discrXGrad, discYGrad, ...
genCT2MRState, genMR2CTState, scores, metrics, ...
imagesOutMRAndCTGenerated, imagesOutCTAndMRGenerated] = ...
modelGradients(genMR2CT, genCT2MR, discMR, discCT, imageCT, imageMR, lambda)
% 画像を一つのドメインから別のドメインへ変換する: CTからMR、そしてその逆
[imageMRGenerated, genCT2MRState] = forward(genCT2MR, imageCT);
[imageCTGenerated, genMR2CTState] = forward(genMR2CT, imageMR);
% 各ドメインにおける実際の画像の予測を対応する識別器ネットワークで計算
predRealMR = forward(discMR, imageMR);
predRealCT = forward(discCT, imageCT);
% 各ドメインにおける生成画像の予測を対応する識別器ネットワークで計算
predGeneratedMR = forward(discMR, imageMRGenerated);
predGeneratedCT = forward(discCT, imageCTGenerated);
% 実際の画像に対する識別器の損失を計算
discMRLossReal = lossReal(predRealMR);
discCTLossReal = lossReal(predRealCT);
% 生成された画像に対する識別器の損失を計算
discMRLossGenerated = lossGenerated(predGeneratedMR);
discCTLossGenerated = lossGenerated(predGeneratedCT);
% 各識別器ネットワークに対する総損失を計算
discMRLossTotal = 0.5 * (discMRLossReal + discMRLossGenerated);
discCTLossTotal = 0.5 * (discCTLossReal + discCTLossGenerated);
% 生成画像に対する生成器の損失を計算
genLossCT2MR = lossReal(predGeneratedMR);
genLossMR2CT = lossReal(predGeneratedCT);
% ラウンドトリップ(サイクル整合性)出力を完了するために、各生成画像に生成器を適用して、対応する元のドメインの画像を得る
cycleImageMR2CT2MR = forward(genCT2MR, imageCTGenerated);
cycleImageCT2MR2CT = forward(genMR2CT, imageMRGenerated);
% 実際の画像と生成画像の間のサイクル整合性損失を計算
cycleLossMR2CT2MR = cycleConsistencyLoss(imageMR, cycleImageMR2CT2MR, lambda);
cycleLossCT2MR2CT = cycleConsistencyLoss(imageCT, cycleImageCT2MR2CT, lambda);
% 同一出力を計算
identityImageMR = forward(genCT2MR, imageMR);
identityImageCT = forward(genMR2CT, imageCT);
% 同一出力間の忠実度損失(SSIM)を計算
fidelityLossMR = mean(1 - multissim(identityImageMR, imageMR), "all");
fidelityLossCT = mean(1 - multissim(identityImageCT, imageCT), "all");
% 総生成器損失を計算
genLossTotal = genLossCT2MR + cycleLossCT2MR2CT + ...
genLossMR2CT + cycleLossMR2CT2MR + fidelityLossMR + fidelityLossCT;
% 生成器のスコアを計算
genCT2MRScore = mean(sigmoid(predGeneratedMR), "all");
genMR2CTScore = mean(sigmoid(predGeneratedCT), "all");
% 識別器のスコアを計算
discMRScore = 0.5 * mean(sigmoid(predRealMR), "all") + ...
0.5 * mean(1 - sigmoid(predGeneratedMR), "all");
discCTScore = 0.5 * mean(sigmoid(predRealCT), "all") + ...
0.5 * mean(1 - sigmoid(predGeneratedCT), "all");
% スコアをセル配列にまとめる
scores = {genCT2MRScore, genMR2CTScore, discMRScore, discCTScore};
% 生成器の勾配を計算
genMR2CTGrad = dlgradient(genLossTotal, genMR2CT.Learnables, RetainData=true);
genCT2MRGrad = dlgradient(genLossTotal, genCT2MR.Learnables, RetainData=true);
% 識別器の勾配を計算
discrXGrad = dlgradient(discMRLossTotal, discMR.Learnables, RetainData=true);
discYGrad = dlgradient(discCTLossTotal, discCT.Learnables);
% メトリクス
psnrLowDose = double(gather(extractdata(mean(psnr(imageMRGenerated, imageMR)))));
psnrHighDose = double(gather(extractdata(mean(psnr(imageCTGenerated, imageCT)))));
ssimLowDose = double(gather(extractdata(mean(multissim(imageMRGenerated, imageMR)))));
ssimHighDose = double(gather(extractdata(mean(multissim(imageCTGenerated, imageCT)))));
metrics = {psnrLowDose, psnrHighDose, ssimLowDose, ssimHighDose};
% CTをMRに変換したミニバッチ画像を返す
imagesOutMRAndCTGenerated = {imageMR, imageCTGenerated};
% MRをCTに変換したミニバッチ画像を返す
imagesOutCTAndMRGenerated = {imageCT, imageMRGenerated};
end
% 損失関数...
% 実画像と生成画像に対してMSE損失関数を定義する。
function loss = lossReal(predictions)
loss = mean((1 - predictions).^2, "all");
end
% 実画像と生成画像に対するサイクル一貫性損失関数を定義する。
function loss = lossGenerated(predictions)
loss = mean((predictions).^2, "all");
end
function loss = cycleConsistencyLoss(imageReal, imageGenerated, lambda)
loss = mean(abs(imageReal - imageGenerated), "all") * lambda;
end
% ミニバッチのデータをGPUに転送する関数
function [out1, out2] = concatenateMiniBatch(im1, im2)
out1 = cat(4, im1{:});
out2 = cat(4, im2{:});
% GPUに転送
if canUseGPU
out1 = gpuArray(out1);
out2 = gpuArray(out2);
end
end
CTとMRIは512×512×1、使用するGPUはQuadro RTX5000です。
どうぞよろしくお願いいたします。
  댓글 수: 2
Joss Knight
Joss Knight 2024년 10월 8일
This is an internal error in a GPU kernel. Please contact support and provide reproduction code. Thanks.
祐矢 関川
祐矢 関川 2024년 10월 8일
Thank you for your tips. I'll try to do that.

댓글을 달려면 로그인하십시오.

답변 (0개)

카테고리

Help CenterFile Exchange에서 GPU Computing에 대해 자세히 알아보기

태그

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by