WEBVTT

00:00.270 --> 00:02.610
こんにちは､ このPythonチュートリアルへようこそ｡ 

00:02.640 --> 00:06.720
よし､ 新しい状態になった後､ メモリを更新すればいいんだな｡ 

00:06.720 --> 00:08.880
そして､ 次のアップデートに対応しましょう｡ 

00:09.240 --> 00:12.240
今のお話では､ 次のアップデートはどうなるのでしょうか｡ 

00:12.570 --> 00:16.560
まあ､ 基本的には1回の移行で終了しています｡ 

00:16.590 --> 00:20.930
遷移の最後の要素である新しい状態の日付を表示しました｡ 

00:20.940 --> 00:23.310
だから､ 今､ また最初からやり直すようなものなんです｡ 

00:23.310 --> 00:28.140
そして､ また最初からやり直すとき､ どんな感じかというと､ この新しい状態の環境に身を置くのです｡

00:28.140 --> 00:31.230
そうすると､ 自然と今やるべきことは何か？

00:31.260 --> 00:37.120
もちろん､ 新しい状態の観測をすでに得ているので､ アクションを再生することです｡ 

00:37.170 --> 00:40.380
さて､ 次はアクションの再生です｡ 

00:40.620 --> 00:46.720
したがって､ 今やるべきことは､ もちろん､ アクションの選択機能を使って､ アクションを再生することです｡ 

00:46.740 --> 00:47.580
では､ やってみましょう｡ 

00:47.580 --> 00:54.150
新しい変数アクションを作成し､ selectアクション機能でアクションを再生してみましょう｡ 

00:54.150 --> 01:02.100
そこで､ selectアクションの関数が､ これから作成される別クラスのオブジェクトのメソッドであることを指定するために､ well first

01:02.100 --> 01:04.220
selfをとっているのです｡

01:04.230 --> 01:08.490
だから､ セルフドットセレクトアクション｡ 

01:08.490 --> 01:11.010
さあ､ セルフドットセレクトアクションです｡ 

01:11.010 --> 01:17.550
そして､ select action関数は状態を入力として受け取るので､ 当然ながら､

01:17.550 --> 01:25.140
現在の入力状態がニューラルネットワークに入ったときの出力を返すことになるからだ｡

01:25.230 --> 01:27.450
そこで､ ここに入力状態を入力する必要があります｡ 

01:27.570 --> 01:33.450
そして､ その状態は､ ちょうど今いる環境で､ 入力状態が新しい状態になったところなので､

01:33.450 --> 01:40.020
もちろん新しい状態なのですが､ 今いる時間で到達した状態は､ 新しい状態です｡

01:40.020 --> 01:44.970
そこで､ セレクトアクション機能では､ 新しい状態を入力しています｡ 

01:44.970 --> 01:45.420
わかりました｡ 

01:45.420 --> 01:51.480
つまり､ このコードでは､ 新しいステートに到達した後に新しいアクションを再生するだけです｡ 

01:51.990 --> 01:52.340
なるほど｡ 

01:52.350 --> 01:58.740
そして今､ それを行動で再生すると､ まあ､ 報酬が得られるので､ 報酬と一緒にフィードバックが得られるわけです｡

01:58.740 --> 02:04.590
ですから､ 100個以上の元素を記憶していれば､ まあ､ 勉強の時間でしょう｡ 

02:04.590 --> 02:10.530
ですから､ 今やらなければならないことは､ 行動を選択した後に論理的にやってくること､ それはもちろんニーズを知ること､

02:10.530 --> 02:15.600
正しい方法で物事を進めているかどうかを学び始めることなのです｡

02:15.600 --> 02:23.850
そして今､ AIに過去100回のイベントでの行動を学習させるというアクションをしたところです｡

02:23.970 --> 02:31.260
しかし､ この学習関数を適用する前に､ すでに100以上のイベントに到達していることを確認するために､ このif条件を作成する必要があります｡

