WEBVTT

00:00.240 --> 00:02.550
こんにちは､ このチュートリアルにようこそ｡ 

00:02.580 --> 00:07.680
前のチュートリアルでは､ マップを初期化しましたが､ 次はエキサイティングなことをしましょう｡ 

00:07.680 --> 00:11.190
コアを作り､ それをクラスで行うのです｡ 

00:11.190 --> 00:30.000
もちろん､ このクラスは多くのプロパティを持つものを作成するのに非常に実用的であることはおわかりいただけると思います｡

00:30.480 --> 00:34.920
そこで､ 環境を記述する上で重要な変数をいくつか用意しました｡ 

00:34.920 --> 00:42.120
例えば､ X軸と車の進行方向の軸との角度を表す「角度」があります｡

00:42.480 --> 00:51.240
次に回転ですが､ これはその最後の回転で､ 0度､ 20度､ -20度のいずれかを記憶しています｡

00:51.330 --> 00:57.660
そして､ 速度､ 速度ベクトルのX座標､ 速度ベクトルのY座標があり､

00:57.660 --> 01:02.610
さらに､ 座標速度Xと速度Yのベクトルがある｡

01:03.240 --> 01:07.110
そして､ センサーと信号がありますが､ これがとても重要なのです｡ 

01:07.140 --> 01:13.080
今回作るクルマには､ センサー1､ センサー2､ センサー3というように､ 3つのセンサーが搭載されています｡ 

01:13.200 --> 01:18.090
センサー1は､ 車の前に香りがあるかどうかを検知します｡ 

01:18.240 --> 01:24.060
そして､ センサー2は､ 車の左側に香りがあるかどうかを検知するセンサーです｡ 

01:24.180 --> 01:29.550
そして､ センサー3は､ 車の右側に香りがあるかどうかを検知するセンサーです｡ 

01:29.700 --> 01:37.050
そして､ この3つのセンサーから､ それぞれのセンサーが受信した信号､ つまりシグナルを得るのです｡

01:37.050 --> 01:40.140
つまり､ 信号1はセンサー1が受信した信号ということになります｡ 

01:40.140 --> 01:46.130
信号2はセンサー2が受信した信号で､ 信号3はセンサー3が受信した信号です｡ 

01:46.140 --> 01:47.550
それで､ どのような効果があるのでしょうか？

01:47.580 --> 01:51.660
シグナル1は､ センサー1周辺の送信密度である｡ 

01:51.660 --> 01:57.900
信号2はセンサー2周辺の香りの密度､ 信号3はセンサー3周辺の砂の密度です｡

01:58.020 --> 02:00.500
そして､ この砂の密度はどのように計算するのでしょうか？

02:00.510 --> 02:01.650
まあ､ それはとても簡単なことです｡ 

02:01.650 --> 02:05.910
それぞれのセンサーの周囲に大きな四角をいくつか取ります｡ 

02:05.910 --> 02:08.790
これは､ 実際には200×200の正方形です｡ 

02:08.790 --> 02:14.340
そして､ それぞれのマス目について､ 20×20＝400となるマス目の総数で､

02:14.340 --> 02:17.790
マス目に含まれる1の数を割ります｡

02:17.790 --> 02:22.320
そして､ 砂の密度は､ 砂に対応するものが得られるのです｡ 

02:22.350 --> 02:27.720
これを各センサーごとに行うと､ 各センサーの周りの砂の密度が分かります｡ 

02:27.720 --> 02:29.070
それがシグナルです｡ 

02:29.460 --> 02:29.820
わかりました｡ 

02:29.820 --> 02:35.250
これで砂の検出はすべて完了し､ あとは移動機能ですね｡ 

02:35.310 --> 02:41.280
そしてもちろん､ コアを左に直進させたり右に行かせたりするのは､ ムーブ機能です｡

02:41.730 --> 02:43.140
では､ さっそく見ていきましょう｡ 

02:43.140 --> 02:52.320
ここでは､ コアの位置の更新を､ 最後の位置（ここを通過した自分）と速度ベクトルで行っています｡

