こんにちは､ このPythonチュートリアルへようこそ｡
さて､ 今日は目が新しい状態になると同時に､ 更新すべきものをすべて更新するupdate関数を作ります｡
だから､ 新しい状態になったら､ ほら､ アクションを更新する必要があるんだ｡
最後に表示されたアクションが新しいアクションになるのはもちろん､ 最後に表示された状態が新しい状態になる｡
そして､ いよいよ最後のご褒美｡
それが､ そのアクションをプレイしたときに得られる新たな報酬になるのです｡
つまり､ アクションを選択した直後に起こる論理的な道筋です｡ トランジションのすべての要素を更新する必要があり､
当然ながら新しいトランジションを取得することになります｡
そこで､ この新しい遷移をメモリに追記する必要があります｡
そして最後に､ 報酬ウィンドウを更新して､ トレーニングの進行状況や探索の進捗を見守ります｡
しかし､ 皆さんに理解していただきたいのは､ 今実装しているAIとマップをようやく結びつけることができるということです｡
マップに戻ると､ ゲームクラスに大きな更新関数があることを思い出してください｡
そこで､ 実際にクルマと一緒にゲームを作り､ クルマがミスをしたときにどう罰せられるかを定義しているのです｡
しかし､ このゲームクラスでは､ この更新関数に注目し､ この更新関数では､ ラインアクションがブレインドット更新に等しく､
報酬が少なく､ シグナルが少ないことに気づきました｡
そして実はこれこそが､ 私たちが作ろうとしていたものなのです｡
このアップデート機能で､ 最後の報酬と最後のシグナルを受け取って､ 次のアクションを再生するようにするところです｡
つまり､ 遷移のさまざまな要素をすべて更新するだけでなく､ ほとんどが最後の報酬と最後のシグナルを得るときに再生すべきアクションを再生することになるのです｡
で､ もちろん､ この更新機能では､ 先ほど実装したselect action関数を使います｡
すべてのアップデートを行う以外に､ これから行うアップデート機能でセレクトアクション機能を統合し､
適切なアクションを選択してプレイできるようにする予定です｡
だから､ この地図との結びつきがとても重要なんです｡
今､ 私たちが作ろうとしているのは､ 結局､ AIとゲーム､ この授業で作るゲームとの接続なのです｡
そして､ 今できることは､ この更新の最後のシグナルを直接受け取ることです｡ なぜなら､ それはまさに､
この2つの引数で作る関数だからです｡
そして､ 念のためお伝えしておきますが､ 脳は私たちの目の対象です｡
つまり､ そのクラスのオブジェクトである｡
これから行うのは､ このアップデート､ less reward, less signalをコピーして､
次の関数にすることで､ ここにペーストします｡
それから､ 念のため､ ここにある名前とは違う名前をいくつか挙げておきたいと思います｡
こちらは報酬が少ないですからね｡
そして､ この最後の報酬とこの報酬を混同しないようにしたいと思います｡
それは危険なことです｡
そこで､ ここではラストワードをリワードに置き換えてみることにします｡
ちなみに､ 信号が少なくても同じです｡
新しい状態に到達し､ 新しいシグナルを得たときに更新を行うことを指定するために､ シグナル､ あるいは新しいシグナルを置きましょう｡
でも､ もちろん､ この報酬は､ 砂の上に行ったり､ 最悪､ マップの一辺に近づきすぎたりすると､
ここでもらえる最後の報酬になるんだけどね｡
そこで､ 最後の報酬を定義するのです｡
この最後の報酬が､ 更新関数の入力となる｡
だから､ ここでは報酬が少ないのです｡
しかし､ ここで私は､ 議論報酬と混同しないように別の名前を与えているだけです｡
ここで最後に一言｡
わかりました｡
これがアップデート機能なんですね｡
そして今度は､ その中に入って､ この2つのことをやってみましょう｡
それは､ トランジションのすべての要素を更新し､ もちろん､ アクションを選択することです｡
なるほど｡
では､ まず何をアップデートする必要があるのでしょうか｡
さて､ お分かりのように､ 新しい状態になったときに更新を行いたいのです｡
ですから､ まず最初に更新するのは､ 明らかにこの新しい状態です｡
それが､ 私たちが到達しようとしている新しい状態です｡
そこで､ この新しい状態､ new state､ そしてequalと呼ぶことにします｡
それで､ どうすればこの新しい状態を手に入れることができるのでしょうか｡
もちろん､ それはセンサーが検知した新しい信号によるものです｡
そして､ 注意点として､ 状態はセンサーの3つの信号､ 信号1､ 信号2､ 信号3､ プラス方向とマイナス方向で構成される信号そのものであることです｡
それが私たちの状態です｡
だから､ 信号が状態であることをしっかり理解すること｡
しかし､ 今は5つの要素からなるシンプルなリストです｡
そして､ これがニューラルネットワークの入力になるので､ トーチテンソルに変換する必要があることを忘れないでください｡
だから､ まさに今､ 私たちはそれを実行しようとしているのです｡
私たちは､ トーチ・ライブラリーを､ そして､ 取るのです｡
Tensorクラス｡
これでよしとしよう｡
これは新しい信号をトーチテンソルに変換するものである｡
それなら､ トーチテンソルの要素がすべてフロートであることを確認したほうがよい｡
そこで､ このようにfloatに変換する型変換を行い､ 最後に次にやるべきことを反射的にやってみることにします｡
もちろん､ その偽物の次元を作るため､ バッチに対応する次元を追加するためです｡
もちろん､ squeeze 関数でこれを行います｡ この関数には､ バッチで使用する偽の次元のインデックスを入力する必要があります
(ゼロ)｡
わかりました｡
そして､ 3つのセンサーの3つの信号に方位を加えたものから方位を引いたものが､ 新しい状態です｡
そしてもちろん､ それはこの行のところで､ このアップデート機能で得られる新しいシグナルに依存します｡
最後の信号で､ 3つの信号にオリエンテーションを加えたものを得ることができます｡
そして､ 注意点として､ この3つの信号は､ センサーの周りで検出された香りの密度を表しています｡
わかりました｡
つまり､ 新しい状態に到達したところで､ 次の更新をしなければならないわけです｡
では､ 先生のお話では､ 今､ 何を更新する必要があるのでしょうか？
この新しい状態に到達した後､ 今すぐアップデートすることが論理的に可能なことは何でしょうか？
さて､ 今アップデートしなければならないのは､ メモリです｡
それはなぜでしょうか？
それは､ 各時刻tにおいて､ 現在の状態をt､ 次の状態をt＋1､ 報酬r t､ 行動a tという遷移が構成されるからである｡
そして今､ 私たちはすでにtを持ち､ Tを持ち､ Tプラス1として遷移の最後の要素を手に入れたところです｡
つまり､ この新しい状態をTプラス1として取得することで､ メモリの新しい遷移を1つ取得することになる｡
そのため､ この新しいトランジションをメモリに追加しなければなりません｡
だから､ 今すぐメモリを更新しなければならないわけです｡
したがって､ これから行うのは､ リプレイ・メモリ・クラスから作成したメモリ・オブジェクトを､ したがって､
selfを取ることです｡
オブジェクトを参照するためのそのメモリ｡
しかし､ selfを使っているので､ update関数にselfを入れなければならない｡
これで､ 自己が何のためにあるのかがよくわかるようになりましたね｡
init関数で作成・初期化した変数を1つ使うのはいつでもです｡
だからセルフドットメモリーで､ 今度はそれを更新する必要があるのです｡
そして､ あなたによると､ どうやってアップデートするつもりなのですか？
さて､ 朗報は､ そのための関数をすでに作ってしまったことです｡
イベントやトランジションをメモリに追記するプッシュ機能です｡
だから､ まさにこれから使うんです｡
これからpush関数を使って､ 先ほど作った新しいトランジションをメモリに追加していきます｡
したがって､ ここではメソッドを使用するため､ イコールではなく､ ドットプッシュを直接使用することにしています｡
そしてまず､ トランジションを追加します｡ 先ほど手に入れた新しいトランジションは､
まず最後の状態なので､ その少ない状態を自己紹介します｡
だから､ それはS-Tそれこそすでに存在するこの1つなのです｡
そして､ この遷移の次の要素は､ もちろん､ 先ほど到達した新しい状態である｡
したがって､ このinit関数で作成し初期化したオブジェクトの変数ではないので､
ここにはselfを入れません｡
直接､ 新しい状態を入れています｡
次に遷移の要素であるアクションですが､ すでに最後のアクションがあり､ この自己の最後のアクションはここだと言っています｡
ですから､ もちろんゼロに等しいのですが､ そうすると当然､ セレクトアクション機能で更新されることになります｡
でも､ これはこれでいいんです｡
そうすると､ セルフドットラストアクションになるわけです｡
でも､ 今は気をつけてください｡
この移行に含まれる要素は､ すべてトーチダンサーであるべきです｡
ご覧のように､ 最後の日付がそうなっています｡
トーチダンサーです｡
新国立はトーチダンサーでもある｡
そして､ これはアクションも同じでなければならない｡
そして､ もちろんご褒美も｡
しかし､ 今､ あなたは､ それが単に数字であることを考えると､ どうしてトーチダンサーになるのか､ と思うでしょう､
ほら､ アクションはゼロ1か2のどちらかです､ でも実は､ それは問題ではないのです｡
このゼロワン､ ツーの変数をトーチダンサーに変換することはまだ可能です｡
これは､ いわゆるロングテンソルに過ぎないだろう｡
longは型であり､ これが整数を格納するテンソルである｡
最後の部分は整数であるため､ 0 1または2である｡
そこで､ これから持っていくのが図書館のトーチです｡
次に､ ここでlongを取る｡ それはlongテンソルクラスで､ 新しいオブジェクトを作る｡ それはlongテンソル自身となる｡
そして､ 自己ラストアクション関数を入力とすることで､ この長期主体を作るのですが､ やはりゼロイチやゼロツーを含む長大なテンソルオブジェクトになります｡
それも､ あくまで移行に伴う整合性をとるために｡
PyTorchを使っているので､ センサーしか入っていないはずですが､ ニューラルネットワークを扱っています｡
ですから､ 私たちはセンサーと一緒になって､ 長いテンソルを作っていかなければならないのです｡
そして最後にもう一つ､ この長い答えの中身が整数であることを確認しなければなりません｡ それを確認するために､
たとえ最後のセクションがゼロ1か2であることがすでに分かっていても､
もう一度このint型の変換をするために､ 私たちの最後のアクションを整数に変換しています｡
これでよしとしよう｡
そして､ 整数の自己の最後のアクションをここで括弧に入れなければならない｡ そうすれば､ この最後のアクションのゼロ1または2そのものとなる1つの要素の長いテンソルが得られる｡
つまり､ 重要なのは､ 0か1か2かの単純な数を､ タッチを持つテンソルに変換する方法だけなのです｡
わかりました｡
そして､ いよいよ移行の最後の要素､ それはもちろん､ 最後のご褒美を手に入れることです｡
init関数で作成した最後の報酬変数は0に初期化されましたが､ もちろんこのコード内で更新されます｡
ある意味､ 負の報酬になるか､ ゴールから遠くなれば､ これもまた負の報酬になります｡
目標に近づけば､ それがプラスの報酬になる｡
そして､ マップの一辺に近づきすぎた場合の最悪の罰として､ まあ､ マイナス1という恐ろしい報酬が待っています｡
そして､ それだけです｡
そこで､ この最後の要素に､ その報酬であるトランジションセルフを加えてみましょう｡
このように､ コピーしたものをここに貼り付けて､ もう一回変換する必要があります｡
ただ､ 報酬が整数ではなく浮動小数点数なので､ 単純にテンソル変換するトーチを作ることにする｡
しかしintsを使わずとも､ ここでは括弧を残しておく｡ なぜなら､ まず数字をリストに入れ､
このリストをtorchテンソルクラスの入力とする必要があるからだ｡
しかし､ 最後の報酬は浮動小数点数なので､ 変換でそれを作る必要はないのです｡
つまり､ このテンソルに向かって､ トーチ・ドット・テンソルを追加し､ 括弧､ 大括弧を追加するだけです｡
そして､ ここで括弧を閉じ､ 括弧も閉じます｡
これでよしとしよう｡
つまり､ 先ほど到達した新しい状態と報酬をまとめると､ 新しい遷移のイベントを観察し､ それをメモリに追加しているのです｡
そして､ この遷移は､ 新しい状態への最後の状態を含んでいます｡
SDプラス1､ 最後にプレイしたアクション80､ 最後の報酬｡
よしっ｡
わかりました｡
あとは､ メモリのアップデートでOKです｡
では､ ちょっと休憩して､ 次のチュートリアルで次のアップデートを担当しましょう｡
それまではお楽しみに｡
I.