2021年6月18日金曜日

ちょっと惹かれるPython1行コード(その2)

 【what is this】前回に引き続き、短くて美しい1行コードを検討します。参考文献[1]を参考にしています。Pythonの初心者が中級へステップアップするのに適しています。小生もこれに該当しますので、個人的な忘備録でもあります。

■例題:漁獲高の平均を上回る漁港をリストアップする
 今回データ分析の対象とするデータ(参考文献[2]を参考とした)を以下に示します。Python numpy配列であるFHには、主要な漁港名9つを格納しています。そして、別のnumpy配列Vには、この漁港の順に、2014年〜2018年の5年間の漁獲高(水揚げ量)を万トン単位で格納してあります。

【解くべき問題】
 上記データ45件(=9漁港x5年)の平均値を一回でも超えた漁港を示すこと。
【解答プログラム】
 以下の1行コードが解答プログラム(出力込み)です!
答えは、"銚子"、"釧路"、"焼津"の3漁港でした。

■一行コードの分解 ...
 上記1行コードをすぐに理解できる人は少ないかもしれません。そこで、その中身を分解してみます。最後には、「なるほど、素晴らしい!」となるでしょう。

(1)平均値を求める
 これは下図のように、簡単です。

(2)平均値を超えるか否かを真偽配列で表す
 この真偽の配列は、下図のように生成することができます。numpyのbroadcastが働いています。

(3)"True"の位置のインデックスを求める
 上図の真偽配列において、'True'となる位置のインデックスを下図のように求めます。ここで、numpy関数nonzeroが使われていますが、'nonzero'は、Pythonでは、'True'に対応することに注意します。全45件のうち、13件が'nonzero'であり、その位置のインデックスは、下図のように2次元配列で表されます。
 例えば、上段の'0'と下段の'0'のペアは、銚子漁港の最初(2014年)のデータが、平均直を超えていることを意味します。また、釧路漁港(上段インデックス4)は、3回平均値を超えたことが分かります。

(4)漁獲高の絶対値はここでは不要
 上図は、2次元配列になっていますが、ここでは、漁港名に対するインデックスだけわかれば良いので、最初の1次元配列だけを取り出します。下図で、'[0]'がそれを実現します。

(5)インデックスのリストを配列に与える
 次に、このインデックスを漁港名に変換するのですが、以下のように、インデックスのリストを配列FHに与えることができます。

 
 これに従って処理を続けると、以下のように、漁港名のリストが得られます。

(6)最後は集合(set)で仕上げ
  最後に、漁港名の重複を除去するため、set関数を適用します。完成!

■補足(Excelファイルを使う)
 上記のnumpy配列FHとVの設定に、以下のようなエクセルファイル(fishVol.xlsx)を利用しても良いでしょう。(pandasを使いますが、別途openpyxl, xlrdのインストールを要します。)

[参考文献]
[1] Christian Mayer, "Python One-Liners", No Starch  Press, 2020.
[2] 図録 主要漁港別水揚げ高(日本地図)とその推移, 2020.https://honkawa2.sakura.ne.jp/7400.html

2021年6月11日金曜日

ちょっと惹かれるPython1行コード(その1)

【what is this】誰でも、短くて美しいコードに憧れます。参考文献[1]には、Pythonによる1行コード(Python One-Liners)の考え方と実例がたくさん載っています。それを参考に1行コードを2つほど書いてみました。

■例題:キノコの毒性に関するデータの学習と学習結果による予測
 機械学習の分類問題として、キノコを有毒か無毒かに分類することをやってみます。図1には、キノコの色(赤、青、黄)、笠の形(丸、角)、柄の長さ(長、短)、場所(地面、樹木)の特性によって、それが有毒か無毒かのデータ(参考文献[2]から引用)があります。これを機械学習によって学習させ、さらに、その学習データが正しく分類(予測)されたかどうかを確認します。

(注)上記データは現実のキノコにそのまま当てはまるものではなく、あくまで機械学習を学ぶために用意された仮想データです。従って、実際のキノコの毒性判定には利用しないでください。