02:31.260 --> 02:37.260
なぜなら､ メモリのランダムなサンプルから学習しているためです｡

02:37.260 --> 02:40.920
万個という巨大なメモリがあるじゃないですか｡ 

02:40.920 --> 02:45.150
100個の要素のメモリから､ いくつかのランダムなサンプルを取っているのです｡ 

02:45.150 --> 02:52.620
そして､ この100個のランダムな遷移のサンプルに含まれる情報から､ AIが学習しているのです｡ 

02:52.620 --> 03:00.660
そこで､ このif条件を作って､ メモリ､ セルフドットメモリの要素数を確認した上で､

03:00.660 --> 03:02.820
注意しましょう｡

03:02.820 --> 03:04.140
ここにちょっとした仕掛けがあるんです｡ 

03:04.140 --> 03:12.330
セルフドットメモリはリプレイメモリクラスのオブジェクトですが､ その後リプレイメモリクラスはメモリである属性を持ちます｡

03:12.330 --> 03:15.240
だから､ 実はセルフメモリーを取る必要があるんです｡ 

03:15.240 --> 03:27.360
そのメモリは､ 1つ目のメモリがリプレイメモリクラスのオブジェクトで､ 2つ目のメモリがここのセルフメモリという属性になります｡

03:27.980 --> 03:36.470
ですから､ もしメモリ内の要素数が100より大きくなるようにしたいのであれば､ 色を付けてください｡ 

03:36.680 --> 03:38.670
そして､ どうなるのでしょうか？

03:38.690 --> 03:45.470
さて､ 学習はできるのですが､ 学習の前に､ この100個の遷移のランダムサンプルを取得する必要があります｡ 

03:45.470 --> 03:48.500
そして､ これはサンプル関数で得ることができます｡ 

03:48.590 --> 03:55.130
そして､ sample関数は異なるバッチを返すので､ 状態の設定時間tは20＋1である｡

03:55.130 --> 03:57.740
アクションは時間tとその時間tの報酬です｡ 

03:57.890 --> 04:03.320
さて､ ここで必要なのは､ 時間tにおける状態のバッチ､ 次の状態のバッチ､ 報酬のバッチ､

04:03.320 --> 04:07.840
行動のバッチのような新しい変数を作ることである｡

04:07.850 --> 04:15.950
そして､ ここで引数につけたのと同じ名前をつけて､ それをここに貼り付ければいいのです｡ 

04:15.950 --> 04:25.950
そして､ これらの変数は､ まさにこれらの状態のバッチを返すので､ サンプル関数が返すものと同じになる｡

04:25.970 --> 04:28.060
次のステート報酬とアクション｡ 

04:28.070 --> 04:33.620
つまり､ 今必要なのは､ 最初にメモリ・オブジェクトを取得することです｡ 

04:33.620 --> 04:40.280
そして､ このメモリオブジェクトから､ 入力として受け取るsampleメソッドを使用することになります｡ 

04:40.280 --> 04:46.250
さて､ そこからAIに学習させたい遷移の数は100です｡ 

04:46.370 --> 04:50.300
そのため､ メモリには100以上のトランジションを持たせるようにしました｡ 

04:50.300 --> 04:54.620
つまり､ 100回の記憶の遷移から学習していくわけです｡ 

04:54.620 --> 04:56.390
だから､ 学習効果が格段に上がるのです｡ 

04:56.390 --> 04:59.450
そして今､ この学びを実現させようというわけです｡ 

04:59.450 --> 05:11.720
さて､ learnメソッドは拡散クラスのメソッドなので､ まあ､ 将来別のクラスから生成されるオブジェクトからこのlearnメソッドにアクセスする必要があります｡

05:11.720 --> 05:14.240
それゆえ､ 取るべきは自分自身なのです｡ 

