讓機器玩遊戲的強化學習(附github)

強化學習

強化學習是代理面臨的學習問題,它經過與動態環境反覆交互試驗從而學習到某種行爲。它是機器學習的主要學習方法之一,智能體從環境到行爲的學習,也就是如何在環境中採起一些列行爲,才能使得回報信號函數的值最大,即得到的累積回報最大。mysql

如今強化學習與深度學習結合的深度強化學習更增強大。git

image

馬爾科夫決策過程

在理解強化學習以前,咱們先了解咱們要解決什麼樣的問題。其實強化學習過程就是優化馬爾科夫決策過程,它由一個數學模型組成,該模型在代理的控制下對隨機結果進行決策。github

image

代理能夠執行某些動做,例如上下左右移動,這些動做可能會獲得一個回報,回報能夠是正數也能夠是負數,它會致使總分數變更。同時動做能夠改變環境並致使一個新的狀態,而後代理能夠執行另一個動做。狀態、動做和回報的集合、轉換規則等,構成了馬爾科夫決策過程。sql

決策相關元素

  • 狀態集合,全部可能狀態。
  • 動做集合,全部動做,它能使某個狀態轉換爲另外一狀態。
  • 狀態轉移機率,特定的狀態下執行不一樣動做的機率分佈。
  • 回報函數,從一個狀態到另外一個狀態所獲得的回報。
  • 折扣因子,用於決定將來回報的重要性。

image

強化學習訓練主要就是計算各個狀態下不一樣動做的回報,並不是瞬間完成的,而是要通過大量嘗試。下一個狀態取決於當前狀態和動做,而且狀態不依賴於先前的狀態,沒有記憶,符合馬爾可夫性。數組

馬爾科夫過程的優化

強化學習是agent與環境之間的迭代交互,須要考慮幾點:bash

  • 處於某種狀態,決策者將在該狀態下選擇一個動做;
  • 能隨機進入一個新狀態並給決策者相應的回報做爲響應;
  • 狀態轉移函數選擇的動做將影響新狀態的選擇;

Q學習

Q學習便是學習不一樣狀態下各個動做的質量,它定義爲網絡

Q_\pi(s,a) = E_\pi[C_t|S_t=s,A_t=a]

它一樣能夠變換成Bellman Equation形態,併發

Q_\pi(s,a) = E_\pi[R_{t+1} +\gamma Q_\pi(S_{t+1},A_{t+1}) | S_t=s,A_t=a]

最優動做價值函數,app

Q_*(s,a) = Max_\pi  Q_\pi(s,a)

Q_*(s,a) = E_\pi[MaxR_{t+1} +\gamma Max_{S_{t+1}} Q_\pi(S_{t+1},A_{t+1}) | S_t=s,A_t=a]

能夠看到最大化當前的動做價值函數就是最大化當前回報和下一時刻狀態的最優動做價值函數。dom

動做價值函數雖然能直接計算出Q值,但實際學習時並無直接使用該Q值來更新,而是經過漸進的方式來更新。學習的方法可用以下僞代碼說明,首先初始化Q學習的狀態集和動做集組成的數組,而後觀察初始狀態,接着不斷重複執行:選擇一個動做,觀察回報並轉移到新狀態,更新Q學習數組值,涉及迭代方式更新,因爲咱們不能知道下一刻狀態的Q值,因此更新時用以前迭代的Q值來更新這次迭代的Q值,其中α表示學習率。

initialize Q[numstates,numactions] arbitrarily
observe initial state s
repeat
    select and carry out an action a
    observe reward R and new state s' Q[s,a] = Q[s,a] + α(R + γmaxa'Q[s',a'] - Q[s,a])
    s = s' until terminated 複製代碼

小遊戲

有個小遊戲,以下圖,進入入口後初始位置爲A,陰影部分表示大炕,踩進去就沒命了得重來,操做能夠上下左右,最終走到H位置就算勝利。

image

實現Q學習

先定義地圖的大小,以及大坑的位置、入口和出口。

