Main Content

step 함수와 reset 함수를 사용하여 사용자 지정 환경 만들기

이 예제에서는 MATLAB® step 함수와 reset 함수를 자체적으로 작성하여 사용자 지정 환경을 만드는 방법을 보여줍니다.

rlFunctionEnv 함수를 사용하여 관측값 사양, 행동 사양, 사용자가 제공하는 step 함수와 reset 함수로부터 MATLAB 강화 학습 환경을 만들 수 있습니다. 그런 다음 이 환경에서 강화 학습 에이전트를 훈련시킬 수 있습니다. 이 예제에서는 필요한 step 함수와 reset 함수가 이미 정의되어 있습니다.

사용자 지정 함수를 사용하여 환경을 만드는 것은 많은 헬퍼 함수가 필요하지 않고 특별한 시각화 요구 사항이 없는 비교적 단순한 환경에 특히 유용합니다. 더 복잡한 환경의 경우 템플릿 클래스를 사용하여 환경 객체를 만들 수 있습니다. 자세한 내용은 클래스 템플릿에서 사용자 지정 환경 만들기 항목을 참조하십시오.

강화 학습 환경을 만드는 방법에 대한 자세한 내용은 Reinforcement Learning EnvironmentsCreate Custom Simulink Environments 항목을 참조하십시오.

이산 행동 공간 카트-폴 MATLAB 환경

카트-폴 환경은 카트의 비구동 관절에 붙어 있는 막대로, 카트는 마찰이 없는 트랙을 따라 움직입니다. 훈련 목표는 이 진자가 넘어지지 않고 똑바로 서 있게 만드는 것입니다.

이 환경의 경우 다음이 적용됩니다.

  • 위쪽으로 똑바로 균형이 잡혀 있을 때의 진자 위치는 0라디안이고, 아래쪽으로 매달려 있을 때의 위치는 π라디안입니다.

  • 진자의 초기 각이 –0.05라디안과 0.05라디안 사이이고 위쪽을 향해 있을 때 시작합니다.

  • 에이전트에서 환경으로 전달되는 힘 행동 신호는 –10N 또는 10N입니다.

  • 환경에서 관측하는 값은 카트 위치, 카트 속도, 진자 각, 진자 각속도입니다.

  • 막대가 수직에서 12도 이상 기울거나 카트가 원래 위치에서 2.4m 이상 이동하면 에피소드가 종료됩니다.

  • 막대가 위쪽을 향해 바로 서 있는 매 시간 스텝마다 보상 +1이 주어집니다. 진자가 넘어지면 벌점 –10이 적용됩니다.

이 모델에 대한 자세한 설명은 Load Predefined Control System Environments 항목을 참조하십시오.

관측값 및 행동 사양

환경에서 관측하는 값은 카트 위치, 카트 속도, 진자 각, 진자 각 도함수입니다.

ObsInfo = rlNumericSpec([4 1]);
ObsInfo.Name = "CartPole States";
ObsInfo.Description = 'x, dx, theta, dtheta';

환경에는 에이전트가 힘 값 -10N 또는 10N 중 하나를 카트에 적용할 수 있는 이산 행동 공간이 있습니다.

ActInfo = rlFiniteSetSpec([-10 10]);
ActInfo.Name = "CartPole Action";

환경 행동과 관측값을 지정하는 방법에 대한 자세한 내용은 rlNumericSpec 항목과 rlFiniteSetSpec 항목을 참조하십시오.

환경에 대한 reset 함수와 step 함수 정의하기

사용자 지정 환경을 정의하려면 먼저 사용자 지정된 step 함수와 reset 함수를 지정하십시오. 이들 함수는 현재 작업 폴더 또는 MATLAB 경로에 있어야 합니다.

reset 함수는 환경의 초기 상태를 설정합니다. 이 함수에는 다음 시그니처가 있어야 합니다.

[InitialObservation,Info] = myResetFunction()

첫 번째 출력 인수는 초기 관측값입니다. 두 번째 출력 인수는 한 스텝에서 다음 스텝으로 전달하려는 유용한 환경 정보(예: 환경 상태 또는 상태와 파라미터가 포함된 구조체)일 수 있습니다.

훈련(또는 시뮬레이션) 에피소드가 시작될 때 train(또는 sim)은 reset 함수를 호출하고 두 번째 출력 인수를 사용하여 사용자 지정 환경의 Info 속성을 초기화합니다. 훈련(또는 시뮬레이션) 스텝 중에 train(또는 sim)은 Info의 현재 값을 StepFcn의 두 번째 입력 인수로 제공한 다음, StepFcn에서 반환된 네 번째 출력 인수를 사용하여 Info의 값을 업데이트합니다.

이 예제에서는 두 번째 인수를 사용하여 카트-폴 환경의 초기 상태, 즉 카트의 위치와 속도, 진자 각, 진자 각 도함수를 저장합니다. reset 함수는 환경이 재설정될 때마다 카트 각도를 임의의 값으로 설정합니다.