05:14.240 --> 05:23.690
そのため､ selfはそのオブジェクトをクラスに参照し､ このlearnメソッドとして､ 入力するlearnメソッドを学習します｡

05:23.690 --> 05:30.080
もちろんここにいる連中は､ バッチ状態バッチ､ 次の日付､ バッチの報酬､ バッチのアクション｡ 

05:30.470 --> 05:38.900
これがメモリからサンプリングされたバッチで､ トランジションが100個あるので､ 100個のバッチを取得することができます｡ 

05:38.900 --> 05:46.220
そして､ この100の遷移から､ 100の状態､ 106の状態､ 100の報酬､ 100の行動をとります｡ 

05:47.190 --> 05:49.590
では､ ここでそれを再生してみましょう｡ 

05:49.590 --> 05:51.480
これからが学びの本番です｡ 

05:51.630 --> 05:54.150
このようなランダムなバッチから発生するのです｡ 

05:54.480 --> 05:55.290
完璧です｡ 

05:55.680 --> 06:04.010
そして今必要なのは､ 新しい状態に到達してアクションを実行した後の､ 一番最後の更新です｡

06:04.020 --> 06:11.460
さて､ アクションを再生することができましたが､ まだ自分自身であるアクション､ つまり最後のアクション変数を更新していないのです｡

06:11.460 --> 06:13.530
だから､ これを忘れないようにしよう｡ 

06:13.530 --> 06:14.850
今すぐやりましょう｡ 

06:14.880 --> 06:26.760
我々は､ 最後のアクション自己ドット最後のアクションイコールと､ もちろんここで再生したばかりのアクションをselectアクション機能で更新します｡

06:27.030 --> 06:27.450
わかりました｡ 

06:27.450 --> 06:30.300
では､ 最後のアクションはそれから更新されるのですね｡ 

06:30.300 --> 06:31.680
新国立も同じです｡ 

06:31.680 --> 06:38.400
新しい状態に到達しましたが､ 最後の状態はもちろん20の状態の前なので､

06:38.400 --> 06:40.530
まだ更新していません｡

06:40.530 --> 06:44.760
しかし､ 今は時刻Tプラス1にTプラス1として新しい状態に到達しているので｡ 

06:44.760 --> 06:49.980
さて､ 最後の状態はここでこの新しい状態になるため､ 同様に更新する必要があります｡ 

06:50.010 --> 06:56.040
セルフドットの最後の状態は､ 私たちの新しい状態に等しい｡ 

06:57.120 --> 06:57.940
これでよしとしよう｡ 

06:57.960 --> 06:59.550
そして､ 今度は何を更新する必要があるのか｡ 

06:59.580 --> 07:01.460
さて､ 残るはひとつだけ｡ 

07:01.470 --> 07:03.270
それはもちろん､ ご褒美です｡ 

07:03.420 --> 07:08.060
そして､ その報酬は､ まさに現実に得られる報酬なのです｡ 

07:08.070 --> 07:16.920
これがこのアップデート関数の引数になり､ マップに接続すると､ 最後の報酬になるわけです｡

07:16.920 --> 07:23.210
それが､ この到達した新しい状態でアクションを起こした直後に得られる報酬なのです｡ 

07:23.220 --> 07:28.020
だから､ このままどこかのセントに行くと､ この最後の報酬が悪いマイナス1になってしまうのです｡ 

07:28.140 --> 07:31.950
ゴールから遠ざかれば､ 少しでも良い報酬を得ることができる｡ 

07:31.950 --> 07:33.330
マイナス0です｡  2.

07:33.360 --> 07:38.550
ゴールに近づけば､ ちょっといいご褒美のオープンワンがもらえます｡ 

07:38.550 --> 07:43.320
また､ マップの一辺に近づきすぎると､ まあ､ それは悪い罰になるでしょう｡ 

07:43.320 --> 07:45.180
各エッジでマイナス1ずつを得ることになる｡ 

