使用自动多 GPU 支持训练网络
R2026b此示例说明如何使用自动并行支持在本地计算机上使用多个 GPU 进行深度学习训练。
训练深度学习网络通常需要几个小时或几天的时间。借助并行计算,您可以使用多个 GPU 加快训练速度。要了解有关并行训练选项的详细信息,请参阅Scale Up Deep Learning in Parallel, on GPUs, and in the Cloud。
下载数据集
Flowers 数据集包含 3670 个 224×224 大小的花卉图像,这些图像属于五类(雏菊、蒲公英、玫瑰、向日葵和郁金香)。下载并提取数据集。
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 来加快网络训练速度。下图显示在具有四个 NVIDIA® A5000 的 Linux 计算机上,GPU 的数量对整个训练时间的加速情况。您观察到的加速将取决于您的硬件和代码。通常,计算密集程度更高的训练(例如涉及大图像的训练)使用多个 GPU 时受益更多。

要验证训练是否有效地使用了所有可用的 GPU,您可以使用 GPU Monitor (Parallel Computing Toolbox)。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
将预测结果收集到单个数组中。
YTest = cat(1,YTest{:});确定网络的准确度并绘制混淆图。
accuracy = sum(YTest==imdsTest.Labels)/numel(imdsTest.Labels)
accuracy = 0.8000
confusionchart(imdsTest.Labels,YTest)

另请参阅
trainnet | trainingOptions | dlnetwork | imageDatastore