Start_python’s diary

ふたり暮らし

アラフィフ夫婦のフリーランスプラン

Deep Q-Network(DQN)エラーが大量に起こって安定しない

Deep Q-Network(DQN)による倒立振子 第1回

はじめに

今回からDeep Q-Network(DQN)を勉強します。ざっとコードを見た感じでは絶望的にまったくわかりません。

一日二日では終わりそうにないのでその日に進んだ分だけ載せていきます。十分に理解できるのには数か月もしくは理解できることはないのかもしれませんがいけるとこまでいってみます。

 

プログラムのコードは

CartPoleでDQN(deep Q-learning)、DDQNを実装・解説【Phythonで強化学習:第2回】

こちらからそのまま使わせていただきました。

 

まずはコピペで動作確認

f:id:Start_python:20191201080851g:plain

200試行を過ぎても安定しません。

 

「WARNING:tensorflow:From C:Users.condaenvsstart_pythonlibsite-packageskerasackend ensorflow_backend.py:174: The name tf.get_default_session is deprecated. Please use tf.compat.v1.get_default_session instead.」

こんなのがずらっと出てましたのでどこかでエラーが出てそうです。

f:id:Start_python:20191201081156p:plain

298試行で自動終了しましたが最後まで安定しなかったです。

 

 

モジュールとは?

関数(def)とは?

クラスとは?

メソッドとは?

 

 

プログラムのコードの解読

# [0]必要なライブラリのインポート
import gym  # 倒立振子(cartpole)の実行環境
import numpy as np
import time
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
from keras.utils import plot_model
from collections import deque
from gym import wrappers  # gymの画像保存
from keras import backend as K

# [1]損失関数の定義
# 損失関数に関数を使用します
def huberloss(y_true, y_pred):
    return K.mean(K.minimum(0.5*K.square(y_pred-y_true), K.abs(y_pred-y_true)-0.5), axis=1)


# [2]Q関数をディープラーニングのネットワークをクラスとして定義
class QNetwork:
    def __init__(self, learning_rate=0.01, state_size=4, action_size=2, hidden_size=10):
        self.model = Sequential()
        self.model.add(Dense(hidden_size, activation='relu', input_dim=state_size))
        self.model.add(Dense(hidden_size, activation='relu'))
        self.model.add(Dense(action_size, activation='linear'))
        self.optimizer = Adam(lr=learning_rate)  # 誤差を減らす学習方法はAdam
        # self.model.compile(loss='mse', optimizer=self.optimizer)
        self.model.compile(loss=huberloss, optimizer=self.optimizer)

    # 重みの学習
    def replay(self, memory, batch_size, gamma, targetQN):
        inputs = np.zeros((batch_size, 4))
        targets = np.zeros((batch_size, 2))
        mini_batch = memory.sample(batch_size)

        for i, (state_b, action_b, reward_b, next_state_b) in enumerate(mini_batch):
            inputs[i:i + 1] = state_b
            target = reward_b

            if not (next_state_b == np.zeros(state_b.shape)).all(axis=1):
                # 価値計算(DDQNにも対応できるように、行動決定のQネットワークと価値観数のQネットワークは分離)
                retmainQs = self.model.predict(next_state_b)[0]
                next_action = np.argmax(retmainQs)  # 最大の報酬を返す行動を選択する
                target = reward_b + gamma * targetQN.model.predict(next_state_b)[0][next_action]   

            targets[i] = self.model.predict(state_b)    # Qネットワークの出力
            targets[i][action_b] = target               # 教師信号
            self.model.fit(inputs, targets, epochs=1, verbose=0)  # epochsは訓練データの反復回数、verbose=0は表示なしの設定


# [3]Experience ReplayとFixed Target Q-Networkを実現するメモリクラス
class Memory:
    def __init__(self, max_size=1000):
        self.buffer = deque(maxlen=max_size)

    def add(self, experience):
        self.buffer.append(experience)

    def sample(self, batch_size):
        idx = np.random.choice(np.arange(len(self.buffer)), size=batch_size, replace=False)
        return [self.buffer[ii] for ii in idx]

    def len(self):
        return len(self.buffer)


# [4]カートの状態に応じて、行動を決定するクラス
class Actor:
    def get_action(self, state, episode, targetQN):   # [C]t+1での行動を返す
        # 徐々に最適行動のみをとる、ε-greedy法
        epsilon = 0.001 + 0.9 / (1.0+episode)

        if epsilon <= np.random.uniform(0, 1):
            retTargetQs = targetQN.model.predict(state)[0]
            action = np.argmax(retTargetQs)  # 最大の報酬を返す行動を選択する

        else:
            action = np.random.choice([0, 1])  # ランダムに行動する

        return action
# [5] メイン関数開始---------------------------------------------------- # [5.1] 初期設定-------------------------------------------------------- DQN_MODE = 1 # 1がDQN、0がDDQNです LENDER_MODE = 1 # 0は学習後も描画なし、1は学習終了後に描画する env = gym.make('CartPole-v0') num_episodes = 299 # 総試行回数 max_number_of_steps = 200 # 1試行のstep数 goal_average_reward = 195 # この報酬を超えると学習終了 num_consecutive_iterations = 10 # 学習完了評価の平均計算を行う試行回数 total_reward_vec = np.zeros(num_consecutive_iterations) # 各試行の報酬を格納 gamma = 0.99 # 割引係数 islearned = 0 # 学習が終わったフラグ isrender = 0 # 描画フラグ # --- hidden_size = 16 # Q-networkの隠れ層のニューロンの数 learning_rate = 0.00001 # Q-networkの学習係数 memory_size = 10000 # バッファーメモリの大きさ batch_size = 32 # Q-networkを更新するバッチの大記載
# [5.2]Qネットワークとメモリ、Actorの生成-------------------------------------------------------- mainQN = QNetwork(hidden_size=hidden_size, learning_rate=learning_rate) # メインのQネットワーク targetQN = QNetwork(hidden_size=hidden_size, learning_rate=learning_rate) # 価値を計算するQネットワーク # plot_model(mainQN.model, to_file='Qnetwork.png', show_shapes=True) # Qネットワークの可視化 memory = Memory(max_size=memory_size) actor = Actor()

 

解説

実際に使用されるまではdefの関数定義とクラスの定義はサクッと流します。

huberloss(関数の定義)

・ネットワークの重み

・二乗誤差と絶対誤差の小さい方を使用

・Huber損失関数を定義

・tensorflowのwhere関数を使用

QNetwork(クラスの定義)

・入力層+中間層2層+出力層

・replayメソッドで重みの学習

Memory(クラスの定義)

・学習する内容を保存しておく記憶クラス

・addメソッドで追加

・sampleメソッドでランダムに引数分だけ保存内容を取り出す

・lenメソッドで現在保存されている量を返す

Actor(クラスの定義)

・get_actionメソッドでCartを右に押すか左に押すかを決める

変数の初期設定

今はこんな変数があるのかと頭に入れておきます。実際使われたときにまた見返します。

Qネットワーク、メモリ、Actorの生成

「mainQN = QNetwork(hidden_size=hidden_size, learning_rate=learning_rate) # メインのQネットワーク」

調べていくとここでエラーが起こっていることがわかりました。詳しくエラーの原因を調べていきます。

 

 

本日はここまで。次回に続きます。

 

 

参考サイト

neuro-educator.com

 

 

保存ファイル

lesson49.py

 

 

文責:Luke