kerneltyu’s tech blog

理系学生です.

【論文】Human Feedback as Action Assignment in Interactive Reinforcement Learning

こんにちは、ご無沙汰です。今回は読んだ論文の内容のまとめをここに記録しようと思います。自分は強化学習に対して人の知識を転移するというような研究をしていて、Human-friendlyな転移方法は何か?ということに興味を持っています。自分用のメモのように記述しているので、なんのこっちゃ分からないかも知れませんが、ご容赦ください。スキムした程度で、全体像をぼんやり掴んだという状態で書いてます。

論文情報

ジャーナル論文です。2020年、ACM Transactions on Autonomous and Adaptive Systemsで掲載されています。University of Technology Sydneyの人たちで、Syed Ali RazaさんとMary-Anne Williamsさんの2人。自分は初めて見た人たち。

要約

Interactive Reinforcement Learningの枠組みで人がエージェントの状態-行動を見て評価する方法と人が現在の状態を観測して、好ましい行動を選択する方法をSokobanドメインで比較したところ、後者の方が人が教示しやすかったという内容。ベースはReward Shapingで、どちらも報酬値としてエージェントに人の知識を伝播させる。与え方が異なるだけ。

方法

Shaping from Reward Assignment

人が与えた報酬を環境から生成される報酬地に足し合わせる方法。人が与える報酬は4段階や7段階で離散的に与える。

Shaping from Action Assignment

人が与えた行動を報酬値に変換し、環境報酬に足し合わせる方法。人は状態を見て、行動を与える。


\pi^h_t(s) = a_b

人が与えた行動を上記で記述すると、生成する報酬関数は下記のように記述する。


