在做project的時候接觸到DQN(deep Q-Network)和一個超強大的package,gym。在這裡就寫一寫如何用
DQN網路
去進行玩遊戲。
1。什麼是DQN網路:
在強化學習當中,比較著名的一個演算法是Q-learning演算法,它的核心思想是先初始化一個Q表,然後根據以下式子不斷迭代更新這個Q表,直到收斂,那麼這個Q表就是我們需要求的最優策略。
其中S代表當前狀態,A是執行的動作,
是在狀態S下執行動作A之後的狀態。具體就不詳細多說了,有興趣的個人覺得這篇部落格講的挺不錯的
但是在實際生產環境中,有時候這個Q表會很大,儲存和更新會消耗大量的計算資源,甚至有些超大的Q表根本不可能進行完整儲存。那麼當問題的狀態集合規模很大的時候,一個可行的建模方法是
價值函式
的近似表示(Value Function Approximation)。
我們首先引入一個
狀態價值函式
,這個這個函式由引數
描述,並且接受狀態
作為輸入,計算後得到的狀態
的價值,就是我們的期望:
類似的我們可以引入一個
動作價值函式
價值函式近似的方法有很多,最簡單的我們可以有線性表示法,用
表示狀態
的特徵向量,那麼這個時候狀態價值函式我們可以近似表示為:
除了線性表示法之後,我們還可以用決策樹,最近領,神經網路來表達
狀態函式
。那麼當Q-learning中的Q表用神經網路的方法來進行價值函式近似,這就叫做Deep Q-learning ,簡稱DQN。下面我們將用一個程式程式碼來演示一下DQN的實際情況。
2。什麼是Gym
Gym是強化學習中很強大的一個包,有了它我們可以把更多的精力放在演算法的構建上面,而不需要花費過多的時間去搭建環境,下面我簡單的說一下gym的使用
我們先對 OpenAI 的 gym 庫的幾個核心概念作個簡單介紹。
想象一下你在玩貪吃蛇,你需要分析當前遊戲的
狀態(State)
,例如你所處的位置,周圍的障礙物等,才能夠決定下一步的
動作(Action)
,上下左右。那你每走一步,就會得到一個
獎勵(Reward)
。這個獎勵可能是正向獎勵(Positive Reward),也可能是負向獎勵(Negative Reward),比如撞到了障礙物。重複N次這樣的過程,直到遊戲
結束(Done)
。
下面我們用一個gym中最經典的一個遊戲環境Cartpole Game來熟悉一下這幾個概念的含義。在這個例子中,Action是隨機選擇的。
import
gym
import
random
import
time
env
=
gym
。
make
(
“CartPole-v0”
)
# 載入遊戲環境
state
=
env
。
reset
()
score
=
0
while
True
:
time
。
sleep
(
0。1
)
env
。
render
()
# 顯示畫面
action
=
random
。
randint
(
0
,
1
)
# 隨機選擇一個動作 0 或 1
state
,
reward
,
done
,
_
=
env
。
step
(
action
)
# 執行這個動作
score
+=
reward
# 每回合的得分
if
done
:
# 遊戲結束
(
‘score: ’
,
score
)
# 列印分數
break
env
。
close
()
下面我們用一個簡單的小車爬坡的遊戲來實現一下DQN
from
collections
import
deque
import
random
import
gym
import
numpy
as
np
from
tensorflow。keras
import
models
,
layers
,
optimizers
class
DQN
(
object
):
def
__init__
(
self
):
self
。
step
=
0
self
。
update_freq
=
200
# 模型更新頻率
self
。
replay_size
=
2000
# 訓練集大小
self
。
replay_queue
=
deque
(
maxlen
=
self
。
replay_size
)
self
。
model
=
self
。
create_model
()
self
。
target_model
=
self
。
create_model
()
def
create_model
(
self
):
“”“建立一個隱藏層為100的神經網路”“”
STATE_DIM
,
ACTION_DIM
=
2
,
3
model
=
models
。
Sequential
([
layers
。
Dense
(
100
,
input_dim
=
STATE_DIM
,
activation
=
‘relu’
),
layers
。
Dense
(
ACTION_DIM
,
activation
=
“linear”
)
])
model
。
compile
(
loss
=
‘mean_squared_error’
,
optimizer
=
optimizers
。
Adam
(
0。001
))
return
model
def
act
(
self
,
s
,
epsilon
=
0。1
):
“”“預測動作”“”
# 剛開始時,加一點隨機成分,產生更多的狀態
if
np
。
random
。
uniform
()
<
epsilon
-
self
。
step
*
0。0002
:
return
np
。
random
。
choice
([
0
,
1
,
2
])
return
np
。
argmax
(
self
。
model
。
predict
(
np
。
array
([
s
]))[
0
])
def
save_model
(
self
,
file_path
=
‘MountainCar-v0-dqn。h5’
):
(
‘model saved’
)
self
。
model
。
save
(
file_path
)
def
remember
(
self
,
s
,
a
,
next_s
,
reward
):
“”“歷史記錄,position >= 0。4時給額外的reward,快速收斂”“”
if
next_s
[
0
]
>=
0。4
:
reward
+=
1
self
。
replay_queue
。
append
((
s
,
a
,
next_s
,
reward
))
def
train
(
self
,
batch_size
=
64
,
lr
=
1
,
factor
=
0。95
):
if
len
(
self
。
replay_queue
)
<
self
。
replay_size
:
return
self
。
step
+=
1
# 每 update_freq 步,將 model 的權重賦值給 target_model
if
self
。
step
%
self
。
update_freq
==
0
:
self
。
target_model
。
set_weights
(
self
。
model
。
get_weights
())
replay_batch
=
random
。
sample
(
self
。
replay_queue
,
batch_size
)
s_batch
=
np
。
array
([
replay
[
0
]
for
replay
in
replay_batch
])
next_s_batch
=
np
。
array
([
replay
[
2
]
for
replay
in
replay_batch
])
Q
=
self
。
model
。
predict
(
s_batch
)
Q_next
=
self
。
target_model
。
predict
(
next_s_batch
)
# 使用公式更新訓練集中的Q值
for
i
,
replay
in
enumerate
(
replay_batch
):
_
,
a
,
_
,
reward
=
replay
Q
[
i
][
a
]
=
(
1
-
lr
)
*
Q
[
i
][
a
]
+
lr
*
(
reward
+
factor
*
np
。
amax
(
Q_next
[
i
]))
# 傳入網路進行訓練
self
。
model
。
fit
(
s_batch
,
Q
,
verbose
=
0
)
然後是訓練網路
env
=
gym
。
make
(
‘MountainCar-v0’
)
episodes
=
1000
# 訓練1000次
score_list
=
[]
# 記錄所有分數
agent
=
DQN
()
for
i
in
range
(
episodes
):
s
=
env
。
reset
()
score
=
0
while
True
:
a
=
agent
。
act
(
s
)
next_s
,
reward
,
done
,
_
=
env
。
step
(
a
)
agent
。
remember
(
s
,
a
,
next_s
,
reward
)
agent
。
train
()
score
+=
reward
s
=
next_s
if
done
:
score_list
。
append
(
score
)
(
‘episode:’
,
i
,
‘score:’
,
score
,
‘max:’
,
max
(
score_list
))
break
# 最後10次的平均分大於 -160 時,停止並儲存模型
if
np
。
mean
(
score_list
[
-
10
:])
>
-
160
:
agent
。
save_model
()
break
env
。
close
()
訓練完之後,我們載入這個模型,看看實際的效果
import
time
import
gym
import
numpy
as
np
from
tensorflow。keras
import
models
env
=
gym
。
make
(
‘MountainCar-v0’
)
model
=
models
。
load_model
(
‘MountainCar-v0-dqn。h5’
)
s
=
env
。
reset
()
score
=
0
while
True
:
env
。
render
()
time
。
sleep
(
0。01
)
a
=
np
。
argmax
(
model
。
predict
(
np
。
array
([
s
]))[
0
])
s
,
reward
,
done
,
_
=
env
。
step
(
a
)
score
+=
reward
if
done
:
(
‘score:’
,
score
)
break
env
。
close
()
其實gym裡面還有很多有趣的遊戲,不過有的訓練量有點大,小破電腦撐不住,這裡就先搞這一個看看