主要内容

使用自定义训练循环的基于模型的强化学习

这个例子展示了如何为基于模型的强化学习(MBRL)算法定义一个自定义训练循环。您可以使用此工作流,使用强化学习工具箱™软件中的策略和值函数表示,使用自定义训练算法来训练MBRL策略。

在本例中,您使用转换模型在车杆环境中训练自定义DQN[2]代理时生成更多经验。本例中使用的算法基于基于模型的策略优化算法(MBPO)[1]。原始的MBPO算法训练随机模型的集合和软演员-评论家(SAC)代理在具有连续动作的任务中。相比之下,本例在具有离散动作的任务中训练确定性模型和DQN代理的集成。下图总结了本例中使用的算法。

代理通过与环境交互产生真实的体验。这些经验用于训练一组转换模型,转换模型用于生成额外的经验。然后,训练算法使用真实经验和生成的经验来更新代理策略。

创建环境

对于本例,强化学习策略是在离散的车杆环境中训练的。在这种环境下,目标是通过在推车上施加力(动作)来平衡杆子。属性创建环境rlPredefinedEnv函数。固定随机生成器种子的再现性。有关此环境的详细信息,请参见负载预定义控制系统环境

clear clc rngSeed = 1;rng (rngSeed);环境= rlPredefinedEnv(“CartPole-Discrete”);

从环境中提取观察和操作规范。

obsInfo = getObservationInfo(env);actInfo = getActionInfo(env);

获得观测数(numObservations)和行动(numActions).

numObservations = obsInfo.Dimension(1);numActions = nummel (actInfo.Elements);%离散动作的数量,-10或10numContinuousActions = 1;%的力量

评论家建设

DQN是一种基于价值的强化学习算法,它使用评论来估计贴现累积奖励。在本例中,评论家网络包含fullyConnectedLayer,reluLayer层。

qNetwork = [featureInputLayer(obsInfo.Dimension(1)),“归一化”“没有”“名字”“状态”) fullyConnectedLayer(24日“名字”“CriticStateFC1”) reluLayer (“名字”“CriticRelu1”) fullyConnectedLayer(24日“名字”“CriticStateFC2”) reluLayer (“名字”“CriticCommonRelu”) fullyConnectedLayer(长度(actInfo.Elements),“名字”“输出”));qNetwork = dlnetwork(qNetwork);

使用指定的神经网络和选项创建评论家表示。有关更多信息,请参见rlQValueRepresentation

criticOpts = rlRepresentationOptions(“LearnRate”, 0.001,“GradientThreshold”1);rlQValueRepresentation(qNetwork,obsInfo,actInfo,“观察”, {“状态”}, criticOpts);

创建转换模型

基于模型的强化学习使用环境的过渡模型。该模型通常由一个过渡函数、一个奖励函数和一个终端状态函数组成。

  • 过渡函数根据当前的观察和动作预测下一个观察。

  • 奖励函数预测给定当前观察、行动和下一次观察的奖励。

  • 终端状态函数在给定观测值的情况下预测终端状态。

如下图所示,本例使用三个转换函数作为转换模型的集合,在不与环境交互的情况下生成样本。在这个例子中给出了真实的奖励函数和真实的终端状态函数。

为转换模型定义三个神经网络。神经网络预测下一个观测值和当前观测值之间的差异

numModels = 3;transitionNetwork1 = createTransitionNetwork(numObservations, numContinuousActions);transitionNetwork2 = createTransitionNetwork(numObservations, numContinuousActions);transitionNetwork3 = createTransitionNetwork(numObservations, numContinuousActions);transitionNetworkVector = [transitionNetwork1, transitionNetwork2, transitionNetwork3];

创建经验缓冲区

创建一个经验缓冲区来存储代理经验(观察、行动、下一次观察、奖励和isDone)。

myBuffer。bufferSize = 1e5;myBuffer。bufferIndex = 0;myBuffer。currentBufferLength = 0;myBuffer。观察=零(numObservations,myBuffer.bufferSize);myBuffer。nexobservation = 0 (numObservations,myBuffer.bufferSize); myBuffer.action = zeros(numContinuousActions,1,myBuffer.bufferSize); myBuffer.reward = zeros(1,myBuffer.bufferSize); myBuffer.isDone = zeros(1,myBuffer.bufferSize);