07:45.210 --> 07:46.980
だから､ それが最後の1枚になるんです｡ 

07:46.980 --> 07:50.610
現実には､ 地図の上でそれがリアルに起こっているのです｡ 

07:50.610 --> 07:53.430
そして､ これがアップデート関数の引数になる｡ 

07:53.430 --> 07:55.920
最後のこの言葉､ まさにこれですね｡ 

07:55.920 --> 08:02.250
そして､ これがupdate関数の引数なので､ この報酬に対応し､

08:02.250 --> 08:13.530
したがって､ このinit関数で最初に初期化された最後の報酬変数が､ 私たちが得る新しい報酬になる自己である｡

08:13.530 --> 08:19.260
現実にはそれが報酬であったり､ 同じように報酬が少なかったりするのです｡ 

08:20.620 --> 08:21.250
わかりました｡ 

08:21.250 --> 08:23.530
そこで､ 今度は最後のご褒美を更新しました｡ 

08:23.710 --> 08:29.650
そして今､ 最後の報酬を手に入れたので､ さて､ 報酬ウィンドウを更新することができます｡ 

08:29.680 --> 08:36.910
ここで､ クラスのオブジェクトの変数の一つとして初期化した報酬ウィンドウを覚えていますね｡ 

08:36.940 --> 08:44.050
それは､ 過去100回の報酬の平均を取ることで､ このトレーニングがどのように進んでいるかを把握するためのウィンドウです｡

08:44.140 --> 08:49.890
つまり､ 報酬の平均がどのように推移しているかを示すスライディングウィンドウのようなものです｡ 

08:49.900 --> 08:55.180
それで､ ちょうど最後の報酬を得たところなので､ まあ､ 報酬ウィンドウを更新すればいいわけです｡ 

08:55.300 --> 08:56.800
それで､ どうやってアップデートするのか｡ 

08:56.830 --> 09:00.550
さて､ この最後の報酬をウィンドウに追加するだけでよいのです｡ 

09:00.550 --> 09:05.200
したがって､ 私がやることは､ 報酬の窓を取ることです｡ 

09:05.200 --> 09:07.490
その報酬の窓口を務める｡ 

09:07.510 --> 09:08.290
これです｡ 

09:08.290 --> 09:12.280
そして､ append関数を使ってみます｡ 

09:12.280 --> 09:16.360
そして､ append関数の内部では､ 要素を入力する必要があります｡ 

09:16.360 --> 09:18.670
リワードウィンドウにアペンドしたい｡ 

09:18.670 --> 09:20.560
そしてそれはもちろん､ ご褒美でもあります｡ 

09:21.400 --> 09:21.760
わかりました｡ 

09:21.760 --> 09:22.440
完璧です｡ 

09:22.450 --> 09:29.800
そして､ この報酬ウィンドウは固定サイズになるため､ ウィンドウが大きくなることはないんですね｡

09:29.800 --> 09:35.200
時間と共にスライドする一定の大きさのウィンドウで､ 報酬の進化を見せることになるのです｡ 

09:35.200 --> 09:38.560
そして､ この窓の大きさを決める必要があります｡ 

09:38.560 --> 09:43.390
そして､ 単純にこのウィンドウで手にする報酬の手段の数です｡ 

09:43.690 --> 09:49.120
それで､ 例えば､ 最後の100語の1000の手段を取得してみましょう｡ 

09:49.120 --> 09:56.200
それで､ それを確認するために､ if then, Len, then we take our rewardを追加するのです｡ 

09:57.020 --> 09:57.740
窓の様子｡ 

09:57.980 --> 10:13.640
そして､ 報酬ウィンドウの要素数が1000より大きい場合､ この報酬ウィンドウの最初の要素を削除することを追加します｡

10:13.640 --> 10:18.230
そして､ この報酬ウィンドウの最初の要素は､ インデックスが0です｡ 

