1. 程式人生 > >強化學習之猜猜我是誰--- Deep Q-Network ^_^

強化學習之猜猜我是誰--- Deep Q-Network ^_^

導致 line d+ callbacks ima new div pan dense

Deep Q-Network和Q-Learning怎麽長得這麽像,難道它們有關系?

沒錯,Deep Q-Network其實是Q-Learning融合了神經網絡的一種方法

這次我們以打飛機的一個例子來講解Deep Q-Network,什麽打飛機?嘻嘻,我們接著看

簡要

Deep Q-Network簡稱DQN

神經網絡有什麽作用呢,在Q-Learning中我們使用Q表來記錄經驗的,通過神經網絡我們就不需要Q表了,當我們把狀態和動作輸入到神經網絡中時,經過神經網絡的分析等到action,在環境復雜的下我們的機器可能無法承受不住如此龐大的Q表把,所有就需要神經網絡這個好幫手了

技術分享圖片

是不是發現了相似之處,它其實只是在Q-Learning的基礎的加了一些小東西,

  • 記憶庫 (用於重復學習)
  • 神經網絡計算 Q 值
  • 暫時凍結 q_target 參數 (切斷相關性)

DQN的核心部分就是記憶庫,它會記錄下所有經歷過的步驟,然後反復的進行學習

遊戲開始

首先我們先搭建環境,在gym的環境下我們創建一個打飛機的遊戲

技術分享圖片

env=gym.make(BeamRider-ram-v0)

重磅出擊了,接下來是我們的核心部分,DQN的實現

首先我們初始化DQN的參數

    def __init__(self):
        self.ALPHA=0.001
        self.GAMMA=0.95
        self.ESPLION=1.0
        self.ESPLION_DECAY
=0.99 self.ESPLION_MIN=0.0001 self.action_size=env.action_space.n self.state_size=env.observation_space.shape[0] self.model=self._build_model() self.memory=deque(maxlen=5000)

童鞋們是不是發現多了兩個參數,model和memory,model就是我們的神經網絡模型,而memroy沒錯就是我們的記憶庫

我們創建一個簡單的神經網絡模型,不過這個神經網絡模型是空的,用於我們的演示,在這裏我用的是kears

    def _build_model(self):
        model=Sequential()
        model.add(Dense(24, input_dim=self.state_size, activation=relu))
        model.add(Dense(24,activation=relu))
        model.add(Dense(self.action_size,activation=linear))
        model.compile(loss=mse,optimizer=Adam(lr=self.ALPHA))
        return model

經過神經網絡我們得到我們下一步的動作

    def choose_action(self,obervation):
        if np.random.uniform()<self.ESPLION:
            return env.action_space.sample()

     #經過神經網絡得到action action
=self.model.predict(obervation) return np.argmax(action[0])

開始向記憶庫中添加我們的經歷

    def update_memory(self,obervation,action,reward,obervation_,done):
        self.memory.append((obervation,action,reward,obervation_,done))

這次的訓練有所不同,我們是在記憶庫中獲取一些經驗然後進行學習

    def learn(self):
        if len(self.memory)<batch_size:
            return
        minibach=random.sample(self.memory,batch_size)
        for state,action,reward,next_state,done in minibach:
            target=reward
            if not done:
                target=reward+self.GAMMA*np.amax(self.model.predict(next_state)[0])

            target_f=self.model.predict(state)
            target_f[0][action]=target

            self.model.fit(state,target_f,epochs=1,verbose=0)

        if self.ESPLION>self.ESPLION_MIN:
            self.ESPLION*=self.ESPLION_DECAY

為了有一個以後有一個良好的分數,我們不僅要看眼前還要有長遠的眼光,這裏和Q-learning,Sarsa一樣,我在上方用紅色標記出來了

我們發現多了兩個參數,ESPLION_MIN,ESPLION_DACAY,這個是做什麽用的呢,為了讓我們的程序不在一直探索我們設置了這兩個參數,ESPLION_DECAY用來減少我們的ESPLION值ESPLION_MIN用來規定我們最少探測的次數,當低於這個後我們遍不再進行DECAY

我們運行這個程序

剛開始時我們的戰鬥機一直陣亡, 漸漸的它學會了擊落敵方飛機

技術分享圖片

經過一段時間的戰鬥後,戰鬥機也就越來越厲害了

技術分享圖片

Double DQN

DQN還有很多變種,其中一種是Double DQN

因為Q-learning中存在Qmax,正是因為Qmax的存在而導致overestimate(過估計),如果DQN發現經過神經網絡輸出後Q值特被的大,這就是overestimate

