WEBVTT

00:00.150 --> 00:02.490
こんにちは､ このPythonチュートリアルへようこそ｡ 

00:02.610 --> 00:12.210
さて､ 今日は目が新しい状態になると同時に､ 更新すべきものをすべて更新するupdate関数を作ります｡

00:12.210 --> 00:15.940
だから､ 新しい状態になったら､ ほら､ アクションを更新する必要があるんだ｡ 

00:15.960 --> 00:22.470
最後に表示されたアクションが新しいアクションになるのはもちろん､ 最後に表示された状態が新しい状態になる｡

00:22.470 --> 00:24.030
そして､ いよいよ最後のご褒美｡ 

00:24.030 --> 00:27.180
それが､ そのアクションをプレイしたときに得られる新たな報酬になるのです｡ 

00:27.180 --> 00:33.060
つまり､ アクションを選択した直後に起こる論理的な道筋です｡ トランジションのすべての要素を更新する必要があり､

00:33.060 --> 00:37.230
当然ながら新しいトランジションを取得することになります｡

00:37.230 --> 00:40.080
そこで､ この新しい遷移をメモリに追記する必要があります｡ 

00:40.080 --> 00:49.380
そして最後に､ 報酬ウィンドウを更新して､ トレーニングの進行状況や探索の進捗を見守ります｡

00:49.380 --> 00:55.380
しかし､ 皆さんに理解していただきたいのは､ 今実装しているAIとマップをようやく結びつけることができるということです｡

00:55.380 --> 01:06.090
マップに戻ると､ ゲームクラスに大きな更新関数があることを思い出してください｡

01:06.090 --> 01:12.930
そこで､ 実際にクルマと一緒にゲームを作り､ クルマがミスをしたときにどう罰せられるかを定義しているのです｡

01:12.930 --> 01:19.230
しかし､ このゲームクラスでは､ この更新関数に注目し､ この更新関数では､ ラインアクションがブレインドット更新に等しく､

01:19.260 --> 01:24.600
報酬が少なく､ シグナルが少ないことに気づきました｡

01:24.600 --> 01:28.200
そして実はこれこそが､ 私たちが作ろうとしていたものなのです｡ 

01:28.200 --> 01:37.590
このアップデート機能で､ 最後の報酬と最後のシグナルを受け取って､ 次のアクションを再生するようにするところです｡

01:37.590 --> 01:48.990
つまり､ 遷移のさまざまな要素をすべて更新するだけでなく､ ほとんどが最後の報酬と最後のシグナルを得るときに再生すべきアクションを再生することになるのです｡

01:49.140 --> 01:56.970
で､ もちろん､ この更新機能では､ 先ほど実装したselect action関数を使います｡

01:56.970 --> 02:03.300
すべてのアップデートを行う以外に､ これから行うアップデート機能でセレクトアクション機能を統合し､

02:03.300 --> 02:07.650
適切なアクションを選択してプレイできるようにする予定です｡

02:07.650 --> 02:10.350
だから､ この地図との結びつきがとても重要なんです｡ 

02:10.350 --> 02:19.470
今､ 私たちが作ろうとしているのは､ 結局､ AIとゲーム､ この授業で作るゲームとの接続なのです｡

02:19.470 --> 02:26.400
そして､ 今できることは､ この更新の最後のシグナルを直接受け取ることです｡ なぜなら､ それはまさに､

02:26.400 --> 02:30.300
この2つの引数で作る関数だからです｡

02:30.450 --> 02:34.320
そして､ 念のためお伝えしておきますが､ 脳は私たちの目の対象です｡ 

02:34.320 --> 02:37.950
つまり､ そのクラスのオブジェクトである｡ 

02:38.280 --> 02:45.480
これから行うのは､ このアップデート､ less reward, less signalをコピーして､

02:45.480 --> 02:50.220
次の関数にすることで､ ここにペーストします｡

02:50.250 --> 02:56.010
それから､ 念のため､ ここにある名前とは違う名前をいくつか挙げておきたいと思います｡ 

02:56.010 --> 02:57.390
こちらは報酬が少ないですからね｡ 

02:57.390 --> 03:00.660
そして､ この最後の報酬とこの報酬を混同しないようにしたいと思います｡ 

03:00.660 --> 03:01.950
それは危険なことです｡ 

03:01.950 --> 03:06.090
そこで､ ここではラストワードをリワードに置き換えてみることにします｡ 

03:06.090 --> 03:08.850
ちなみに､ 信号が少なくても同じです｡ 

03:08.850 --> 03:18.690
新しい状態に到達し､ 新しいシグナルを得たときに更新を行うことを指定するために､ シグナル､ あるいは新しいシグナルを置きましょう｡

03:18.690 --> 03:26.480
でも､ もちろん､ この報酬は､ 砂の上に行ったり､ 最悪､ マップの一辺に近づきすぎたりすると､

03:26.490 --> 03:31.320
ここでもらえる最後の報酬になるんだけどね｡

03:31.320 --> 03:33.960
そこで､ 最後の報酬を定義するのです｡ 

03:33.960 --> 03:37.290
この最後の報酬が､ 更新関数の入力となる｡ 

03:37.290 --> 03:39.330
だから､ ここでは報酬が少ないのです｡ 

03:39.330 --> 03:45.810
しかし､ ここで私は､ 議論報酬と混同しないように別の名前を与えているだけです｡ 

03:45.810 --> 03:46.920
ここで最後に一言｡ 

03:47.460 --> 03:47.850
わかりました｡ 

03:47.850 --> 03:50.040
これがアップデート機能なんですね｡ 

03:50.040 --> 03:53.880
そして今度は､ その中に入って､ この2つのことをやってみましょう｡ 

03:53.880 --> 03:58.770
それは､ トランジションのすべての要素を更新し､ もちろん､ アクションを選択することです｡ 

03:59.130 --> 03:59.420
なるほど｡ 

03:59.490 --> 04:01.530
では､ まず何をアップデートする必要があるのでしょうか｡ 

04:01.740 --> 04:06.600
さて､ お分かりのように､ 新しい状態になったときに更新を行いたいのです｡ 

04:06.600 --> 04:10.590
ですから､ まず最初に更新するのは､ 明らかにこの新しい状態です｡ 

04:10.590 --> 04:12.390
それが､ 私たちが到達しようとしている新しい状態です｡ 

04:12.540 --> 04:17.160
そこで､ この新しい状態､ new state､ そしてequalと呼ぶことにします｡ 

04:17.160 --> 04:19.770
それで､ どうすればこの新しい状態を手に入れることができるのでしょうか｡ 

04:19.800 --> 04:25.350
もちろん､ それはセンサーが検知した新しい信号によるものです｡ 

04:25.620 --> 04:37.260
そして､ 注意点として､ 状態はセンサーの3つの信号､ 信号1､ 信号2､ 信号3､ プラス方向とマイナス方向で構成される信号そのものであることです｡

04:37.260 --> 04:38.400
それが私たちの状態です｡ 

04:38.400 --> 04:42.420
だから､ 信号が状態であることをしっかり理解すること｡ 

04:42.420 --> 04:45.990
しかし､ 今は5つの要素からなるシンプルなリストです｡ 

04:45.990 --> 04:52.170
そして､ これがニューラルネットワークの入力になるので､ トーチテンソルに変換する必要があることを忘れないでください｡

04:52.200 --> 04:54.630
だから､ まさに今､ 私たちはそれを実行しようとしているのです｡ 

04:54.660 --> 04:59.640
私たちは､ トーチ・ライブラリーを､ そして､ 取るのです｡ 

04:59.930 --> 05:01.410
Tensorクラス｡ 

05:01.430 --> 05:02.330
これでよしとしよう｡ 

05:02.330 --> 05:08.660
これは新しい信号をトーチテンソルに変換するものである｡ 

05:08.990 --> 05:13.970
それなら､ トーチテンソルの要素がすべてフロートであることを確認したほうがよい｡ 

05:13.970 --> 05:24.260
そこで､ このようにfloatに変換する型変換を行い､ 最後に次にやるべきことを反射的にやってみることにします｡

05:24.260 --> 05:29.000
もちろん､ その偽物の次元を作るため､ バッチに対応する次元を追加するためです｡ 

05:29.000 --> 05:36.650
もちろん､ squeeze 関数でこれを行います｡ この関数には､ バッチで使用する偽の次元のインデックスを入力する必要があります

05:36.710 --> 05:40.040
(ゼロ)｡

05:40.610 --> 05:41.150
わかりました｡ 

05:41.150 --> 05:47.960
そして､ 3つのセンサーの3つの信号に方位を加えたものから方位を引いたものが､ 新しい状態です｡

05:48.110 --> 05:55.400
そしてもちろん､ それはこの行のところで､ このアップデート機能で得られる新しいシグナルに依存します｡

05:55.400 --> 05:59.570
最後の信号で､ 3つの信号にオリエンテーションを加えたものを得ることができます｡ 

05:59.570 --> 06:05.870
そして､ 注意点として､ この3つの信号は､ センサーの周りで検出された香りの密度を表しています｡ 

06:06.290 --> 06:06.830
わかりました｡ 

06:06.830 --> 06:13.460
つまり､ 新しい状態に到達したところで､ 次の更新をしなければならないわけです｡

06:13.460 --> 06:16.370
では､ 先生のお話では､ 今､ 何を更新する必要があるのでしょうか？

06:16.400 --> 06:22.160
この新しい状態に到達した後､ 今すぐアップデートすることが論理的に可能なことは何でしょうか？

06:22.370 --> 06:25.700
さて､ 今アップデートしなければならないのは､ メモリです｡ 

06:25.700 --> 06:26.750
それはなぜでしょうか？

06:26.750 --> 06:37.550
それは､ 各時刻tにおいて､ 現在の状態をt､ 次の状態をt＋1､ 報酬r t､ 行動a tという遷移が構成されるからである｡

06:37.550 --> 06:47.150
そして今､ 私たちはすでにtを持ち､ Tを持ち､ Tプラス1として遷移の最後の要素を手に入れたところです｡

06:47.330 --> 06:55.280
つまり､ この新しい状態をTプラス1として取得することで､ メモリの新しい遷移を1つ取得することになる｡ 

06:55.280 --> 07:01.490
そのため､ この新しいトランジションをメモリに追加しなければなりません｡

07:01.700 --> 07:03.890
だから､ 今すぐメモリを更新しなければならないわけです｡ 

07:03.890 --> 07:10.910
したがって､ これから行うのは､ リプレイ・メモリ・クラスから作成したメモリ・オブジェクトを､ したがって､

07:10.910 --> 07:13.040
selfを取ることです｡

07:13.850 --> 07:16.880
オブジェクトを参照するためのそのメモリ｡ 

07:16.880 --> 07:22.220
しかし､ selfを使っているので､ update関数にselfを入れなければならない｡ 

07:22.700 --> 07:25.270
これで､ 自己が何のためにあるのかがよくわかるようになりましたね｡ 

07:25.280 --> 07:30.830
init関数で作成・初期化した変数を1つ使うのはいつでもです｡ 

07:31.400 --> 07:33.890
だからセルフドットメモリーで､ 今度はそれを更新する必要があるのです｡ 

07:33.890 --> 07:36.830
そして､ あなたによると､ どうやってアップデートするつもりなのですか？

07:36.920 --> 07:41.090
さて､ 朗報は､ そのための関数をすでに作ってしまったことです｡ 

07:41.090 --> 07:46.940
イベントやトランジションをメモリに追記するプッシュ機能です｡ 

07:46.940 --> 07:48.920
だから､ まさにこれから使うんです｡ 

07:48.920 --> 07:54.470
これからpush関数を使って､ 先ほど作った新しいトランジションをメモリに追加していきます｡ 

07:54.470 --> 08:03.860
したがって､ ここではメソッドを使用するため､ イコールではなく､ ドットプッシュを直接使用することにしています｡

08:04.010 --> 08:09.770
そしてまず､ トランジションを追加します｡ 先ほど手に入れた新しいトランジションは､

08:09.770 --> 08:13.910
まず最後の状態なので､ その少ない状態を自己紹介します｡

08:14.000 --> 08:18.410
だから､ それはS-Tそれこそすでに存在するこの1つなのです｡ 

08:18.410 --> 08:23.540
そして､ この遷移の次の要素は､ もちろん､ 先ほど到達した新しい状態である｡ 

08:23.540 --> 08:29.150
したがって､ このinit関数で作成し初期化したオブジェクトの変数ではないので､

08:29.150 --> 08:31.340
ここにはselfを入れません｡

08:31.340 --> 08:33.590
直接､ 新しい状態を入れています｡ 

08:35.190 --> 08:43.580
次に遷移の要素であるアクションですが､ すでに最後のアクションがあり､ この自己の最後のアクションはここだと言っています｡

08:43.590 --> 08:49.950
ですから､ もちろんゼロに等しいのですが､ そうすると当然､ セレクトアクション機能で更新されることになります｡ 

08:49.950 --> 08:51.030
でも､ これはこれでいいんです｡ 

08:51.030 --> 08:55.440
そうすると､ セルフドットラストアクションになるわけです｡ 

08:55.620 --> 08:56.970
でも､ 今は気をつけてください｡ 

08:57.000 --> 09:01.470
この移行に含まれる要素は､ すべてトーチダンサーであるべきです｡ 

09:01.590 --> 09:03.720
ご覧のように､ 最後の日付がそうなっています｡ 

09:03.720 --> 09:05.100
トーチダンサーです｡ 

09:05.130 --> 09:07.500
新国立はトーチダンサーでもある｡ 

09:07.620 --> 09:10.440
そして､ これはアクションも同じでなければならない｡ 

09:10.440 --> 09:11.940
そして､ もちろんご褒美も｡ 

09:11.940 --> 09:17.220
しかし､ 今､ あなたは､ それが単に数字であることを考えると､ どうしてトーチダンサーになるのか､ と思うでしょう､

09:17.220 --> 09:22.200
ほら､ アクションはゼロ1か2のどちらかです､ でも実は､ それは問題ではないのです｡

09:22.200 --> 09:28.410
このゼロワン､ ツーの変数をトーチダンサーに変換することはまだ可能です｡ 

09:28.440 --> 09:31.320
これは､ いわゆるロングテンソルに過ぎないだろう｡ 

09:31.320 --> 09:35.670
longは型であり､ これが整数を格納するテンソルである｡ 

09:35.670 --> 09:39.240
最後の部分は整数であるため､ 0 1または2である｡ 

09:39.420 --> 09:43.290
そこで､ これから持っていくのが図書館のトーチです｡ 

09:43.950 --> 09:53.460
次に､ ここでlongを取る｡ それはlongテンソルクラスで､ 新しいオブジェクトを作る｡ それはlongテンソル自身となる｡

09:53.460 --> 10:04.650
そして､ 自己ラストアクション関数を入力とすることで､ この長期主体を作るのですが､ やはりゼロイチやゼロツーを含む長大なテンソルオブジェクトになります｡

10:04.650 --> 10:08.640
それも､ あくまで移行に伴う整合性をとるために｡ 

10:08.640 --> 10:13.980
PyTorchを使っているので､ センサーしか入っていないはずですが､ ニューラルネットワークを扱っています｡

10:13.980 --> 10:18.360
ですから､ 私たちはセンサーと一緒になって､ 長いテンソルを作っていかなければならないのです｡ 

