FC2ブログ

*All archives* |  *Admin*

<<10  2018/11  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  12>>
はじめてのpython&Tensorflowその13・強化学習苦戦中
一人麻雀の強化学習について、
環境とエージェントを組んで、方策勾配法とかActor-criticとかをやろうとしているのですが、なかなか思うような結果が出ずに苦戦してます。

たぶん環境は作れてるけど、エージェントの重みパラメータ更新のところがあやしいです。

こんな感じのコードを書いています。

class Agent:
def __init__(self, state_dim, action_dim, gamma = 1.0, learning_rate = 2e-4, seed = 123):#gamma = 0.95
# 初期化では状態と行動の次元数を設定する。
# 割引率γや学習率を設定し、エピソードの状態、行動、報酬、リターンの系列を初期化する
  (省略)

def step(self,nyuryoku_manzu,nyuryoku_pinzu,nyuryoku_sozu,nyuryoku_jihai,reward):
# 状態と報酬を受け取り、行動の確率に基づいて行動をサンプリングし、出力する
# 状態、行動、報酬は系列に保存する
action_distribution = self.policy(nyuryoku_manzu,nyuryoku_pinzu,nyuryoku_sozu,nyuryoku_jihai)#方策関数から切る牌分布を出力
action = np.random.choice(range(self.action_dim), p=action_distribution.numpy())#乱数と分布から実際の切る牌を決定
value_predict = self.value(nyuryoku_manzu,nyuryoku_pinzu,nyuryoku_sozu,nyuryoku_jihai,action)#行動価値関数から行動価値を予測する。
self.episode_states_manzu.append(nyuryoku_manzu)
self.episode_states_pinzu.append(nyuryoku_pinzu)
self.episode_states_sozu.append(nyuryoku_sozu)
self.episode_states_jihai.append(nyuryoku_jihai)
self.episode_actions.append(action)
self.episode_rewards.append(reward)
self.episode_value_predeict= np.append(self.episode_value_predeict,value_predict)
self.stepsu+=1
return action
def end_episode(self,final_reward):
# 最終的な報酬を受け取ってエピソードを終了する
# このとき、各時点を基準としてエピソードのリターンを計算する
(省略)
def reset(self):
# エピソードの系列をリセットする
(省略)

def update_policy(self):
# 方策勾配法の更新則を適用してパラメタを更新
actions_one_hot = np.array([[ 1 if i == a else 0 for i in range(self.action_dim)] for a in self.episode_actions])#actionをone-hotベクトル化
with tf.GradientTape() as tape:#Actorパラメータ更新

action_distributions = self.policy_network([tf.convert_to_tensor(np.array(self.episode_states_manzu,dtype=np.float32)),
tf.convert_to_tensor(np.array(self.episode_states_pinzu,dtype=np.float32)),
tf.convert_to_tensor(np.array(self.episode_states_sozu,dtype=np.float32)),
tf.convert_to_tensor(np.array(self.episode_states_jihai,dtype=np.float32))
])
action_log_probabilities = tf.log(tf.reduce_sum(action_distributions * actions_one_hot,reduction_indices = 1))#logπ(a|s)

loss = tf.reduce_mean(- action_log_probabilities * (self.episode_value_predeict)) #logπ(a|s)*Q(a,s)
grads = tape.gradient(loss, self.policy_network.variables) #勾配
self.optimizer.apply_gradients(zip(grads, self.policy_network.variables), global_step=self.step_counter)#勾配適用

with tf.GradientTape() as tape2:#Criticパラメータ更新
values = self.critic_network([tf.convert_to_tensor(np.array(self.episode_states_manzu,dtype=np.float32)),
tf.convert_to_tensor(np.array(self.episode_states_pinzu,dtype=np.float32)),
tf.convert_to_tensor(np.array(self.episode_states_sozu,dtype=np.float32)),
tf.convert_to_tensor(np.array(self.episode_states_jihai,dtype=np.float32)),
tf.convert_to_tensor(actions_one_hot.astype(np.float32))
])
value_loss = tf.nn.l2_loss(self.episode_rewards[-1] - values[-1])
for i in range(self.stepsu-2,-1,-1):
value_loss = value_loss + tf.nn.l2_loss(self.episode_rewards[i]+ self.gamma * values[i+1] - values[i])#TD誤差
value_grads = tape2.gradient(value_loss,self.critic_network.variables)#勾配
self.optimizer_forvalue.apply_gradients(zip(value_grads, self.critic_network.variables), global_step=self.step_counter_forvalue)#勾配適用

コードの一部を晒して、どこか通りすがりの頭のいい人に、間違ってるところを指摘してもらえたらうれしい、的な淡い願望。

環境の報酬について、
・上がったら+10点
・流局時に-1点×シャンテン数
で設定して動かしてみたのですが、報酬の移動平均(直近100エピソードの平均)をグラフ化したのがこんな感じ。

181113-01.png
学習できてる雰囲気まったくなし。うーむ。

初期方策がランダムなので、まず手牌にある牌を切ってくれるところが難関になってます。
アドバンテージ関数なるものを使ってやるのがベースライン的にいいという情報まではつかんだのですが、フィッシャー情報行列というものがいまいちよくわからんので、実装には至ってないです。

最初から方策勾配法とかActor-criticとか難しいことはしないで、素直にDQNから入ったほうがいいのだろうか?
行動価値関数QをDQNで推定して、方策の初期値は訓練データありでやったやつを入れたら多少はまともに動くのだろうか?
スポンサーサイト



プロフィール

nisi5028

Author:nisi5028
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
FC2カウンター
フリーエリア
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード