这个例子展示了如何使用强化学习(RL)来学习配水系统的最优泵调度策略。
下图显示了一个配水系统。
在这里:
是从蓄水池供应至水箱的水量。
为满足使用需要而从水箱中流出的水量。
强化学习agent的目标是调度水泵运行数量,使系统能量消耗最小化,同时满足使用需求( ).储罐系统的动力学由下列方程控制。
在这里 和 .24小时内的需求是时间的函数
哪里 是预期的需求和 表示需求不确定性,需求不确定性从均匀随机分布中抽样。
供给量由运行泵的数量决定, 根据下面的映射。
为了简化问题,功率消耗被定义为运行的泵的数量, .
下面的函数是对这种环境的奖励。为了避免溢出或清空水箱,如果水的高度接近最大或最小水位,将增加额外的成本, 或 ,分别。
要根据所考虑的天数来生成和生成水需求剖面,请使用发电需水量
函数的定义。
num_days = 4;%天数[WaterDemand, T_max] = generateWaterDemand (num_days);
查看需求配置文件。
地块(需水量)
打开配电系统的Simulink模型。金宝app
mdl=“watertankscheduling”;open_system (mdl)
除了强化学习代理,在控制律MATLAB函数块中定义了一个简单的基线控制器。这个控制器根据水位激活一定数量的泵。
指定初始水位。
h0 = 3;%m
指定模型参数。
采样时间=0.2;最大H_=7;最大油箱高度(m)A_tank = 40;%储罐面积(m^2)
要为Simulink模型创建环境接口,首先定义操作和观察规范,金宝app肌动蛋白
和obsInfo
,分别。所选的药剂作用是泵的数量。代理观测是作为连续时间信号测量的水位。
actInfo = rlFiniteSetSpec ([0, 1, 2, 3]);obsInfo = rlNumericSpec ([1]);
创建环境接口。
env=rlSi金宝appmulinkEnv(mdl,mdl+“/RL代理”、obsInfo actInfo);
指定一个自定义重置函数(在本例末尾定义),该函数随机化初始水位和需水量。这样做可以让代理接受不同初始水位和每集需水量函数的培训。
env。ResetFcn = @(在)localResetFcn(的);
DQN代理使用批判q值函数表示来逼近给定的观察和行动的长期回报。要创建批评家,首先要创建一个深度神经网络。有关创建深度神经网络值函数表示的更多信息,请参见创建策略和值函数表示.
%修复随机生成器种子以获得再现性。rng (0);
为评论家创建一个深度神经网络。对于本例,使用非递归神经网络。要使用递归神经网络,集合useLSTM
到真正的
.
useLSTM = false;如果UselTM layers=[sequenceInputLayer(obsInfo.Dimension(1),“名称”,“状态”,“归一化”,“没有”) fullyConnectedLayer (32,“名称”,“fc_1”) reluLayer (“名称”,“relu_body1”)第1层(32,“名称”,“lstm”) fullyConnectedLayer (32,“名称”,“fc_3”) reluLayer (“名称”,“relu_body3”)完整连接层(numel(actInfo.元素),“名称”,“输出”));其他的[featureInputLayer(obsInfo.Dimension(1)),“名称”,“状态”,“归一化”,“没有”) fullyConnectedLayer (32,“名称”,“fc_1”) reluLayer (“名称”,“relu_body1”) fullyConnectedLayer (32,“名称”,“fc_2”) reluLayer (“名称”,“relu_body2”) fullyConnectedLayer (32,“名称”,“fc_3”) reluLayer (“名称”,“relu_body3”)完整连接层(numel(actInfo.元素),“名称”,“输出”));结束
指定用于创建评论家表示的选项。
criticOpts = rlRepresentationOptions (“LearnRate”,0.001,“GradientThreshold”1);
使用定义的深度神经网络和选项创建批评家表示。
评论家=rlQValueRepresentation(图层图、obsInfo、actInfo、,...“观察”,{“状态”}, criticOpts);
要创建代理,首先指定代理选项。如果使用的是LSTM网络,则将序列长度设置为20
.
opt=rlDQNAgentOptions(“SampleTime”, SampleTime);如果UselTM opt.SequenceLength=20;其他的opt.SequenceLength=1;结束opt.DiscountFactor = 0.995;opt.ExperienceBufferLength = 1 e6;opt.EpsilonGreedyExploration.EpsilonDecay = 1 e-5;opt.EpsilonGreedyExploration.EpsilonMin = .02点;
使用定义的选项和评论家表示创建代理。
代理= rlDQNAgent(评论家,选择);
要培训代理,首先指定培训选项。对于本示例,请使用以下选项。
跑步训练1000集,每集持续装天花板(T_max / Ts)
时间的步骤。
在“事件管理器”对话框中显示培训进度(设置阴谋
选项)
指定用于培训的选项rlTrainingOptions
对象
trainOpts = rlTrainingOptions (...“MaxEpisodes”,1000,...“MaxStepsPerEpisode”,ceil(T_max/SampleTime),...“冗长”假的,...“阴谋”,“培训进度”,...“StopTrainingCriteria”,“情节计数”,...“StopTrainingValue”,1000,...“ScoreAveragingWindowLength”, 100);
虽然在本例中不这样做,但您可以在培训过程中保存代理。例如,以下选项将使用大于或等于的奖励值保存每个代理-42年
.
如果需要的话,使用SaveAgentCriteria保存代理。SaveAgentCriteria =“EpisodeReward”;trainOpts。SaveAgentValue = -42;
训练代理人使用火车
函数。培训此代理是一个计算密集型过程,需要几个小时才能完成。要在运行此示例时节省时间,请通过设置doTraining
到假
.自己训练代理人,设置doTraining
到真正的
.
doTraining=false;如果doTraining%培训代理人。trainingStats =火车(代理,env, trainOpts);其他的%加载示例的预训练代理。装载(“金宝appSimulinkWaterDistributionDQN.mat”,“代理人”)结束
下图显示了培训进度。
为了验证训练后的agent的性能,将其模拟在水箱环境中。有关代理模拟的更多信息,请参见rlSimulationOptions
和sim卡
.
要模拟代理性能,请通过切换手动开关块来连接RL代理块。
set_param (mdl +“/手动开关”,“西南”,' 0 ');
设置每个模拟的最大步骤数和模拟的数量。对于本例,运行30个模拟。环境复位函数设置了不同的初始高度,每次模拟的需水量也不同。
NumSimulations=30;simOptions=rlSimulationOptions(“MaxSteps”,T_max/SampleTime,...“NumSimulations”,数值模拟);
为了将agent与基线控制器在相同条件下进行比较,对环境重置函数中使用的初始随机种子进行重置。
env。ResetFcn (“重置种子”);
根据环境模拟代理。
experienceDQN=sim(环境、代理、simOptions);
要将DQN代理与基线控制器进行比较,必须使用相同的模拟选项和重置功能的初始随机种子模拟基线控制器。
启用基线控制器。
set_param (mdl +“/手动开关”,“西南”,' 1 ');
为了将agent与基线控制器在相同条件下进行比较,对环境复位函数中使用的随机种子进行复位。
env。ResetFcn (“重置种子”);
根据环境模拟基线控制器。
experienceBaseline = sim (env,代理,simOptions);
初始化代理和基线控制器的累计奖励结果向量。
resultVectorDQN = 0 (num道模拟,1);resultVectorBaseline = 0 (NumSimulations, 1);
计算代理和基线控制器的累计奖励。
为ct=1:numSimulationsResultVectorDQn(ct)=和(经验Qn(ct).奖励);resultVectorBaseline(ct)=和(经验基线(ct).奖励);结束
绘制累积奖励。
绘图([resultVectorDQN resultVectorBaseline],“o”甘氨胆酸)组(,“克斯蒂克”,1:NumSimulations)xlabel(“模拟编号”)伊拉贝尔(“累积奖励”)传奇(“DQN”,“基线”,“位置”,“NorthEastOutside”)
代理获得的累积奖励始终在-40左右。该值远大于基线控制器获得的平均奖励。因此,DQN代理在节能方面始终优于基线控制器。
水需求函数
函数[需水量,T_max]=发电需水量(num_天)T=0:(num_天*24)-1;%人力资源T_max=T(end);需求平均值=[28,28,28,45,55,110,280,450,310,170,160,145,130,...150, 165, 155, 170, 265, 360, 240, 120, 83, 45, 28]';%立方米/小时需求= repmat (Demand_mean 1 num_days);需求=需求(:);给需求增加噪音a=-25;%立方米/小时b = 25;%立方米/小时需求噪音=a+(b-a)。*兰德(努梅尔(需求),1);水需求=时间序列(需求+需求噪音,t);水需求。名称=“水需求”;结束
复位功能
函数in=localResetFcn(in)%使用持久随机种子值来评估代理和基线%相同条件下的控制器。持续的随机种子如果isempty(randomSeed)randomSeed=0;结束如果strcmp(在,“重置种子”)随机种子=0;返回结束随机种子=随机种子+1;rng(随机种子)%随机用水需求。num_days = 4;H_max = 7;[WaterDemand ~] = generateWaterDemand (num_days);assignin (“基地”,“WaterDemand”WaterDemand)%将初始高度随机化。h0 = 3 * randn;而h0 <= 0 || h0 | h0结束黑色=“水箱调度/水箱系统/初始水位”;在= setBlockParameter(黑色,“价值”num2str (h0));结束