WEBVTT

00:00.330 --> 00:02.640
こんにちは､ このPythonチュートリアルへようこそ｡ 

00:02.670 --> 00:05.400
さて､ これから非常にエキサイティングなチュートリアルが待っています｡ 

00:05.430 --> 00:08.830
まず､ ニューラルネットワークのアーキテクチャを作るところから始めます｡ 

00:08.850 --> 00:16.230
つまり､ AIの核となる､ その都度再生するアクションを返すニューラルネットワークを作るのです｡

00:16.230 --> 00:16.490
ほらね｡ 

00:16.740 --> 00:17.970
では､ こうしてみましょう｡ 

00:17.970 --> 00:22.950
そこで､ ニューラルネットワークをオブジェクトにしたいので､ クラスを作ることにします｡ 

00:22.950 --> 00:25.020
そして､ その方がずっと便利だからです｡ 

00:25.170 --> 00:28.280
Know a classは､ 私たちが作りたいもののモデルなのです｡ 

00:28.290 --> 00:34.820
ニューラルネットワークを作りたいのですが､ そのためには､ すべてクラスに含まれるような何らかの命令を作る必要があります｡

00:34.830 --> 00:37.740
そして､ この授業では､ 2つの関数を作ることにします｡ 

00:37.740 --> 00:43.050
まず､ init関数ですが､ これはクラスを作るときにいつも出てくる関数で､

00:43.050 --> 00:46.500
基本的にオブジェクトの変数を定義します｡

00:46.500 --> 00:52.410
それがニューラルネットワークで､ グローバル変数とは対照的に､ オブジェクトにアタッチされた変数がありますよね｡

00:52.590 --> 00:57.840
そして､ このinit関数でニューラルネットワークのアーキテクチャを定義します｡

00:57.840 --> 01:03.630
入力状態の符号化ベクトルが5次元なので､ 5つの入力ニューロンで構成される入力層を定義し､

01:03.630 --> 01:07.920
次にいくつかの隠れ層を定義することになります｡

01:07.920 --> 01:13.950
まずは1つの隠れ層から始めて､ 他のニューラルネットワークのアーキテクチャを試してみるのもいいかもしれませんね｡

01:13.950 --> 01:21.780
そしてもちろん､ 最終的には出力レイヤーに､ 各時刻に再生可能なアクションが格納されます｡

01:21.990 --> 01:24.570
ですから､ このinit関数で行うのはまさにこれです｡ 

01:24.570 --> 01:30.390
そして､ クラスの中にもう一つ関数を作ります｡ これが前進関数で､ ニューラルネットワークのニューロンを活性化する関数です｡

01:30.390 --> 01:37.290
つまり､ 信号を活性化する関数です｡

01:37.290 --> 01:46.710
もちろん純粋に非線形な問題を扱っているので､ 整流器活性化関数を使いますが､ この整流器関数は線形性を壊してしまいます｡

01:46.950 --> 01:53.280
しかし､ ほとんどの場合､ このフォワード関数はニューラルネットワークの出力であるQ値を返すように作っています｡

01:53.280 --> 02:03.810
しかし､ 各アクションに対して1つのキュー値を持っており､ 後でキュー値の最大値を取るか､ ソフトマックス法を用いて最終的なアクションを返すことになる｡

02:03.810 --> 02:05.190
それは追々見ていくとして｡ 

02:05.190 --> 02:12.360
そこで､ このチュートリアルでは､ まずinit関数を実装し､ 次回はforward関数を実装する予定です｡

02:12.600 --> 02:13.710
では､ こうしてみましょう｡ 

02:13.710 --> 02:16.980
まず､ クラスの紹介をする必要があります｡ 

02:16.980 --> 02:18.180
そこで､ まずは授業から｡ 

02:18.180 --> 02:22.800
そして､ このクラスに名前を付けます｡ まあ､ networkと呼ぶこともできます｡ 

02:23.400 --> 02:34.980
そして､ このネットワーククラスでは､ 継承と呼ばれるオブジェクト・プログラミングのテクニックを使います｡

02:34.980 --> 02:43.950
つまり､ これから作るネットワーク・クラスは､ より大きなクラスであるRN DOTモジュールの子クラスなのです｡

02:44.250 --> 02:51.660
つまり､ このモジュールクラスのすべてのツールを継承することで､ もちろんニューラルネットワークを実装するためのツールになるわけです｡

