主要内容

使用自动多 GPU 支持训练网络

此示例说明如何使用自动并行支持在本地计算机上使用多个 GPU 进行深度学习训练。

训练深度学习网络通常需要几个小时或几天的时间。借助并行计算,您可以使用多个 GPU 加快训练速度。要了解有关并行训练选项的详细信息,请参阅Scale Up Deep Learning in Parallel, on GPUs, and in the Cloud

要求

在运行此示例之前,您必须将 CIFAR-10 数据集下载到本地计算机。要下载 CIFAR-10 数据集,请使用 downloadCIFARToFolders 函数,此函数作为支持文件包含在此示例中。要访问此文件,请以实时脚本形式打开此示例。使用以下代码将该数据集下载到您的当前目录。如果您已有 CIFAR-10 的本地副本,则可以略过本节。

directory = pwd;
[locationCifar10Train,locationCifar10Test] = downloadCIFARToFolders(directory);
Downloading CIFAR-10 data set...done.
Copying CIFAR-10 to folders...done.

加载数据集

使用 imageDatastore 对象加载训练和测试数据集,并提取类的名称。在以下代码中,确保数据存储的位置指向本地计算机中的 CIFAR-10。

imdsTrain = imageDatastore(locationCifar10Train, ...
 IncludeSubfolders=true, ...
 LabelSource="foldernames");

imdsTest = imageDatastore(locationCifar10Test, ...
 IncludeSubfolders=true, ...
 LabelSource="foldernames");

classNames = categories(imdsTrain.Labels);

要使用增强的图像数据训练网络,请创建 augmentedImageDatastore 对象。使用随机平移和水平翻转。数据增强有助于防止网络过拟合和记忆训练图像的具体细节。

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

定义网络架构和训练选项

为 CIFAR-10 数据集定义一个网络架构。为了简化代码,使用对输入进行卷积的卷积块。池化层对空间维度进行下采样。

blockDepth = 4; % blockDepth controls the depth of a convolutional block.
netWidth = 32; % netWidth controls the number of filters in a convolutional block.

layers = [
    imageInputLayer(imageSize) 
    
    convolutionalBlock(netWidth,blockDepth)
    maxPooling2dLayer(2,Stride=2)
    convolutionalBlock(2*netWidth,blockDepth)
    maxPooling2dLayer(2,Stride=2)    
    convolutionalBlock(4*netWidth,blockDepth)
    averagePooling2dLayer(8) 
    
    fullyConnectedLayer(10)
    softmaxLayer];

指定训练选项。

  • 通过将执行环境设置为 "multi-gpu",使用多个 GPU 训练网络。当您使用多个 GPU 时,就增加了可用的计算资源。根据 GPU 的数量扩大小批量大小,以保持每个 GPU 上的工作负载不变。在此示例中,GPU 的数量是两个。根据小批量大小缩放学习率。在 GPU 上进行训练需要 Parallel Computing Toolbox™ 许可证和受支持的 GPU 设备。有关受支持设备的信息,请参阅GPU 计算要求 (Parallel Computing Toolbox)

  • 使用学习率调度,以随着训练的进行降低学习率。

  • 打开训练进度图可在训练过程中获得可视化的反馈数据。

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

options = trainingOptions("sgdm", ...
    ExecutionEnvironment="multi-gpu", ... % Turn on automatic multi-gpu support.
    InitialLearnRate=initialLearnRate, ... % Set the initial learning rate.
    MiniBatchSize=miniBatchSize, ... % Set the MiniBatchSize.
    Verbose=false, ... % Do not send command line output.
    Plots="training-progress", ... % Turn on the training progress plot.
    Metrics="accuracy", ...
    L2Regularization=1e-10, ...
    MaxEpochs=60, ...
    Shuffle="every-epoch", ...
    ValidationData=imdsTest, ...
    ValidationFrequency=floor(numel(imdsTrain.Files)/miniBatchSize), ...
    LearnRateSchedule="piecewise", ...
    LearnRateDropFactor=0.1, ...
    LearnRateDropPeriod=50);

训练网络

使用 trainnet 函数训练神经网络。对于分类,使用交叉熵损失。

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

自动多 GPU 支持可以利用多个 GPU 来加快网络训练速度。下图显示在具有四个 NVIDIA© TITAN Xp GPU 的 Linux 计算机上,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);

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

将预测结果收集到单个数组中。

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

确定网络的准确度并绘制混淆图。

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

定义辅助函数

定义一个函数,以便在网络架构中创建卷积模块。

function layers = convolutionalBlock(numFilters,numConvLayers)
    layers = [
        convolution2dLayer(3,numFilters,Padding="same")
        batchNormalizationLayer
        reluLayer];
    
    layers = repmat(layers,numConvLayers,1);
end

另请参阅

| | |

主题