Этот пример показывает, как применить Байесовую оптимизацию к глубокому обучению и найти оптимальные сетевые гиперпараметры и опции обучения для сверточных нейронных сетей.
Чтобы обучить глубокую нейронную сеть, необходимо задать архитектуру нейронной сети, а также опции учебного алгоритма. Выбор и настройка этих гиперпараметров могут быть трудными и занять время. Байесова оптимизация является алгоритмом, хорошо подходящим для оптимизации гиперпараметров моделей регрессии и классификации. Можно использовать Байесовую оптимизацию, чтобы оптимизировать функции, которые недифференцируемы, прерывисты, и длительны, чтобы оценить. Алгоритм внутренне поддерживает Гауссову модель процесса целевой функции и использует оценки целевой функции, чтобы обучить эту модель.
Этот пример показывает как:
Загрузите и подготовьте набор данных CIFAR-10 к сетевому обучению. Этот набор данных является одним из наиболее широко используемых наборов данных для тестирования моделей классификации изображений.
Задайте переменные, чтобы оптимизировать использующую Байесовую оптимизацию. Эти переменные являются опциями учебного алгоритма, а также параметрами самой сетевой архитектуры.
Задайте целевую функцию, которая принимает значения переменных оптимизации как входные параметры, задает сетевую архитектуру и опции обучения, обучает и подтверждает сеть и сохраняет обучивший сеть на диск. Целевая функция задана в конце этого скрипта.
Выполните Байесовую оптимизацию путем минимизации ошибки классификации на наборе валидации.
Загрузите лучшую сеть от диска и оцените его на наборе тестов.
Загрузите набор данных CIFAR-10 [1]. Этот набор данных содержит 60 000 изображений, и каждое изображение имеет размер 32 32 и три цветовых канала (RGB). Размер целого набора данных составляет 175 Мбайт. В зависимости от вашего интернет-соединения может занять время процесс загрузки.
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 оценок целевой функции. Чтобы обучить нейронные сети параллельно на нескольких графических процессорах, установите значение 'UseParallel'
к true
. Если вы имеете один графический процессор и устанавливаете значение 'UseParallel'
к true
, то все рабочие совместно используют тот графический процессор, и вы не получаете учебного ускорения и увеличиваете возможности графического процессора, исчерпывающего память.
После того, как каждая сеть закончила обучение, bayesopt
распечатывает результаты к командному окну. Функция bayesopt
затем возвращает имена файлов в BayesObject.UserDataTrace
. Целевая функция сохраняет обучивший нейронные сети на диск и возвращает имена файлов в bayesopt
.
BayesObject = bayesopt(ObjFcn,optimVars, ... 'MaxTime',14*60*60, ... 'IsObjectiveDeterministic',false, ... 'UseParallel',false);
|===================================================================================================================================| | Iter | Eval | Objective | Objective | BestSoFar | BestSoFar | SectionDepth | InitialLearn-| Momentum | L2Regulariza-| | | result | | runtime | (observed) | (estim.) | | Rate | | tion | |===================================================================================================================================| | 1 | Best | 0.19 | 2201 | 0.19 | 0.19 | 3 | 0.012114 | 0.8354 | 0.0010624 |
| 2 | Accept | 0.3224 | 1734.1 | 0.19 | 0.19636 | 1 | 0.066481 | 0.88231 | 0.0026626 |
| 3 | Accept | 0.2076 | 1688.7 | 0.19 | 0.19374 | 2 | 0.022346 | 0.91149 | 8.242e-10 |
| 4 | Accept | 0.1908 | 2167.2 | 0.19 | 0.1904 | 3 | 0.97586 | 0.83613 | 4.5143e-08 |
| 5 | Accept | 0.1972 | 2157.4 | 0.19 | 0.19274 | 3 | 0.21193 | 0.97995 | 1.4691e-05 |
| 6 | Accept | 0.2594 | 2152.8 | 0.19 | 0.19 | 3 | 0.98723 | 0.97931 | 2.4847e-10 |
| 7 | Best | 0.1882 | 2257.5 | 0.1882 | 0.18819 | 3 | 0.1722 | 0.8019 | 4.2149e-06 |
| 8 | Accept | 0.8116 | 1989.7 | 0.1882 | 0.18818 | 3 | 0.42085 | 0.95355 | 0.0092026 |
| 9 | Accept | 0.1986 | 1836 | 0.1882 | 0.18821 | 2 | 0.030291 | 0.94711 | 2.5062e-05 |
| 10 | Accept | 0.2146 | 1909.4 | 0.1882 | 0.18816 | 2 | 0.013379 | 0.8785 | 7.6354e-09 |
| 11 | Accept | 0.2194 | 1562 | 0.1882 | 0.18815 | 1 | 0.14682 | 0.86272 | 8.6242e-09 |
| 12 | Accept | 0.2246 | 1591.2 | 0.1882 | 0.18813 | 1 | 0.70438 | 0.82809 | 1.0102e-06 |
| 13 | Accept | 0.2648 | 1621.8 | 0.1882 | 0.18824 | 1 | 0.010109 | 0.89989 | 1.0481e-10 |
| 14 | Accept | 0.2222 | 1562 | 0.1882 | 0.18812 | 1 | 0.11058 | 0.97432 | 2.4101e-07 |
| 15 | Accept | 0.2364 | 1625.7 | 0.1882 | 0.18813 | 1 | 0.079381 | 0.8292 | 2.6722e-05 |
| 16 | Accept | 0.26 | 1706.2 | 0.1882 | 0.18815 | 1 | 0.010041 | 0.96229 | 1.1066e-05 |
| 17 | Accept | 0.1986 | 2188.3 | 0.1882 | 0.18635 | 3 | 0.35949 | 0.97824 | 3.153e-07 |
| 18 | Accept | 0.1938 | 2169.6 | 0.1882 | 0.18817 | 3 | 0.024365 | 0.88464 | 0.00024507 |
| 19 | Accept | 0.3588 | 1713.7 | 0.1882 | 0.18216 | 1 | 0.010177 | 0.89427 | 0.0090342 |
| 20 | Accept | 0.2224 | 1721.4 | 0.1882 | 0.18193 | 1 | 0.09804 | 0.97947 | 1.0727e-10 |
|===================================================================================================================================| | Iter | Eval | Objective | Objective | BestSoFar | BestSoFar | SectionDepth | InitialLearn-| Momentum | L2Regulariza-| | | result | | runtime | (observed) | (estim.) | | Rate | | tion | |===================================================================================================================================| | 21 | Accept | 0.1904 | 2184.7 | 0.1882 | 0.18498 | 3 | 0.017697 | 0.95057 | 0.00022247 |
| 22 | Accept | 0.1928 | 2184.4 | 0.1882 | 0.18527 | 3 | 0.06813 | 0.9027 | 1.3521e-09 |
| 23 | Accept | 0.1934 | 2183.6 | 0.1882 | 0.1882 | 3 | 0.018269 | 0.90432 | 0.0003573 |
| 24 | Accept | 0.303 | 1707.9 | 0.1882 | 0.18809 | 1 | 0.010157 | 0.88226 | 0.00088737 |
| 25 | Accept | 0.194 | 2189.1 | 0.1882 | 0.18808 | 3 | 0.019354 | 0.94156 | 9.6197e-07 |
| 26 | Accept | 0.2192 | 1752.2 | 0.1882 | 0.18809 | 1 | 0.99324 | 0.91165 | 1.1521e-08 |
| 27 | Accept | 0.1918 | 2185 | 0.1882 | 0.18813 | 3 | 0.05292 | 0.8689 | 1.2449e-05 |
__________________________________________________________ Optimization completed. MaxTime of 50400 seconds reached. Total function evaluations: 27 Total elapsed time: 51962.3666 seconds. Total objective function evaluation time: 51942.8833 Best observed feasible point: SectionDepth InitialLearnRate Momentum L2Regularization ____________ ________________ ________ ________________ 3 0.1722 0.8019 4.2149e-06 Observed objective function value = 0.1882 Estimated objective function value = 0.18813 Function evaluation time = 2257.4627 Best estimated feasible point (according to models): SectionDepth InitialLearnRate Momentum L2Regularization ____________ ________________ ________ ________________ 3 0.1722 0.8019 4.2149e-06 Estimated objective function value = 0.18813 Estimated function evaluation time = 2166.2402
Загрузите лучшую сеть, найденную в оптимизации и ее точности валидации.
bestIdx = BayesObject.IndexOfMinimumTrace(end); fileName = BayesObject.UserDataTrace{bestIdx}; savedStruct = load(fileName); valError = savedStruct.valError
valError = 0.1882
Предскажите метки набора тестов и вычислите тестовую ошибку. Обработайте классификацию каждого изображения в наборе тестов как независимые события с определенной вероятностью успеха, что означает, что количество неправильно классифицированных изображений следует за биномиальным распределением. Используйте это, чтобы вычислить стандартную погрешность (testErrorSE
) и аппроксимированный 95%-й доверительный интервал (testError95CI
) коэффициента ошибок обобщения. Этот метод часто называется Вальдовым методом. bayesopt
определяет лучшую сеть с помощью набора валидации, не подвергая сеть набору тестов. Затем возможно, что тестовая ошибка выше, чем ошибка валидации.
[YPredicted,probs] = classify(savedStruct.trainedNet,XTest); testError = 1 - mean(YPredicted == YTest)
testError = 0.1864
NTest = numel(YTest); testErrorSE = sqrt(testError*(1-testError)/NTest); testError95CI = [testError - 1.96*testErrorSE, testError + 1.96*testErrorSE]
testError95CI = 1×2
0.1756 0.1972
Постройте матрицу беспорядка для тестовых данных. Отобразите точность и отзыв для каждого класса при помощи сводных данных строки и столбца.
figure('Units','normalized','Position',[0.2 0.2 0.4 0.4]); cm = confusionchart(YTest,YPredicted); cm.Title = 'Confusion Matrix for Test Data'; cm.ColumnSummary = 'column-normalized'; cm.RowSummary = 'row-normalized';
Отобразите некоторые тестовые изображения вместе с их предсказанными классами и вероятностями тех классов.
figure idx = randperm(numel(YTest),9); for i = 1:numel(idx) subplot(3,3,i) imshow(XTest(:,:,:,idx(i))); prob = num2str(100*max(probs(idx(i),:)),3); predClass = char(YPredicted(idx(i))); label = [predClass,', ',prob,'%']; title(label) end
Задайте целевую функцию для оптимизации. Эта функция выполняет следующие шаги:
Принимает значения переменных оптимизации как входные параметры. bayesopt
вызывает целевую функцию с текущими значениями переменных оптимизации в таблице с каждым именем столбца, равным имени переменной. Например, текущим значением сетевой глубины раздела является optVars.SectionDepth
.
Задает сетевую архитектуру и опции обучения.
Train и подтверждает сеть.
Сохраняет обучивший сеть, ошибку валидации и опции обучения к диску.
Возвращает ошибку валидации и имя файла сохраненной сети.
function ObjFcn = makeObjFcn(XTrain,YTrain,XValidation,YValidation) ObjFcn = @valErrorFun; function [valError,cons,fileName] = valErrorFun(optVars)
Задайте сверточную архитектуру нейронной сети.
Добавьте дополнение в сверточные слои так, чтобы пространственный выходной размер всегда был тем же самым как входным размером.
Каждый раз вы субдискретизируете пространственные размерности фактором двух использований, макс. объединяющих слои, увеличиваете число фильтров по фактору два. Выполнение так гарантирует, что объем вычисления, требуемого в каждом сверточном слое, является примерно тем же самым.
Выберите количество фильтров, пропорциональных 1/sqrt(SectionDepth)
, так, чтобы сети различных глубин имели примерно то же количество параметров и потребовали о том же объеме вычисления на итерацию. Чтобы увеличить число сетевых параметров и полной сетевой гибкости, увеличьте numF
. Чтобы обучить еще более глубокие сети, измените область значений переменной SectionDepth
.
Используйте convBlock(filterSize,numFilters,numConvLayers)
, чтобы создать блок numConvLayers
сверточные слои, каждый с заданным filterSize
и фильтрами numFilters
и каждым сопровождаемым пакетным слоем нормализации и слоем ReLU. Функция convBlock
задана в конце этого примера.
imageSize = [32 32 3]; numClasses = numel(unique(YTrain)); numF = round(16/sqrt(optVars.SectionDepth)); layers = [ imageInputLayer(imageSize) % The spatial input and output sizes of these convolutional % layers are 32-by-32, and the following max pooling layer % reduces this to 16-by-16. convBlock(3,numF,optVars.SectionDepth) maxPooling2dLayer(3,'Stride',2,'Padding','same') % The spatial input and output sizes of these convolutional % layers are 16-by-16, and the following max pooling layer % reduces this to 8-by-8. convBlock(3,2*numF,optVars.SectionDepth) maxPooling2dLayer(3,'Stride',2,'Padding','same') % The spatial input and output sizes of these convolutional % layers are 8-by-8. The global average pooling layer averages % over the 8-by-8 inputs, giving an output of size % 1-by-1-by-4*initialNumFilters. With a global average % pooling layer, the final classification output is only % sensitive to the total amount of each feature present in the % input image, but insensitive to the spatial positions of the % features. convBlock(3,4*numF,optVars.SectionDepth) averagePooling2dLayer(8) % Add the fully connected layer and the final softmax and % classification layers. fullyConnectedLayer(numClasses) softmaxLayer classificationLayer];
Задайте опции для сетевого обучения. Оптимизируйте начальный темп обучения, импульс SGD и силу регуляризации L2.
Задайте данные о валидации и выберите, 'ValidationFrequency'
оценивают таким образом, что trainNetwork
подтверждает сеть однажды в эпоху. Обучайтесь для постоянного числа эпох и понизьте темп обучения фактором 10 в течение прошлых эпох. Это уменьшает шум обновлений параметра и позволяет сетевым параметрам успокоиться ближе к минимуму функции потерь.
miniBatchSize = 256; validationFrequency = floor(numel(YTrain)/miniBatchSize); options = trainingOptions('sgdm', ... 'InitialLearnRate',optVars.InitialLearnRate, ... 'Momentum',optVars.Momentum, ... 'MaxEpochs',60, ... 'LearnRateSchedule','piecewise', ... 'LearnRateDropPeriod',40, ... 'LearnRateDropFactor',0.1, ... 'MiniBatchSize',miniBatchSize, ... 'L2Regularization',optVars.L2Regularization, ... 'Shuffle','every-epoch', ... 'Verbose',false, ... 'Plots','training-progress', ... 'ValidationData',{XValidation,YValidation}, ... 'ValidationFrequency',validationFrequency);
Используйте увеличение данных, чтобы случайным образом инвертировать учебные изображения вдоль вертикальной оси, и случайным образом перевести их до четырех пикселей горизонтально и вертикально. Увеличение данных помогает препятствовать тому, чтобы сеть сверхсоответствовала и запомнила точные детали учебных изображений.
pixelRange = [-4 4]; imageAugmenter = imageDataAugmenter( ... 'RandXReflection',true, ... 'RandXTranslation',pixelRange, ... 'RandYTranslation',pixelRange); datasource = augmentedImageDatastore(imageSize,XTrain,YTrain,'DataAugmentation',imageAugmenter);
Обучите сеть и постройте учебный прогресс во время обучения. Закройте все учебные графики после того, как обучение закончится.
trainedNet = trainNetwork(datasource,layers,options); close(findall(groot,'Tag','NNET_CNN_TRAININGPLOT_FIGURE'))
Оцените обучивший сеть на наборе валидации, вычислите предсказанные метки изображения и вычислите коэффициент ошибок данных о валидации.
YPredicted = classify(trainedNet,XValidation); valError = 1 - mean(YPredicted == YValidation);
Создайте имя файла, содержащее ошибку валидации, и сохраните сеть, ошибку валидации и опции обучения к диску. Целевая функция возвращает fileName
как выходной аргумент, и bayesopt
возвращает все имена файлов в BayesObject.UserDataTrace
. Дополнительный необходимый выходной аргумент cons
задает ограничения среди переменных. Нет никаких переменных ограничений.
fileName = num2str(valError) + ".mat"; save(fileName,'trainedNet','valError','options') cons = []; end end
Функция convBlock
создает блок numConvLayers
сверточные слои, каждый с заданным filterSize
и фильтрами numFilters
и каждым сопровождаемым пакетным слоем нормализации и слоем ReLU.
function layers = convBlock(filterSize,numFilters,numConvLayers) layers = [ convolution2dLayer(filterSize,numFilters,'Padding','same') batchNormalizationLayer reluLayer]; layers = repmat(layers,numConvLayers,1); end
[1] Krizhevsky, Алекс. "Изучая несколько слоев функций от крошечных изображений". (2009). https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf
bayesopt
| trainNetwork
| trainingOptions