主要内容

使用自定义函数创建MATLAB环境

这个例子展示了如何通过在MATLAB®中提供自定义动态函数来创建一个车杆环境。

使用rlFunctionEnv函数,您可以从观察规范、操作规范和用户定义创建MATLAB强化学习环境一步而且重置功能。然后你可以在这个环境中训练一个强化学习代理。必要的一步而且重置本例中已经定义了函数。

使用自定义函数创建环境对于动态不太复杂的环境、没有特殊可视化需求的环境或与第三方库有接口的环境非常有用。对于更复杂的环境,可以使用模板类创建环境对象。有关更多信息,请参见从模板创建自定义MATLAB环境

有关创建强化学习环境的更多信息,请参见创建MATLAB强化学习环境而且创建Simul金宝appink强化学习环境

车杆MATLAB环境

车杆环境是一根连接在车的非驱动关节上的杆,它沿着无摩擦的轨道移动。训练目标是使钟摆直立不倒。

对于这种环境:

  • 向上平衡摆的位置为0弧度,向下悬挂的位置是π弧度。

  • 钟摆以-0.05到0.05之间的初始角度直立开始。

  • 从agent到环境的力动作信号为-10 ~ 10n。

  • 从环境中观测到的数据包括小车位置、小车速度、摆角和摆角导数。

  • 如果杆子与垂直方向的距离超过12度,或者推车从原来的位置移动超过2.4米,则该事件终止。

  • 每一步杆子保持直立,奖励为+1。当钟摆下降时,惩罚值为-10。

有关此模型的更多信息,请参见负载预定义控制系统环境

观察和行动规范

从环境中观测到的数据包括小车位置、小车速度、摆角和摆角导数。

ObservationInfo = rlNumericSpec([4 1]);ObservationInfo。Name =“CartPole州”;ObservationInfo。描述='x, dx, d '

环境有一个离散的动作空间,代理可以在其中对推车应用两种可能的力值:-1010N。

ActionInfo = rlFiniteSetSpec([-10 10]);ActionInfo。Name =“CartPole行动”

有关指定环境操作和观察的详细信息,请参见rlNumericSpec而且rlFiniteSetSpec

使用函数名创建环境

要定义自定义环境,首先指定自定义一步而且重置功能。这些函数必须在您当前的工作文件夹或MATLAB路径中。

自定义重置函数设置环境的默认状态。此函数必须具有以下签名。

[InitialObservation,LoggedSignals] = myResetFunction()

将信息从一个步骤传递到下一个步骤,例如环境状态,使用LoggedSignals.在这个例子中,LoggedSignals包含推车环境的状态:推车的位置和速度、摆角和摆角导数。的重置函数在每次环境重置时将推车角度设置为随机值。

对于本例,使用中定义的自定义重置函数myResetFunction.m

类型myResetFunction.m
function [InitialObservation, LoggedSignal] = myResetFunction() %重置函数,将自定义车杆环境置于随机%初始状态。% Theta(随机化)T0 = 2 * 0.05 * rand() - 0.05;% Thetadot Td0 = 0;% x x0 = 0;% Xdot Xd0 = 0;以日志信号形式返回初始环境状态变量。LoggedSignal。State = [X0;Xd0;T0;Td0];InitialObservation = LoggedSignal.State;结束

自定义一步函数指定环境如何根据给定的操作进入下一个状态。此函数必须具有以下签名。

[观察,奖励,IsDone,LoggedSignals] = myStepFunction(动作,LoggedSignals)

为了获得新状态,环境将动态方程应用于存储在其中的当前状态LoggedSignals,这类似于给微分方程一个初始条件。新的状态被存储在其中LoggedSignals并作为输出返回。

对于本例,使用中定义的自定义step函数myStepFunction.m.为了实现简单,这个函数每次都重新定义物理常数,比如推车质量一步是执行。

类型myStepFunction.m
function [NextObs,Reward,IsDone,LoggedSignals] = myStepFunction(Action,LoggedSignals) %自定义步骤函数,为函数% name case构造车极环境。此函数将给定的动作应用于环境,并为一个模拟步骤评估系统动态。定义环境常数。%重力加速度(m/s^2)重力= 9.8;购物车质量% CartMass = 1.0;极点质量% PoleMass = 0.1;HalfPoleLength = 0.5;输入可施加的最大力MaxForce = 10;%采样时间Ts = 0.02;%事件失败的极点角度AngleThreshold = 12 * pi/180; % Cart distance at which to fail the episode DisplacementThreshold = 2.4; % Reward each time step the cart-pole is balanced RewardForNotFalling = 1; % Penalty when the cart-pole fails to balance PenaltyForFalling = -10; % Check if the given action is valid. if ~ismember(Action,[-MaxForce MaxForce]) error('Action must be %g for going left and %g for going right.',... -MaxForce,MaxForce); end Force = Action; % Unpack the state vector from the logged signals. State = LoggedSignals.State; XDot = State(2); Theta = State(3); ThetaDot = State(4); % Cache to avoid recomputation. CosTheta = cos(Theta); SinTheta = sin(Theta); SystemMass = CartMass + PoleMass; temp = (Force + PoleMass*HalfPoleLength*ThetaDot*ThetaDot*SinTheta)/SystemMass; % Apply motion equations. ThetaDotDot = (Gravity*SinTheta - CosTheta*temp) / ... (HalfPoleLength*(4.0/3.0 - PoleMass*CosTheta*CosTheta/SystemMass)); XDotDot = temp - PoleMass*HalfPoleLength*ThetaDotDot*CosTheta/SystemMass; % Perform Euler integration. LoggedSignals.State = State + Ts.*[XDot;XDotDot;ThetaDot;ThetaDotDot]; % Transform state to observation. NextObs = LoggedSignals.State; % Check terminal condition. X = NextObs(1); Theta = NextObs(3); IsDone = abs(X) > DisplacementThreshold || abs(Theta) > AngleThreshold; % Get reward. if ~IsDone Reward = RewardForNotFalling; else Reward = PenaltyForFalling; end end