■
SVMとRandomForestの一行コード(学習と予測)
 2つの手法(SVM-サポートベクタマシンとRandomForest)によるPython1行コードとその予測結果を示します。図2は、SVMの場合です。Python numpy配列のスライシング(特性データと正解レベルを分離するため)を行い、学習(.fit)結果を予測(.predict)へ接続しています。確かに、素早く簡潔なコーディングとなりました。学習に用いたデータに対する予測結果は、正解率89%でした。9件のうち1件のみが誤まった判定となりましたが、こんな少ないデータでも良く予測できることが確認できました。


 次は、RandamForestによる場合です。こちらの結果は正解率100%でした。素晴らしい!やり方は、SVMの場合と同様です。


 なお、図1での特性データは数値で与えたが、日本語で与えたい場合は以下のようにして、別途用意した辞書型変数Dを使い、map(lambda式を使う)処理を施せばよい。以下の実行結果は、図3での実行結果と同じになります。


 上図の変数Yの計算は、以下のどちらでも良いでしょうが、2番目の方がちょっとだけ分かりやすいかもしれません。
 Y = np.array(list(map(lambda i : list(map(lambda j : D[j], i)), X)))
 Y = np.array(list(map(lambda i : [D[j] for j in i], X)))

■何のために1行コードを書くのか
 さて、参考文献[1]の最後に、以下のような叙述がありました。納得ですね。
Don't cram everything into a single line of code just to show off your one-liner superpower. Instead, why not use it to make existing codebases more readable by unraveling their most complex one-liners?
(単に何でもかんでも1行に詰め込むのではなく、複雑なコードを読みやすくするために!)

[参考文献]
[1] Christian Mayer, "Python One-Liners", No Starch  Press, 2020.
[2] 黒橋禎夫, "改訂版 自然言語処理", 放送大学教育振興会, 2020.

2021年6月9日水曜日

「強化学習理論入門」の最終章は深層学習だった

 【what is this】強化学習理論入門を書籍[1]で学んできましたが、その最終章(第5章)は深層学習でQ-Learningを行うものでした。ここでその技術を述べることはできませんが、最後の例題「あるけあるけゲーム」でその魅力に浸りたいと思います。

■DQN(Deep Q Network)
 これまでに、行動ポリシーπについて、状態価値関数Vπ(s)や、行動-状態価値関数qπ(s, a)を計算して、最善の行動ポリシーを求めることをやってきました。しかし、状態(s)の数が非常に大きい場合などは、全ての状態についてこれらの関数値を保存しながら利用することは困難となります。(例えば、囲碁の場合、盤面の状態の数は10の172乗というとてつもない数になると言われています。)
 そういう状況で、状態価値関数や行動-状態価値関数の近似値を、ニューラルネットワークを利用して計算するというのが、この書籍[1]の最終章のテーマです。特に、先に述べたQ-Learningをニューラルネットワークで行うのが、DQN(Deep Q Network)です。また、この実行性能をさらに高めるために、「モンテカルロ・ツリーサーチ」の基本(実行時の一歩先読み)についても取り上げられています。

■DQNによる「あるけあるけゲーム」
 ここでとりあげる「あるけあるけゲーム」の規則は、図1の右側の説明にあります。キャラクターは障害物(および自分の辿った場所)を避けて、できるだけ長く歩く、というものです。何の方策もなく歩くと、図1の結果のように、長さ(Length)5程度で短く終わる場合が多いです。自分の軌跡に戻ってしまってゲーム終了となる場合も多いです。


 これに対して、DQNで一定程度学習した後に歩かせると、図2のとおり、長さ20程度まで伸びる場合が多いです。


 このDQNでの学習結果を使って、実行時にさらに一歩先読みする方法(モンテカルロ・ツリーサーチの考え方に基づく)によれば、図3のとおり、著しく長く歩くことができます。なかなか素晴らしい結果だと思います。


