強化学習の行動価値関数について
強化学習ではある状態に対してどのような行動をとれば、その後に得られる総報酬が最大化されるかを学習していきます。
強化学習ではこの指標を「行動価値」とよび、「行動価値関数」というもので表現しています。
行動価値関数の理想的な定義は、状態と行動を渡すと時刻以降で得られる報酬の総和を返してくれるものです。
つまりざっくり式で表すと
$$ Q(s_t,a_t) = r_t + r_{t+1} + r_{t+2} + r_{t+3} + ・・・\;\;\;\;\;\;\;\;(1)$$
のようになってほしいわけです。
ですがこの定義だと、(報酬が常に同符号だと仮定すると)値が無限に発散してしまいます。 また、行動が大きな影響を与えるのは報酬であって、報酬に大きな影響を与えるのは行動です。にもかかわらず全てのが同列に扱われているのは不適切であると考えられます。
そこで割引率というものを導入します。は0~1の値で、経過時間に応じて報酬に乗算していきます。
式(1)に割引率を適用すると以下のようになります。
$$ Q(s_t,a_t) = r_t +\color{red}{\gamma}・r_{t+1} + \color{red}{{\gamma}^2}・r_{t+2} + \color{red}{{\gamma}^3}・r_{t+3} + ・・・\;\;\;\;\;\;\;\;(2)$$
これによって行動価値はある一定値に定まります。
さて、行動価値関数の定義ができたところで、これを実際に学習していきたいわけです。
機械学習では、目標となる数式の両辺の情報が手に入れば、教師あり学習として学習できます。
ということで情報を集めていきたいわけですが、式(2)の右辺が無限和になっていて、全て集めるのは困難です。
そこで、式(2)を少し工夫します。
$$ Q(s_t,a_t) = r_t +{\gamma}・r_{t+1} + {{\gamma}^2}・r_{t+2} + {{\gamma}^3}・r_{t+3} + ・・・$$ $$ \;\;\;\;\;\;\;\;\;\;\;\;\;\;= r_t +{\gamma}・(r_{t+1} + {{\gamma}}・r_{t+2} + {{\gamma}^2}・r_{t+3} + ・・・)$$ $$ \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;= r_t +{\gamma}・Q(s_{t+1},a_{t+1})\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;(3)$$
式(3)のようにしますと、両辺の情報が時刻と時刻のみで構成されているため、容易に集めることができます。
そして、あらゆる状態行動の組み合わせで式(3)の等号が満たされるなら、実質的に式(2)が満たされているとみなすことができます。
を作るために学習しているのに、学習中にを使ってもいいのか?と思われる方もいらっしゃるかと思います。
これが強化学習の特徴的な部分で、教師信号も学習していくということです。
分かりづらかったかもしれませんが、ざっくりとはこんな感じです。
もう少し勉強します~。
python3 pickleで簡易データベース
プログラム内で使った変数などの各種情報を一旦外部に保存しておきたいことってありますよね。
MySQLなどしっかりしたデータベースが使えればいいんですけど、SQL文を覚えたりしないといけないので割と敷居が高いです。
そこで、MySQLを使わずに簡易的にデータベースを作る方法を紹介します。
・データ保存
import pickle data = ~~~ with open("filename","wb") as f pickle.dump(data,f)
wbはバイト形式で書き込むということです。 dataの型はなんでも大丈夫みたいです(ちゃんと検証してはいない)。
listを保存しておけば簡易的なデータベースとして使えますね!
・データ読み込み
import pickle with open("filename","rb") as f data = pickle.load(f)
これでdataの内容が復元できます。
pickleを使えばデータを外部に保存できるので、プログラムが終了した後に、別のプログラムで再利用することが可能になります。
ただファイルに落とすだけですのでセキュリティ面は保証できません。 重要なデータには使わないようにしましょう。
オイラー素数が楕円の格子点と関係していた件
オイラー素数とはオイラーの素数生成式で表される素数のことです。
この式が非常の多くの素数を生成することは以前の記事で紹介しました。単純な二次多項式がこのような振る舞いをするのには, 何か理由があるはずだと考えられていますが, 今のところよくわかっていません。
そこで, 私自身少々気になって色々調べてみることにしました。
そしてわかったことは, 素数生成式で表現される合成数には規則があるということです。
自然数列では合成数が一次関数(2n, 3n…)で現れるのに対し, 素数生成式では二次関数で現れることがわかりました。
その式を変形していくと以下のような楕円の式が導かれました。
$$ x^2+(4a-1)y^2-(4b+2)y-1=0 $$
この楕円上の格子点がの素数性, もっと言えば約数の個数に関係していることがわかりました。
Youtubeに内容の一部を公開しています!
何か知ってる方いらっしゃいましたらぜひご教授ください!
python3 文字列内の変数展開
文字列内に変数の値を組み込みたいことってよくありますよね。
そんなときに使える方法4つをまとめます。
1.f-stringsを使う
name = "isato" age = 23 print(f"私は{name}です。{age}歳です。") # => 私はisatoです。23歳です。
2.str.format()を使う
name = "isato" age = 23 print("私は{0}です。{1}歳です。".format(name,age)) # => 私はisatoです。23歳です。
3.%演算子を使う
name = "isato" age = 23 print("私は%sです。%d歳です。" %(name,age)) # => 私はisatoです。23歳です。
4.+演算子を使う
name = "isato" age = 23 print("私は"+name+"です。"+str(age)+"歳です。") # => 私はisatoです。23歳です。
f-stringが使いやすくていいと思います!
他のやり方も覚えておいて損はないでしょう。
ウラムの螺旋の三次元拡張
YouTubeに公開しています。
ウラムの螺旋を三次元拡張してみた
通常版のウラムの螺旋では、正方形から次に大きい正方形を作るように軌跡を描いていきました。
この考えを拡張して、立方体から次に大きい立方体を作るように軌跡を描けば三次元拡張ができると考えました。
可視化にはplotlyというライブラリを用いました。
二次元版では直線が二次関数になっていました。じゃあ三次元版の直線は三次関数になってほしいですね。
動画の最後で確かめています。
三乗数しか調べていませんが、三次関数が直線で現れていることが確かめられました。
一方で気になる素数の分布は今のところよく分からないです...。
何かわかった方はぜひコメントください!
python 辞書型とタプル型を用いた2次元データ
タイトルを見られた方は、なんでそんなややこしいことするの?って思われたかもしれません。確かに用途によっては、他の作り方でも十分です。
タイトルのようにするメリットは、領域が確保されていないときでも要素を指定できることです。
詳しく説明します。
C言語とかだと最初に int list[10][10] のように領域を確保してから、list[2][5] = 7 のように要素にアクセスします。
しかしpythonは領域を動的に確保するので、このようには書けません。(numpyとかではできます)
では領域を動的に確保しながら要素を指定したいときはどうすればいいでしょう。
一つの答えとして以下のようにすれば良いです。(2, 5)という要素に7を格納したい場合は
data = {}
data[(2,5)] = 7
のようにします。
タプル(2,5)が整数7と紐づけられるため、2次元データとして扱うことが可能です。
numpy使えばよくね?って思われた方もいらっしゃると思います。
numpyは基本的には数値を格納して計算に使うものです。それに比べて、このやり方では要素は数値以外でも問題ありません。リストを格納してもいいし、辞書を格納してもいいわけです。また動的確保なので、無駄な領域を確保する必要がないという利点もあります。
そう言った意味では結構汎用性は高いと思っています。
もっといい方法があれば、ぜひ教えてください!