こんにちは､ このPythonチュートリアルへようこそ｡
このチュートリアルでは､ ディープラーニングモデルを実装するための最初の一歩を踏み出します｡
つまり､ 基本的にはディープラーニングアルゴリズムの全工程を実装するところなんです｡
で､ 前に作ったものを使うわけです｡
それが､ 記憶を再生するニューラルネットワークのアーキテクチャであり､ これをディープラーニング全体のプロセスに統合することです｡
そして､ このディープラーニングのアルゴリズム全体は､ 1つのクラスに収まることになります｡
人工知能を実装するために作っている最後の授業なんですね｡
そして､ このクラスには､ 異なる機能が含まれるだけです｡
init関数は､ 深層学習モデル自身を表す将来の深層学習オブジェクトに付随するすべての変数を作成し､
初期化するもので､ 他にもいくつかの関数があります｡
そのひとつは､ もちろん､ その都度､ 適切な行動を選択することでしょう｡
また､ アップデート機能､ スコアを取得し､ 学習状況を把握するためのスコア機能も用意する予定です｡
探査がうまくいって､ エクスプロージョンに移れるようなら､ モデルを保存する機能､
つまり車の頭脳を保存する機能､ そして最終的にはロード機能を持たせることになります｡
そこで､ いくつかの機能を作っています｡
各チュートリアルで1つの関数を作っていきますが､ 今日はクラスを作るときのいつものようにinit関数から始めてみましょう｡
しかし､ 最初にクラスを紹介することを忘れないでください｡ D､ Q､ Nはdeep
Q networkと呼びます｡
では､ このdefの中にダブルアンダースコアを入れて､ またダブルアンダースコアを入れて､ 括弧をつけましょう｡
そこで､ このinit関数でご理解いただいたように､ オブジェクトに付属する変数を導入していきます｡
これから数行が単独で始まり､ 基本的にディープQネットワークを実装するために必要なすべての変数を作成し､
初期化します｡
例えば､ ディープニューラルネットワークが必要なので､ ネットワークのオブジェクトを作成し､
次にメモリが必要です｡
メモリ用に別の変数を作成することにします｡
そこで､ そのメモリに別の変数selfを用意します｡
しかし､ そうなると､ 私たちが作らなければならないのは､ それだけではありません｡
最後の状態､ 最後のセクション､ 最後の報酬のためのいくつかの変数｡
それはもちろん､ ディープラーニングのアルゴリズムに見られるような変数のことですね｡
それから､ 他には？
さらに､ AIがミスをしたときに､ そのミスにどれだけ貢献するかに応じて重みを更新する確率的勾配降下法を実行するオプティマイザーが必要になりますね｡
そして､ 基本的にはこれで初期化するための変数ができたと思います｡
しかし､ このinit関数では､ いくつかの引数を入力することになります｡
まず､ いつものようにself､ これは我々のオブジェクトを参照する引数である｡
そして､ ご存知の通り､ ネットワーク・クラスのオブジェクトを作成することになります｡
さて､ ネットワーククラスは､ init関数の引数として､ input､ size､ end actionを取ります｡
まあ､ それはこちらも同じなんですけどね｡
ネットワーククラスのオブジェクトを作成するときに､ NBアクションの引数で入力サイズの引数を選択する必要があります｡
ですから､ コピーすればいいのです｡
と｡
ここで向き合う｡
そして､ ここからが本番です｡
つまり､ これらの引数は､ 今度は別のクラスのいくつかの引数にもなるのです｡
現在のクラスの将来のオブジェクトを作るときはいつでも､ 将来の深層学習モデルで､
入力サイズを指定する必要があります｡ これは､ 状態をエンコードするベクトルの次元数､
入力状態､ アクション数､ つまり車が取りうるアクションの数です｡
だから､ これらは左へ行くか､ まっすぐ行くか､ 右へ行くかと念を押しているんです｡
よし､ 完璧だ｡
それから､ トランジションの記憶を得るためのメモリオブジェクトを作成するために､ リプレイメモリクラスのオブジェクトを作成することになりますね｡
init関数の中で､ 容量の引数がありますが､ これは一度だけ､ 実際にはメモリを作成するときに使うだけで､
その後はどこにも使わないので､ まあ､ 容量の引数を指定する必要はないでしょう｡
このようにすることもできますが､ ここではメモリに持たせたい遷移の数を直接入力することにします｡
しかし､ そうなると必要な引数は1つ少なくなり､ 深層学習モデルのガンマパラメータになります｡
このガンマパラメータは遅延係数であることを忘れないでください｡
それが方程式のパラメータです｡
それゆえ､ この後何度か使うことになるので､ ここに書いておきます｡
では､ ここに書いておきましょう｡
ガンマと呼ぶことにする｡
これが引数の名前です｡ これで､ このinit関数に必要なすべての引数が揃いました｡
つまり､ 深層学習モデルを作成するときはいつでも､ 現在のクラスの新しいオブジェクトを作成するときはいつでも､
ということです｡
さて､ 引数として入力サイズ､ アクション数､ ガンマパラメータを指定する必要がありますが､ それらの実数値は近日中に入力する予定です｡
わかりました｡
それでは､ init関数の中に入ってみましょう｡
なるほど｡
だから今､ 基本的にこれは簡単なことなんだ｡
これから初期化､ 必要な変数をすべて作成するところです｡
というわけで､ まずは1つ目から｡
まず､ ガンマは実際に遅延係数から始めてみましょう｡
これは変数なので､ オブジェクトにアタッチしたいのですが､ selfから始めます｡
つまり､ ガンマは我々の現在のモデルの変数になるわけです｡
つまり､ このクラスのオブジェクトを作成するときに入力される引数がガンマに等しいと自己判断してください｡
そこでγと､ 2つ目の引数になります｡
つまり､ 第2引数はリワードウィンドウになるわけです｡
では､ このリワードウィンドウとは何でしょうか？
これは､ 過去100回の報酬の平均値のスライディングウィンドウで､ AIのパフォーマンスの進化を評価するために使用されます｡
この報酬ウィンドウに報酬の平均値を入れて､ 時間と共にスライドさせるんだ｡
そして､ 私たちが観測したいのは､ 時間とともに増加する過去100回の報酬の平均値です｡
そこで､ self dot reward, underscore windowで初期化してみましょう｡
そして､ これは過去100件の報酬の平均をスライディングウィンドウにするものなので､
空のリストとして初期化し､ 時間の経過とともに報酬の平均を追加することにします｡
よし､ じゃあ､ もっと盛り上げよう｡
それでは､ ニューラルネットワークを作成してみましょう｡
そこで､ 基本的にそれがモデルの中心であることから､ セルフドットモデルと呼ぶことにしました｡
だから､ モデルということにしているんです｡
そしてこのモデルは､ ネットワーク・クラスのオブジェクトにほかならないだろう｡
そして､ このようなオブジェクトを作成するために､ クラスnetwork､ 次に括弧を取り､ ここではネットワーククラスの引数を入力するだけです｡
しかし､ これらの引数はinit関数の引数に入れたので､ ここでコピーしてネットワーク・クラスに貼り付けるだけでいいのです｡
そして､ そこに行く｡
このコードで､ 深層学習モデル用のニューラルネットワークを1つ作成します｡
完璧です｡
それなら､ 思い出を作ろう｡
そこで再び､ self dot memoryと呼ぶ新しい変数を作成します｡
これもリプレイメモリークラスのオブジェクトになります｡
では､ クラスの名前をコピーして､ ここにペーストしてみましょう｡
そして､ いくつかの括弧の中に､ 容量を入力する必要があります｡ 容量とは､ init関数の引数であり､ ここで入力する必要がある唯一の引数だからです｡
では､ どのような容量を選べばいいのでしょうか｡
それは､ 遷移の数､ イベントの数､ 状態の少なさ､ 新しい状態､ 行動の少なさ､ 報酬の少なさに対応することを覚えておいてください｡
前のチュートリアルで述べたように､ 10万個の遷移をメモリに取り込み､ このメモリからサンプリングして少数のランダムな遷移を取得し､
それを基にモデルが学習します｡
なるほど｡
だから､ 今､ 私たちは記憶しているのです｡
完璧です｡
では､ オプティマイザーを手に入れましょう｡
そこで､ 再びselfで､ optimizerと呼ぶ新しい変数を作成します｡
だから､ オプティマイザーは､ 私たちの将来のGQのオブジェクトの別の変数なので､ その自己オプティマイザー｡
さて､ 上に戻ってみると､ 確率的勾配降下を実行するためのすべてのツールを含むtorchのモジュールであるOptimをインポートしていることがわかります｡
このモジュールにはもちろんいくつかのオプティマイザが含まれていて､ optimというショートカットをつけています｡
そこで､ これから行うのは､ Optimというモデルを取り出し､ このモジュールからオプティマイザの一つを取り出すということです｡
というわけで､ ご覧の通り､ ここにずらりと並んでいます｡
優秀なものが多い｡
例えば､ アームスプロップは優れたオプティマイザーです｡
それは例えば､ 通常のニューラルネットワークや教師なしディープラーニングに強く推奨されるものです｡
しかし､ もう一つ優れていて､ 私たちが選ぶのは､ アトムオプティマイザです｡
これがあれば､ いい自動運転車ができあがるということですね｡
でもまた､ 他のものを試してみるのも全然OKです｡
アームスプロップも試せますが､ 今回のモデルではアトムを選択します｡
エンターキーを押していますが､ 実はここに大文字のAがあることにお気づきでしょうか｡
それは､ atomクラスのオブジェクトを作成しているからです｡
これはクラスですが､ オブジェクトはアトムオプティマイザそのものになります｡
しかし､ これはクラスなので､ いくつかの引数を入力する必要があります｡
アトムクラスの引数と引数は､ アトムオプティマイザーをカスタマイズできるすべてのパラメータです｡
例えば､ 学習率や減衰率などのパラメータが典型的ですね｡
そして､ モデルのすべてのパラメータを取る他に､ 学習率を指定する｡
そこで､ 私たちのモデルのパラメータといえば､ セルフドットモデルで得ることができます｡
これが､ 私たちが作ったモデルです｡ ネットワークの授業で作った独習モデルです｡
だから独学モデル｡
そして､ モデルのパラメータを評価するために､ もう1つのドットと､ いくつかの括弧を付けてパラメータを非常に簡単に追加します｡
つまり､ アトムオプティマイザーと､ ここで作成したニューラルネットワークを接続するだけです｡
そして､ 先ほど述べたように､ 学習速度を追加します｡ この引数はl
rで､ 学習が速くなりすぎないような値に設定します｡
学習率を大きくしすぎると､ AIがちゃんと学習しないんです｡
AIに探索の時間を与え､ 失敗から学ばせたいのです｡
例えば､ 砂の上に乗ったり､ 壁に近づきすぎたりといったミスをしたとき､
私たちはAIに学習させる時間を与えたいと思っています｡
ニューラルネットワークが正しく更新されるのを待ちたい｡
それで､ いくつか試してみて行き着いた学習率の良い値が「0」です｡ 01.
わかりました｡
そして､ これだけで､ オプティマイザーを作ることができるのです｡
つまり､ 基本的にはatomクラスのオブジェクトを作成していることになります｡
素晴らしい｡
そして､ 最後に必要な3つの変数は､ 遷移イベントを構成する変数である｡
それが最後の州であり､ 最後のセクションであり､ 最後の報酬なのですね｡
このように､ 基本的にはこれから作成するもので､ あとは初期化するだけです｡
では､ まず最終日の様子から｡
最後の日付は self dot, last underscore state と呼ぶことにして､ どのように初期化するのか？
さて､ 最後の状態は､ 5次元のベクトルであり､ 環境の1つの状態をコード化しているベクトルであることを思い出してください｡
そして､ この5つの次元は､ 念のために言っておくと､ 左・直・右の3つのセンサーの信号と､
向きとマイナスの方向である｡
つまり､ これは直感的にはベクトルなのですが､ PyTorchではベクトル以上のものである必要があるのです｡
実際にはトーチテンソルである必要があります｡
しかし､ トーチテンソルであるだけでなく､ もう1つ､ バッチに対応する偽次元と呼ぶべき次元を持つ必要があるのです｡
そして､ 最後の状態がニューラルネットワークの入力になるからだ｡
しかし､ 一般的にニューラルネットワークを扱う場合､ TensorFlowキャリーにしてもPyTorchにしても､ まあ､
入力ベクトルが単体で単純なベクトルになることはありえないわけです｡
バッチリでないとダメなんです｡
ネットワークは入力観測のバッチしか受け付けないので､ 入力状態ベクトルのためのテンソルを作成するだけでなく､
バッチに対応するこの偽の次元を作成することにする｡
では､ これをやってみましょう｡ まず､ トーチテンソルを初期化します｡
そのためには､ これほどシンプルなものはないわけです｡
torchライブラリ､ そしてdot､ そしてtensorクラスを使います｡ なぜなら､ ご想像の通り､ これはtensorオブジェクトであるtensorクラスの新しいオブジェクトを作成するためです｡
そして､ このテンソルクラスでは
テンソルのサイズを指定する引数を一つ入力する必要がある｡
テンソルは1つの型を持つ配列のようなものだと考えていただければよい｡
しかし､ 基本的に今これが表すのは､ もちろんこの入力状態であり､ これはベクトルとして見ることができます｡
そして､ このテンソルが持つべき要素数を指定することです｡
もちろん､ 入力サイズを使う必要がある｡ 入力サイズとは､ まさに入力状態ベクトルの次元数のことだからだ｡
今はセンサーと言うべきでしょう｡
そして､ 私たちが単純にテンソルクラスに入力する必要があるのは､ テンソルオブジェクトを作成することである｡
まあ､ 入力サイズなんですけどね｡
そして､ 後に入力サイズは5となる｡
よし､ これでいいんだ｡
それがまず第一に行われます｡
当然のことながら､ テンソルを初期化しただけです｡
でも､ その時､ 忘れてはいけないのが､ もうひとつのことです｡
偽の次元を作成する必要があります｡ なぜなら､ これがネットワークの入力として期待されるものであり､
この1つのイチジク次元を作成する必要があります｡
バッチに対応する偽の次元は､ この最後の変数の最初の次元になりますよね｡
そのためには､ dot thenとsqueezeを追加するだけです｡
そして､ いくつかの括弧の中に､ この曖昧な次元のインデックスを入力する必要がある｡
そして､ 今言ったように､ この偽物の次元は国家の最初の次元でなければならないのです｡
Pythonのインデックスは0から始まるので､ この新しい次元が最初の次元になるように､ 0を入力する必要があります｡
つまり､ バッチに対応する最初の次元と､ テンソルに対応する次元があり､ そこには入力状態の5つの要素が含まれることになる｡
信号の向きは3つ､ マイナスの向きもあります｡
そして､ 入力状態を適切に初期化し､ 完璧な状態にします｡
そして､ あと2つの変数｡
そして､ 次の変数が最後のアクションになるので､ それはとても簡単なことになります｡
つまり､ 最後のアクションでオブジェクトのために新しい変数を作成していたわけです｡
このセクションの最初のチュートリアルで､ アクションはゼロ1か2のどちらかになるとお話しました｡
そして､ アクション2の回転ベクトルを使って､ これらのアクションのインデックスを回転の角度に変換するのですが､
ゼロ20または-20を思い出してください｡
実際にそれで記憶をリフレッシュすることができます｡
まあ､ まさにここなんですけどね｡
回転によるアクション｡
アクションがゼロの場合は､ まあ､ ここでの最初のインデックスに対応することになります｡
つまり､ ゼロ､ アクションが1の場合､ これはこのベクトルのインデックス､ 1に対応することになります｡
だから20度｡
そして､ アクションが2つなら､ -20度になる｡
これが､ アクションを再生したときのクルマの回転角度になるんです｡
わかりました｡
したがって､ アクションはゼロ1か2のどちらかになるので､ まあ､ アクションはしたがって単純な数字になります｡
というわけで､ 非常にシンプルに､ ゼロに初期化することができるのです｡
ここではテンソルも何も作成する必要はない｡
それをゼロで初期化すればよいのです｡
そして最後に､ まあ､ これが最後のご褒美ですね｡
だから､ セルフドット最後のご褒美｡
これでよしとしよう｡
そしてまた､ 報酬はフロート数で､ マイナス1からプラス1の間だと記憶しています｡
だから､ またこの数字なんです｡
そして､ アクションについては､ 0に初期化して､ これで完了です｡
おめでとうございます！init機能の準備が整いました｡
さて､ ここからはワクワクするような話です｡
そして､ 私にとって最も重要なことは､ その都度､ その都度､ どの行動をとるかを決めることです｡
T そして､ 次のチュートリアルでは､ まさにそれを実現するために､ Select Action Methodを作成します｡
では､ 次のチュートリアルでこれをやってみましょう｡
そしてそれまで､ iを楽しんでください｡