使用定义的观察规范、操作规范和函数名构建自定义环境。

env = rlFunctionEnv(ObservationInfo,ActionInfo,“myStepFunction”“myResetFunction”);

要验证环境的运行情况,rlFunctionEnv自动调用validateEnvironment在创建环境之后。

使用函数句柄创建环境

您还可以定义自定义函数,这些函数具有超出所需最小集的其他输入参数。例如,传递附加参数__arg1而且最长对于step和rest函数,使用以下代码。

[InitialObservation,LoggedSignals] = myResetFunction(arg1,arg2) [Observation,Reward,IsDone,LoggedSignals] = myStepFunction(Action,LoggedSignals,arg1,arg2)

使用这些函数rlFunctionEnv,必须使用匿名函数句柄。

ResetHandle = @()myResetFunction(arg1,arg2);@(Action,LoggedSignals) myStepFunction(Action,LoggedSignals,arg1,arg2);

有关更多信息,请参见匿名函数

使用额外的输入参数可以创建更有效的环境实现。例如,myStepFunction2.m包含一个自定义一步将环境常量作为输入参数的函数(envConstants).通过这样做,该函数避免了在每个步骤中重新定义环境常量。

类型myStepFunction2.m
function [NextObs,Reward,IsDone,LoggedSignals] = myStepFunction2(Action,LoggedSignals,EnvConstants) %自定义步骤函数,为函数%句柄情况构建车极环境。此函数将给定的动作应用于环境,并为一个模拟步骤评估系统动态。检查给定的操作是否有效。如果~ ismember(行动,[-EnvConstants。MaxForce EnvConstants.MaxForce])错误('向左移动必须是%g,向右移动必须是%g。',…-EnvConstants.MaxForce EnvConstants.MaxForce);end力=动作;从记录的信号中解包状态向量。状态= LoggedSignals.State;XDot =状态(2); Theta = State(3); ThetaDot = State(4); % Cache to avoid recomputation. CosTheta = cos(Theta); SinTheta = sin(Theta); SystemMass = EnvConstants.MassCart + EnvConstants.MassPole; temp = (Force + EnvConstants.MassPole*EnvConstants.Length*ThetaDot*ThetaDot*SinTheta)/SystemMass; % Apply motion equations. ThetaDotDot = (EnvConstants.Gravity*SinTheta - CosTheta*temp)... / (EnvConstants.Length*(4.0/3.0 - EnvConstants.MassPole*CosTheta*CosTheta/SystemMass)); XDotDot = temp - EnvConstants.MassPole*EnvConstants.Length*ThetaDotDot*CosTheta/SystemMass; % Perform Euler integration. LoggedSignals.State = State + EnvConstants.Ts.*[XDot;XDotDot;ThetaDot;ThetaDotDot]; % Transform state to observation. NextObs = LoggedSignals.State; % Check terminal condition. X = NextObs(1); Theta = NextObs(3); IsDone = abs(X) > EnvConstants.XThreshold || abs(Theta) > EnvConstants.ThetaThresholdRadians; % Get reward. if ~IsDone Reward = EnvConstants.RewardForNotFalling; else Reward = EnvConstants.PenaltyForFalling; end end

创建包含环境常量的结构。

%重力加速度,单位为m/s^2envConstants。重力= 9.8;手推车的%质量envConstants。MassCart = 1.0;%极点的质量envConstants。maspole = 0.1;杆子长度的一半envConstants。长度= 0.5;输入可以施加的最大力envConstants。MaxForce = 10;%采样时间envConstants。Ts = 0.02;%失败的角度envConstants。的taThresholdRadians = 12 * pi/180;%插曲失败的距离envConstants。XThreshold = 2.4;%奖励每一步平衡车杆envConstants。RewardForNotFalling = 1;当横担未能平衡时,%扣分envConstants。罚分= -5;

创建自定义的匿名函数句柄一步函数,通过envConstants作为一个额外的输入参数。因为envConstants在那个时间有空吗StepHandle时,函数句柄包含这些值。即使清除了变量,值也会保留在函数句柄中。

StepHandle = @(Action,LoggedSignals) myStepFunction2(Action,LoggedSignals,envConstants);

使用相同的重置函数,将其指定为函数句柄,而不是使用其名称。

ResetHandle = @() myResetFunction;

使用自定义函数句柄创建环境。

env2 = rlFunctionEnv(ObservationInfo,ActionInfo,StepHandle,ResetHandle);

验证自定义函数

在您的环境中训练代理之前,最佳实践是验证自定义函数的行为。方法初始化您的环境重置函数并运行一个模拟步骤一步函数。为了重现性,在验证前设置随机生成器种子。

验证使用函数名创建的环境。

rng (0);InitialObs = reset(env)
InitialObs =4×10 0 0.0315 0
[NextObs,Reward,IsDone,LoggedSignals] = step(env,10);NextObs
NextObs =4×10 0.1947 0.0315 -0.2826

验证使用函数句柄创建的环境。

rng (0);InitialObs2 = reset(env2)
InitialObs2 =4×10 0 0.0315 0
[NextObs2,Reward2,IsDone2,LoggedSignals2] = step(env2,10);NextObs2
NextObs2 =4×10 0.1947 0.0315 -0.2826

两个环境都成功地初始化和模拟,在中产生相同的状态值NextObs

另请参阅

相关的话题