02:52.320 --> 02:58.440
つまり､ 速度ベクトルのおかげで､ 位置は速度ベクトルの方向に更新されることになる｡ 

02:58.710 --> 03:05.040
次に､ 回転を取得します｡ これは､ このコードのさらに下にあります｡ 

03:05.160 --> 03:11.010
回転は回転アクションに等しいここで我々は､ アクションを選択し､ 回転を取得します｡ 

03:11.100 --> 03:15.090
そして､ この自転は回転に等しいわけです｡ 

03:15.090 --> 03:21.690
この回転で､ 左や右に行くコアをどう回転させればいいのかがわかります｡

03:22.230 --> 03:29.220
そして､ X軸とコアの方向の軸の間の角度であることを思い出しながら､ 角度を更新します｡

03:29.340 --> 03:35.280
コアが回転すると､ 当然センサーも回転しますから､ rotate関数を使ってセンサーを回転させ､

03:35.280 --> 03:45.420
そこに新しい位置を追加する必要があるのです｡

03:45.480 --> 03:48.870
そして､ なぜこのベクトルが30ゼロになるのか｡ 

03:48.870 --> 03:53.910
まあ､ それは単純に30がコアとセンサーの距離だからなんですけどね｡ 

03:53.910 --> 03:58.380
コアとコアが検出するものとの距離のことですね｡ 

03:58.980 --> 04:04.050
そして､ センサーが更新されると､ 今度は信号が更新されるわけです｡ 

04:04.050 --> 04:07.020
そして､ ここでは､ 私が説明したとおりの方法で､ 信号を計算します｡ 

04:07.020 --> 04:12.840
センサーのX座標を取得し､ マイナス10からプラス10までのすべてのセルを取得します｡ 

04:13.170 --> 04:18.840
次に､ Y座標についても同様に､ マイナス10からプラス10までのすべてのセルを取り出します｡ 

04:18.840 --> 04:28.020
そこで､ センサーを囲む20×20画素の正方形を求め､ この正方形の中ですべての1の値を合計するのです｡

04:28.020 --> 04:32.820
つまり､ 基本的には､ セルには0か1のどちらかが含まれているので､ すべてのセルを合計します｡ 

04:32.820 --> 04:37.950
そして､ 20×20の2乗には20×20＝400個のセルがあるので｡ 

04:37.950 --> 04:43.230
さて､ これを400で割ると､ 正方形の中に一度だけ入る密度が求まる｡ 

04:43.230 --> 04:48.300
こうして､ センサーの周りの細胞の密度を示す信号が得られるのです｡ 

04:48.300 --> 04:54.840
そして､ 2つ目のセンサーと3つ目のセンサーにも同じようにして､ 2つ目の信号と3つ目の信号を得ることができました｡

04:54.960 --> 04:55.190
なるほど｡ 

04:55.290 --> 04:56.760
つまり､ 感覚を察知することですね｡ 

04:56.760 --> 05:00.060
それから､ ここの3行のコードがとても重要です｡ 

05:00.060 --> 05:06.060
これも､ クルマがマップの端に到達したときに与えたい､ 悪い報酬のひとつです｡

05:06.390 --> 05:14.250
私たちは､ クルマが壁に突進するのを防ぎたいので､ 壁に近づきすぎたときにペナルティを課したいと思っています｡

05:14.400 --> 05:16.230
それゆえ､ ここではそのようなことをするのです｡ 

05:16.410 --> 05:25.110
最初のセンサーが長さマイナス10より大きければ､ ここが長いからここより大きいということです｡

05:25.110 --> 05:27.360
だから､ もっと長く､ マイナス10がここにある｡ 

05:27.360 --> 05:34.110
だから､ もしセンサー1×が長いより大きければ､ マイナス10はここにあるすべてのポイントを懸念し､

05:34.110 --> 05:41.470
車がマップの右端に近づいている場合､ または自己センサー1×が10より低い場合である｡

05:41.490 --> 05:42.420
それがここなんですね｡ 