02:51.660 --> 02:57.720
これは､ オブジェクト指向プログラミングにおける非常に強力で効率的なトリックで､ 継承と呼ばれているんですね｡ 

02:57.720 --> 03:02.310
そして今､ このモジュールの親クラスを継承しています｡ 

03:02.610 --> 03:03.360
わかりました｡ 

03:03.360 --> 03:05.910
そして､ これでクラスの中に入る準備ができました｡ 

03:05.910 --> 03:14.040
というわけで､ 実はエンターキーを2回押しています｡ 2つの関数を作るので､ まずはinit関数からです｡

03:14.040 --> 03:20.370
init関数は､ アンダースコアを2つ使って､ このように名前を付けなければなりません｡ 

03:20.370 --> 03:28.440
そしてまたアンダースコアにするのはPythonの構文で､ そうしなければならないだけで､ 引数を入力する必要があります｡

03:28.440 --> 03:30.180
というわけで､ 3つの主張があります｡ 

03:30.180 --> 03:35.700
1つ目は､ 実は自己と自己という強制的な論法です｡ 

03:35.700 --> 03:42.750
これから作るこのクラスから生成されるオブジェクトを指すというのは､ 不思議とありません｡

03:42.750 --> 03:44.280
この授業は､ 私たちが作っているんですよ｡ 

03:44.280 --> 03:48.900
これは､ 私たちが構築したいニューラルネットワークのモデルであり､ 命令のようなものです｡ 

03:48.900 --> 03:53.400
そして､ 授業の準備が整ったら､ 好きなだけニューラルネットワークを作ればいいのです｡ 

03:53.400 --> 03:57.450
そして､ これらのニューラルネットワークは､ それぞれこのクラスの何らかのオブジェクトになる｡ 

03:57.600 --> 04:05.670
そして､ このオブジェクトを他の目的で使用することになるので､ オブジェクトの変数が何であるかを特定する必要があります｡

04:05.670 --> 04:11.820
そして､ これを見破るために､ このselfを使って､ オブジェクトを参照していることを指定しているのです｡ 

04:11.820 --> 04:20.400
そこで､ 自分のオブジェクトの変数を使いたいときは､ 変数の前に self を使って､ これがオブジェクトの変数であることを指定することにします｡

04:21.180 --> 04:21.480
わかりました｡ 

04:21.480 --> 04:22.770
それが第一の主張ですね｡ 

04:22.770 --> 04:30.120
そして､ もう一つの引数は､ もちろん入力ニューロンの数と出力ニューロンの数である｡

04:30.300 --> 04:34.170
そこで､ 入力ニューロンの数､ これを入力サイズと呼ぶことにします｡ 

04:35.430 --> 04:44.730
入力ベクトルは､ 3つの信号＋方向＋マイナス方向の5次元ですから､ 実際には5つです｡

04:44.880 --> 04:50.970
これが､ 環境の1つの状態を表す､ 符号化された値のベクトルです｡ 

04:51.000 --> 04:54.750
この5つの値だけで､ 環境の状態を表現することができるのです｡ 

04:54.750 --> 04:59.400
より少ない価値観や､ より多くの価値観を考えることもできたのですが､ それを試してみたのです｡ 

04:59.400 --> 05:05.300
そして､ 実際には､ 左から1つ､ 前から1つ､ 右から1つの信号が必要なので､ 理にかなっています｡

05:05.310 --> 05:12.090
車を運転するとき､ 360の信号､ つまりGoogleカーの上部にある信号のようなものにすればよかったんです｡

05:12.090 --> 05:15.510
でも､ 3つのセンサーで完全に自動運転ができるんです｡ 

05:15.780 --> 05:22.050
そして､ このオリエンテーションとマイナス・オリエンテーションで､ 目指すゴールを把握するのです｡

05:22.290 --> 05:28.680
そして､ もちろん､ 行動に対応するニューラルネットワークの出力ニューロンがあります｡ 

05:28.680 --> 05:32.700
そして､ 左回り､ 直進､ 右回りの3つのアクションが考えられます｡ 

05:32.700 --> 05:36.240
それゆえ､ 私はそれを呼んでアクションとするつもりです｡ 

05:36.240 --> 05:37.800
そして､ その数は3人になります｡ 

05:38.370 --> 05:38.670
わかりました｡ 

05:38.670 --> 05:46.110
でも､ ここまでは入力に名前をつけるだけで､ あとはその変数を使ってニューラルネットワークの中で計算をします｡