■上記DQNの構成と実行時間
 このゲームを、如何にしてベルマン方程式に結びつけるか(アクション、報酬、状態の設計)、そして、さらにどのようにニューラルネットワークで学習させるのか、それを学べるのが、この書籍の第5章なのです。図4はその最終的な結論としてのDQNのネットワーク構成です。詳細を掴むにはこの書籍を読んで戴く必要がありますが、画像認識で多用されている畳み込みフィルター(conv2d層)が使われている点がポイントの一つです。これは、別々のレイヤーに置かれたキャラクタと障害物の位置関係を把握するためです。


 畳み込みフィルタ(5x5を8種)、隠れ層2層(2,048ニューロンと1,024ニューロン)などが含まれているので、辺の重みやフィルタ値など合計で約500万個のパラメータを最適化することになります。そのため、Google Colab(GPU利用)で、図2に示した学習に約30分を要しました。しかし、パラメータ数は膨大のようにみえますが、上記のゲーム場面のすべての状態数よりははるかに少ないです。

■本書[1]で学んだ感想
 基礎から始めて高度な強化学習理論が実に丁寧に説明されており、最後まで挫折せずに読めました。書籍によっては、最初は緻密な説明がなされていても、途中から杜撰な叙述になったり、急に飛ばしはじめたりする場合もあるのですが、本書は全くぶれることなく、最後まで緻密な説明で貫かれています。Pythonのコードの説明も、同様に非常に詳しく、読者にとってとてもありがたい。完全に理解したとは言えないかも知れないが、この強化学習理論の専門書(5章構成、全283ページ)を丸々一冊読み上げたということで、力がついた気がします。
 なお、著者自身によって、この書籍全体を要約解説したスライド50枚も公開[2]されており、(本書を読み終わった後に)知識を整理するのに大いに役立つと感じました。

■本書に関する小生のブログ記事
 実は、この書を読みながら、自分のメモとして、これまでに、以下の記事をこのブログに書いて来ましたので、よろしけばご参考にされたい。

[第1章] 強化学習のゴールと課題
[第2章] 環境モデルを用いた強化学習の枠組み
[第3章] 行動ポリシーの改善アルゴリズム
[第4章] サンプリングを用いた学習法
[第5章] ニューラルネットワークによる関数近似
 ・「強化学習理論入門」の最終章は深層学習だった(↑今回の記事)

[参考文献]
[1] 中井悦司:ITエンジニアのための強化学習理論入門、技術評論社、2020年7月
[2] 中井悦司:60分で学ぶ「強化学習理論入門」、2020/09/04
https://speakerdeck.com/enakai00/60fen-dexue-bu-qiang-hua-xue-xi-li-lun-ru-men?slide=50

2021年6月4日金曜日

強化学習:モンテカルロ法とQ-Learning

【what is this】強化学習に関するさらなる続編です。前回のレンタカーショップ問題とは異なり、環境モデルが分からない場合の例としての迷路問題をとりあげます。そして、その解法としての、モンテカルロ法とQ-Learningの性能を観察します。

■迷路問題とレンタカーショップ問題
 先のレンタカーショップ問題では、ある状態Sにおいて行動aを取った場合に、得られる報酬rと次の状態S'が起こる条件付き確率が分かっている(計算できる)必要がありました。しかし、現実の問題ではそれを満たさない場合も多いです。以下に述べる迷路問題(開始点から終点までの最短経路を求める)もその一つです。