05:42.420 --> 05:49.080
車がマップの左端に近づいてきたり､ センサーYが大きめマイナス10より大きくなったら､

05:49.080 --> 05:51.810
マップの上端です｡

05:51.870 --> 05:57.960
また､ あるいは自己センサーyが10より小さい場合は､ そこがマップの下辺となる｡ 

05:58.470 --> 06:06.360
そして､ センサー1がこの4つのエッジのいずれかに到達していれば､ センサーの信号を入れることになるわけです｡

06:06.360 --> 06:08.430
信号1は､ センサー1の信号です｡ 

06:08.550 --> 06:10.260
1になるように設定します｡ 

06:10.260 --> 06:11.400
それはどういうことなのか？

06:11.400 --> 06:15.330
それは､ 香りの密度を高めるようなフルセンドということです｡ 

06:15.360 --> 06:17.100
最悪の事態を招いてしまったようなものです｡ 

06:17.100 --> 06:19.440
車が止まってしまうという感覚はすごくありますね｡ 

06:19.440 --> 06:23.940
だから信号が1つになり､ したがって車はひどく悪い報酬を得ることになる｡ 

06:24.300 --> 06:24.720
わかりました｡ 

06:24.720 --> 06:29.520
そして､ センサー2とセンサー3からの信号2､ 信号3についても同じようにしました｡ 

06:30.280 --> 06:30.730
わかりました｡ 

06:30.730 --> 06:32.950
そして､ ゲームクラスを作成します｡ 

06:32.950 --> 06:38.050
というわけで､ ここまでは車しか作っていないので､ 基本的にはゲームを作るためのクラスです｡ 

06:38.200 --> 06:44.380
そして今度は､ もちろんマップも作らなければならないし､ ゲーム自体も作らなければならないので､ ゲームをするわけではありません｡

06:44.380 --> 06:46.690
ゲームをするのは､ 私たちのAIです｡ 

06:46.690 --> 06:52.030
そして､ 実際に障害物を避けながら､ 空港から繁華街へ､ あるいはその逆へと移動するゲームです｡ 

06:52.270 --> 07:01.690
このゲームクラスでは､ 車のようなオブジェクトをいくつか作成し､ 次に最も重要な更新関数を定義する必要があります｡

07:01.690 --> 07:12.040
というのも､ この更新機能で､ 目標達成のために車が行うべき行動をその都度選択することになるからです｡

07:12.040 --> 07:20.470
そして､ この行動こそが､ 私たちの人工知能の核となるニューラルネットワークの出力となるのです｡

07:20.770 --> 07:29.620
そして､ このアクションは車の脳から返されます｡ これは､ AIファイルで作ることになる現在のクラスのオブジェクトであることを思い出してください｡

07:29.650 --> 07:37.120
このオブジェクトは update と呼ばれるメソッドを持っており､ 最後の報酬と最後のシグナルを入力として受け取ります｡

07:37.390 --> 07:40.930
だから､ 最後の報酬はもちろん､ クルマが得た最後の報酬である｡ 

07:40.930 --> 07:45.490
そして最後の信号は､ もちろん3つのセンサーのうち最後の信号です｡ 

07:45.490 --> 07:51.160
センサー1からの信号1､ センサー2からの信号2､ センサー3からの信号3｡ 

07:51.160 --> 07:56.710
しかし､ それ以外に2つの入力を追加しています｡ それは､ ゴールに対する車の向きです｡ 

07:56.710 --> 08:01.510
そのため､ 例えば車がゴールに向かっている場合､ 向きは0に等しくなる｡ 

08:01.510 --> 08:06.550
少し右に寄ると､ 45度に近い向きになります｡ 

08:06.640 --> 08:11.200
また､ 少し左に行くと､ 向きは-45度に近くなります｡ 

08:11.710 --> 08:15.160
つまり､ これが入力状態の4番目の入力です｡ 

08:15.160 --> 08:18.760
そして､ 最後の入力は､ マイナス方向です｡ 

08:18.760 --> 08:22.480
つまり､ 通常､ ニューラルネットワークの入力は独立である｡ 