05:46.930 --> 05:48.400
よし､ それなら

05:49.000 --> 05:52.150
まずはPyTorchの別のトリックを使ってみることにします｡ 

05:52.180 --> 05:54.340
この仕掛けがスーパーファンクションです｡ 

05:54.460 --> 05:59.170
これは､ 実はRNモジュールを継承した機能なんです｡ 

05:59.170 --> 06:02.560
そのため､ モジュールツールの継承を行う必要があったわけです｡ 

06:02.560 --> 06:04.300
これは､ 私たちが最初に使うツールです｡ 

06:04.300 --> 06:11.320
そして､ 基本的には､ このスーパートリック､ スーパーファンクションを使って､ モジュールのツールを使えるようにしているだけなのです｡

06:11.380 --> 06:13.060
だから､ その方がずっと効率的なんです｡ 

06:13.450 --> 06:18.280
そして､ このスーパーファンクションの中で､ 最初にネットワークを指定する必要があるんだ｡ 

06:18.400 --> 06:24.460
これがネットワークの子クラスで､ モジュールの親クラスとオブジェクトを継承して､

06:24.460 --> 06:35.020
ドットやイニシャル関数を追加しています｡

06:35.380 --> 06:35.740
わかりました｡ 

06:35.740 --> 06:46.150
これは､ そのモジュールのすべてのツールを使用するだけのトリックで､ 次のステップである入力レイヤーの指定に進むことができるわけです｡

06:46.300 --> 06:53.230
つまり､ 基本的に私がしなければならないのは､ オブジェクトにアタッチされる新しい変数を導入し､

06:53.230 --> 06:56.950
この変数に入力ニューロンの数を格納することです｡

06:56.950 --> 07:00.160
だから､ 入力サイズと混同しないように｡ 

07:00.160 --> 07:10.270
入力サイズはinit関数の引数ですが､ それはまだオブジェクトにアタッチされる変数ではありません｡

07:10.270 --> 07:15.190
さて､ 先ほど述べたように､ 代わりにオブジェクトにアタッチされることを指定する必要があります｡ 

07:15.190 --> 07:22.000
そこで､ selfドットを使って､ オブジェクトに付けられたこの最初の変数に名前を付けています｡ 

07:22.000 --> 07:24.730
それで､ 入力と同じ名前をつければいいのです｡ 

07:24.730 --> 07:32.980
これをinput sizeと呼び､ init関数の引数がinput sizeであることと等しいとすることができる｡

07:33.520 --> 07:33.880
わかりました｡ 

07:33.880 --> 07:39.430
したがって､ ネットワーク・クラスからオブジェクトを作成し､

07:39.430 --> 07:45.190
入力サイズを指定するたびに､ たとえば5を入力すると､ ここには5があるので､

07:45.190 --> 07:54.850
オブジェクトの入力サイズ変数には5という値が設定されることになります｡

07:55.300 --> 07:55.690
わかりました｡ 

07:55.690 --> 08:01.990
そして､ これはオブジェクトにアタッチしたい他の変数についても同じです｡ 

08:01.990 --> 08:07.930
そして､ ご想像の通り､ これは出力ニューロンの数を表す変数になります｡ 

08:08.080 --> 08:15.040
そして､ オブジェクトのselfを取り､ このオブジェクトの2番目の変数に名前をつけて､ それを呼び出すと､

08:15.040 --> 08:17.620
アクションになるのです｡

08:17.950 --> 08:24.220
そして､ これはこの引数と同じになり､ アクションの数､ つまり出力ニューロンの数を与えます｡

08:24.220 --> 08:28.060
そして､ それをイコールとし､ アクションとするのです｡ 

08:28.150 --> 08:30.640
つまり､ actuallyとbe actionは3つになる｡ 

08:30.640 --> 08:37.480
したがって､ ネットワークへのオブジェクトに付属する変数とアクションは､ 3という値を得ることになります｡ 

08:38.080 --> 08:39.670
実は､ ここに警告を見ることができるのです｡ 

08:39.670 --> 08:47.470
これは､ RNのショートカットを使っているからで､ このショートカットを使って､ 最後のmoduleのところで使うようにすれば､

08:47.470 --> 08:52.690
消えます｡

08:52.690 --> 08:53.470
さあ､ どうぞ｡ 

08:53.500 --> 08:54.340
完璧です｡ 

