メインコンテンツ

車線維持支援用 DQN エージェントの学習

この例では、Simulink® で車線維持支援 (LKA) のために深層 Q 学習ネットワーク (DQN) エージェントに学習させる方法を示します。DQN エージェントの詳細については、深層 Q ネットワーク (DQN) エージェントを参照してください。

再現性のための乱数ストリームの固定

サンプル コードには、さまざまな段階で乱数の計算が含まれる場合があります。サンプル コード内のさまざまなセクションの先頭にある乱数ストリームを固定すると、実行するたびにセクション内の乱数シーケンスが維持されるため、結果が再現される可能性が高くなります。詳細については、Results Reproducibilityを参照してください。シード 0 で乱数ストリームを固定し、メルセンヌ・ツイスター乱数アルゴリズムを使用します。乱数生成に使用されるシード制御の詳細については、rngを参照してください。

previousRngState = rng(0,"twister");

出力 previousRngState は、ストリームの前の状態に関する情報が格納された構造体です。例の最後で、状態を復元します。

自車の Simulink モデル

この例では、自車の車両運動に関する単純な自転車モデルを強化学習の環境として使用します。学習の目標は、フロント ステアリング角度を調整することにより、車線のセンターラインに沿って自車を走行させ続けることです。この例では、Lane Keeping Assist System Using Model Predictive Control (Model Predictive Control Toolbox)と同じ車両モデルを使用します。自車の車両運動は以下のパラメーターによって指定します。

m = 1575;   % total vehicle mass (kg)
Iz = 2875;  % yaw moment of inertia (mNs^2)
lf = 1.2;   % longitudinal distance from CG to front tires (m)
lr = 1.6;   % longitudinal distance from CG to rear tires (m)
Cf = 19000; % cornering stiffness of front tires (N/rad)
Cr = 33000; % cornering stiffness of rear tires (N/rad)
Vx = 15;    % longitudinal velocity (m/s)

サンプル時間 Ts とシミュレーション期間 Tf を秒単位で定義します。

Ts = 0.1;
T = 15;

LKA システムの出力は、自車のフロント ステアリング角度です。自車の物理的な制限をシミュレートするには、ステアリング角度を範囲 [-0.5,0.5] rad に制約します。

u_min = -0.5;
u_max = 0.5;

道路の曲率は定数 0.001 (m-1) で定義されます。横方向偏差の初期値は 0.2 m で、相対ヨー角の初期値は –0.1 rad です。

rho = 0.001;
e1_initial = 0.2;
e2_initial = -0.1;

モデルを開きます。

mdl = "rlLKAMdl";
open_system(mdl);
agentblk = mdl + "/RL Agent";

このモデルでは、次のようにします。

  • エージェントから環境へのステアリング角度アクション信号は、-15 ~ 15 度とする。

  • 環境からの観測値は、横方向の偏差 e1、相対ヨー角 e2、それらの微分 e˙1e˙2、およびそれらの積分 e1e2 とする。

  • シミュレーションは、横方向の偏差が |e1|>1. となったときに終了する。

  • 各タイム ステップ t で与えられる報酬 rt は次のとおりとする。

rt=-(10e12+5e22+2u2+5e˙12+5e˙22)

ここで、u は前のタイム ステップ t-1 からの制御入力です。

環境インターフェイスの作成

自車用の強化学習環境オブジェクトを作成します。これを行うには、まず観測仕様とアクション仕様を作成します。

observationInfo = rlNumericSpec([6 1], ...
    LowerLimit=-inf*ones(6,1), ...
    UpperLimit=inf*ones(6,1));
observationInfo.Name = "observations";
observationInfo.Description = ...
    "Lateral deviation and relative yaw angle";
actionInfo = rlFiniteSetSpec((-15:15)*pi/180);
actionInfo.Name = "steering";

次に、環境オブジェクトを作成します。

env = rlSimulinkEnv(mdl,agentblk,observationInfo,actionInfo);

オブジェクトは離散行動空間をもち、エージェントは -15 度 ~ 15 度の 31 種類の可能なステアリング角のいずれかを適用できます。観測値は、横方向の偏差、相対ヨー角、これらの時間微分、これらの時間積分から成る 6 次元のベクトルです。

横方向の偏差と相対ヨー角の初期条件を定義するには、無名関数ハンドルを使用して環境リセット関数を指定します。このリセット関数は、横方向の偏差と相対ヨー角の初期値をランダム化します。

env.ResetFcn = @(in)localResetFcn(in);

DQN エージェントの作成

DQN エージェントは、パラメーター化された Q 値関数近似器を使用して方策の価値を推定します。

DQN エージェントは離散行動空間をもちますが、(多出力の) ベクトル Q 値関数クリティックを作成することもできます。これは通常、単出力クリティックよりも効率的です。

離散ベクトル Q 値関数は、観測値のみを入力として受け取り、取り得る離散行動の数と同じ数の要素をもつ単一のベクトルを出力として返します。各出力要素の値は、現在の観測値に対応する状態から、要素番号に対応するアクションを実行する (その後は方策に従う) ことに対する割引累積長期報酬の期待値を表します。

クリティック内のパラメーター化された Q 値関数をモデル化するには、1 つの入力 (6 次元の観測状態) と 31 個の要素 (-15 度 ~ 15 度の範囲で等間隔に配置されたステアリング角度) から成る 1 つの出力ベクトルをもつ深層ニューラル ネットワークを使用します。