08:22.480 --> 08:29.230
線形性はありませんが､ ニューラルネットワークが重みで修正するだけなので､ これを追加してもあまり意味がありません｡

08:29.230 --> 08:37.750
それでも､ このマイナス方向を加えることで､ まあ､ 車の訓練で探索を安定させることができることに気がつきました｡

08:37.750 --> 08:42.550
AIがいつも同じ方向に探索しないように､ こうしているわけです｡ 

08:42.550 --> 08:48.640
このマイナスの向きをつけることで､ 右にも左にも探索できるようにしています｡ 

08:48.640 --> 08:55.720
そして､ この3つの信号､ プラス方向とマイナス方向が､ エンコードされたベクトルの5つの入力となり､

08:55.720 --> 08:58.810
ネットワークに入ることになるのです｡

08:58.810 --> 09:02.380
これがネットワークに入る入力ベクトルです｡ 

09:02.620 --> 09:10.450
そして､ それがネットワークに入った後､ まあ､ ネットワークがアウトプットを返すわけですが､ これがその都度再生するアクションになるわけです｡

09:10.450 --> 09:16.450
そして､ この更新関数が返す出力には､ ネットワークそのものと､ ネットワークの出力が含まれる｡

09:16.720 --> 09:26.110
そのため､ 入力状態である最後の信号と､ 少ない報酬を入力しなければなりません｡

09:26.820 --> 09:27.180
わかりました｡ 

09:27.180 --> 09:37.230
そして､ 区の平均スコアを更新し､ 回転を更新し､ 移動関数を使って､ 選択された行動に従って車を回転させます｡

09:37.230 --> 09:43.410
ゴールまでの車の距離を更新し､ センサーの位置を更新していくのです｡ 

09:43.410 --> 09:48.270
1球､ 2球､ 3球とも､ 地図上のセンサーを表す球に相当します｡ 

09:48.270 --> 09:49.770
それはすぐにわかると思います｡ 

09:50.400 --> 10:04.000
というのも､ この部分は､ クルマが砂の上に乗ってしまった場合にペナルティを課す場所だからです｡

10:04.020 --> 10:06.350
そこで､ その速度を落とすのです｡ 

10:06.360 --> 10:09.900
このように､ 速度が6になるのが普通なんですね｡ 

10:09.900 --> 10:12.570
そして､ それがどこかの砂の上に行けば､ 1つになる｡ 

10:12.570 --> 10:14.250
だから､ 1つに減速されるのです｡ 

10:14.250 --> 10:17.550
砂地に入ると､ 車が減速するのがわかると思います｡ 

10:17.850 --> 10:21.720
だから遅くなるし､ しかも悪い報酬を得ることになる｡ 

10:21.720 --> 10:23.670
マイナス1点の報酬を得る｡ 

10:23.670 --> 10:25.950
そしてそれは､ 実は最悪の報酬なのです｡ 

10:25.950 --> 10:27.510
最高のご褒美は1つ｡ 

10:27.540 --> 10:31.770
最悪の報酬はマイナス1､ 報酬はマイナス1～プラス1の間です｡ 

10:32.400 --> 10:39.150
そうでなければ､ 砂の上でなければ､ いつもの速度､ 6速のままです｡ 

10:39.270 --> 10:40.890
そして､ さらに何かを追加する｡ 

10:40.890 --> 10:45.660
もしそれがゴールに近づいているのなら､ 少しプラスの報酬を得ることができます｡ 

10:45.660 --> 10:52.530
そして､ ゴールから遠ざかると､ まあ､ マイナス0という少しマイナスの報酬が発生するわけです｡  2.

10:53.380 --> 10:57.180
そして､ 最後に報酬に関わる条件です｡ 

10:57.190 --> 11:02.710
それは､ 先ほどお話したように､ コアがエッジのひとつに近づきすぎている場合です｡ 

11:02.740 --> 11:04.920
フルサンドの話をしたのを覚えていますか？