這是原本的DQN中的Q實現技術分享圖片

這是Double DQN中的Q實現技術分享圖片

這樣我們用Q估計來的動作放在Q實現中來預測出我們要選擇的動作這樣來防止overestimate

所有在初始化參數時,我們再添加一個具有相同結構的神經網絡模型

在使用DQN時我們發現並不是很穩定,使用DDQN時則相對穩定些

技術分享圖片

技術分享圖片

game over

以下是所有的代碼,小夥伴們可以試一下

#coding:utf-8
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
from keras.utils import plot_model
import numpy as np
import gym
import random
from collections import deque
from keras.callbacks import Callback
import matplotlib.pyplot as plt

batch_size=32
losses=[]
class LossHistory(Callback):
    def on_batch_end(self, batch, logs=None):
        losses.append(logs.get(loss))

class Agent(object):
    def __init__(self):
        self.ALPHA=0.001
        self.GAMMA=0.95
        self.ESPLION=1.0
        self.ESPLION_DECAY=0.99
        self.ESPLION_MIN=0.001
        self.action_size=env.action_space.n
        self.state_size=env.observation_space.shape[0]
        self.memory=deque(maxlen=5000)
        self.model=self._build_model()

    def _build_model(self):
        model=Sequential()
        model.add(Dense(24, input_dim=self.state_size, activation=relu))
        model.add(Dense(24,activation=relu))
        model.add(Dense(self.action_size,activation=linear))
        model.compile(loss=mse,optimizer=Adam(lr=self.ALPHA))
        return model

    def choose_action(self,obervation):
        if np.random.uniform()<self.ESPLION:
            return env.action_space.sample()

        action=self.model.predict(obervation)
        return np.argmax(action[0])

    def update_memory(self,obervation,action,reward,obervation_,done):
        self.memory.append((obervation,action,reward,obervation_,done))

    def plot_model(self):
        plot_model(self.model, to_file=./save_graph/model.png)

class DDQNAgent(Agent):
    def __init__(self):
        super(DDQNAgent,self).__init__()
        self.target_model=self._build_model()
        self.update_target_model()


    def update_target_model(self):
        self.target_model.set_weights(self.model.get_weights())

    def learn(self):
        if len(self.memory)<batch_size:
            return
        minibach=random.sample(self.memory,batch_size)
        for state,action,reward,next_state,done in minibach:
            target=self.model.predict(state)
            if done:
                target[0][action]=reward
            else:
                old_model=self.model.predict(next_state)[0]
                new_model=self.target_model.predict(next_state)[0]
                target[0][action]=reward+self.GAMMA*new_model[np.argmax(old_model)]

            self.model.fit(state,target,epochs=1,verbose=0)

        if self.ESPLION>self.ESPLION_MIN:
            self.ESPLION*=self.ESPLION_DECAY


class DQNAgent(Agent):
    def learn(self):
        if len(self.memory)<batch_size:
            return
        minibach=random.sample(self.memory,batch_size)
        for state,action,reward,next_state,done in minibach:
            target=reward
            if not done:
                target=reward+self.GAMMA*np.amax(self.model.predict(next_state)[0])

            target_f=self.model.predict(state)
            target_f[0][action]=target

            self.model.fit(state,target_f,epochs=1,verbose=0)

        if self.ESPLION>self.ESPLION_MIN:
            self.ESPLION*=self.ESPLION_DECAY


history_loss=LossHistory()
env=gym.make(BeamRider-ram-v0)

# agent=DQNAgent()
agent=DDQNAgent()
totcal=0
for e in range(50001):
    obervation=env.reset()
    obervation=np.reshape(obervation,[1,agent.state_size])
    done=False
    index=0
    while not done:
        # env.render()
        action=agent.choose_action(obervation)

        obervation_,reward,done,info=env.step(action)
        obervation_= np.reshape(obervation_, [1, agent.state_size])
        reward=-10 if done else reward

        agent.update_memory(obervation,action,reward,obervation_,done)
        obervation=obervation_

        index+=1
        totcal+=reward

        if done:
            agent.update_target_model()
        #     if len(losses)!=0:
        #         plt.plot(range(len(losses)),losses)
        #         plt.savefig(‘./save_graph/loss.png‘)

    if e%50==0:
        agent.model.save(./AirRaid_model.h5)
    agent.learn()
    agent.plot_model()

    print esp {},reward {} espilon {}.format(e,totcal/index,agent.ESPLION)

本篇文章意在帶領小夥伴們進入強化學習的殿堂 ^_^

強化學習之猜猜我是誰--- Deep Q-Network ^_^