メインコンテンツ

自動マルチ GPU のサポートを使用したネットワークの学習

R2026b

この例では、自動並列サポートを使用した深層学習のために、ローカル マシンで複数の GPU を使用する方法を説明します。

多くの場合、深層学習ネットワークの学習には数時間または数日かかります。並列計算を使用すると、複数の GPU を使用して学習を高速化できます。並列学習のオプションの詳細については、並列処理、GPU、およびクラウドによる深層学習のスケール アップを参照してください。

データ セットのダウンロード

Flowers データ セットには、5 つのクラス (デイジー、タンポポ、バラ、ヒマワリ、およびチューリップ) に属し、サイズが 224×224 である 3670 個の花のイメージが格納されています。データ セットをダウンロードして解凍します。

url = "http://download.tensorflow.org/example_images/flower_photos.tgz";
downloadFolder = tempdir;
filename = fullfile(downloadFolder,"flower_dataset.tgz");

dataFolder = fullfile(downloadFolder,"flower_photos");

if ~exist(dataFolder,"dir")
    fprintf("Downloading Flowers data set (218 MB)... ")
    websave(filename,url);
    untar(filename,downloadFolder)
    fprintf("Done.\n")
end
Downloading Flowers data set (218 MB)... 
Done.

データ セットの読み込みと分割

imageDatastore オブジェクトを使用してデータ セットを読み込み、すべてのイメージが均一なサイズになるようにイメージのサイズを変更します。学習中にイメージを読み込むたびにサイズを変更するのではなく、イメージのサイズを事前に変更しておくことで、無駄な処理を減らすことができます。

imds = imageDatastore(dataFolder, ...
    IncludeSubfolders=true, ...
    LabelSource="foldernames");

imageSize = [224 224];

resizedImages = dir(fullfile(dataFolder,"flower_photos","**","*.png"));
if isempty(resizedImages)
    tds = transform(imds,@(x) imresize(x,imageSize));

    writeall(tds,dataFolder, ...
        OutputFormat="png", ...
        FolderLayout="duplicate");
end

imdsUniform = imageDatastore(dataFolder, ...
    IncludeSubfolders=true, ...
    LabelSource="foldernames");

データを学習セット (90%) とテスト セット (10%) に分割します。

[imdsTrain,imdsTest] = splitEachLabel(imdsUniform,0.9,"randomized");

classNames = categories(imdsTrain.Labels);
numClasses = numel(classNames);

拡張イメージ データを使用してネットワークに学習させるために、augmentedImageDatastore オブジェクトを作成します。ランダムな平行移動と水平方向の反転を使用します。データ拡張は、ネットワークで過適合が発生したり、学習イメージの正確な詳細が記憶されたりすることを防止するのに役立ちます。

pixelRange = [-30 30];
imageAugmenter = imageDataAugmenter( ...
    RandXReflection=true, ...
    RandXTranslation=pixelRange, ...
    RandYTranslation=pixelRange);
augmentedImdsTrain = augmentedImageDatastore(imageSize,imdsTrain, ...
    DataAugmentation=imageAugmenter);

ネットワーク アーキテクチャと学習オプションの定義

ResNet-50 ネットワークを定義し、データ セットに合わせて出力クラスの数を調整します。

net = imagePretrainedNetwork("resnet50",NumClasses=numClasses,Weights="none");

学習オプションを指定します。

  • 実行環境を "multi-gpu" に設定し、複数の GPU を使用してネットワークに学習させます。複数の GPU を使用する場合、利用可能な計算リソースを増やします。GPU の数でミニバッチ サイズをスケールアップし、各 GPU での作業負荷を一定に維持します。ミニバッチ サイズに応じて学習率をスケーリングします。GPU での学習には、Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスの詳細については、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。

  • 学習率のスケジュールを使用して、学習の進行に応じて学習率を下げます。

  • 学習の進行状況プロットをオンにして、学習中に、可視化されたフィードバックを取得します。