% Define number of inputs, neurons, and outputs
nI = observationInfo.Dimension(1);  % number of inputs (6)
nL = 24;                            % number of neurons
nO = numel(actionInfo.Elements);    % number of outputs (31)

% Define network as array of layer objects
dnn = [
    featureInputLayer(nI)
    fullyConnectedLayer(nL)
    reluLayer
    fullyConnectedLayer(nL)
    reluLayer
    fullyConnectedLayer(nO)
    ];

% Convert to dlnetwork object
dnn = dlnetwork(dnn);

パラメーターの数を表示し、ネットワーク構成を表示します。

summary(dnn)
   Initialized: true

   Number of learnables: 1.5k

   Inputs:
      1   'input'   6 features
plot(dnn)

Figure contains an axes object. The axes object contains an object of type graphplot.

dnn および観測仕様とアクション仕様を使用して、クリティックを作成します。詳細については、rlQValueFunctionを参照してください。

critic = rlVectorQValueFunction(dnn,observationInfo,actionInfo);

rlOptimizerOptionsを使用して、クリティックの学習オプションを指定します。

criticOptions = rlOptimizerOptions( ...
    LearnRate=1e-3, ...
    GradientThreshold=1, ...
    L2RegularizationFactor=1e-4);

rlDQNAgentOptionsを使用して DQN エージェントのオプションを指定し、クリティックの学習オプションを含めます。

agentOptions = rlDQNAgentOptions(...
    SampleTime=Ts,...
    UseDoubleDQN=true,...
    CriticOptimizerOptions=criticOptions,...
    ExperienceBufferLength=1e6,...
    MiniBatchSize=64);
agentOptions.EpsilonGreedyExploration.EpsilonDecay = 1e-4;

次に、指定したクリティック表現とエージェントのオプションを使用して、DQN エージェントを作成します。詳細については、rlDQNAgentを参照してください。

agent = rlDQNAgent(critic,agentOptions);

エージェントの学習

エージェントに学習させるには、まず、学習オプションを指定します。この例では、次のオプションを使用します。

  • 最大 5000 個のエピソードについて、各学習エピソードを実行 (各エピソードの持続時間は最大 ceil(T/Ts) タイム ステップ)。

  • [強化学習の学習モニター] ダイアログ ボックスで学習の進行状況を表示し (Plots オプションを training-progress に設定)、コマンド ラインの表示を無効化 (Verbose オプションを false に設定)。

  • エピソード報酬が –1 に達したら学習を停止。

  • 累積報酬が –2.5 を超える各エピソードについてエージェントのコピーを保存。

学習オプションの詳細については、rlTrainingOptionsを参照してください。

maxepisodes = 5000;
maxsteps = ceil(T/Ts);
trainingOpts = rlTrainingOptions(...
    MaxEpisodes=maxepisodes,...
    MaxStepsPerEpisode=maxsteps,...
    Verbose=false,...
    Plots="training-progress",...
    StopTrainingCriteria="EpisodeReward",...
    StopTrainingValue=-1,...
    SaveAgentCriteria="EpisodeReward",...
    SaveAgentValue=-2.5);

再現性のために乱数ストリームを固定します。

rng(0,"twister");

関数 train を使用して、エージェントに学習させます。学習は計算量が多いプロセスのため、完了するのに数時間かかります。この例の実行時間を節約するために、doTrainingfalse に設定して事前学習済みのエージェントを読み込みます。エージェントに学習させるには、doTrainingtrue に設定します。

doTraining = false;
if doTraining    
    % Train the agent.
    trainingStats = train(agent,env,trainingOpts);
else
    % Load the pretrained agent for the example.
    load("SimulinkLKADQNMulti.mat","agent");       
end

DQN エージェントのシミュレーション

再現性のために乱数ストリームを固定します。

rng(0,"twister");

学習済みエージェントの性能を検証するには、次の 2 つの行のコメントを解除し、環境内でこのエージェントをシミュレートします。エージェントのシミュレーションの詳細については、rlSimulationOptions および sim を参照してください。

% simOptions = rlSimulationOptions(MaxSteps=maxsteps);
% experience = sim(env,agent,simOptions);

確定的な初期条件で学習済みエージェントのデモを実行するには、このモデルを Simulink でシミュレートします。

e1_initial = -0.4;
e2_initial = 0.2;
sim(mdl)

プロットが示すように、横方向の誤差 (上部プロット) と相対ヨー角 (下部プロット) は両方とも 0 に近づきます。車両はセンターラインから外れた状態 (-0.4 m)、およびヨー角の誤差がゼロでない状態 (0.2 rad) から出発します。車線維持支援により、約 2.5 秒後に自車がセンターラインに沿って走行するようになります。ステアリング角 (中央プロット) は、コントローラーが約 2 秒後に定常状態に達することを示しています。

previousRngState に保存されている情報を使用して、乱数ストリームを復元します。

rng(previousRngState);

リセット関数

function in = localResetFcn(in)
    % reset lateral deviation and relative yaw angle to random values
    in = setVariable(in,"e1_initial", 0.5*(-1+2*rand)); 
    in = setVariable(in,"e2_initial", 0.1*(-1+2*rand));
end

参考

関数

オブジェクト

ブロック

トピック