08:54.340 --> 08:55.840
今､ 私たちは警告を発していません｡ 

08:55.840 --> 09:01.420
ここでの警告はすべて､ インポートしたものがまだ使われていないことを指定するためのものです｡ 

09:01.420 --> 09:02.020
でも､ それでいいんです｡ 

09:02.020 --> 09:03.940
この後､ 使用する予定です｡ 

09:04.510 --> 09:07.870
よし､ ではもう2つ変数を用意しよう｡ 

09:07.870 --> 09:09.880
4つのオブジェクトを定義したいと思います｡ 

09:09.880 --> 09:16.510
そしてこれが､ ニューラルネットワークの異なる層間の完全な接続となります｡

09:16.510 --> 09:23.380
つまり､ 今は隠れ層1つだけで構成されるニューラルネットワークを作りたいので､ まあ完全な接続が2つあることになりますね｡

09:23.380 --> 09:32.200
入力層と隠れ層の間には1/1の完全な接続があり､ 隠れ層と出力層の間には1/2の完全な接続があることになる｡

09:32.200 --> 09:34.630
では､ まず最初にフル接続するところから始めましょう｡ 

09:34.630 --> 09:37.900
FC1ということにしています｡ 

09:37.900 --> 09:43.420
また､ ここでもselfを使って､ FC oneが私のオブジェクトの変数であることを指定しています｡ 

09:43.570 --> 09:45.190
だから､ そのFC1をセルフで｡ 

09:45.800 --> 09:47.440
と同じになる｡ 

09:47.450 --> 09:53.870
そして今度はRNモジュールを使って､ linearという関数を使ってみます｡ 

09:54.020 --> 10:01.580
そして､ まさにこの入力層のニューロンと隠れ層のニューロンとの間の完全な接続を行うためです｡

10:01.940 --> 10:03.910
そして､ フル接続とはどういうことでしょうか？

10:03.920 --> 10:09.770
つまり､ 入力層のすべてのニューロンは､ すべて隠れ層のすべてのニューロンに接続されることになる｡

10:09.980 --> 10:16.010
そこで､ この完全な接続を行うために､ いくつかの引数を入力する必要があるこの一次関数を使用します｡ 

10:16.010 --> 10:19.670
そして､ これらの主張はご覧の通り､ 特徴としてあります｡ 

10:19.670 --> 10:23.800
つまり､ これが接続したい第1層のニューロン数です｡ 

10:23.810 --> 10:28.400
次にout featuresですが､ これは2層目のニューロンを接続したい数です｡ 

10:28.400 --> 10:32.240
右側の層が隠れ層で､ バイアスは真に等しい｡ 

10:32.270 --> 10:33.470
偏っているイコール真実ということですね｡ 

10:33.500 --> 10:39.440
バイアスを持つためにデフォルト値を維持し､ ニューロンを取り付ける方法だけでなく､

10:39.440 --> 10:43.130
各層に重みと1つのバイアスを持つことにします｡

10:43.370 --> 10:46.040
というわけで......さて､ 何を入力すればいいのか､ 見てみましょう｡ 

10:46.040 --> 10:51.770
つまり､ featuresの最初の引数は､ 入力層の入力ニューロンの数である｡ 

10:51.770 --> 10:52.820
それで､ 何なんですか？

10:52.820 --> 10:54.860
まあ､ 実際には入力サイズなんですけどね｡ 

10:54.860 --> 11:03.440
これがinit関数の引数で､ 後で3つの信号の向きとマイナスの向きを5つずつ等しくすることになります｡

11:03.950 --> 11:04.880
それでは､ どうぞ｡ 

11:04.910 --> 11:08.780
第1引数の入力サイズを入力する｡ 

11:09.700 --> 11:12.730
そして､ 2つ目の論点は､ 機能に関するものです｡ 

11:12.730 --> 11:20.120
つまり､ 2層目､ つまり1層目に完全に接続される2層目に欲しいニューロンの数です｡

11:20.140 --> 11:24.820
そこで問題は､ この隠れ層に何個のニューロンを入れるかです｡ 

11:25.000 --> 11:27.340
まあ､ パラメータのチューニングはかなりやりましたね｡ 

11:27.340 --> 11:28.930
いろいろと実験してみたんです｡ 

11:28.930 --> 11:31.870
それがAIであったり､ ディープラーニングであったりするわけです｡ 