■モンテカルロ法とQ-Learning
 ここでは、迷路問題に対する解法として、モンテカルロ法とQ-Learningなどを検討しています。本記事は、実際のところ、これまでと同じく、中井悦司著[1]の第4章を学んだ成果を簡単に書いたものです。
 モンテカルロ法では、上に述べたような条件付き確率に頼るのではなく、シミュレーションによって、行動aに対して得られる結果の情報にもとづいて学習を行います。この方法では、シュミレーションのエピソード(episode:開始点から終了点に達する)が完了した情報が必要です。これに対して、Q-Learningと呼ばれる方法は、エピソードの完了を待たずに、1ステップ分の新しい情報を使って学習を進められる点が特徴です。

 手法の詳細は、参考文献[1]などをお読みいただきたいのですが、ここでは結果だけを示して、さらに知識を深める手掛かりとしたいと思います。図1は、両方法による迷路の最短経路の探索結果です。開始点(S)からゴール(G)を目指して、壁(#)を避けながら、上下左右のいずれかへ進みます。両方法で辿ったパスは違っていますが、ともに最適解になっているはずです。注目すべきは、学習に要した時間です。Q-Learningの方が圧倒的な高性能を示しました。


 これらの性能をさらに明確に示しているのが、図2です。学習中にどれだけの長さのepisodeを得たかを比較しています。モンテカルロ法では、初期の段階では、非常に長いepisodeを取得しながら学習しています。つまり、長いパスをさまよってなかなかゴールへ辿り着かない状況となっています。これに対して、Q-Learningでは、開始まもなく、急激に短いパスとなり、効率的に学習が行われていること示しています。


■感想
 冒頭に述べた中井悦司著[1]では、今回の第4章(Q-Learningあたり)がクライマックスと言えましょう。しかし、書籍全体の約6割を占める第3章「環境が分かっている場合」の状態価値関数による(ベルマン方程式に基づく)統計学的な厳密解の求め方までで、それに必要な基礎は出来上がっています。つまり、第3章まで熟読すれば、第4章はスムーズに理解できるはずです。この書では、非常に丁寧な叙述が特色であることを強く感じます。また、確認のためのPythonコードについても詳しい説明がついていますので、少なくとも、Pythonの初級を終えていれば、理解にはほとんど困らないと思います。

[参考文献]
[1] 中井悦司:ITエンジニアのための強化学習理論入門、技術評論社、2020年7月

2021年5月28日金曜日

レンタカーショップ問題(強化学習での行動ポリシー最適化)

    【what is this】強化学習における「状態価値関数」をとりあげてきましたが、今回もその続編です。理論と手法の詳細は参考文献[1]を熟読戴くことにして、ここでは、「レンタカーショップ問題」と呼ばれる複雑な問題がこれに基づいて解けることを楽しみたいと思います。

■レンタカーショップ問題(Jack's Car Rental)
 この問題は著名なSuttonの著作[2]にありますが、簡潔に1ページに纏められており、そこから自分でプログラムを作るのは難しそうです。しかし、中井悦司著[2]では、実に丁寧にこの問題の設定と具体的な解法(Pythonプログラム付き)が解説されており、非常に有用です。このブログ記事は、それにしたがって学んだ結果を小生なりにまとめたものです。

 図1に、この問題の設定条件を示しました。2つの店Aと店Bを持つオーナーが、車貸出しによる利益を最大にするために取るべき行動(戦略)を求めます。その行動とは、営業終了後の夜間に、2つの店の間で適当な台数の車を移動させることです。両店の貸出し/返却の台数の発生確率が異なるため、翌日の営業に備えて、両店の車の台数を調整する必要があるのです。ただし、車を移動することで一定の損失(余分なガソリン代など)が発生します。


 両店の貸出し/返却の台数の発生確率は、ポアソン分布に従っており、その期待値は図1の説明文にあるように分かっているとします。図2に示すような確率分布となります。


■マルコフ決定過程における確率的な状態遷移
 この問題を解くためのベースとなる状態遷移を図3のように定めます。ある時点の状態は、店Aと店Bに現在残っている車の台数のペアとします。営業終了時(午前中は貸出しのみ、午後は返却のみ)の状態をSとします。それに対するアクションa(行動a)は、夜間に店Aから店Bへ|a|台の車を移動させることを意味します。逆向きの移動ではaの値は負値になります。その行動が終わり、さらに翌日の営業が終了した時点の状態をS'とします。つまり、状態Sにアクションaを適用した結果の状態がS'です。

 状態S'では、車の移動による損失と、貸出しによる利益が確率から計算されています。貸し出し/返却台数は乱数で決まるので、図3の遷移は、確率的な状態遷移を含むマルコフ決定過程といえます。この状態遷移をもとに、先の記事でも述べたベルマン方程式を作ることができます。ベルマン方程式を解くことは、各状態の価値(状態価値関数)を計算することになります。

 そして、状態価値関数はアクションaによって決まるわけであり、どの状態に対しても最も大きな状態価値観数値を与えるアクションを求める方法があります。その一つが、ここで使われている価値反復法と呼ばれるものです。

■価値反復法によるレンタカーショップ問題の最適解
 この方法は(詳細はここには書けませんが)、行動-状態価値関数計算とGreedyポリシーの更新と状態価値関数の更新をセットとして、全ての可能な状態(店Aと店Bに残っている台数のあらゆる組合せ)について行います。それを、すべての状態について変動がなくなるまで反復します。反復一回あたり計算量(可能なあらゆる台数についての確率計算を含む)は相当に大きくなりますが、種々の効率化手法がとられます。最終的には、比較的少ない反復回数(数十回程度)で収束解(最適解)が得られるようです。図4は、収束の途中の解(行動ポリシー)を示しています。


 そして、図5は、収束した最適解(最適行動ポリシー)の拡大図です。一つのマスは、一つの状態(店Aと店Bに残っている台数のペア)です。マスの中の数値は、店A→店Bへ|a|台の車を移動するという行動を意味します。この結果を眺めてみて、十分納得ができるように思います。

 全体としては、残っている台数が両店間で偏っている場合は、それを補正する方向になっています。ただし、両店の貸出し台数の期待値(ポアソン分布の)の違いを反映して、店Aから店Bへの移動が多くなっています。
 例えば、店Aに15台、店Bに2台残っている状態では、限度いっぱいの5台を店Bへ移動すべきとなっています。これは、店Bの方がポアソン分布の期待値が大きいことを反映しています。逆に、店Aに2台、店Bに15台残っている状態では、店Bの方が期待値は大きいものの、店Bから1台を店Aへ(少し損失は生ずるが)移動した方が全体の貸し出し数は増えるという判定となっています。


 図5の最適行動ポリシーによる状態価値関数の値を図6に示します。両店にともに車が多く残っている方が、翌日の営業での利益を大きく期待できることを示しており、これも納得できます。

■感想
 冒頭に述べた中井悦司著[1]は、全体で5章の構成、本文全276頁です。今回の話題は、そのうちに第3章(全体の約6割)までの集大成と言えます。つまり、状態遷移を表す条件付き確率が全て計算できる「環境が分かっている」場合の基本的な強化学習理論の結論であると言えましょう。

[参考文献]
[1] 中井悦司:ITエンジニアのための強化学習理論入門、技術評論社、2020年7月
[2] Richard S. Sutton and Andrew G. Barto, "Reinforcement Learning : An Introduction", second edition, The MIT Press, 2018.

2021年5月22日土曜日

MIT App Inventor Summer Appathon(ハッカソン)のご紹介

すでにご存知の方も多いと思いますが、簡単にご紹介致します。


このハッカソン(Appathonとなっていますが)、名称の通り、MIT App Inventorを利用します。この開発環境には、各種Webサービス連携、データベース機能(CloudDB, FirebaseDB等)、種々の組込みセンサや外部ボードとの連携(シリアル、BLE等)、豊富なGUIやメディア機能、JavaやJavaScriptの呼び出し、等々が標準装備されています。さらに、多彩なExtensions(特に機械学習関係、Unixコマンド使用、等々)も続々提供されています。

大学でのセミナーや卒研レベルにも有用かと思います。下記の通り、混成チームもありですから、この沈みがちな時世に、教員と学生が絆を深める(強める)機会として共同で挑戦と言うのもありそうです。

他のコンテストなどと同様に、創造的発想が重視されますが、それを実現したスマホアプリの提出が必須です。審査員は、提出されたソースコードを可能な限りビルドして動作を確認するようです。もしも、使用される外部デバイスなどを用意できない場合は、(提出必須の)ドキュメントと動作ビデオでも審査されるようです。

ハッカソンなので、開発期間はテーマ開示後2週間です。(ただし、昨年度のテーマや入賞作品を参考に、事前準備はある程度可能でしょう。)子供/大人、個人/グループ(子供大人混成含む)などのトラックがあります。例年、世界各国からかなり多数のエントリがある一方、最終的に完全な提出まで漕ぎ着ける人はそれほど多くはないようです。かなりキツそうですが、それだけにやり甲斐があるでしょう。当然ながら、未発表作品に限られます。

入賞作品はMITのサイトに大きく掲載され、世界中の人に認めてもらえるという、本来の姿の栄誉を受けられます。(入賞賞品は特にありませんが)純粋に創作活動を讃える場のように思います。

(補足)--------------
えっ、冒頭の説明があってもなお、App Inventorではもの足りない? (^^ゝ
Really? Then you are a true professional. But don't you find the following few applications that work with Java and JavaScript helpful? :-)

●例1→かなり複雑な計算を含む処理にはJavaを使う。
既存のJavaコードをブロックから呼び出す例は以下にあります。
App Inventor for Android で SVM(サポートベクトルマシン)分類

●例2→自分好みの新たなブロックをJavaで自作する。
JSONのデコード用の新たなブロックをJavaで作った例です。
A JSON Decoding Extension for App Inventor (1)

●例3→JavaよりもJavaScriptを使いたいのならば。(基本編)
Make MIT APP Inventor more powerful with JavaScript

●例4→もっとJavaScriptを活用する。(学習済みモデルの利用)
MIT App InventorとGoogle Teachable Machine2を連携させた例です。

●例5→Eddystone信号でmicro:bitと連携する。
Cooperation between micro:bit and MIT App Inventor with Eddystone signals (No.1)

2021年5月17日月曜日

利尻岳(北海道)五月の風景

  最近になって、北海道にも新型コロナウィルスに関する緊急事態宣言が発令されました。現地へ出かけることはできませんが、利尻町のホームページで公開されているライブカメラで利尻岳(利尻富士とも呼ばれる日本百名山の一つで標高1,721m)の様子を楽しむことができます。最近そこで閲覧した、残雪の美しい山の風景を以下に載せたいと思います。


●利尻町ホームページ
(注)上記写真掲載は、上記の「利尻町ホームページへのリンクを希望される方へ」の利用ガイドラインに沿って行っています。

2021年5月15日土曜日

トランザクションデータのグループ化(JavaとPython)

    【what is this】トランザクションデータなど、複数のカラム(キー)からなるデータを、特定のいくつかのカラムについて、階層的にグループ化したい場合があります。JavaとPythonを使って、簡単な例で試してみます。

 本記事で扱う小さなデータ(csvファイル)とソースコード(JavaとNotebook形式Python)はこちらにありますので、よろしければお使い下さい。

■例題:トランザクションデータ(通貨取引)のグループ化
 何をしたいのかを、図1で説明します。図1(a)は、参考資料[1]のcsvデータを若干編集したものです。先頭行は、3つのカラム名(City, Currency, Value)を示しています。2行目以降のトランザクションを集約して、右側の(b)に示すように、取引所(City)でグループ化し、さらに通貨(Currency)毎の取引額(Value)の平均値を求めたい。この処理は、初歩的なプログラミングでも可能ではありますが、恐らく、込み入ったものになるでしょう。ここでは、分かりやすく、効率的なプログラムにしたいのです。


■JavaのStream、groupingByの利用
 図2に示したJavaプログラムは、StreamとCollectionのチュートリアルである参考資料[1]を参考にしています。まず、1〜2行目で上記のcsvデータを読み込み、3行目でトランザクションを3つのカラム対応のデータに分割しますが、データの先頭行は不要なので4行目のfilterで削除します。5行目では、各トランザクションに対するオブジェクトを生成しています。そのクラスの定義は(b)にあります。このオブジェクトのプロパティを利用して、6〜7行目で、Cityについてグループ化し、さらにCurrencyについて纏めてそれらの平均値を得ています。ストリームに対するgroupingByが2重に適用されているところがポイントです。ここで、例えば、「Tranz::getCity」は、トランザクションオブジェクトに対して、一斉にクラスTranzのメソッドを適用する(Cityデータを得る)ことを意味します。8〜11行目は結果の出力表示です。


 1〜7行目までの、2重のグループ化では、if文もforループ文も使われておらず、処理の流れを把握しやすいのが魅力です。実行結果は、図1(b)のようになります。

■ Pythonのpandas、groupbyの利用
 次に同じことを、資料[2]を参考にしてPythonでやってみます。グルーピングの考え方はJavaの場合と同じですが、Pythonでの記述量は、図2(a)のように大幅に少なくできます。実質1行(4〜5行目に渡る)で、右側の(b)の実行結果が得られます!素晴らしいですね。PythonのモジュールPandasを使っており、そのなかのgroupbyが効果的に働いています。そして、Javaの場合に切り捨てた先頭行のカラム名(City, Currency, Value)が、自動的に内部で生成されるオブジェクトに対応しています。


 このように、PythonのPandasは効率的プログラミングに貢献しています。しかしながら、これで全面的にPythonの勝利ということではないでしょう。Javaの場合は、明示的に生成したオブジェクトと一連の処理がstreamとして分かりやすいという捨てがたい魅力があります。また、JavaのStream(とそしてラムダ式)は、マルチコアマシン上での並列実行性能を高めるためにあるとも言われますので、大規模データ処理の場合の性能比較も楽しみになります。

[参考資料]
[1] Raoul-Gabriel Urma, "Java SE8ストリームを使用したデータ処理(パート1 & パート2)", Oracle.com/JavaMagazine, March/April, 2014.
[2] Soner Yıldırım, "3 Python Pandas Tricks for Efficient Data Analysis",
https://towardsdatascience.com/3-python-pandas-tricks-for-efficient-data-analysis-6324d013ef39

2021年5月14日金曜日

状態価値関数(ベルマン方程式に基づく)に親しむ(その2)

   【what is this】前回の記事では、ベルマン方程式に基づく「状態価値関数」とは何かをビジュアルに表示して理解しました。そこでは、動き(行動)を決めるための特定の「行動ポリシー」についての状態価値関数を扱ったのですが、今回は、この状態価値関数の値をどの状態においても最大にする(最も優れた)行動ポリシーの自動探索です。

■2次元Grid Worldに対する状態価値関数(復習)
 図1左側の2次元の指定マスから開始して、ひとマスづつ進めて、右下隅のゴールをめざします。移動方向は上下左右ですが、それぞれ選択確率があります。ここでは、右と下へそれぞれ確率0.5で選択され、それ以外は確率0とします。このような行動ポリシーをπRDとします。移動する毎に報酬(-1という負値)が付与されます。各マスからゴールをめざして得られる報酬の合計見込み額が状態価値関数の値です。これは、統計学での「期待値」であり、これが大きいほど少ないステップでゴールします。図1右側の数値は、各マスの状態価値関数値です。ゴールGに比較的近いマスでの値の絶対値は、そこからゴールに至る移動回数と一致しています。


 ここで、中央に「落とし穴P」があることにご注意下さい。移動先がこのPとなる場合は、ただちに、ワープ確率αで左上隅に戻り、確率(1-α)でゴールへ達します。α=0.4の場合は、Pに達すると確率0.6でゴールしてしまうわけですから、Pの回りでの期待値は少し高まるでしょう。実際、例えば、Pの上と左は-6.3となっており、Pが存在しなかった場合の-7.0よりも大きくなっています。

■最適な行動ポリシーを自動的に探索する
 上記では、特定の行動ポリシーπRDについての状態価値関数を示しました。次にやりたいことは、このπRDよりも優れた(大きい状態価値関数値を与える)行動ポリシーを見つけることです。詳細は、参考文献[1]などをご覧いただきたいのですが、その具体的な方法はいくつかあります。ここでは、「ポリシー反復法」と呼ばれるものを使いました。この方法は、簡単に言えば、囲碁の場合でもそうかと思いますが、「一手だけ先読みして最適そうな手をとる」の繰り返しになります。

 ところで、上記の例題の場合、「最適な行動ポリシーπ*」とは具体的にどんなものでしょうか。それは、上記πRDでの確率は0だった左や上方向への行動も含むことになります。そして、「最適」の言葉どおり、各状態(本例ではマス)ごとに、いずれかの方向への移動の確率を1に設定することになります。具体例を図2でご覧下さい。


 落とし穴にP関するワープ確率αの値などは、図1と同じです。図2左側のマスの中の太矢印は、確率1となった行動(移動方向)を示しています。Pの左側と上側の矢印は、積極的に落とし穴Pへ向かっています。これは最適行動ポリシーとして納得できるでしょう。図2右側は、その場合の状態価値関数ですが、こちらも同様に納得できます。

 さらに図3をご覧ください。ワープ確率α=0.1の場合は、もっと高い確率(=0.9)で素早くゴールに達することができるため、Pの広範な周辺のセルからの移動がPに向かっています。これが最適ポリシーになることも理解できます。


 今回の記事はこれでお終いですが、最後に、もっと大きなグリッドで、この技術の素晴らしさを楽しみましょう!美しい図4の結果をご覧下さい。


■まとめ
 分かってしまえば、それほど難しくありません。しかし、「状態の価値」という捕まえ難い概念を、コンピュータで扱えるようにしたこの理論と手法は素晴らしいです。これを最初に編み出した先人に敬意を表したい気持ちになります。さらに、一歩づつ先へ進みたいと思います。また、参考文献[1]の丁寧で精緻な叙述は、学習意欲を維持するのに非常に大きく貢献しています。本記事は、これ基づいて(説明文や図は小生の自作ですが)書きました。

[参考文献]
[1] 中井悦司:ITエンジニアのための強化学習理論入門、技術評論社、2020年7月

2021年5月10日月曜日

状態価値関数(ベルマン方程式に基づく)に親しむ(その1)

  【what is this】現代AI技術において、強化学習(Reinforcement Learning)は重要です。これをご存じ無い方、または、(実は私もこれに該当しますが)少しは知っているがもっと明確にしたい方のために、ベルマン方程式に基づく「状態価値関数」とは何かをビジュアルに観察して、親しみを持ちましょう。さらに先をめざす手掛かりとして。

■ベルマン方程式にもとづく状態価値関数
 詳細を把握するには、例えば中井悦司著の強化学習に関する書籍[1]を読んでいただく必要がありますが、ここでは、状態価値関数の一面に親しむことにします。実際、以下の内容は、この書籍の第2章(pp.45-100)を学んで得られる成果(結論)なのです。

■例題:2次元Grid Worldに対する状態価値関数
 強化学習の定番例題のひとつに、2次元GridWorldがあります。そのバリエーションは多様ですが、ここでは図1のような設定にします。すなわち、2次元の特定のマスからひとマスづつ進めて、右下隅のゴールをめざします。ただし、進行方向は右か下かに限定され、それぞれ1/2の確率で選択されます。どのマスから開始すれば少ない移動回数でゴールできるでしょうか。(この例ではそれは自明かも知れませんが、一般的な解決手法を得たいのです。)

 ここで「状態価値関数」とは、各マスからゴールへ到達するという観点から、そのマスの価値(有利性)を示すものと言えます。統計の言葉で言えば「期待値」です。本例では、移動する毎に報酬(-1という負値)を与えることにします。従って、報酬の合計が大きいほど、少ない回数でゴールできます。この報酬と上記の移動確率などから「ベルマン方程式」というのが導出され、その解が「状態価値関数」に相当します。

 詳細理論はおいておき、本例に対する状態価値関数をみてみます。図1(a)では、予想どおり、左上隅から右下隅方向へ向かって、「価値」が高くなっています。マスの上の数値が状態価値関数の値であり、それが大きいほど価値が高いです。グラフでは、赤が濃いほど大きな数値で、青が濃いほど小さな数値を示しています。


 一方、図1(b)では、中央に「落とし穴」を設定しました。移動先がこの穴Pとなる場合は、直ちに、左上隅へ戻るか(確率=0.9で)、右下隅ゴールへ(確率=0.1で)移動してしまいます。したがって、これは確率的に不都合な落とし穴です。実際、この落とし穴の上、左、左上方向のマスの価値は低くなっています。図1(c)は、これとは逆に好都合の落とし穴です。落とし穴の上、左のマスの価値は高くなっており、この場合も納得できる結果が得られています。

 さらに、以下の図2は、グリッドを19x19に拡大した場合です。図1に比べて、より鮮明な結果をみることができます。


■まとめ
 ここでは、マスの右と下へある確率で移動する、という特定の行動ポリシーのもとで状態価値関数をみました。別の行動ポリシー(例えば、右と下へ移動する確率が均等でなかったり、斜め方向にも移動するなど)の場合は、当然、この状態価値関数は変わります。また、どのマスから開始しても、いつもこの関数値が一番大きくなる行動ポリシーを見つけることや、大規模なworldに対する状態価値関数の効率的な計算法も大きなテーマになります。

[参考文献]
[1] 中井悦司:ITエンジニアのための強化学習理論入門、技術評論社、2020年7月