11:04.930 --> 11:11.000
まあ､ コアがマップの左端に近づきすぎている場合は､ 報酬がマイナス1されるんですけどね｡ 

11:11.020 --> 11:15.250
マップの右端に近づきすぎると､ 2マイナス1の報酬が発生します｡ 

11:15.400 --> 11:20.050
また､ マップの下端に近づきすぎると､ 報酬がマイナス1されます｡ 

11:20.050 --> 11:25.150
そして､ マップの左上に近づきすぎると､ 報酬がマイナス1されます｡ 

11:25.150 --> 11:27.360
だから､ それはひどい仕打ちだ｡ 

11:27.370 --> 11:31.180
そうすれば､ 他のことに急がないことを､ いかに早く学習するかがわかるでしょう｡ 

11:31.750 --> 11:32.170
わかりました｡ 

11:32.170 --> 11:36.430
そして､ ゴールに到達したときに更新するものです｡ 

11:36.430 --> 11:40.930
つまり､ 車が最初のゴールである空港に到着すると､ そこは地図の左上で､ 一方ゴールは地図の右下､

11:40.930 --> 11:47.470
つまりダウンタウンに変わるわけですが､ ここではまさにそれをやっているわけです｡

11:47.470 --> 11:55.030
ゴールのX座標とY座標を更新し､ 車からゴールまでの距離を更新しています｡

11:55.720 --> 11:56.170
わかりました｡ 

11:56.170 --> 11:58.180
そうすると､ あまり重要ではなくなりますね｡ 

11:58.180 --> 12:08.020
これは､ 洞窟に関連する道路や障害物を地図上に描けるようにするためのペイントツールを追加するためのクラスです｡

12:08.050 --> 12:09.400
よかったら見てみてください｡ 

12:09.400 --> 12:17.320
このコードのコミコミ版を提供し､ さらに深くSky Vでやるならどうすればいいのか､ リファレンスを提供します｡

12:17.320 --> 12:22.510
でも､ 人工知能からさらに進んでいるので､ その詳細は割愛します｡

12:22.600 --> 12:26.860
そして､ この最後のコードセクションも同じように､ car app クラスを使用しています｡ 

12:26.860 --> 12:31.240
それは､ APIのボタン､ クリア､ セーブ､ ロードを追加するだけです｡ 

12:31.240 --> 12:32.710
だから､ ここではそうしているのです｡ 

12:32.710 --> 12:34.720
キャンバス保存をクリアする｡ 

12:34.720 --> 12:36.010
そしてそれは､ 実はとても重要なことなのです｡ 

12:36.010 --> 12:43.150
ロード機能とは､ 車の頭脳をロードするために地図上に追加した別のツールで､

12:43.150 --> 12:51.730
車のメモリ､ つまり地図上でのナビゲーション方法をロードするためのものです｡

12:52.000 --> 13:00.430
そして最後に､ 全体を動かす最後のコードセクション､ つまりマップとAIそのものを動かすコードです｡

13:00.700 --> 13:03.280
そして､ 実は今､ それを実行しようとしているのです｡ 

13:03.310 --> 13:06.730
このコードで作るものをすべて見てみましょう｡ 

13:06.730 --> 13:10.300
だから今はAIは実装されていない｡ 

13:10.300 --> 13:13.780
そのため､ コードは非常にランダムな動きをすることになります｡ 

13:13.780 --> 13:15.850
実際に昆虫のように見えるでしょう｡ 

13:15.850 --> 13:17.590
しかし､ 心配しないでください､ 私たちはそれを解決します｡ 

13:17.590 --> 13:26.320
実際のクルマと同じように動くように訓練するだけでなく､ 道路に沿ったり､ 障害物を避けたりするナビゲーションを訓練します｡

13:26.320 --> 13:27.550
では､ こうしてみましょう｡ 

13:27.550 --> 13:32.230
全部選択して実行する｡ 

13:32.230 --> 13:35.050
そして､ こちらが地図で､ こちらが車です｡ 

13:35.530 --> 13:35.980
わかりました｡ 