10:18.360 --> 10:25.560
そして最後にもう一つ､ この長い答えの中身が整数であることを確認しなければなりません｡ それを確認するために､

10:25.560 --> 10:30.660
たとえ最後のセクションがゼロ1か2であることがすでに分かっていても､

10:30.660 --> 10:38.760
もう一度このint型の変換をするために､ 私たちの最後のアクションを整数に変換しています｡

10:39.060 --> 10:39.720
これでよしとしよう｡ 

10:39.720 --> 10:52.560
そして､ 整数の自己の最後のアクションをここで括弧に入れなければならない｡ そうすれば､ この最後のアクションのゼロ1または2そのものとなる1つの要素の長いテンソルが得られる｡

10:52.560 --> 10:59.160
つまり､ 重要なのは､ 0か1か2かの単純な数を､ タッチを持つテンソルに変換する方法だけなのです｡

10:59.930 --> 11:00.290
わかりました｡ 

11:00.290 --> 11:06.620
そして､ いよいよ移行の最後の要素､ それはもちろん､ 最後のご褒美を手に入れることです｡

11:06.650 --> 11:12.890
init関数で作成した最後の報酬変数は0に初期化されましたが､ もちろんこのコード内で更新されます｡

11:12.890 --> 11:23.960
ある意味､ 負の報酬になるか､ ゴールから遠くなれば､ これもまた負の報酬になります｡

11:23.960 --> 11:26.870
目標に近づけば､ それがプラスの報酬になる｡ 

11:26.870 --> 11:34.010
そして､ マップの一辺に近づきすぎた場合の最悪の罰として､ まあ､ マイナス1という恐ろしい報酬が待っています｡

11:34.010 --> 11:34.970
そして､ それだけです｡ 

11:36.100 --> 11:40.690
そこで､ この最後の要素に､ その報酬であるトランジションセルフを加えてみましょう｡ 

11:40.810 --> 11:49.510
このように､ コピーしたものをここに貼り付けて､ もう一回変換する必要があります｡

11:49.540 --> 11:57.310
ただ､ 報酬が整数ではなく浮動小数点数なので､ 単純にテンソル変換するトーチを作ることにする｡

11:57.310 --> 12:01.450
しかしintsを使わずとも､ ここでは括弧を残しておく｡ なぜなら､ まず数字をリストに入れ､

12:01.450 --> 12:06.790
このリストをtorchテンソルクラスの入力とする必要があるからだ｡

12:06.790 --> 12:11.250
しかし､ 最後の報酬は浮動小数点数なので､ 変換でそれを作る必要はないのです｡ 

12:11.260 --> 12:21.310
つまり､ このテンソルに向かって､ トーチ・ドット・テンソルを追加し､ 括弧､ 大括弧を追加するだけです｡

12:21.400 --> 12:27.070
そして､ ここで括弧を閉じ､ 括弧も閉じます｡ 

12:27.280 --> 12:28.150
これでよしとしよう｡ 

12:28.630 --> 12:37.060
つまり､ 先ほど到達した新しい状態と報酬をまとめると､ 新しい遷移のイベントを観察し､ それをメモリに追加しているのです｡

12:37.330 --> 12:41.650
そして､ この遷移は､ 新しい状態への最後の状態を含んでいます｡ 

12:41.650 --> 12:46.480
SDプラス1､ 最後にプレイしたアクション80､ 最後の報酬｡ 

12:46.480 --> 12:47.190
よしっ｡ 

12:47.830 --> 12:48.310
わかりました｡ 

12:48.310 --> 12:51.130
あとは､ メモリのアップデートでOKです｡ 

12:51.130 --> 12:55.570
では､ ちょっと休憩して､ 次のチュートリアルで次のアップデートを担当しましょう｡ 

12:55.810 --> 12:56.950
それまではお楽しみに｡ 

12:56.980 --> 12:57.300
I.