创建一个模型经验缓冲区,用于存储由模型生成的经验。

myModelBuffer。bufferSize = 1e5;myModelBuffer。bufferIndex = 0;myModelBuffer。currentBufferLength = 0;myModelBuffer。观察=零(numObservations,myModelBuffer.bufferSize);myModelBuffer。nexobservation = 0 (numObservations,myModelBuffer.bufferSize); myModelBuffer.action = zeros(numContinuousActions,myModelBuffer.bufferSize); myModelBuffer.reward = zeros(1,myModelBuffer.bufferSize); myModelBuffer.isDone = zeros(1,myModelBuffer.bufferSize);

配置培训

将培训配置为使用以下选项。

  • 最大训练次数- 250次

  • 每次训练最大步数- 500步

  • 折扣因子- 0.99

  • 训练终止条件- 10集的平均奖励达到480

numEpisodes = 250;maxStepsPerEpisode = 500;折扣因子= 0.99;aveWindowSize = 10;trainingTerminationValue = 480;

配置模型选项。

  • 只有在收集了2000个样本后才能建立列车转换模型。

  • 每集使用真实经验缓冲区中的所有经验训练模型。使用256的迷你批处理大小。

  • 该模型在每一集开始时生成长度为4的轨迹。

  • 生成的轨迹数是numGenerateSampleIterationxnumModelsxminiBatchSize= 20 × 3 × 256 = 15360。

  • 使用与DQN代理相同的贪心参数,除了最小的贪心值。

  • 使用最小的epsilon值0.1,这比用于与环境交互的值要高。这样做可以让模型生成更多样化的数据。

warmStartSamples = 2000;numEpochs = 1;miniBatchSize = 256;horizonLength = 4;epsilonMinModel = 0.1;numGenerateSampleIteration = 20;sampleGenerationOptions。horizonLength = horizonLength;sampleGenerationOptions。numGenerateSampleIteration = numGenerateSampleIteration; sampleGenerationOptions.miniBatchSize = miniBatchSize; sampleGenerationOptions.numObservations = numObservations; sampleGenerationOptions.epsilonMinModel = epsilonMinModel;%优化器选项Velocity1 = [];Velocity2 = [];Velocity3 = [];衰减= 0.01;动量= 0.9;learnRate = 0.0005;

配置DQN培训选项。

  • 使用ε贪心算法,初始值为1,最小值为0.01,衰减率为0.005。

  • 每4步更新一次目标网络。

  • 设置真实经验与生成经验之比为0.2:0.8RealRatio到0.2。设置RealRatio到1.0与无模型DQN相同。

  • 在每个环境步骤中执行5个渐变步骤。

= 1;epsilonMin = 0.01;epsilonDecay = 0.005;targetupdatfrequency = 4;realRatio = 0.2;%设置为1以运行标准DQNnumGradientSteps = 5;

创建一个向量,用于存储每个训练集的累积奖励。

episodecumulativeredvector = [];

创建用于模型训练可视化的图形hBuildFigureModelhelper函数。

[trainingPlotModel, linelosstraain1, linelosstraain2, linelosstraain3, axModel] = hBuildFigureModel();

方法创建用于模型验证可视化的图形hBuildFigureModelTesthelper函数。

[testPlotModel, lineLossTest1, axModelTest] = hbuildfigu重塑测试();

为DQN代理训练可视化创建一个图形hBuildFigurehelper函数。

[trainingPlot,lineReward,lineAveReward, ax] = hBuildFigure;

火车代理

使用自定义训练循环训练代理。训练循环使用以下算法。每集:

  1. 训练转换模型。

  2. 使用转换模型生成经验,并将样本存储在模型经验缓冲区中。

  3. 创造真实的体验。为此,使用策略生成一个操作,将该操作应用到环境中,并获得结果观察、奖励和已完成值。

  4. 通过从经验缓冲区和模型经验缓冲区中采样经验来创建一个迷你批处理。

  5. 计算目标Q值。

  6. 计算损失函数相对于临界表示参数的梯度。

  7. 使用计算梯度更新评论家表示。

  8. 更新培训可视化。

  9. 如果评论家已经接受了充分的培训,就终止培训。

