このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
ステップ関数とリセット関数を使用したカスタム環境の作成
この例では、独自の MATLAB® 関数 step
と reset
を作成してカスタム環境を作成する方法を示します。
関数rlFunctionEnv
を使用すると、観測仕様、アクション仕様、および提供する関数 step
と関数 reset
から MATLAB 強化学習環境を作成できます。その後、この環境で強化学習エージェントに学習させることができます。この例では、必要な関数 step
と関数 reset
は既に定義されています。
多くの補助関数を必要とせず、特別な可視化要件がない単純な環境では、カスタム関数を使用した環境を作成することが特に役立ちます。より複雑な環境の場合は、テンプレート クラスを使用して環境オブジェクトを作成できます。詳細については、Create Custom Environment from Class Templateを参照してください。
強化学習環境の作成の詳細については、Reinforcement Learning EnvironmentsおよびCreate Custom Simulink Environmentsを参照してください。
離散行動空間カートポール MATLAB 環境
カートポール環境は、摩擦のないトラックに沿って移動するカート上の非駆動ジョイントに取り付けられたポールです。学習の目標は、振子が倒れず直立した状態を維持することです。
この環境では、次のようにします。
振子が倒立平衡状態となっている位置を 0 ラジアンとし、鉛直下向きとなっている位置を ラジアンとする。
振子は、-0.05 ラジアンから 0.05 ラジアンまでの初期角度で直立して開始する。
エージェントから環境への力のアクション信号は、-10 N または 10 N とする。
環境からの観測値は、カートの位置、カートの速度、振子の角度、および振子の角速度とする。
ポールが垂直から 12 度を超えるか、カートが元の位置から 2.4 m を超えて移動した場合、エピソードの終了とする。
ポールが直立を保っているすべてのタイム ステップに対し、+1 の報酬が提供される。振子が落下すると、-10 のペナルティが適用される。
このモデルの詳細については、Load Predefined Control System Environmentsを参照してください。
観測仕様とアクション仕様
環境からの観測値は、カートの位置、カートの速度、振子の角度、および振子の角度の微分です。
ObsInfo = rlNumericSpec([4 1]); ObsInfo.Name = "CartPole States"; ObsInfo.Description = 'x, dx, theta, dtheta';
この環境は、エージェントが 2 つの有効な力の値 (-10
または 10
N) のいずれかをカートに適用できる離散行動空間をもちます。
ActInfo = rlFiniteSetSpec([-10 10]);
ActInfo.Name = "CartPole Action";
環境アクションと観測値の指定の詳細については、rlNumericSpec
およびrlFiniteSetSpec
を参照してください。
環境のリセット関数とステップ関数の定義
カスタム環境を定義するには、まずカスタム関数 step
と reset
を指定します。これらの関数は、現在の作業フォルダーまたは MATLAB パス上になければなりません。
関数 reset
は、環境の初期状態を設定します。この関数は次のシグネチャをもたなければなりません。
[InitialObservation,Info] = myResetFunction()
最初の出力引数は初期観測値です。2 番目の出力引数には、あるステップから次のステップに渡す任意の有用な環境情報 (環境の状態、状態やパラメーターを格納する構造体など) を指定できます。
学習 (またはシミュレーション) エピソードの開始時に、train
(または sim
) はリセット関数を呼び出し、2 番目の出力引数を使用してカスタム環境の Info
プロパティを初期化します。学習 (またはシミュレーション) ステップにおいて、train
(または sim
) は、Info
の現在の値を StepFcn
の 2 番目の入力引数として指定し、StepFcn
によって返された 4 番目の出力引数を使用して Info
の値を更新します。
この例では、2 番目の引数を使用して、カートポール環境の初期状態 (カートの位置と速度、振子の角度、振子の角度の微分) を保存します。関数 reset
は、環境がリセットされるたびにカートの角度をランダムな値に設定します。
この例では、myResetFunction.m
で定義されたカスタム リセット関数を使用します。
type myResetFunction.m
function [InitialObservation, InitialState] = myResetFunction() % Reset function to place custom cart-pole environment into a random % initial state. % Theta (randomize) T0 = 2 * 0.05 * rand() - 0.05; % Thetadot Td0 = 0; % X X0 = 0; % Xdot Xd0 = 0; % Return initial environment state variables as logged signals. InitialState = [X0;Xd0;T0;Td0]; InitialObservation = InitialState; end
関数 step
は、あるアクションに基づいて、環境が次の状態にどのように進むかを指定します。この関数は次のシグネチャをもたなければなりません。
[NextObservation,Reward,IsDone,UpdatedInfo] = myStepFunction(Action,Info)
新しい状態を計算するために、ステップ関数は Info
に保存されている現在の状態に動的方程式を適用します。その後、関数は更新された状態を UpdatedInfo
に返します。次の学習 (またはシミュレーション) ステップで、train
または sim
は、前のステップで取得した 4 番目の出力引数 UpdatedInfo
を受け取り、それを 2 番目の入力引数 Info
としてステップ関数に提供します。
この例では、myStepFunction.m
で定義されたカスタム ステップ関数を使用します。実装を簡単にするために、この関数は step
が実行されるたびにカートの質量などの物理定数を再定義します。別の方法は、リセット関数で物理定数を定義し、状態とパラメーターの両方を格納する構造体として Info
を定義し、Info
を使用して物理定数と環境状態を保存することです。この代替実装を使用すると、必要に応じて、シミュレーション時や学習時に一部のパラメーターを簡単に変更することができます。
type myStepFunction.m
function [NextObs,Reward,IsDone,NextState] = myStepFunction(Action,State) % Custom step function to construct cart-pole environment for the function % name case. % % This function applies the given action to the environment and evaluates % the system dynamics for one simulation step. % Define the environment constants. % Acceleration due to gravity in m/s^2 Gravity = 9.8; % Mass of the cart CartMass = 1.0; % Mass of the pole PoleMass = 0.1; % Half the length of the pole HalfPoleLength = 0.5; % Max force the input can apply MaxForce = 10; % Sample time Ts = 0.02; % Pole angle at which to fail the episode 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. 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 to calculate next state. NextState = State + Ts.*[XDot;XDotDot;ThetaDot;ThetaDotDot]; % Copy next state to next observation. NextObs = NextState; % Check terminal condition. X = NextObs(1); Theta = NextObs(3); IsDone = abs(X) > DisplacementThreshold || abs(Theta) > AngleThreshold; % Calculate reward. if ~IsDone Reward = RewardForNotFalling; else Reward = PenaltyForFalling; end end
rlFunctionEnv
を使用して、観測仕様とアクション仕様、および関数 step
と関数 reset
の名前を使用してカスタム環境オブジェクトを作成します。
env = rlFunctionEnv(ObsInfo,ActInfo,"myStepFunction","myResetFunction");
環境の動作を確認するために、rlFunctionEnv
は環境の作成後に自動的にvalidateEnvironment
を呼び出します。
無名関数を使用して追加の引数を渡す
rlFunctionEnv
に渡さなければならないカスタム リセット関数とカスタム ステップ関数には、それぞれ 0 個と 2 個の引数が必要ですが、無名関数を使用することでこの制限を回避できます。具体的には、rlFunctionEnv
に渡される関数 reset
と関数 step
を無名関数 (それぞれ 0 個と 2 個の引数) として定義します。これらの無名関数は次に、追加の引数をもつカスタム関数を呼び出します。
たとえば、追加の引数 arg1
と arg2
を関数 step
と関数 reset
の両方に渡すには、次の関数を記述できます。
[InitialObservation,Info] = myResetFunction(arg1,arg2) [Observation,Reward,IsDone,Info] = myStepFunction(Action,Info,arg1,arg2)
次に、MATLAB ワークスペースの arg1
と arg2
を使用して、それぞれ 0 個と 2 個の引数をもつ無名関数 reset
と無名関数 step
に対し、以下のハンドルを定義します。
ResetHandle = @() myResetFunction(arg1,arg2); StepHandle = @(Action,Info) myStepFunction(Action,Info,arg1,arg2);
ResetHandle
と StepHandle
の作成時に arg1
と arg2
が使用可能な場合、両方の無名関数のワークスペースにそれらの値が含められます。MATLAB ワークスペースから変数をクリアした場合でも、値は関数のワークスペース内に保持されます。ResetHandle
と StepHandle
が評価されると、myResetFunction
と myStepFunction
が呼び出され、arg1
と arg2
のコピーが渡されます。詳細については、無名関数を参照してください。
追加の入力引数を使用すると、より効率的な環境実装を作成できます。たとえば、myStepFunction2.m
は、環境定数を 3 番目の入力引数 (envPars
) として受け取るカスタム ステップ関数です。そうすることで、この関数は各ステップで環境定数が再定義されることを回避します。
type myStepFunction2.m
function [NextObs,Reward,IsDone,NextState] = myStepFunction2(Action,State,EnvPars) % Custom step function to construct cart-pole environment for the function % handle case. % % This function applies the given action to the environment and evaluates % the system dynamics for one simulation step. % Check if the given action is valid. if ~ismember(Action,[-EnvPars.MaxForce EnvPars.MaxForce]) error('Action must be %g for going left and %g for going right.',... -EnvPars.MaxForce,EnvPars.MaxForce); end Force = Action; % Unpack the state vector from the logged signals. XDot = State(2); Theta = State(3); ThetaDot = State(4); % Cache to avoid recomputation. CosTheta = cos(Theta); SinTheta = sin(Theta); MassPole = EnvPars.MassPole; HalfLen = EnvPars.HalfLength; SystemMass = EnvPars.MassCart + MassPole; temp = (Force + MassPole*HalfLen*ThetaDot*ThetaDot*SinTheta)/SystemMass; % Apply motion equations. ThetaDotDot = (EnvPars.Gravity*SinTheta - CosTheta*temp)... / (HalfLen*(4.0/3.0 - MassPole*CosTheta*CosTheta/SystemMass)); XDotDot = temp - MassPole*HalfLen*ThetaDotDot*CosTheta/SystemMass; % Perform Euler integration. NextState = State + EnvPars.Ts.*[XDot;XDotDot;ThetaDot;ThetaDotDot]; % Copy next state to next observation. NextObs = NextState; % Check terminal condition. X = NextObs(1); Theta = NextObs(3); IsDone = abs(X) > EnvPars.XThreshold || ... abs(Theta) > EnvPars.ThetaThresholdRadians; % Calculate reward. if ~IsDone Reward = EnvPars.RewardForNotFalling; else Reward = EnvPars.PenaltyForFalling; end end
環境パラメーターを格納する構造体を作成します。
% Acceleration due to gravity in m/s^2 envPars.Gravity = 9.8; % Mass of the cart envPars.MassCart = 1.0; % Mass of the pole envPars.MassPole = 0.1; % Half the length of the pole envPars.HalfLength = 0.5; % Max force the input can apply envPars.MaxForce = 10; % Sample time envPars.Ts = 0.02; % Angle at which to fail the episode envPars.ThetaThresholdRadians = 12 * pi/180; % Distance at which to fail the episode envPars.XThreshold = 2.4; % Reward each time step the cart-pole is balanced envPars.RewardForNotFalling = 1; % Penalty when the cart-pole fails to balance envPars.PenaltyForFalling = -5;
カスタム ステップ関数を呼び出す無名関数を作成し、追加の入力引数として envPars
を渡します。
StepHandle = @(Action,Info) myStepFunction2(Action,Info,envPars);
envPars
は StepHandle
の作成時に使用可能なため、無名関数ワークスペースには envPars
のコピーが含まれます。StepHandle
が評価されると、myStepFunction2
が呼び出され、envPars
のコピーが渡されます。
同じ関数 reset
を、名前ではなく関数ハンドルとして指定し、それを使用します。
ResetHandle = @() myResetFunction;
無名関数へのハンドルを使用して環境を作成します。
env2 = rlFunctionEnv(ObsInfo,ActInfo,StepHandle,ResetHandle);
カスタム関数の出力の視覚的な検証
rlFunctionEnv
は環境の作成後に自動的にvalidateEnvironment
を呼び出しますが、関数の出力を視覚的に検証して、関数の動作が期待どおりであることをさらに確認すると便利な場合があります。これを行うには、関数 reset
を使用して環境を初期化し、関数 step
を使用して 1 つのシミュレーション ステップを実行します。再現性をもたせるために、検証前に乱数発生器のシードを設定します。
関数名を使用して作成された環境を検証します。
rng(0); InitialObs = reset(env)
InitialObs = 4×1
0
0
0.0315
0
[NextObs,Reward,IsDone,Info] = step(env,10); NextObs
NextObs = 4×1
0
0.1947
0.0315
-0.2826
関数ハンドルを使用して作成された環境を検証します。
rng(0); InitialObs2 = reset(env2)
InitialObs2 = 4×1
0
0
0.0315
0
[NextObs2,Reward2,IsDone2,Info2] = step(env2,10); NextObs2
NextObs2 = 4×1
0
0.1947
0.0315
-0.2826
両方の環境が正常に初期化およびシミュレーションされ、NextObs
に同じ状態値が生成されています。