H^d(s,a,s') = \Omega(\pi^h_t(s), \pi_t(s))

人が選択した行動とエージェントが選択した行動を比較する関数\Omegaを通した結果を報酬値とする。関数\Omegaは、具体的に書くと、


H^d(s,a,s') = \left\{ \begin{array}{l}
1&\mbox{if } \pi_t^h(s) = \pi_t(s) \\
-1&\mbox{otherwise.}
\end{array} \right.

エージェントが選択した行動と人が選択した行動が一致すれば正の報酬、一致しなければ負の報酬という関数。

感想

人が自分で行動を選択する方がエージェントの状態行動を観測して評価するのより、与えやすいというのは直感通りな結果。状態行動を観測して評価を与えるという枠組みだと、自分にとって好ましい行動を選択するまで観測をしないといけない。それだったら、自分で直接やってしまうよとなるのは自然な気もする。けど、これって人が簡単に行動を伝えれる場合っていう前提がある気がする。人にとって操作が難しいようなドメインの場合では成り立たない。Sokobanでの検証しかなくて、Sokobanはこの前提が成り立つドメイン。実験の組み立てや評価の仕方などは参考にできるところが多いので、これからじっくり読んでいこう。

追加調査

  1. HRIの評価方法であるNARSやGodsped questionnaire、RoSAS
  2. novelty effectについて
  3. Natural instructions to obtain rewards from a human分野
  4. Newtonian Action Advice & Bayesian Q-learning

DeepMindLabのPython Module導入

前回の投稿から続いて今度はDeepMindLabのPython Moduleの導入をします。 これによってOpenAIgymのような形で、pythonによるプログラムで環境から観測を受け取ったり、行動を環境に適用させたりすることができます。

Python Moduleの導入に関しては、下記に記述があるので、それにそって書きます。

github.com

インストール

$ git clone https://github.com/deepmind/lab.git && cd lab
b$ azel build -c opt --python_version=PY3 //python/pip_package:build_pip_package
./bazel-bin/python/pip_package/build_pip_package /tmp/dmlab_pkg
$ pip install /tmp/dmlab_pkg/deepmind_lab-1.0-py2-none-any.whl --force-reinstall

これでインストールができたかと思います。下記のテストコードを走らせると

import deepmind_lab
import numpy as np

# Create a new environment object.
lab = deepmind_lab.Lab("tests/empty_room_test", ['RGB_INTERLEAVED'],
                       {'fps': '30', 'width': '80', 'height': '60'})
lab.reset(seed=1)

# Execute 100 walk-forward steps and sum the returned rewards from each step.
print(sum(
    [lab.step(np.array([0,0,0,1,0,0,0], dtype=np.intc)) for i in range(0, 100)]))

おそらく、

ModuleNotFoundError: No module named 'dm_env'

というエラーに遭遇します。これは単純にdm_envというモジュールが無いだけなので落ち着いてpip installします。

pip install dm_env

これでテストコードが走るようになるかと思います。

以上!

DeepMindLabのインストール

1年ぶりの投稿になります。お久しぶりです。

インストールで詰まったときの解決策ばかりになるような気もしますが、自分でも見返すんでどんどんメモっていこうと思います。

3年前くらいに強化学習の環境のプラットフォームがどんどん公開されていたときにGoogleDeepMindが公開した強化学習用のプラットフォームのDeepMindLabをインストールしたときに詰まったところをメモしておきます。

DeepMindLabのGitHubこちら

基本的にはREADMEに従えばインストールできます。ちなみにUbuntuにしか対応していません。Macは明示されていませんが使えるらしい。Branchにmacosっていうのがありますね。ただ、自分のMacではうまく行かなかったような気がします。

環境

まずは自分のPC環境はUbuntu LTS 18.04です。Pythonは3.7を使いました。

手順

Bazelのインストール

はじめにビルドツールはBazelを使うので、Bazelをインストールします。

docs.bazel.build

Ubuntuの項目を見て手順に従うと、(他のOSの方はそのOSにあった手順に従ってください。) はじめに、パッケージのダウンロード元をaptに追加する。

$ sudo apt install curl
$ curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
$ echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list

次に、

$ sudo apt update && sudo apt install bazel

インストールをします。 最後に、JDKをインストールします。これは任意です。Javaのコードをビルドしたいときだけです。今回必要無いかと思いますが、一応。

$ sudo apt install openjdk-8-jdk

これでBazelのインストールは終わりです。

DeepMindLabのインストール

次にDeepMindLabのインストールです。git cloneで落としてきます。

$ git clone https://github.com/deepmind/lab.git

これでbazelコマンドを使って、実行すると...

$ cd lab
$ bazel run :python_random_agent --define graphics=sdl -- \
               --length=10000 --width=640 --height=480

下記のメッセージが出て、実行できませんでした。

No package 'libffi' found
中略
FAILED: Build did NOT complete successfully
FAILED: Build did NOT complete successfully

どうやらlibffiが無いとのこと、なのでlibffiをインストールしましょう。 いくつか探していると。

$ apt-get install libffi-dev

でインストールできるとのこと(意外とここに時間がかかった)。インストールして実行すると....

$ bazel run :python_random_agent --define graphics=sdl -- \
               --length=10000 --width=640 --height=480

f:id:kerneltyu:20191204181414p:plain

実行できました!!ランダムエージェントなのでメチャクチャな動きしてます、、、、

これでやっとDeepMindLabで遊べますね〜

追記

なかなか良いレポジトリを発見しました。 ここのWikiの手順通りに進めればよさげ。 github.com

【メモ:本】Tensorflow活用ガイドのサンプルコードで躓いた時の対処

機械学習アプリケーション開発入門TensorFlow活用ガイドの4章 自然言語処理サンプルコードWindows上で動かそうとしたときに詰まった個所とその対処法について残します.4-3文書の分類のコードについてです.

環境

エラーとその対処

Traceback (most recent call last):
  File "classify\preprocess.py", line 164, in <module>
    exit(main(sys.argv[1:]))
  File "classify\preprocess.py", line 150, in main
    args.valid_samples
  File "C:\Users\kernel\Miniconda3\envs\tensorflow\lib\random.py", line 318, in sample
    raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative

サンプルが適切じゃない旨のエラー,確認してみると,正しくデータを入力できていなかったみたいです.問題は54行目あたりのdata_generatorメソッドへの引数であるvalid.pathがすべてNaNになっているのが問題でした.さらに調べると

df.reindex([np.random.permutation(df.index)])

この命令後にdfの要素がすべてNaNになっていました.これは,以下のように変更することで改修できました.

df.reindex(np.random.permutation(df.index))

np.random.permutation(df.index)でndarray型が返ってくるにも関わらず多次元リストにして渡していたのが良くなかったみたいです.ここを直すと次は以下のようなエラーが返ってきました.

Traceback (most recent call last):
  File "classify\preprocess.py", line 165, in <module>
    exit(main(sys.argv[1:]))
  File "classify\preprocess.py", line 147, in main
    save_data(data_generator(train.path, train.label), train_output_path)
  File "classify\preprocess.py", line 67, in save_data
    for x, y in generator:
  File "classify\preprocess.py", line 57, in data_generator
    for line in i_:
UnicodeDecodeError: 'cp932' codec can't decode byte 0x81 in position 4: illegal multibyte sequence

うん,Windows特有のやつですね.Windowsはファイルを読み込むときに指定が無ければ,自動でcp932に変換されるらしいので,utf-8を指定してあげなければなりません.

qiita.com

data_generatorメソッド内のopenメソッドに指定がなかったので,以下のように修正.

with open(path, encoding=ENCODING) as i_:

これで無事に動きました.

今更ながら方策反復(Policy iteration)を勉強(実装)してみた

 こんばんは,大学院に進学してから本格的に機械学習の勉強をし始めました.その学習記録を残そうかなと思います.まぁ,自分で実装したアルゴリズムとかだけを書いていくつもりです.
 今回は,強化学習をやっている人なら誰しも目を通したことがあるはずのSutton本から方策反復(※方策勾配法じゃないよ)の説明と実装を共有しようと思います.なんで方策反復かというと調べてパッと出て来なかったっていう理由です(笑)
 強化学習の基礎はわかっているという前提で話を進めていきます.強化学習については調べたら色々Webページが出てくるので,それを見てください.下記の記事なんかいいじゃないでしょうか?方策反復(Policy iteration)についてざっくり触れられています.

qiita.com

方策反復(Policy iteration)とは?

 有限MDP(マルコフ決定過程)が与えられた時に,方策の評価と方策の更新を繰り返し行い,最適な方策を得るアルゴリズムのことです.動的計画法の一種で,計算結果をメモリで保持しながら繰り返し計算を行います.現在の一般的な強化学習は,MDPに関する情報を完全には必要としないのですが,今回の方策反復はMDPの情報を完全に必要とします.Model-basedな手法であるとも言えます(最近よく聞くModel-basedな手法はモデルの完全な情報が所与ではなく,モデル自体の学習と方策の学習の両方を行うので,区別してください).有限MDPの情報を完全に必要とするということがどういうことかというと,報酬関数 R(s,a,s') と状態遷移関数P(s,a,s')が完全にわかっている(入力として与えられる)ということを意味しています.これらの情報が自明であれば,動的計画法を用いて最適な方策を求めることができます.
 今回はエピソード的タスクで,特殊な状態(終端状態)をもつタスクを考え,強化学習の文脈で(昔は)よく使われた迷路問題を扱います.

用語の定義

 アルゴリズムの説明の前に今後使用する変数や関数を表す表記,タスクの定義をしておきます.まず,変数や関数の定義は以下の通りです.

表記 意味
 a \in A 行動集合Aに含まれる行動
 s \in S 状態集合Sに含まれる状態
 s' \in S^{+} 終端状態を含む状態集合[tex: S^{+}から得られる状態
 r_{t} tステップで得られた報酬
\pi(a|s) 状態sで行動aを取る確率.これが方策
\mathbb{E}_{\pi} 方策 \pi の元での期待値
\(v\) 状態価値関数

 次に,タスクについてです.扱う迷路問題は以下のような迷路です.Sutton本に書かれているのと同じ形式です.

f:id:kerneltyu:20180610235202p:plain

 上図に示した通り,行動は上下左右の4つが可能であり,各マスが状態を示しており,1-14が各状態の識別子として割り振られています.色付きのマスが終端状態であり,図には書かれていませんが,それぞれ0と15とナンバリングをします.Sutton本では,全ての遷移(状態からの行動)に対して-1の報酬が獲得されるという設定です.しかし,今回は終端状態への遷移で+1の報酬が獲得され,それ以外は報酬が獲得されないという設定にします.どちらの報酬設定でも良いのですが,ちょっと変えてみました.方策は決定的であるとします.
 さて,この迷路問題タスクにおいてそれぞれの(終端状態以外の)状態から終端状態に到達するまでの最短経路を導く方策を導きます.

方策反復(Policy iteration)の手続き

 方策反復の具体的な手続きについて見ていきます.早速いかに,疑似コードを示します.Sutton本からの引用です.

f:id:kerneltyu:20180611194211p:plain

 方策反復は大きく3つのステップに分かれます.初期化(Initialization)と方策評価(Policy evaluation)と方策更新(Policy improvement)です.初期化では,状態価値関数と方策の初期化を行います.実装ではどちらとも \mathbf{0} で初期化しました.方策反復では,方策の更新がされなくなるまで繰り返し,方策評価と方策更新を繰り返します.方策評価では,更新量 \delta\theta よりも小さくなるまで,全状態の状態価値関数 V(s) の更新を繰り返し行います.方策更新では,すべての状態に対して,行動の価値 \sum_{s',r} p(s',r|s,a)[r+\gamma V(s')] が最も大きい行動を状態 s における行動aとして更新を行います.

方策評価とは?

f:id:kerneltyu:20180611214141p:plain
 方策評価とは字面の通り,方策を評価する手続きのことを指します.方策の評価は,状態価値関数\(V(s)\)を更新することによって行います.なぜ状態価値関数の更新が方策の評価になるのかというと,方策が状態価値関数によって決定づけられるからです.これについては方策更新の項目で説明をします.
 ここでは,方策評価における状態価値関数の導出について説明します.そもそも強化学習は期待報酬を最大化するような方策を学習することが目的である枠組みです.期待報酬は,状態価値関数V(s)や行動価値関数Q(s,a)(いわゆるQ値)の形で表されます.ここで方策\piで得られる状態価値関数をv_{\pi}(s)とすると,
$$ \begin{align} v_{\pi}(s) &= \mathbb{E}_{\pi}[G_t|S_t=s] \\ &= \mathbb{E}_{\pi}[R_{t+1}+\gamma G_{t+1}|S_t=s] \\ &= \mathbb{E}_{\pi}[R_{t+1}+\gamma v_{\pi}(S_{t+1})|S_t=s] \\ &= \sum_{a} \pi(a|s) \sum_{s',r} p(s', r|s,a)[r+\gamma v_{\pi}(s')] \end{align} $$

 上記のような式を得ることができます.ここで,決定的でない方策\pi(a|s)の場合は確率値をとるのですが,今回は決定的な方策\pi(s)を考えるので,導出した式は以下のように書き変わります. $$ \begin{align} v_{\pi}(s) &= \mathbb{E}_{\pi}[R_{t+1}+\gamma v_{\pi}(S_{t+1})|S_t=s] \\ &= \sum_{s',r} p(s', r|s,a)[r+\gamma v_{\pi}(s')] \end{align} $$  期待値計算で行動の確率値を考える必要がなくなったということです.この式が先ほど示した状態価値関数の更新で用いられている式を表しています.ここでこの更新の意味を考えてみると方策を更新する前の状態価値関数を更新後の方策\pi(s)を取った時に得られる状態価値関数に更新するために繰り返し計算していることになります.

方策更新とは?

f:id:kerneltyu:20180611214145p:plain
 方策更新は,先ほど説明した方策評価で得られた状態価値関数v_{\pi}(s)でgreedyになるような方策に更新する手続きです.ここで,行動価値関数について少しふれておきます.行動価値はある行動a をとった時の期待報酬を表しています.状態価値との違いとしては,行動aをとった時というところです.状態価値は,状態sでとれる行動すべてを考慮しなければなりませんでしたが,行動価値は,状態sで行動aを取った時のみを考慮します.すなわち状態sで行動aを取った時の期待報酬を表しています.この行動価値によって行動aがどれほど良いかを測ることができます.行動価値関数q(s,a)を以下に示します. $$ \begin{align} q_{\pi}(s,a) &= \mathbb{E}[R_{t+1}+\gamma v_{\pi}(S_{t+1})|S_t=s, A_{t}=a] \\ &= \sum_{s',r} p(s', r|s,a)[r+\gamma v_{\pi}(s')] \end{align} $$ 実はさっき示した決定的な方策をとった時の状態価値関数とほとんど同じなんですよね(笑).でも,行動aか方策\pi(s)かが違います.よく見てください.この行動価値関数が,方策更新では使われます.方策を更新している個所を見ると,状態sにおいて可能な行動aの行動価値関数で最も大きい行動価値を得ることのできるaを方策として採用しています.
 これでなんで最適な方策が得られるのとかはSuttonの本を読んでください.参考文献で示します.

実装コード

実装では,下記のページでOpenAiGymをベースにした迷路問題を用いていたのでそれを参考にさせていただきました.というよりここで方策反復が触れられてなかったからこのブログ書いたまである.

qiita.com

コードは僕のGitHubにあります!

実行結果

f:id:kerneltyu:20180611230343p:plain

 上記のような結果が得られるかと思います.迷路問題と初期の状態価値関数,初期の方策,学習後の状態価値関数,学習後の方策を示しています.学習後の状態価値関数を見ると終端状態に近いほど高い状態価値が得られていることがわかります.学習後の方策ではどの状態からスタートしたも終端状態に最短距離で到達することが確認できると思います.
 コードを少しいじれば5×5迷路問題と拡張できると思います.更新で全状態と全行動に対して計算を行うので少なくともO(|S||A|)の計算量がかかるので迷路のサイズをあまり大きくしすぎると計算が終わらないと思います.

おわりに

以上, 方策反復について解説してみました.疲れた...けど楽しいですね!今後も書いていけたらなと思います.間違いとかあれば気軽に指摘してください(^^)b

参考文献

[1] Richard S. Sutton and Andrew G. Barto, Reinforcement Learning: An Introduction Second edition, http://incompleteideas.net/book/bookdraft2017nov5.pdf, 2018/6/11参照.
[2] @neka-nat, 逆強化学習を理解する, https://qiita.com/neka-nat@github/items/aaab6184aea7d285b103, 2018/6/11 参照.

TensorflowでFutureWarning: Conversion of the second argument ... が出た時

お久しぶりです.

Tensorflowを本格的に始めようとしてTensorflowをインストールをしました. インストールできたはいいものの,FutureWarningが出てしまいました.実行には何の問題もないんですが,出力が非常に見にくい! 調べて見たら,issueに改善方法が書かれていたので,メモ代わりにここに残しておきます.出たFutureWarningが下記です.


/Users/kerneltyu/anaconda3/envs/RL/lib/python3.6/site-packages/h5py/__init__.py:34: 
FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`. from ._conv import register_converters as _register_converters
    

まぁ,h5pyに問題があるのは一目瞭然で,h5pyのissueを見に行ったら,解決策が載っていました.


pip install h5py==2.8.0rc1
    

こいつでh5pyのバージョン2.8.0rc1をインストールしてあげれば,FutureWarning出なくなりました.

Anaconda仮想環境構築からOpenAi Gymのフルインストール

前回にOpenAiGymの導入でのエラーについて書いたが、今回はAnacondaで作成した仮想環境上でフルインストールを行いました。 まずAnacondaで仮想環境を作成して、activateする手順です。 仮想環境は、pythonのバージョンとかライブラリの管理が楽になるので使います。

//仮想環境の構築
Orion:~ kerneltyu $  conda create -n RL python=3.6 anaconda
//仮想環境RLのactivate
Orion:~ kerneltyu $ source activate RL
(RL) Orion:~ kerneltyu$
(RL) Orion:~ kerneltyu$ conda info -e
# conda environments:
#
RL                    *  /Users/kerneltyu/anaconda3/envs/RL
root                     /Users/kerneltyu/anaconda3

これで仮想環境の構築とactivateはOK! これからOpenAiGymの導入をしていきます。 まず、cmakeをインストールする。(インストール済みなら省略してください)

yoshihiro-kato.blogspot.jp

上記の通りにインストール! 次にここを参考に github.com

(RL) Orion:~ kerneltyu$ cd /Users/kerneltyu/anaconda3/envs/RL/bin
(RL) Orion:bin kerneltyu $ git clone https://github.com/openai/mujoco-py.git
(RL) Orion:bin kerneltyu $ cd mujoco-py
(RL) Orion:mujoco-py kerneltyu $ sudo python setup.py install
(RL) Orion:mujoco-py kerneltyu $ cd ..

これでmujoco-pyのインストール完了 次にgymのフルインストールをします。

(RL) Orion:bin kerneltyu $ brew install cmake boost boost-python sdl2 swig wget
(RL) Orion:bin kerneltyu $ git clone https://github.com/openai/gym
(RL) Orion:bin kerneltyu $ cd gym
(RL) Orion:gym kerneltyu $ sudo pip install -e .[all]
FileNotFoundError: [Errno 2] No such file or directory: '/Users/kerneltyu/anaconda3/envs/RL/lib/python3.6/site-packages/__pycache__/cython.cpython-36.pyc'

こんなエラーが出たら

(RL) Orion:gym kerneltyu $ sudo pip install -e .[all] --ignore-installed Cython

としましょう。これで回避できるはずです。 以上でOpenAiGymのフルインストール完了です。