▶ 実 行
▶ 実行
クリア
# OpenAI Gym Certpole DDQN # AWAIT命令のプラグインを取り込む !「https://n3s.nadesi.com/plain/1899.js」を取り込む # なでしこv3版のOpen AI Gym Certpoleの環境を取り込む !「https://n3s.nadesi.com/plain/1927.nako3」を取り込む TensorFlowJsURLとは変数 TensorFlowJsURLは「https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.0.0/dist/tf.fesm.min.js」 TFとは変数 TFはNULL 強化学習 ●強化学習とは TFはTFJSインポートをAWAIT # TFの"enableDebugMode"を[]でJSメソッド実行 QENVとは変数 ENVとは変数 QENVはQENV作成 ENVはGYM作成 QENV["イテレーション数"]は0 # イテレーションを繰り返す オンの間繰り返す QENV["ゲーム数"]は0 # ゲームを繰り返す (QENV["ゲーム数"]<QENV["イテレーションゲーム数"])の間繰り返す QENV["STATE"]はGYMリセット QENV["エピソード報酬"]は0 QENV["ステップ"]は0 続行フラグとは変数 続行フラグはオン # 1ゲーム分のステップを行う (続行フラグ=オン)の間繰り返す ACTIONとは変数 ACTIONはQENVのACTION取得 結果とは変数 結果はACTIONでGYMステップ GYM描画 次STATEとは変数 REWARDとは変数 次STATEは結果[0] REWARDは結果[1] QENV["エピソード報酬"]はQENV["エピソード報酬"]+REWARD REWARDは0 もし、結果[2]ならば、 もし、結果[3]ならば、 REWARDは1.0 違えば REWARDは-1.0 ここまで 続行フラグはオフ 違えば REWARDは0.0 ここまで QENVからQENV["STATE"]にACTIONで次STATEのREWARDをリプレイ登録 QENV["STATE"]は次STATE QENVのACTIONで状態表示 QENVの報酬グラフ描画 QENVのバッチ学習 QENV["ステップ"]はQENV["ステップ"]+1 (1.0/QENV["FPS"])秒待つ ここまで QENV["ゲーム数"]はQENV["ゲーム数"]+1 QENV["エピソード"]はQENV["エピソード"]+1 QENV["エピソード報酬履歴"]にQENV["エピソード報酬"]を配列追加 もし、(QENV["エピソード報酬履歴"]の配列要素数)>QENV["エピソード報酬履歴最大数"]ならば、 QENV["エピソード報酬履歴"]の0を配列切取 QENV["エピソード報酬履歴起点"]はQENV["エピソード報酬履歴起点"]+1 ここまで ここまで QENV["イテレーション数"]はQENV["イテレーション数"]+1 QENVのバッチ学習 QENV["主ネットワーク"]からQENV["対象ネットワーク"]にTFウェイト複製 ここまで ここまで ●QENV作成とは QENVとは変数 QENVは{ GAMMA:0.99, 学習率:0.0001, イテレーションゲーム数:20, エピソード:1, ゲーム数:1, ステップ:0, イテレーション数:1, STATE:NULL, エピソード報酬:0, エピソード報酬履歴:[], 画面幅:描画中キャンバス["width"], 画面高:描画中キャンバス["height"], エピソード報酬履歴起点:0, リセット猶予:0, リセット待機ステップ:0, バッチサイズ:32, リプレイバッファ:[], リプレイバッファ容量:10000 } QENV["グラフX"]はQENV["画面幅"]/10 QENV["グラフY"]はQENV["画面高"]/3*2 QENV["グラフW"]はQENV["画面幅"]-QENV["グラフX"]*2 QENV["グラフH"]はQENV["画面高"]/3-20 QENV["エピソード報酬履歴最大数"]はQENV["グラフW"] QENVにモデルネットワーク準備 QENVで戻る ここまで ●Qネットワーク作成とは MODELとは変数 OPTSとは変数 LAYERとは変数 MODELはTFの"sequential"を[]でJSメソッド実行 OPTSは{ "units": 32, "activation": "relu", "inputShape": [4], } LAYERはTF["layers"]の"dense"を[OPTS]でJSメソッド実行 MODELの"add"を[LAYER]でJSメソッド実行 OPTSは{ "units": 32, "activation": "relu", } LAYERはTF["layers"]の"dense"を[OPTS]でJSメソッド実行 MODELの"add"を[LAYER]でJSメソッド実行 OPTSは{ "units": 2, "activation": "linear", } LAYERはTF["layers"]の"dense"を[OPTS]でJSメソッド実行 MODELの"add"を[LAYER]でJSメソッド実行 MODELで戻る ここまで ●(QENVに)モデルネットワーク準備とは QENV["主ネットワーク"]はQネットワーク作成 QENV["対象ネットワーク"]はQネットワーク作成 OPTIMIZERとは変数 OPTSとは変数 OPTIMIZERはTF["train"]の"adam"を[QENV["学習率"]]でJSメソッド実行 OPTSは{ "loss": TF["losses"]["huberLoss"], "optimizer": OPTIMIZER, "metrics": ['accuracy'], } QENV["主ネットワーク"]の"compile"を[OPTS]でJSメソッド実行 QENV["主ネットワーク"]からQENV["対象ネットワーク"]にTFウェイト複製 ここまで ●(QENVからSTATEにACTIONでNEXT_STATEのREWARDを)リプレイ登録とは [STATE,ACTION,NEXT_STATE,REWARD]をQENV["リプレイバッファ"]に配列追加 もし、(QENV["リプレイバッファ"]の配列要素数)≧QENV["リプレイバッファ容量"]ならば、 QENV["リプレイバッファ"]の0から200を配列取出 ここまで ここまで ●(QENVの)バッチ学習とは もし、(QENV["リプレイバッファ"]の配列要素数)<QENV["バッチサイズ"]ならば、 戻る ここまで STATEリストとは変数 ACTIONリストとは変数 STATE_NEXTリストとは変数 REWARDリストとは変数 Lとは変数 Iとは変数 アイテムとは変数 STATEリストは[] ACTIONリストは[] STATE_NEXTリストは[] REWARDリストは[] LはQENV["リプレイバッファ"]の配列要素数 (QENV["バッチサイズ"])回繰り返す IはLの乱数 アイテムはQENV["リプレイバッファ"][I] STATEリストにアイテム[0]を配列追加 ACTIONリストにアイテム[1]を配列追加 STATE_NEXTリストにアイテム[2]を配列追加 REWARDリストにアイテム[3]を配列追加 ここまで STATEとは変数 STATE_NEXTとは変数 NEXTQ推論とは変数 NEXTA推論とは変数 CURR推論とは変数 STATEはSTATEリストをTFtensor2d STATE_NEXTはSTATE_NEXTリストをTFtensor2d NEXTQ推論はQENV["対象ネットワーク"]の"predictOnBatch"を[STATE_NEXT]でJSメソッド実行 NEXTA推論はQENV["主ネットワーク"]の"predictOnBatch"を[STATE_NEXT]でJSメソッド実行 CURR推論はQENV["主ネットワーク"]の"predictOnBatch"を[STATE]でJSメソッド実行 STATE_NEXTをTFdispose 次Qとは変数 次Aとは変数 現Qとは変数 次QはNEXTQ推論の"data"を[]でJSメソッド実行をAWAIT 次AはNEXTA推論の"data"を[]でJSメソッド実行をAWAIT 現QはCURR推論の"data"を[]でJSメソッド実行をAWAIT 目標Qリストとは変数 Jとは変数 REWARDとは変数 目標Qとは変数 次最大Qとは変数 目標Qリストは[] (QENV["バッチサイズ"])回繰り返す Iは回数-1 JはACTIONリスト[I] REWARDはREWARDリスト[I] 目標Qは[] 次最大Qは次Q[I*2+0] もし、次A[I*2+1]>次A[I*2+0]ならば 次最大Qは次Q[I*2+1] ここまで 目標Q[J]はREWARD+QENV["GAMMA"]*次最大Q 目標Q[1-J]は現Q[I*2+1-J] 目標Qリストに目標Qを配列追加 ここまで NEXTQ推論をTFdispose NEXTA推論をTFdispose CURR推論をTFdispose OPTSとは変数 OPTSは{ "epochs":1, } 目標Qは目標QリストをTFtensor2d QENV["主ネットワーク"]の"fit"を[STATE,目標Q,OPTS]でJSメソッド実行をAWAIT STATEをTFdispose 目標QをTFdispose ここまで ●(QENVの)ACTION取得とは Eとは変数 Eは0.5*(1/(QENV["イテレーション数"]+1)) もし、E<RNDならば、 STATEとは変数 推論とは変数 データとは変数 STATEは[QENV["STATE"]]をTFtensor2d 推論はQENV["主ネットワーク"]の"predictOnBatch"を[STATE]でJSメソッド実行 データは推論の"data"を[]でJSメソッド実行をAWAIT STATEをTFdispose 推論をTFdispose もし、データ[0]>データ[1]ならば、 0で戻る 違えば 1で戻る ここまで ここまで 2の乱数で戻る ここまで ●(QENVの)報酬グラフ描画とは 1に線太さ設定 黒色に線色設定 空に塗り色設定 [QENV["グラフX"],QENV["グラフY"],QENV["グラフW"],QENV["グラフH"]]の四角描画 「12px sans-serif」に描画フォント設定 描画中コンテキスト["textAlign"]は"right" 描画中コンテキスト["textBaseline"]は"middle" [QENV["グラフX"]-2,QENV["グラフY"]]に500を文字描画 [QENV["グラフX"]-2,QENV["グラフY"]+QENV["グラフH"]]に0を文字描画 描画中コンテキスト["textAlign"]は"center" [QENV["グラフX"],QENV["グラフY"]+QENV["グラフH"]+8]に(1+QENV["エピソード報酬履歴起点"])を文字描画 [QENV["グラフX"]+QENV["グラフW"],QENV["グラフY"]+QENV["グラフH"]+8]に(QENV["エピソード報酬履歴起点"]+QENV["エピソード報酬履歴最大数"])を文字描画 Xとは変数 Yとは変数 報酬とは変数 Xは0 報酬でQENV["エピソード報酬履歴"]を反復する 青色に塗り色設定 青色に線色設定 Yは報酬/500*QENV["グラフH"] [QENV["グラフX"]+X,QENV["グラフY"]+QENV["グラフH"]-Y,1,1]に四角描画 XはX+1 ここまで ここまで ●(QENVのACTIONで)状態表示とは 「16px sans-serif」に描画フォント設定 描画中コンテキスト["textAlign"]は"right" 描画中コンテキスト["textBaseline"]は"middle" [140,10]に「イテレーション:」を文字描画 [200,10]にQENV["イテレーション数"]を文字描画 [280,10]に「ゲーム:」を文字描画 [320,10]にQENV["ゲーム数"]を文字描画 [430,10]に「ステップ:」を文字描画 [470,10]にQENV["ステップ"]を文字描画 [530,10]に「操作:」を文字描画 Mとは変数 ACTIONで条件分岐 0ならば、 Mは「←」 ここまで 1ならば、 Mは「→」 ここまで 違えば、 Mは「?」 ここまで ここまで [550,10]にMを文字描画 ここまで ●TFJSインポートとは TensorFlowJsURLを動的インポートで戻る ここまで ●(Aを)TFtensor2dとは TFの"tensor2d"を[A]でJSメソッド実行で戻る ここまで ●(Aを)TFdisposeとは TFの"dispose"を[A]でJSメソッド実行 ここまで ●(SRCからDSTに)TFウェイト複製とは 学習フラグとは変数 学習フラグはNULL もし、SRC["trainable"]がDST["trainable"]でなければ、 学習フラグはDST["trainable"] ここまで WEIGHTとは変数 WEIGHTはSRCの"getWeights"を[]でJSメソッド実行 DSTの"setWeights"を[WEIGHT]でJSメソッド実行 もし、学習フラグ≠NULLならば、 DST["trainable"]は学習フラグ ここまで ここまで ●(Sを)動的インポートとは 『(function(s) {return import(s);})』を[S]でJS関数実行で戻る ここまで ●RNDとは 『Math.random』を[]でJS関数実行で戻る ここまで