こんにちは､ このPythonチュートリアルへようこそ｡
それでは､ 最後にリプレイ・メモリー・クラスに実装する関数を1つ紹介します｡
それがシンプルな機能です｡
それはもちろん､ 私たちの記憶からランダムにサンプルを取り出すためです｡
したがって, この関数はこれらのランダムなサンプルを返します｡
わかりました｡
では､ 実装してみましょう｡
サンプルと呼ぶことにします｡
さあ､ どうぞ｡
そして､ この関数は2つの引数を入力として受け取る｡
1枚目､ いつものように自分｡
リプレイメモリークラスの我々の未来のオブジェクト｡
そして2つ目の論点は､ 推測してみることはできないか､ ということです｡
さて､ 私たちはいくつかのサンプル､ 決まった大きさのものを取っているので､ サンプルの大きさを選ぶ必要があります｡
そして､ より正確には､ バッチサイズと呼んでいます｡
これが､ 第2引数のバッチサイズにつける名前です｡
そして､ そこに行く｡
2つの引数が揃ったので､ サンプル関数を実装してみましょう｡
さて､ 少し専門的な話になりますが､ 頑張って説明したいと思います｡
そこで､ まずはsamplesという変数を作成します｡
これはちょうど､ メモリのサンプルを格納するための変数です｡
わかりました｡
だからサンプルイコール｡
では､ そのサンプルをどうやって入手するのか？
さて､ まず､ 私たちは記憶からこれらのサンプルを得ているので､ 記憶を取る必要があります｡
そして､ 取得したいサンプルにはバッチサイズの要素が含まれているため､ おそらくバッチサイズが必要になります｡
そのため､ メモリとバッチサイズが必要で､ さらに､ これらのサンプルの良いフォーマットを得るために､ PyTorchやPythonのトリックが必要です｡
そこでどうするかというと､ コードの行を書き､ それを要素ごとに説明するのです｡
では､ やってみましょう｡
まずはZIP機能を取ることから始めています｡
何をするものなのか､ すぐに説明するつもりです｡
そして､ このZIP関数の中に､ 星を追加していきます｡
それも拡大していこうと思います｡
星とランダムドットのサンプル｡
ランダムというのは､ ご想像の通り､ ここで取り込んだランダムライブラリのことですね｡
それが､ このランダムライブラリをインポートすることになった最大の理由です｡ ランダムなサンプルを採取していたからです｡
そこで､ このランダムライブラリから､ サンプル関数を使用します｡
これが変数で､ これが関数です｡
そこで､ かっこを付けてみる｡
さて､ sampleは関数なので､ 引数を入力する必要があります｡
つまり､ 見ての通り､ 最初の引数はselfです｡
また､ 自己といえば､ これは自己のメモリ､ つまり未来のインスタンスのメモリ､ リプレイメモリクラスのオブジェクトに相当する｡
だから､ ここにその記憶の自己を追加するのです｡
そして､ 2番目の引数は､ ご想像の通り､ メモリからランダムに取り出したいバッチのサイズで､
バッチサイズという名前を付けています｡
つまり､ 第2引数はバッチサイズになるわけです｡
わかりました｡
というわけで､ コードの行がタイプされたので､ 今度はそれが何をするものなのかを説明します｡
まず､ このランダムサンプル機能では､ バッチサイズという一定の大きさを持つメモリから､ いくつかのランダムなサンプルを取っているわけです｡
だから､ それは理解できる｡
しかし､ それではこのZIPストア機能は何をするものなのでしょうか？
まあ､ 何の不思議もないんですけどね｡
ちょうどリシェイプ機能のようなものです｡
だから､ 例えば､ ここにちょっとコモンをつけて､ 削除することを説明するだけです｡
そこで､ 例えば､ 次のような要素のリストがあるとします｡
例えば､ 最初に1､ 2､ 3､ そして2番目の要素､ 4､ 5､ 6というように｡
つまり､ 3つの要素1, 2, 3と4, 5, 6の2つのタプルのリストがあるわけです｡
では､ 星をつけたままZIP機能をかけると､ さて､ 何になるのでしょう？
つまり､ ZIPスターリストは､ 新しいリストと同じで､ 異なる形状のものになるのです｡
そして､ この異なる形状が､ 1つの4､ そして2､ 3､ そして5､ 6となるのです｡
わかりました｡
というわけで､ まさにその通りです｡
ただ､ リストの形が変わってしまうんです｡
なるほど｡
さて､ このZIPスターリストが何をするものなのかは理解していただけたと思いますが､ では､ なぜそれをしなければならないのかを説明します｡
つまり､ ご理解いただいたように､ イベントをメモリに追加していくわけですが､ イベントは､ まず状態､ 次にアクション､
そして報酬という形になっています｡
しかし､ 我々のアルゴリズムでは､ このような形式は必要ないのです｡
実際には､ サンプルは次のような形式にしたい｡ 状態のサンプル､ アクションのサンプル､
報酬のサンプルの3つからなる形式である｡
そこで､ 例えばこの1～3は､ 状態1､ 行動1､ 報酬1､ そして状態から行動へ､
報酬2だとします｡
さて､ 私たちが欲しいのは､ 状態1のためのバッチと滞在2のためのバッチのそれぞれ1つ アクション2のアクション1のためのバッチの1つと､
報酬1のための3つ目のバッチです｡
そして､ 私たちは2人でした｡
これは､ 次に期待される形式です｡ なぜなら､ 次にこれらのバッチをPyTorch変数にラップするからです｡
そして､ pythonの変数は､ テンソルとグラディエントの両方を含む変数であることを思い出してください｡
そしてそれは､ テンソルに関して微分できるようになるためには､
テンソルと勾配を含む変数という構造が必要なのです｡
繰り返しになりますが､ これがPyTorchの仕組みです｡
まとめると､ 状態と行動と報酬のそれぞれについて1つのバッチを作成し､ これらのバッチを別々にいくつかのPyTorch変数に入れ､
それぞれが勾配を得ることで､ 最終的にそれぞれを区別することができるようになります｡
わかりました｡
それがこの機能の目的なんですね｡
だから､ このコメントは削除させてください｡
そして､ あとはサンプルを返すだけです｡
つまり､ 先ほど説明したように､ サンプルを直接返すことができないのは､ サンプルをPyTorchの変数に入れたいからという単純な理由です｡
各サンプルに対してこれを行うには､ map関数を使用します｡ このmap関数は､
サンプルからテンソルや勾配を含むタッチ変数へのマッピングを行います｡
このように､ このmap関数はいくつかの引数を取ります｡
最初の引数は関数で､ この関数がサンプルをいくつかの教えられる変数に変換する関数になる予定です｡
そして､ 第二引数には､ この関数を適用したいものを指定します｡
これがこの関数の引数になるわけです｡
それゆえ､ どうなるのでしょうか？
それはもちろんサンプルになります｡
ここでは第2引数にサンプルを指定しますが､ 次にそれぞれのサンプルを適用する関数を定義しましょう｡
そこで､ ここで関数を定義するために､ まずLambdaと呼ぶ関数に名前を付ける必要があります｡
これはラムダを与える名前に過ぎず､ 次にこの関数の変数になるxが与えられる｡
つまり､ これは私が変数につけた名前とコロンだけなのです｡
そして､ ここでは関数の式を示す｡
これが､ このラムダ関数が返したいものである｡
それで､ どうなるかというと､ まあ､ トーチ変数に変換したり､ サンプルしたりするものになるはずなんです｡
そのための変数関数については､ 以前のチュートリアルですでに触れました｡
変数関数は､ トーチテンソルから､ このテンソルと勾配を含む変数への変換を行うものである｡
というのも､ Xはサンプルにラムダが適用された後のサンプルになるからです｡
でも､ それだけじゃないんです｡
最後にもうひとつ､ 技術的な実装が必要です｡
それは､ サンプルに含まれる各バッチ､ 例えば､ a1､ a2､ a3などのアクションのバッチについて､
状態に対応する1次元に関して連結しなければならないことである｡
そして､ なぜこのような連結をしなければならないのか｡
それは､ すべてがうまく調和するためなのです｡
つまり､ 各行で状態､ 行動､ 報酬が同じ時間に対応する｡
T そうすると､ 最終的にはすべてのバッチがうまく整列したリストができ､ 各バッチはピトーチ変数になります｡
では､ この連結はどのようにすればいいのでしょうか｡
さて､ torchライブラリのcat関数を使う必要があります｡
そこで､ ここにトーチを追加し､ それにXに適用する猫を追加します｡
しかし､ このcat関数の中で､ その連結を行う次元を指定する必要があるのです｡
そして､ 先ほど述べたように､ これはインデックスがゼロの最初の次元です｡
そして､ ここからが本番です｡
機能の準備はできています｡
このラムダ関数がサンプルを受け取り, 1次元目に関して連結し, 最終的にセンサーと勾配を含むトーチ変数に変換します．これにより,
後で確率的グリッドを適用する際に, 重みを更新するための微分ができるようになります．
さて､ この関数の準備は整いました｡
そして､ map関数の2番目の引数として､ このラムダ関数を適用する対象を指定する必要があります｡
つまり､ すべてのサンプルに対してこのラムダ関数を適用し､ 最終的に各バッチをpytorch変数とするバッチのリストを取得するのです｡
わかりました｡
というわけで､ かなりテクニカルな話になってしまいましたが､ これで少なくともすべてがうまくいくようになりました｡
まあ､ この技はこの後使いませんけどね｡
ここでしか使わない｡
ですから､ ここで技術的な詳細を深く理解する必要がなければ､ まあ､ それはそれでいいのです｡
この3行をコピーするだけで､ メモリのサンプルになります｡
PyTorchで人工知能を作ろうと思えば､ 思いのままです｡
しかし､ これでこの再生記憶クラスの体験再生が実装され､ 次の最後のクラス､ つまりディープラーニングモデル全体に移行できるようになったのは良いニュースです｡
この深層学習モデルでは､ もちろんネットワークが経験を積み､ 再生し､ そして残りのすべての深層学習アルゴリズムがあります｡
だから､ もっと大きなクラスになるんです｡
これから10個くらいの関数を作りますが､ それは､ 何が起こっているのかをよく理解してもらうために､ 段階を踏んでやっているからに他なりません｡
だから､ 早くディープラーニングモデルを実装したいんです｡
それまでは､ Iをお楽しみください｡