targetCritic =批评家;modelTrainedAtleastOnce = false;totalStepCt = 0;开始= tic;集(trainingPlotModel,“可见”“上”);集(testPlotModel,“可见”“上”);集(trainingPlot,“可见”“上”);episodeCt = 1:numEpisodes如果myBuffer。currentBufferLength > miniBatchSize &&...totalStepCt > warmStartSamples如果realRatio < 1.0%----------------------------------------------% 1。列车转换模型。%----------------------------------------------训练三个转换模型[transitionNetworkVector(1)、loss1 velocity1] =...trainTransitionModel (transitionNetworkVector (1),...myBuffer、velocity1 miniBatchSize,...numEpochs,动量,learnRate);[transitionNetworkVector(2)、loss2 velocity2] =...trainTransitionModel (transitionNetworkVector (2),...myBuffer、velocity2 miniBatchSize,...numEpochs,动量,learnRate);[transitionNetworkVector(3)、loss3 velocity3] =...trainTransitionModel (transitionNetworkVector (3),...myBuffer、velocity3 miniBatchSize,...numEpochs,动量,learnRate);modelTrainedAtleastOnce = true;%显示培训进度D = duration(0,0,toc(start),“格式”“hh: mm: ss”);addpoints(lineLossTrain2,episodeCt,loss2) addpoints(lineLossTrain3,episodeCt,loss3)“Model1”“Model2”“Model3”);标题(axModel,“模型训练进度-插曲:”...+ episect +,消失:"+字符串(d)%----------------------------------------------% 2。使用模型生成经验。%----------------------------------------------创建numGenerateSampleIteration x horizonLength x numModels x miniBatchSize% ex) 20 × 4 × 3 × 256 = 61440个样品myModelBuffer = generatessamples (myBuffer,myModelBuffer,...actInfo transitionNetworkVector、评论家,...ε,sampleGenerationOptions);结束结束%----------------------------------------------与环境和训练人员互动。%----------------------------------------------重置剧情开始时的环境。观察= reset(env);(maxStepsPerEpisode,1);errorprediction = 0 (maxStepsPerEpisode,1);step pct = 1:maxStepsPerEpisode%----------------------------------------------% 3。创造一种体验。%----------------------------------------------totalStepCt = totalStepCt + 1;根据当前的观察,计算使用策略的操作。如果rand() < epsilon action = actInfo.usample;动作=动作{1};其他的action = getAction(批评家,{观察});结束% Udpate如果totalStepCt > warmStartSamples epsilon = max(epsilon*(1-epsilonDecay),epsilonMin);结束将动作应用到环境中,并获得结果观察和奖励。[nexobservation,reward,isDone] = step(env,action);检查预测dx = predict(transtionnetworkvector (1),...dlarray(观察,“CB”), dlarray(行动,“CB”));predictednexobservation =观察+ dx;errorPreddiction (stepCt) =...√(sum((nexobservation - predictednexobservation).^2));储存行动、观察、奖励和已经完成的体验myBuffer = storeExperience(myBuffer,观察,动作,...nextObservation、奖励、结束);episodeReward(stepCt) =奖励;观察=下一个观察;培训DQN代理商gradientCt = 1:numGradientSteps如果myBuffer。currentBufferLength >= miniBatchSize &&...totalStepCt > warmStartSamples%-----------------------------------------------------% 4。来自经验缓冲区的小批量样本。%-----------------------------------------------------[sampledObservation, sampledAction sampledNextObservation、sampledReward sampledIsdone] =...sampleMinibatch (modelTrainedAtleastOnce、realRatio miniBatchSize、myBuffer myModelBuffer);%-----------------------------------------------------% 5。计算目标Q值。%-----------------------------------------------------计算目标Q值[targetQValues, MaxActionIndices] = getMaxQValue(target批评家,...{重塑(sampledNextObservation [numObservations 1 miniBatchSize])});计算非终结状态的目标targetQValues(~logical(sampledIsdone)) = sampledReward(~logical(sampledIsdone)) +...discountFactor。* targetQValues逻辑(sampledIsdone) (~);计算终端状态的目标targetQValues(logical(sampledIsdone)) = sampledReward(logical(sampledIsdone));lossData。batchSize = miniBatchSize;lossData。actInfo = actInfo;lossData。actionBatch = sampledAction;lossData。targetQValues = targetQValues;%-----------------------------------------------------% 6。计算梯度。%-----------------------------------------------------criticGradient = gradient(批评家,@criticLossFunction,...{重塑(sampledObservation [numObservations 1 miniBatchSize])}, lossData);%----------------------------------------------------% 7。使用梯度更新评论家网络。%----------------------------------------------------批评家=优化(批评家,批评家梯度);结束结束定期更新目标批评家如果mod(totalStepCt, targetUpdateFrequency)==0 targetCritic =批评家;结束到达终端条件时停止。如果结束打破结束结束%章节结束%----------------------------------------------------------------% 8。更新培训可视化。%----------------------------------------------------------------episodeCumulativeReward = sum(episodeReward);episodecumulativeredvector = cat(2,...episodeCumulativeRewardVector episodeCumulativeReward);movingAveReward = movmean(episodecumulativerwardvector,...aveWindowSize, 2);addpoints (lineReward episodeCt episodeCumulativeReward);addpoints (lineAveReward、episodeCt movingAveReward(结束));标题(ax,“训练进度-插曲:”+ episect +...,总步骤:"+ string(totalStepCt...”,ε:“+字符串(epsilon)) drawnow;errorforecast = errorforecast (1:stepCt);显示一个步骤预测错误。addpoints (lineLossTest1 episodeCt,意味着(errorPreddiction))传说(axModelTest,“Model1”);标题(axModelTest,...模型一步预测误差-插曲+ episect +...,错误:+ string(mean(errorprediction)))现在绘制每10集显示一次训练进度如果(mod(插曲,10)== 0)fprintf(“EP: % d,奖励:%。4 f, AveReward: %。4f,步骤:%d, TotalSteps:%d, epsilon:%f,错误模型:%f\n"...episodeCt、episodeCumulativeReward movingAveReward(结束),...stepCt totalStepCt,ε,意味着(errorPreddiction))结束%-----------------------------------------------------------------------------% 9。如果网络得到了充分的训练,则终止训练。%-----------------------------------------------------------------------------如果max(movingAveReward) > trainingTerminationValue打破结束结束
AveReward EP: 10、奖励:12.0000:13.3333,步骤:18日TotalSteps: 261年,ε:1.000000,误差模型:3.786379 EP: 20,奖赏:11.0000,AveReward: 20.1667,步骤:17日TotalSteps: 493年,ε:1.000000,误差模型:3.768267 EP: 30岁的奖赏:34.0000,AveReward: 19.3333,步骤:40岁TotalSteps: 769年,ε:1.000000,误差模型:3.763075 EP: 40岁的奖赏:20.0000,AveReward: 13.8333,步骤:26日TotalSteps: 960年,ε:1.000000,误差模型:3.797021 EP: 50岁的奖赏:13.0000,AveReward: 22.5000,步骤:19日TotalSteps: 1192年,ε:1.000000,误差模型:3.813097 EP: 60岁的奖赏:32.0000,AveReward: 14.8333,步骤:38岁TotalSteps: 1399年,ε:1.000000,误差模型:3.821042 EP: 70年,奖赏:12.0000,AveReward: 17.6667,步骤:18日TotalSteps: 1630年,ε:1.000000,误差模型:3.741603 EP: 80年,奖赏:17.0000,AveReward: 16.5000,步骤:23日TotalSteps: 1873年,ε:1.000000,误差模型:3.780144 EP: 90年,奖赏:13.0000,AveReward: 11.8333,步骤:19日TotalSteps: 2113年,ε:0.567555,误差模型:0.222689 EP: 100年,奖赏:198.0000,AveReward:223.5000,步骤:204,TotalSteps:3631, epsilon:0.010000,错误模型:0.283726 EP:110,奖励:381.0000,AveReward:262.5000,步骤:387,TotalSteps:6600, epsilon:0.010000,错误模型:0.117766 EP:120,奖励:79.0000,AveReward:229.5000,步骤:85,TotalSteps:8887, epsilon:0.010000,错误模型:0.081134 EP:130,奖励:234.0000,AveReward:300.5000,步骤:240,TotalSteps:11798, epsilon:0.010000,错误模型:0.063376 EP:140,奖励:500.0000,AveReward:403.5000,步骤:500,TotalSteps:15562,epsilon:0.010000,错误模型:0.036053 EP:150,奖励:500.0000,AveReward:443.6667,步骤:500,TotalSteps:19598, epsilon:0.010000,错误模型:0.032433 EP:160,奖励:349.0000,AveReward:264.0000,步骤:355,TotalSteps:21980, epsilon:0.010000,错误模型:0.037416 EP:170,奖励:231.0000,AveReward:231.8333,步骤:237,TotalSteps:24324, epsilon:0.010000,错误模型:0.029361 EP:180,奖励:311.0000,AveReward:416.6667,步骤:317,TotalSteps:28417, epsilon:0.010000,错误模型:0.026569 EP:190,奖励:500.0000,AveReward:468.6667,步骤:500,TotalSteps:33092, epsilon:0.010000,错误模型:0.014980

模拟剂

要模拟经过训练的代理,首先要重置环境。

Obs0 = reset(env);Obs = obs0;

启用环境可视化,在每次调用环境步骤函数时更新该环境可视化。

情节(env)

对于每个模拟步骤,执行以下操作。

  1. 方法从策略中采样,以获取动作getAction函数。

  2. 使用获得的动作值对环境进行步骤。

  3. 如果达到终端条件,则终止。

actionVector = 0 (1,maxStepsPerEpisode);obsVector = 0 (numObservations,maxStepsPerEpisode+1);obsVector(:,1) = obs0;step pct = 1:maxStepsPerEpisode根据训练的策略选择行动。action = getAction(批评家,{obs});踏入环境。[nextObs,reward,isDone] =步骤(env,动作);obsVector(:,stepCt+1) = nextObs;actionVector(1,stepCt) =动作;检查终端状况。如果结束打破结束obs = nextObs;结束

lastStepCt = stepCt;

测试模型

通过给出当前的观察和行动,预测下一个观察来测试其中一个模型。

modelID = 3;predictedObsVector = 0 (numObservations,lastStepCt);obs = darray (obsVector(:,1),“CB”);predictedObsVector(:,1) = obs;obs = dlarray(obsVector(:,stepCt),“CB”);action = dlarray(actionVector(1,stepCt),“CB”);dx = predict(transitionNetworkVector(modelID),obs, action);predictedObs = obs + dx;predictedObsVector(:,stepCt+1) = predictedObs;结束predictedObsVector = predictedObsVector(:, 1:lastStepCt);图(5)layOut = tiledlayout(4,1,“TileSpacing”“紧凑”);I = 1:4 nexttile;errorPrediction = abs(predictedObsVector(i,1:lastStepCt) - obsVector(i,1:lastStepCt));line1 = plot(errorPrediction,“DisplayName的”的绝对误差);标题(“观察”+ num2str(我));结束标题(布局、“预测绝对误差”

较小的绝对预测误差表明,该模型已成功训练以预测下一次观测。

参考文献

Volodymyr Minh, Koray Kavukcuoglu, David Silver, Alex Graves, Ioannis Antonoglou, Daan Wierstra和Martin Riedmiller。“用深度强化学习玩雅达利。”ArXiv: 1312.5602 (Cs).2013年12月19日。https://arxiv.org/abs/1312.5602

詹纳,迈克尔,贾斯汀·傅,马文·张和谢尔盖·莱文。“何时信任你的模型:基于模型的策略优化。”ArXiv:1907.08253 [Cs, Stat]2019年11月5日。https://arxiv.org/abs/1906.08253

相关的话题