11:31.870 --> 11:38.890
一般的には､ 特定の問題に対してどのようなニューラルネットワークが最適なのか､ 多くの実験を行います｡

11:38.890 --> 11:44.980
それで､ いろいろな値を試して､ 最終的に隠れ層のニューロンを30個､ 30個にしました｡ 

11:44.980 --> 11:48.160
そして､ この数字で､ かなり良い結果が得られることがおわかりいただけると思います｡ 

11:48.160 --> 11:51.520
でもそれなら､ ニューラルネットワークのアーキテクチャを自由に変えてもいい｡ 

11:51.520 --> 11:52.870
自由に遊んでみてください｡ 

11:52.870 --> 11:57.460
隠れ層の隠れニューロンの数を変えるだけでなく､ さらにいくつかの層を追加することで､

11:57.460 --> 12:01.090
より良い車を得ることができるかもしれません｡

12:01.090 --> 12:05.740
しかし､ 3000個のニューロンは､ 良いニューラルネットワークと良い車を手に入れることができます｡ 

12:05.740 --> 12:07.270
だから､ それを目指すのです｡ 

12:07.270 --> 12:08.320
そして､ そこに行く｡ 

12:08.320 --> 12:13.240
この一次関数で初めて完全な接続を実現しました｡ 

12:13.240 --> 12:16.840
入力層と隠れ層の間の完全な接続を行うのです｡ 

12:17.080 --> 12:21.040
そして､ いよいよ2回目の完全接続です｡ 

12:21.040 --> 12:25.030
それが隠れ層と出力層の間の完全な接続です｡ 

12:25.270 --> 12:26.260
そうそう､ そうなんです｡ 

12:26.470 --> 12:30.100
これを2つ目のフルコネクションと呼ぶことにします｡ 

12:30.100 --> 12:32.140
FC 2 そこへ行く｡ 

12:32.140 --> 12:34.900
そして､ やはりこれは私たちのオブジェクトからの変数です｡ 

12:34.900 --> 12:41.140
RNモジュールと1次関数を使いますが､

12:41.140 --> 12:49.060
その前に引数を変更する必要があります｡

12:49.060 --> 12:49.810
それは同じです｡ 

12:49.810 --> 12:55.000
第一は､ 食物連関の第一層に欲しいニューロンの数です｡ 

12:55.000 --> 12:58.960
つまり､ これが隠れ層なので､ 30になります｡ 

12:59.380 --> 13:06.910
そして､ 第2引数は食物連関の第2層のニューロン数で､ これは出力層に相当する｡

13:06.910 --> 13:13.840
そして､ 出力層には､ アクションニューロンがあり､ 後に3つの可能なアクションがあるので､ 3つになります｡

13:13.840 --> 13:19.420
しかし､ これまでのところ､ 我々は我々が定義した名前を使用する必要があります､ それはinit関数の引数の名前であり､

13:19.570 --> 13:23.200
したがって､ 我々はここに入力し､ アクションである｡

13:23.590 --> 13:24.700
そして､ そこに行く｡ 

13:24.700 --> 13:30.910
まず､ 2つのフルコネクションの準備ができ､ 次に､ init関数の準備ができました｡ 

13:31.120 --> 13:36.850
ネットワーク・クラスからオブジェクトを作成するときは､ このようにオブジェクトを初期化します｡ 

13:36.850 --> 13:43.180
オブジェクトを作るとすぐに､ これらの変数､ つまりここにある4つの変数 input sizeとbe

13:43.180 --> 13:46.930
action FC 1とFC 2が定義されることになります｡

13:46.930 --> 13:50.200
こうして､ ニューラルネットワークのアーキテクチャが出来上がるわけです｡ 

13:50.200 --> 14:00.040
作成した各オブジェクトは､ 5つの入力ニューロン､ 30個の隠れニューロン､ 3つの出力ニューロンからなるニューラルネットワークに対応することになります｡

14:00.220 --> 14:01.210
そうそう､ そうなんです｡ 

14:01.240 --> 14:06.520
この関数は整流器活性化関数を用いてニューラルネットワークのニューロンを活性化し､

14:06.520 --> 14:19.210
最終的にニューラルネットワークの出力であるQ値を返すために使用されます｡

14:19.300 --> 14:21.640
だから､ 早く次のチュートリアルでやりたいんです｡ 

14:21.640 --> 14:22.960
そしてそれまで､ お楽しみに｡ 

14:22.960 --> 14:23.530
I.