numGPUs = gpuDeviceCount("available")
numGPUs = 
4
miniBatchSize = 128*numGPUs;
initialLearnRate = 1e-2*miniBatchSize/64;

options = trainingOptions("adam", ...
    ExecutionEnvironment="multi-gpu", ...
    InitialLearnRate=initialLearnRate, ...
    MiniBatchSize=miniBatchSize, ...
    Verbose=false, ...
    Plots="training-progress", ...
    Metrics="accuracy", ...
    MaxEpochs=80, ...
    Shuffle="every-epoch", ...
    ValidationData=augmentedImageDatastore(imageSize,imdsTest), ...
    ValidationFrequency=floor(4*numel(imdsTrain.Files)/miniBatchSize), ...
    LearnRateSchedule="piecewise", ...
    LearnRateDropFactor=0.1, ...
    LearnRateDropPeriod=50);

ネットワークの学習

関数trainnetを使用してニューラル ネットワークに学習させます。分類には、クロスエントロピー損失を使用します。

net = trainnet(augmentedImdsTrain,net,"crossentropy",options);
Starting parallel pool (parpool) using the 'Processes' profile ...
Connected to parallel pool with 4 workers.

自動マルチ GPU のサポートにより、複数の GPU を利用してネットワークの学習を高速化できます。以下のプロットは、4 つの NVIDIA® A5000 GPU が搭載された Linux マシンにおいて、GPU の数が増えるにつれて全体的な学習時間が短縮される様子を示しています。実際に速度がどの程度向上するかは、ハードウェアとコードによって異なります。大きなイメージを扱う学習のように、計算負荷の高い学習では、一般に複数の GPU を使用することでより大きな効果が得られます。

GPU Monitor (Parallel Computing Toolbox)を使用すると、利用できるすべての GPU が学習で効果的に使われているかどうかを確認できます。GPU モニターは、お使いのマシンに搭載されている各 GPU の GPU 使用率、メモリ使用量、およびプロセスをリアルタイムで表示します。

ネットワークのテスト

テスト イメージを分類します。複数の GPU を使用して予測を行うには、データを分割し、並列で予測を行います。

テスト データ セットに含まれている観測値の合計数を判定します。

numObservations = numel(imdsTest.Files);

この例では、学習時に開いた並列プールを使用できます。並列プールが開いていない場合は、GPU の数と同じ数のワーカーをもつ並列プールを開きます。

parpool("Processes",numGPUs);

parfor (Parallel Computing Toolbox)を使用して、イメージの分類を並列で実行します。parfor ループは for ループに似ていますが、ループの反復処理は、並列プール内のワーカー上で並列実行されます。parfor ループの内部は次のようになります。

  • subset 関数を使用して、テスト データのサブセットを選択します。

  • サブセットに対して minibatchpredict 関数を使用し、予測を行います。関数 minibatchpredict は利用可能な GPU がある場合に自動的にそれを使用します。そうでない場合、関数は CPU を使用します。

  • scores2label 関数を使用して、予測スコアをラベルに変換します。

parfor idx = 1:numGPUs
	startIdx = ceil((idx-1)*numObservations/numGPUs) + 1;
    endIdx = ceil(idx*numObservations/numGPUs);
    subdsTest = subset(imdsTest,startIdx:endIdx);
    augSubdsTest = augmentedImageDatastore(imageSize,subdsTest);

    scoresTest = minibatchpredict(net,augSubdsTest,MiniBatchSize=miniBatchSize);
    YTest{idx} = scores2label(scoresTest,classNames);
end

予測を single 型の配列に収集します。

YTest = cat(1,YTest{:});

ネットワークの精度を判定し、混同チャートをプロットします。

accuracy = sum(YTest==imdsTest.Labels)/numel(imdsTest.Labels)
accuracy = 
0.8000
confusionchart(imdsTest.Labels,YTest)

参考

| | |

トピック