13:35.980 --> 13:41.380
だから､ ここに小さく見える昆虫のようなものが私たちの車なんです｡ 

13:41.380 --> 13:45.940
だから､ さっきも言ったように､ 行動はまったくランダムなんです｡ 

13:45.940 --> 13:53.530
そのため､ 車は各時刻に左へ直進するか右へ直進するかを行動でランダムに選択します｡ 

13:53.680 --> 13:58.720
だからナンセンスな動きをするわけで､ それが昆虫のように見えるわけです｡ 

13:59.170 --> 14:01.420
だから､ それはもちろん修正します｡ 

14:01.420 --> 14:08.050
そしてもちろん､ AIが起動しているので､ まあ､ ここの空港であるゴーや､

14:08.050 --> 14:12.910
地図の右下にあるダウンタウンには行きません｡

14:13.520 --> 14:21.500
そして､ このAIをこのコアやこの昆虫に実装するように､ Iを作ることですべてを解決します｡ 

14:21.500 --> 14:26.350
ここに3つのボール､ 黄色いボール､ 赤いボール､ 白いボールがあるのがわかりますね｡ 

14:26.360 --> 14:28.070
これが私たちの3つのセンサーです｡ 

14:28.070 --> 14:32.480
そのため､ 周囲に何らかの香りがあれば､ それを感知することになります｡ 

14:32.480 --> 14:35.480
そして､ 香りといえば......そう､ 投げましょう｡ 

14:35.480 --> 14:41.540
そのためには､ ここを左クリックすればいいんです｡ 

14:42.440 --> 14:45.220
左クリックしたまま送信を描いたり｡ 

14:45.230 --> 14:50.000
だから､ 今は砂を足していますが､ もっと足せばいいんです｡ 

14:50.000 --> 14:55.370
つまり､ 砂を追加するたびに､ ご覧のように砂の配列に1個ずつ追加されていくわけです｡ 

14:55.370 --> 14:59.780
これが砂の配列で､ これが原点のゼロゼロ座標です｡ 

14:59.900 --> 15:01.850
そして､ ここにはたくさんのものがあります｡ 

15:01.850 --> 15:03.920
そして､ ご覧のように､ まあ､ いい感じです｡ 

15:03.920 --> 15:07.130
車はそのまま砂の上に乗ってしまい､ スピードが落ちてしまった｡ 

15:07.400 --> 15:14.780
ですから､ ご覧の通り､ 砂の上に乗っているため､ 本当にスピードが落ちています｡

15:16.130 --> 15:23.900
そこで､ いくつかの道路を描き､ 空港からダウンタウンまでの道路を描き､ 車が道路にとどまり､

15:23.900 --> 15:27.890
障害物を避けるように訓練します｡

15:28.310 --> 15:28.760
わかりました｡ 

15:28.760 --> 15:31.940
そして､ ご覧の通り､ 砂を取り除くクリアボタンがあります｡ 

15:31.970 --> 15:37.100
車の脳を保存するための保存ボタンがあります｡ 

15:37.100 --> 15:44.570
そして実は､ 目を救う､ モデルを救う､ 実はクルマの脳を救う､ お話したスコアカーブがあるのです｡

15:44.780 --> 15:50.870
そして､ コードから離れたり､ コンピュータの電源を切ったりして､ また戻りたいときには､

15:50.870 --> 16:01.010
ロードボタンでモデルをロードする､ つまり脳をロードすることで､ 車の訓練された目を得ることができます｡

16:01.640 --> 16:02.150
わかりました｡ 

16:02.150 --> 16:05.930
だから今は､ 早くIを作り始めたいんです｡ 

16:05.960 --> 16:07.300
これは楽しみですね｡ 

16:07.310 --> 16:13.850
ニューラルネットワークを作り､ 車が思い通りに動かなくなったらすぐに罰を与える｡ 

16:13.880 --> 16:16.160
では､ 次のチュートリアルからやってみましょう｡ 

16:16.160 --> 16:17.770
そしてそれまで､ お楽しみに｡ 

16:17.780 --> 16:18.320
I.