이 예제에서는 myResetFunction.m에 정의된 사용자 지정 reset 함수를 사용합니다.

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)

새 상태를 계산하기 위해, step 함수는 Info에 저장된 현재 상태에 동특성 방정식을 적용합니다. 그런 다음 이 함수는 업데이트된 상태를 UpdatedInfo에 반환합니다. 그다음 훈련(또는 시뮬레이션) 스텝에서 train 또는 sim은 이전 스텝에서 얻은 네 번째 출력 인수 UpdatedInfo를 받아 step 함수에 두 번째 입력 인수 Info로 제공합니다.

이 예제에서는 myStepFunction.m에 정의된 사용자 지정 step 함수를 사용합니다. 구현을 단순하게 하기 위해, 이 함수는 step이 실행될 때마다 카트 질량과 같은 물리 상수를 재정의합니다. 또 다른 방법은 reset 함수에서 물리 상수를 정의하고 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

관측값 사양과 행동 사양, step 함수와 reset 함수의 이름을 사용하여 사용자 지정 환경 객체를 만들려면 rlFunctionEnv를 사용하십시오.

env = rlFunctionEnv(ObsInfo,ActInfo,"myStepFunction","myResetFunction");

사용자 환경의 동작을 검증하기 위해 rlFunctionEnv는 환경을 만든 후 자동으로 validateEnvironment를 호출합니다.

익명 함수를 사용하여 추가 인수 전달하기

rlFunctionEnv에 전달해야 하는 사용자 지정된 reset 함수와 step 함수는 인수가 각각 정확히 0개와 2개여야 하지만, 익명 함수를 사용하면 이 제약을 피할 수 있습니다. 구체적으로, rlFunctionEnv에 전달할 reset 함수와 step 함수를 익명 함수(인수가 각각 0개와 2개임)로 정의합니다. 그러면 이러한 익명 함수가 추가 인수가 있는 사용자 지정 함수를 호출합니다.

예를 들어 추가 인수 arg1arg2step 함수와 reset 함수에 모두 전달하려면 다음 함수를 작성하면 됩니다.

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

그런 다음, MATLAB 작업 공간에서 arg1arg2를 사용하여 인수가 각각 0개와 2개인 익명 reset 함수와 step 함수에 대한 핸들을 다음과 같이 정의합니다.

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

ResetHandleStepHandle이 생성된 시점에 arg1arg2를 사용할 수 있는 경우 두 익명 함수의 작업 공간에 해당 값이 포함됩니다. MATLAB 작업 공간에서 변수를 지우더라도 해당 값은 함수 작업 공간 내에서 유지됩니다. ResetHandleStepHandle이 실행되면 이들은 myResetFunctionmyStepFunction을 호출하고 이들 함수에 arg1arg2의 복사본을 전달합니다. 자세한 내용은 익명 함수 항목을 참조하십시오.

추가 입력 인수를 사용하면 보다 효율적인 환경 구현을 만들 수 있습니다. 예를 들어, myStepFunction2.m은 환경 상수를 세 번째 입력 인수(envPars)로 받는 사용자 지정 step 함수입니다. 그렇게 함으로써, 이 함수는 각 스텝에서 환경 상수가 재정의되는 것을 방지합니다.

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를 추가 입력 인수로 전달하여 사용자 지정 step 함수를 호출하는 익명 함수를 만듭니다.

StepHandle = @(Action,Info) myStepFunction2(Action,Info,envPars);

StepHandle이 생성된 시점에 envPars를 사용할 수 있으므로 익명 함수 작업 공간에 envPars의 복사본이 포함됩니다. StepHandle이 실행되면 이는 myStepFunction2를 호출하고 envPars의 복사본을 전달합니다.

동일한 reset 함수를 사용하되, 그 이름을 사용하는 대신 함수 핸들로 지정합니다.

ResetHandle = @() myResetFunction;

익명 함수에 대한 핸들을 사용하여 환경을 만듭니다.

env2 = rlFunctionEnv(ObsInfo,ActInfo,StepHandle,ResetHandle);

사용자 지정 함수의 출력값을 시각적으로 검사하기

rlFunctionEnv가 환경을 만든 후 validateEnvironment를 자동으로 호출하지만, 함수 출력값을 시각적으로 검사하여 함수가 예상대로 동작하는지 자세히 확인하는 것이 도움이 될 수 있습니다. 그렇게 하려면 reset 함수를 사용하여 환경을 초기화하고 step 함수를 사용하여 시뮬레이션 스텝을 하나 실행하십시오. 재현이 가능하도록, 검증 전에 난수 생성기 시드값을 설정합니다.

함수 이름을 사용하여 만든 환경을 검증합니다.

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에 동일한 상태 값을 생성합니다.

참고 항목

함수

객체

관련 항목