Можно ускорить пользовательские учебные циклы путем работы графического процессора в параллели с помощью нескольких графических процессоров, или в кластере.
Рекомендуется обучить использование графического процессора или нескольких графических процессоров. Только используйте один центральный процессор или несколько центральных процессоров, если у вас нет графического процессора. Центральные процессоры обычно намного медленнее что графические процессоры и для обучения и для вывода. Работа одного графического процессора обычно предлагает намного лучшую эффективность, чем работа нескольких ядер процессора.
Примечание
Эта тема показывает вам, как выполнить пользовательское обучение на графических процессорах, параллельно, и в облаке. Узнать о параллели и рабочих процессах графического процессора с помощью trainNetwork
функционируйте, см.:
Используя графический процессор или параллельные опции требует Parallel Computing Toolbox™. Используя графический процессор также требует поддерживаемого устройства графического процессора. Для получения информации о поддерживаемых устройствах смотрите Поддержку графического процессора Релизом (Parallel Computing Toolbox). Используя удаленный кластер также требует MATLAB® Parallel Server™.
По умолчанию пользовательские учебные циклы работают на центральном процессоре. Автоматическое использование дифференцирования dlgradient
и dlfeval
поддержки, работающие на графическом процессоре, когда ваши данные находятся на графическом процессоре. Чтобы запустить пользовательский учебный цикл на графическом процессоре, просто преобразуйте свои данные в gpuArray
(Parallel Computing Toolbox) во время обучения.
Можно использовать minibatchqueue
управлять вашими данными во время обучения. minibatchqueue
автоматически готовит данные к обучению, включая пользовательскую предварительную обработку и преобразование данных к dlarray
и gpuArray
. По умолчанию, minibatchqueue
возвращает все мини-пакетные переменные на графическом процессоре, если вы доступны. Можно выбрать который переменные возвратиться на графическом процессоре с помощью OutputEnvironment
свойство.
Для примера, показывающего, как использовать minibatchqueue
чтобы обучаться на графическом процессоре, смотрите, Обучат сеть Используя Пользовательский Учебный Цикл.
В качестве альтернативы можно вручную преобразовать данные в gpuArray
в учебном цикле.
Чтобы легко задать среду выполнения, создайте переменную executionEnvironment
это содержит любой "cpu"
, "gpu"
, или "auto"
.
executionEnvironment = "auto"
Во время обучения, после чтения мини-пакета, проверяют опцию среды выполнения и преобразуют данные в gpuArray
при необходимости. canUseGPU
функционируйте проверки на применимые графические процессоры.
if (executionEnvironment == "auto" && canUseGPU) || executionEnvironment == "gpu" dlX = gpuArray(dlX); end
Когда вы обучаетесь параллельно, каждый рабочий обучает сеть одновременно с помощью фрагмента мини-пакета. Это означает, что необходимо объединить градиенты, потерю и любые параметры состояния после каждой итерации, согласно пропорции мини-пакета, обработанного каждым рабочим.
Можно обучаться параллельно на локальной машине, или в удаленном кластере, например, в облаке. Запустите параллельный пул в желаемых ресурсах и разделите свои данные между рабочими. Во время обучения, комбинируют градиенты, потеря и состояние после каждой итерации так, чтобы настраиваемые параметры на каждом рабочем обновились в синхронизации. Для примера, показывающего, как выполнить пользовательское обучение параллельно, смотрите, Обучат сеть параллельно с Пользовательским Учебным Циклом
Рекомендуется обучить использование графического процессора или нескольких графических процессоров. Только используйте один центральный процессор или несколько центральных процессоров, если у вас нет графического процессора. Центральные процессоры обычно намного медленнее что графические процессоры и для обучения и для вывода. Работа одного графического процессора обычно предлагает намного лучшую эффективность, чем работа нескольких ядер процессора.
Настройте параллельную среду, которую вы хотите использовать перед обучением. Запустите параллельный пул с помощью желаемых ресурсов. Для обучения с помощью нескольких графических процессоров начните параллельный пул со стольких же рабочих сколько доступные графические процессоры. Для лучшей эффективности MATLAB автоматически присваивает различный графический процессор каждому рабочему.
Если вы используете свою локальную машину, можно использовать canUseGPU
и gpuDeviceCount
(Parallel Computing Toolbox), чтобы определить, имеете ли вы графические процессоры в наличии. Например, чтобы проверять доступность графических процессоров и начать параллельный пул со стольких же рабочих сколько доступные графические процессоры, используйте следующий код:
if canUseGPU executionEnvironment = "gpu"; numberOfGPUs = gpuDeviceCount("available"); pool = parpool(numberOfGPUs); else executionEnvironment = "cpu"; pool = parpool; end
Если при запуске использование удаленного кластера, например, кластера в облаке, начните параллельный пул со стольких же рабочих сколько количество графических процессоров на машину, умноженную на количество машин.
Для получения дополнительной информации о выборе определенных графических процессоров смотрите, Выбирают Particular GPUs to Use for Training.
Задайте мини-пакетный размер, который вы хотите использовать во время обучения. Для обучения графического процессора методические рекомендации должны увеличить мини-пакетный размер линейно с количеством графических процессоров, для того, чтобы сохранить рабочую нагрузку на каждом графическом процессоре постоянной. Например, если вы - обучение на одном графическом процессоре с помощью мини-пакетного размера 64, и вы хотите масштабировать до обучения с помощью четырех графических процессоров того же типа, можно увеличить мини-пакетный размер до 256 так, чтобы каждый графический процессор процессы 64 наблюдения на итерацию.
Можно использовать следующий код, чтобы увеличить мини-пакетный размер количеством рабочих, где N
количество рабочих в вашем параллельном пуле.
if executionEnvironment == "gpu" miniBatchSize = miniBatchSize .* N end
Если вы хотите использовать мини-пакетный размер что не точно делимый количеством рабочих в вашем параллельном пуле, то распределите остаток на рабочих.
workerMiniBatchSize = floor(miniBatchSize ./ repmat(N,1,N)); remainder = miniBatchSize - sum(workerMiniBatchSize); workerMiniBatchSize = workerMiniBatchSize + [ones(1,remainder) zeros(1,N-remainder)]
В начале обучения переставьте свои данные. Разделите свои данные так, чтобы у каждого рабочего был доступ к фрагменту мини-пакета. Чтобы разделить datastore, используйте partition
функция.
Можно использовать minibatchqueue
управлять данными по каждому рабочему во время обучения. minibatchqueue
автоматически готовит данные к обучению, включая пользовательскую предварительную обработку и преобразование данных к dlarray
и gpuArray
. Создайте minibatchqueue на каждом рабочем, использующем разделенный datastore. Установите MiniBatchSize
свойство с помощью мини-пакетных размеров, вычисленных для каждого рабочего.
В начале каждой учебной итерации используйте gop
(Parallel Computing Toolbox) функция, чтобы проверять, что весь рабочий minibatchqueue
объекты могут возвратить данные. Если у какого-либо рабочего заканчиваются данные, учебные остановки. Если ваш полный мини-пакетный размер не является точно делимым количеством рабочих, и вы не отбрасываете частичные мини-пакеты, у некоторых рабочих могут закончиться данные перед другими.
Запишите свой учебный код в spmd
Блок (Parallel Computing Toolbox), так, чтобы учебный цикл выполнился на каждом рабочем.
spmd % Reset and shuffle the datastore. reset(augimdsTrain); augimdsTrain = shuffle(augimdsTrain); % Partition datastore. workerImds = partition(augimdsTrain,N,labindex); % Create minibatchqueue using partitioned datastore on each worker workerMbq = minibatchqueue(workerImds,... "MiniBatchSize",workerMiniBatchSize(labindex),... "MiniBatchFcn",@preprocessMiniBatch); ... for epoch = 1:numEpochs % Reset and shuffle minibatchqueue on each worker. shuffle(workerMbq); % Loop over mini-batches. while gop(@and,hasdata(workerMbq)) % Custom training loop ... end ... end end
Чтобы гарантировать, что сеть на каждом рабочем извлекает уроки из всех данных и не только данных по тому рабочему, агрегируйте градиенты и используйте агрегированные градиенты, чтобы обновить сеть на каждом рабочем.
Например, предположите, что вы - обучение сеть dlnet
, использование градиентов модели функционирует modelGradients
. Ваш учебный цикл содержит следующий код для оценки градиента, потери и статистики по каждому рабочему:
[workerGradients,dlworkerLoss,workerState] = dlfeval(@modelGradients,dlnet,dlworkerX,workerY);
dlworkerX
и workerY
предиктор и истинный ответ на каждом рабочем, соответственно.Чтобы агрегировать градиенты, используйте взвешенную сумму. Задайте функцию помощника, чтобы суммировать градиенты.
function gradients = aggregateGradients(dlgradients,factor) gradients = extractdata(dlgradients); gradients = gplus(factor*gradients); end
В учебном цикле использовать dlupdate
применять функцию к градиентам каждого настраиваемого параметра.
workerGradients.Value = dlupdate(@aggregateGradients,workerGradients.Value,{workerNormalizationFactor});
Чтобы найти сетевую потерю и точность, например, построить их во время обучения контролировать процесс обучения, агрегировали значения потери и точности на всех рабочих. Как правило, агрегированное значение является суммой значения на каждом рабочем, взвешенном пропорцией мини-пакета, используемого на каждом рабочем. Чтобы агрегировать потери и точность каждая итерация, вычислите весовой коэффициент для каждого рабочего и использования gplus
(Parallel Computing Toolbox), чтобы суммировать значения на каждом рабочем.
workerNormalizationFactor = workerMiniBatchSize(labindex)./miniBatchSize; loss = gplus(workerNormalizationFactor*extractdata(dlworkerLoss)); accuracy = gplus(workerNormalizationFactor*extractdata(dlworkerAccuracy));
Если ваша сеть содержит слои, которые отслеживают статистику ваших обучающих данных, таких как слои нормализации партии., то необходимо агрегировать статистику через всех рабочих после каждой учебной итерации. Выполнение так гарантирует, что сеть изучает статистические данные, которые являются представительными для целого набора обучающих данных.
Можно идентифицировать слои, которые содержат информацию о статистике перед обучением. Например, если вы используете dlnetwork
со слоями нормализации партии. можно использовать следующий код, чтобы найти соответствующие слои.
batchNormLayers = arrayfun(@(l)isa(l,'nnet.cnn.layer.BatchNormalizationLayer'),dlnet.Layers); batchNormLayersNames = string({dlnet.Layers(batchNormLayers).Name}); state = dlnet.State; isBatchNormalizationStateMean = ismember(state.Layer,batchNormLayersNames) & state.Parameter == "TrainedMean"; isBatchNormalizationStateVariance = ismember(state.Layer,batchNormLayersNames) & state.Parameter == "TrainedVariance";
N является общим количеством рабочих, M является общим количеством наблюдений в мини-пакете, mj является количеством наблюдений, обработанных на j th рабочий, и среднее значение и статистика отклонения, вычисленная на того рабочего, и агрегированное среднее значение через всех рабочих.
function state = aggregateState(state,factor,... isBatchNormalizationStateMean,isBatchNormalizationStateVariance) stateMeans = state.Value(isBatchNormalizationStateMean); stateVariances = state.Value(isBatchNormalizationStateVariance); for j = 1:numel(stateMeans) meanVal = stateMeans{j}; varVal = stateVariances{j}; % Calculate combined mean combinedMean = gplus(factor*meanVal); % Calculate combined variance terms to sum varTerm = factor.*(varVal + (meanVal - combinedMean).^2); % Update state stateMeans{j} = combinedMean; stateVariances{j} = gplus(varTerm); end state.Value(isBatchNormalizationStateMean) = stateMeans; state.Value(isBatchNormalizationStateVariance) = stateVariances; end
В учебном цикле используйте функцию помощника, чтобы обновить состояние слоев нормализации партии. с объединенным средним значением и отклонением.
dlnet.State = aggregateState(workerState,workerNormalizationFactor,...
isBatchNormalizationStateMean,isBatchNormalizationStateVariance);
Если вы хотите построить результаты во время обучения, можно отправить данные от рабочих клиенту, использующему DataQueue
объект.
Чтобы легко указать, что график должен идти или прочь, создайте переменную plots
это содержит любой "training-progress"
или "none"
.
plots = "training-progress";
Перед обучением инициализируйте DataQueue
и анимированная линия с помощью animatedline
функция.
if plots == "training-progress" figure lineLossTrain = animatedline('Color',[0.85 0.325 0.098]); ylim([0 inf]) xlabel("Iteration") ylabel("Loss") grid on end
DataQueue
объект. Использование afterEach
вызывать функцию помощника displayTrainingProgress
каждый раз данные отправляются от рабочего клиенту. Q = parallel.pool.DataQueue; displayFcn = @(x) displayTrainingProgress(x,lineLossTrain); afterEach(Q,displayFcn);
displayTrainingProgress
функция помощника содержит код, используемый, чтобы добавить точки в анимированную линию и отобразить учебную эпоху и длительность.function displayTrainingProgress (data,line) addpoints(line,double(data(3)),double(data(2))) D = duration(0,0,data(4),'Format','hh:mm:ss'); title("Epoch: " + data(1) + ", Elapsed: " + string(D)) drawnow end
В учебном цикле, в конце каждой эпохи, используют DataQueue
отправить обучающие данные от рабочих клиенту. В конце каждой итерации агрегированная потеря является тем же самым на каждом рабочем, таким образом, можно отправить данные от одного рабочего.
% Display training progress information. if labindex == 1 data = [epoch loss iteration toc(start)]; send(Q,gather(data)); end
Чтобы обучить несколько сетей параллельно, запустите параллельный пул в своих желаемых ресурсах и использовании parfor
(Parallel Computing Toolbox), чтобы обучить одну сеть на каждом рабочем.
Можно запуститься локально или использование удаленного кластера. Используя удаленный кластер требует MATLAB Parallel Server. Для получения дополнительной информации о ресурсах кластера управления, смотрите, Обнаруживают Кластеры и Профили Кластера Использования (Parallel Computing Toolbox). Если вы имеете несколько графических процессоров и хотите исключить некоторых из обучения, можно выбрать GPU, который вы используете, чтобы обучаться на. Для получения дополнительной информации о выборе определенных графических процессоров смотрите, Выбирают Particular GPUs to Use for Training.
Можно изменить сеть или параметры обучения на каждом рабочем, чтобы выполнить развертки параметра параллельно. Например, в networks
массив dlnetwork
объекты, можно использовать код следующей формы, чтобы обучить несколько различных сетей с помощью тех же данных.
parpool ("local",numNetworks); parfor idx = 1:numNetworks iteration = 0; velocity = []; % Allocate one network per worker dlnet = networks(idx) % Loop over epochs. for epoch = 1:numEpochs % Shuffle data. shuffle(mbq); % Loop over mini-batches. while hasdata(mbq) iteration = iteration + 1; % Custom training loop ... end end % Send the trained networks back to the client. trainedNetworks{idx} = dlnet; end
parfor
концы, trainedNetworks
содержит получившиеся сети, обученные рабочими.Чтобы контролировать процесс обучения на рабочих, можно использовать DataQueue
передать данные обратно от рабочих.
Чтобы легко указать, что график должен идти или прочь, создайте переменную plots
это содержит любой "training-progress"
или "none"
.
plots = "training-progress";
Перед обучением инициализируйте DataQueue
и анимированные линии с помощью animatedline
функция. Создайте подграфик для каждой сети, вы - обучение.
if plots == "training-progress" f = figure; f.Visible = true; for i=1:numNetworks subplot(numNetworks,1,i) xlabel('Iteration'); ylabel('loss'); lines(i) = animatedline; end end
DataQueue
объект. Использование afterEach
вызывать функцию помощника displayTrainingProgress
каждый раз данные отправляются от рабочего клиенту. Q = parallel.pool.DataQueue; displayFcn = @(x) displayTrainingProgress(x,lines); afterEach(Q,displayFcn);
displayTrainingProgress
функция помощника содержит код, используемый, чтобы добавить точки в анимированные линии.function displayTrainingProgress (data,lines) addpoints(lines(1),double(data(4)),double(data(3))) D = duration(0,0,data(5),'Format','hh:mm:ss'); title("Epoch: " + data(2) + ", Elapsed: " + string(D)) drawnow limitrate nocallbacks end
В учебном цикле, в конце каждой итерации, используют DataQueue
отправить обучающие данные от рабочих клиенту. Отправьте parfor
индекс цикла, а также учебная информация так, чтобы точки были добавлены к правильной линии для каждого рабочего.
% Display training progress information.
data = [idx epoch loss iteration toc(start)];
send(Q,gather(data));
Можно использовать Experiment Manager, чтобы запустить пользовательские учебные циклы параллельно. Можно или запустить несколько следов одновременно или запустить одно испытание во время с помощью параллельных ресурсов.
Чтобы запустить несколько испытаний одновременно с помощью одного параллельного рабочего для каждого испытания, настройте пользовательский учебный эксперимент разрешение опции Use Parallel прежде, чем запустить эксперимент.
Чтобы запустить одно испытание во время с помощью нескольких параллельных рабочих, задайте параллельную среду в обучении эксперименту, функционируют и используют spmd
блокируйтесь, чтобы обучить сеть параллельно. Для получения дополнительной информации об обучении одной сети параллельно с пользовательским учебным циклом смотрите, Обучают Одну Сеть параллельно.
Для получения дополнительной информации об обучении в параллели с помощью Experiment Manager смотрите Использование Experiment Manager, чтобы Обучаться параллельно.
parfor
(Parallel Computing Toolbox) | parfeval
(Parallel Computing Toolbox) | gpuArray
(Parallel Computing Toolbox) | dlarray
| dlnetwork