10:19.060 --> 10:19.420
わかりました｡ 

10:19.420 --> 10:24.340
そして今度は､ この報酬ウィンドウが1000以上の要素を得ることがないようにするのです｡ 

10:24.340 --> 10:27.640
それは､ 過去100回の報酬のうち1000回の手段です｡ 

10:27.850 --> 10:28.570
それは完璧だ｡ 

10:28.570 --> 10:34.510
これは､ 報酬の平均が増加しているかどうか､ したがって､ トレーニングがうまくいっているかどうかを確認するために､

10:34.510 --> 10:36.640
一定の大きさのウィンドウとなる｡

10:36.640 --> 10:39.130
そしてそれに応じて､ カードが私たちの思い通りになるなら

10:39.730 --> 10:40.570
完璧です｡ 

10:40.720 --> 10:44.650
そして今､ あなたの言う通り残された小さな小さな一歩を踏み出しました｡ 

10:44.650 --> 10:45.920
どうなるんだろう？

10:45.940 --> 10:57.910
さて､ このupdate関数は､ 報酬ウィンドウの遷移の異なる要素を更新するだけでなく､ この新しい状態に到達したときに再生されたアクションを返すことを覚えておいてください｡

10:57.940 --> 11:02.690
そのため､ マップアクションイコールブレインドットアップデートの中に入っているのです｡ 

11:02.710 --> 11:04.090
最後の言葉､ 最後の合図｡ 

11:04.240 --> 11:10.330
そのため､ 何かを返すことになっており､ 返すことになっているものは､ もちろんアクションです｡

11:10.570 --> 11:16.720
つまり､ ここで必要なのは､ 単純にアクションを返すことだけです｡ 

11:17.080 --> 11:20.020
新しい状態に到達したときに表示されたアクション｡ 

11:20.380 --> 11:21.310
そして､ それだけです｡ 

11:21.520 --> 11:23.600
アップデート機能の準備が整いました｡ 

11:23.620 --> 11:28.990
必要な更新をすべて行い､ 新しい状態になったときにアクションを返します｡ 

11:29.230 --> 11:30.390
それは完璧だ｡ 

11:30.400 --> 11:34.960
それが､ このプロセスの中で､ 最後の難しい行動だった｡ 

11:34.990 --> 11:36.880
あとは子供向けでしょうか｡ 

11:36.910 --> 11:41.800
報酬の平均値と報酬ウィンドウを返すスコア関数を作るだけです｡ 

11:41.980 --> 11:48.520
そして､ アプリケーションを終了してまた戻るときに､ その都度､ 車の頭脳を保存しておくセーブ機能を作っておきます｡

11:48.610 --> 11:54.720
もちろん､ 車に戻ったときに脳をロードできるようにしたいので､ アプリケーションに戻りましょう｡

11:54.730 --> 12:02.320
さて､ 最終的にはsave関数でモデルを保存した後､ モデルをロードするload関数を作ることになります｡

12:02.620 --> 12:06.280
というわけで､ 残すは3機能ですが､ シンプルになりそうです｡ 

12:06.280 --> 12:09.990
そして､ この最初のモジュールの中で最もエキサイティングなセクションを紹介します｡ 

12:10.000 --> 12:11.470
それがデモです｡ 

12:11.500 --> 12:13.650
APIが動作するかどうか確認します｡ 

12:13.660 --> 12:17.980
クルマが目標に到達しているかどうか､ そしてどのように改善できるかを見ていくことになる｡ 

12:17.980 --> 12:21.670
そして､ やがて最初のAIを作ることになるのです｡ 

12:21.940 --> 12:23.890
だから､ 早くデモを始めたいんです｡ 

12:23.920 --> 12:25.810
まずはこの3つの機能を作ってみましょう｡ 

12:25.810 --> 12:27.130
そしてそれまで､ お楽しみに｡ 

12:27.130 --> 12:27.670
I.