ROWS = 5
COLUMNS = 6
ENTRANCE = (0, 0)
EXIT = (4, 5)
BARRIERS = list()
BARRIERS.append((1, 1))
BARRIERS.append((2, 1))
BARRIERS.append((3, 1))
BARRIERS.append((4, 1))
BARRIERS.append((0, 3))
BARRIERS.append((1, 3))
BARRIERS.append((3, 3))
BARRIERS.append((4, 3))
BARRIERS.append((3, 4))
BARRIERS.append((1, 5))
複製代碼

定義Q學習的一些參數設置,TIMES爲嘗試次數,R爲隨機因子,ALPHA爲學習率,GAMMA爲折扣因子,q_values爲q值表,results爲最終結果。

TIMES = 200
R = 0.05
ALPHA = 0.1
GAMMA = 0.9
q_values = dict()
results = list()
複製代碼

初始化q值表,按照行數列數和動做初始化全部q值。

def init_q_values():
    for row in range(0, ROWS):
        for col in range(0, COLUMNS):
            state = State(row, col)
            for action in Actions:
                q = (state.row, state.col, action)
                q_values[q] = 0
複製代碼

定義某個狀態執行某個動做後獲得的新狀態,其中要考慮到地圖的邊緣。

def move(curr_state, action):
    new_state = State(curr_state.row, curr_state.col)
    # check borders
    if action == Actions.up:
        if (new_state.row - 1) >= 0:
            new_state.row -= 1
    elif action == Actions.down:
        if (new_state.row + 1) <= (ROWS - 1):
            new_state.row += 1
    elif action == Actions.left:
        if (new_state.col - 1) >= 0:
            new_state.col -= 1
    elif action == Actions.right:
        if (new_state.col + 1) <= (COLUMNS - 1):
            new_state.col += 1
    return new_state
複製代碼

定義每一步的探索方法,分別執行不一樣動做找到最優的動做,此外還須要有必定機率的隨機動做選擇。

def explore(curr_state):
    rand = random.random()
    if rand <= R:
        return random.choice(list(Actions))
    else:
        best = list()
        best_action = Actions.up
        best_value = -10000000
        for action in Actions:
            q = (curr_state.row, curr_state.col, action)
            if q_values[q] > best_value:
                best_action = action
                best_value = q_values[q]
        best.append(best_action)
        # perhaps it has not only one best action
        for action in Actions:
            q = (curr_state.row, curr_state.col, action)
            if action != best_action:
                if q_values[q] == best_value:
                    best.append(action)
        return random.choice(best)
複製代碼

定義更新狀態操做,一旦選出最優的動做後將進行狀態的更新,也就是更新q值表,若是到達出口則回報爲0,若是掉入大坑則回報爲-100。

def update(curr_state, last_action):
    q = (curr_state.row, curr_state.col, last_action)
    new_state = move(curr_state, last_action)
    position = (new_state.row, new_state.col)
    reward = -1
    if position == EXIT:
        reward = 0
    elif position in BARRIERS:
        reward = -100
    old_value = q_values[q]
    max_new = max([q_values[(new_state.row, new_state.col, a)] for a in Actions])
    q_values[q] = old_value + ALPHA * (reward + (GAMMA * max_new) - old_value)
    curr_state.row = new_state.row
    curr_state.col = new_state.col
複製代碼

好比咱們訓練200次後,最終根據q值表就能夠找到最佳的執行動做序列以下,說明通過這些動做操做後能成功到達出口。

Actions.right
Actions.right
Actions.down
Actions.down
Actions.right
Actions.right
Actions.right
Actions.down
Actions.down
Actions.down
複製代碼

github

github.com/sea-boat/Ma…

-------------推薦閱讀------------

個人開源項目彙總(機器&深度學習、NLP、網絡IO、AIML、mysql協議、chatbot)

爲何寫《Tomcat內核設計剖析》

個人2017文章彙總——機器學習篇

個人2017文章彙總——Java及中間件

個人2017文章彙總——深度學習篇

個人2017文章彙總——JDK源碼篇

個人2017文章彙總——天然語言處理篇

個人2017文章彙總——Java併發篇


跟我交流,向我提問:

歡迎關注:

相關文章
相關標籤/搜索