cycleGANにおけるGPUに連携するminibatchの設定について
조회 수: 3 (최근 30일)
이전 댓글 표시
以下のエラーが出ており、先に進めないので、ご教示頂けると幸いです。
次を使用中のエラー: 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
2024년 10월 8일
This is an internal error in a GPU kernel. Please contact support and provide reproduction code. Thanks.
답변 (0개)
참고 항목
카테고리
Help Center 및 File Exchange에서 GPU Computing에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!