准备数据
下载 CIFAR-10 数据集 [1]。该数据集包含 60,000 个图像,每个图像的大小为 32×32,并具有三个颜色通道 (RGB)。整个数据集的大小为 175 MB。下载过程可能需要一些时间,具体取决于您的 Internet 连接情况。
datadir = tempdir;
downloadCIFARData(datadir);
加载 CIFAR-10 数据集,用作训练图像和标签以及测试图像和标签。要启用网络验证,请将 5000 个测试图像用于验证。
[XTrain,YTrain,XTest,YTest] = loadCIFARData(datadir);
idx = randperm(numel(YTest),5000);
XValidation = XTest(:,:,:,idx);
XTest(:,:,:,idx) = [];
YValidation = YTest(idx);
YTest(idx) = [];
您可以使用以下代码显示训练图像的样本。
figure;
idx = randperm(numel(YTrain),20);
for i = 1:numel(idx)
subplot(4,5,i);
imshow(XTrain(:,:,:,idx(i)));
end
选择要优化的变量
选择要使用贝叶斯优化对哪些变量进行优化,并指定搜索范围。此外,指定变量是否为整数以及是否搜索对数空间中的区间。优化以下变量:
网络部分深度。此参数控制网络的深度。网络有三个部分,每个部分都有 SectionDepth 个相同的卷积层。因此卷积层的总数为 3*SectionDepth。脚本稍后部分中的目标函数在每个层中采用与 1/sqrt(SectionDepth) 成比例的卷积滤波器数量。因此,对于不同的部分深度,每次迭代的参数数量和所需的计算量大致相同。
初始化学习率。最佳学习率取决于您的数据以及您正在训练的网络。
随机梯度下降动量。动量在当前参数更新中包含一个与前一次迭代中的更新成比例的贡献,从而在更新中增加惯性。这会使参数更新更加平滑,并减少随机梯度下降固有的噪声。
L2 正则化强度。使用正则化以防止过拟合。搜索正则化强度的空间以查找良好的值。数据增强和批量归一化也有助于正则化网络。
optimVars = [
optimizableVariable('SectionDepth',[1 3],'Type','integer')
optimizableVariable('InitialLearnRate',[1e-2 1],'Transform','log')
optimizableVariable('Momentum',[0.8 0.98])
optimizableVariable('L2Regularization',[1e-10 1e-2],'Transform','log')];
执行贝叶斯优化
使用训练数据和验证数据作为输入,为贝叶斯优化器创建目标函数。目标函数训练一个卷积神经网络并返回对验证集的分类误差。该函数在此脚本的末尾定义。由于 bayesopt 使用基于验证集的误差率来选择最佳模型,因此最终网络可能会对验证集过拟合。随后基于独立测试集测试最终选择的模型,以估计泛化误差。
ObjFcn = makeObjFcn(XTrain,YTrain,XValidation,YValidation);
通过最大程度地减小对验证集的分类误差来执行贝叶斯优化。以秒为单位指定总优化时间。为了最好地利用贝叶斯优化的能力,您应该执行至少 30 次对象函数评估。要在多个 GPU 上并行训练网络,请将 'UseParallel' 值设置为 true。如果您有一个 GPU 并将 'UseParallel' 值设置为 true,则所有工作进程将共用该 GPU,这不仅无法加速训练,而且会增加 GPU 耗尽内存的几率。
每个网络完成训练后,bayesopt 将结果显示到命令行窗口。然后,bayesopt 函数返回 BayesObject.UserDataTrace 中的文件名。目标函数将经过训练的网络保存到磁盘,并将文件名返回到 bayesopt。
BayesObject = bayesopt(ObjFcn,optimVars, ...
'MaxTime',14*60*60, ...
'IsObjectiveDeterministic',false, ...
'UseParallel',false);
|===================================================================================================================================|
|