強化学習のための貯水タンク カスタム Simulink 環境
この例では、貯水タンクの Simulink® 環境について説明します。この環境は、rlwatertank Simulink モデルに基づいており、タンク内の水位を制御するために (コントローラーではなく) RL Agent ブロックを含んでいます。
このモデルをシミュレーションするには、エージェントを作成し、そのエージェントを RL Agent ブロックで指定しなければなりません。この環境を使用してエージェントに学習させる例については、DDPG エージェントを使用したタンク内の水位の制御を参照してください。
mdl = "rlwatertank";
open_system(mdl)
このモデルには、次の信号に接続する RL Agent ブロックが既に含まれています。
スカラー アクション出力信号
観測入力信号のベクトル
スカラー報酬入力信号
シミュレーション停止用の logical 入力信号
アクション仕様
強化学習環境は、エージェントからアクション信号を受け取り、それらのアクションに応じて観測信号を生成します。カスタムの Simulink 環境を作成するには、まずアクション仕様オブジェクトと観測仕様オブジェクトを作成します。カスタム Simulink 環境の詳細については、Create Custom Simulink Environmentsを参照してください。
この環境のアクション信号は、プラントに送信される流量制御信号です。これは連続変数で表されます。連続信号を搬送するアクション チャネルの仕様オブジェクトを作成するには、rlNumericSpecを使用します。流量制御信号は非負で、下限が 0、上限が 1 に正規化されています。この信号は、Water Tank System サブシステムに送信される前にスケーリングされます。
actInfo = rlNumericSpec([1 1], LowerLimit=0, UpperLimit=1);
actInfo.Name = "flow rate control signal";代わりに、可能な値の離散集合からアクション信号が取られる場合、rlFiniteSetSpecを使用して仕様を作成します。
観測仕様
この環境では、エージェントに送信される 3 つの観測信号があり、ベクトル信号として指定されます。観測ベクトルは です。ここで、次のようになります。
はタンク内の水位。
。ここで、 は水位の基準値。
generate observations サブシステムで観測信号を計算します。
open_system(mdl + "/generate observations")
観測仕様から成る 3 要素ベクトルを作成します。水位の下限として 0 を指定し、他の観測信号は無制限のままにします。
obsInfo = rlNumericSpec([3 1], ... LowerLimit=[-inf -inf 0 ]', ... UpperLimit=[ inf inf inf]'); obsInfo.Name = "observations"; obsInfo.Description = "integrated error, error, and measured height";
アクションまたは観測値がバス信号で表される場合は、関数bus2RLSpecを使用して仕様を作成します。
報酬信号
スカラー報酬信号を構成します。この例では、次の報酬を指定します。
誤差が 0.1 未満の場合、報酬は正となり、それ以外の場合は負になります。また、水位が 0 ~ 20 の範囲外の場合は、大きな報酬ペナルティが発生します。
この報酬を calculate reward サブシステムで構成します。
open_system(mdl + "/calculate reward")
停止信号
学習エピソードとシミュレーションを終了するには、ブロックの isdone 入力端子に logical 信号を指定します。この例では、 または の場合にエピソードを終了します。
この信号を stop simulation サブシステムで計算します。
open_system(mdl + "/stop simulation")
環境オブジェクトの作成
Simulink モデル用の環境オブジェクトを作成します。
env = rlSimulinkEnv(mdl,mdl + "/RL Agent",obsInfo,actInfo);リセット関数の追加
モデルのパラメーター、変数、または状態をランダム化するカスタム リセット関数を作成することもできます。この例では、例の終わりで定義されているリセット関数 localResetFcn が基準信号と初期水位をランダム化し、対応するブロック パラメーターを設定します。
env.ResetFcn = @(in)localResetFcn(in);
スクリプト内で最初に呼び出されたときにリセット関数が常に同じランダムな初期値を返すようにするには、trainまたはsimを呼び出す前に乱数ストリーム ジェネレーターを固定します。たとえば、シード 0 で乱数ストリームを固定し、メルセンヌ・ツイスター乱数アルゴリズムを使用します。
previousRngState = rng(0,"twister");乱数生成に使用されるシード制御の詳細については、rngを参照してください。結果の再現性に関する詳細については、Results Reproducibilityを参照してください。
学習済みエージェントの読み込みと環境のシミュレーション
例DDPG エージェントを使用したタンク内の水位の制御で学習させた DDPG エージェントを読み込みます。
load("WaterTankDDPG.mat","agent")
既定では、エージェントはシミュレーション時に貪欲 (したがって決定的) 方策を使用します。代わりに探索方策を使用するには、UseExplorationPolicy エージェントのプロパティを true に設定します。
環境内でこのエージェントのシミュレーションを 100 ステップ実行し、経験を出力として返します。詳細については、rlSimulationOptionsおよびsimを参照してください。
simOpts = rlSimulationOptions(MaxSteps=100,StopOnError="on");
experience = sim(env,agent,simOpts);
シミュレーションにおいてエージェントが収集する報酬の合計を表示します。
sum(experience.Reward)
ans = 890
previousRngState に保存されている情報を使用して、乱数ストリームを復元します。
rng(previousRngState);
ローカル リセット関数
sim 関数は、各シミュレーション エピソードの開始時にリセット関数を呼び出し、train 関数は、各学習エピソードの開始時にリセット関数を呼び出します。リセット関数は入力として Simulink.SimulationInput (Simulink) オブジェクトを受け取り、出力として同じ型のオブジェクトを返します。出力オブジェクトには、モデルに一時的に適用される変更が指定され、これらの変更はシミュレーションまたは学習の完了時に破棄されます。この例のリセット関数は、setBlockParameter (Simulink)を使用して基準信号と初期水位のランダムな値を指定します。詳細については、Reset Function for Simulink Environmentsを参照してください。
function in = localResetFcn(in) % Randomize reference signal blk = sprintf("rlwatertank/Desired \nWater Level"); h = 3*randn + 10; while h <= 0 || h >= 20 h = 3*randn + 10; end in = setBlockParameter(in,blk,Value=num2str(h)); % Randomize initial water height h = 3*randn + 10; while h <= 0 || h >= 20 h = 3*randn + 10; end blk = "rlwatertank/Water-Tank System/H"; in = setBlockParameter(in,blk,InitialCondition=num2str(h)); end