最近研究强化学习,结合莫凡大神的视频与众多优秀的博客给出自己的理解
上代码
import numpy as np
import pandas as pd
import time
from rope.refactor.importutils import actions
from bokeh.layouts import column
from sympy.physics.units.dimensions import action
from anaconda_navigator.utils.constants import ACTIONS
from Cython.Plex import Actions
from anaconda_project.local_state_file import SERVICE_RUN_STATES_SECTION
from astropy.utils import state
from tensorflow.contrib.timeseries.python.timeseries import state_management
from argparse import _get_action_name
from ipywidgets.widgets import interaction
from ipywidgets.widgets.tests import test_interaction
from nltk.grammar import is_terminal
from _ast import While, Not
from numba.tests.test_optional import a_is_b
np.random.seed(2) #reproducible
#global variables
N_STATES = 6 #the length of the 1 dimentional world
ACTIONS = ['left','right'] #available actions
EPSILON = 0.9 # greedy police
ALPHA = 0.1 #learning rate
LAMBDA = 0.9 #discount factor
MAX_EPISODES = 13
FRESH_TIME = 0.3 #fresh time one move
def build_q_table(n_states,actions):
table = pd.DataFrame(
np.zeros((n_states,len(actions))),
columns=actions)
print(table)
return table
def choose_action(state,q_table):
#This is how to choose an action
state_actions = q_table.iloc[state,:]
if (np.random.uniform()>EPSILON) or (state_actions.all()==0):
action_name = np.random.choice(ACTIONS)
else:
action_name = state_actions.argmax()
return action_name
def get_env_feedback(S,A):
#This is how agent will interact with the environment
if A == 'right':
if S == N_STATES - 2:
S_ = 'terminal'
R = 1
else:
S_ = S+1
R = 0
else:
R = 0
if S == 0:
S_ = S
else:
S_ = S-1
return S_,R
def update_env(S,episode,step_counter):
env_list = ['-']*(N_STATES-1)+['T']
if S=='terminal':
interaction = 'Episode %s:total_steps = %s'%(episode+1,step_counter)
print('\r{}'.format(interaction))
time.sleep(2)
print('\r ',end='')
else:
env_list[S]='o'
interaction = ''.join(env_list)
print('\r{}'.format(interaction),end='')
time.sleep(FRESH_TIME)
def rl():
# mian part of RL loop
q_table = build_q_table(N_STATES, ACTIONS)
for episode in range(MAX_EPISODES):
step_counter = 0
S = 0
is_terminal = False
update_env(S, episode, step_counter)
while not is_terminal:
A = choose_action(S, q_table)
S_,R = get_env_feedback(S, A)
q_predict = q_table.ix[S,A]
if S_ !='terminal':
q_target = R+LAMBDA*q_table.iloc[S_,:].max()
else:
q_target = R
is_terminal = True
q_table.ix[S,A]+= ALPHA*(q_target-q_predict)
S = S_
update_env(S, episode, step_counter+1)
step_counter += 1
return q_table
if __name__ == '__main__':
q_table = rl()
print('\r\nQ_table:\n')
print(q_table)
上边是简易代码实现,与算法的基本流程
(1)首先根据行列创建Q_table,初始化为0,用于Q值(可以将之理解为智能体的大脑)更新,Q值表示给定最佳policy的状态下采取相应动作获得的最大未来奖励期望。
(2)更新环境。将最初的状态初始化为最左边
(3)再初始状态下选动作,根据ε-greedy方法
每次都采取当前状态效用值最大的动作,那会不会有更好的选择一直没有被探索到?agent一直会被桎梏在以往的经验之中。而假若agent在这里每次随机选取一个动作,会不会因为探索了太多无用的状态而导致收敛缓慢?
于是就有人提出了ε-greedy方法(有一定概率的贪婪,不是每次都应最大的),即每个状态有ε的概率进行探索(即随机选取动作),而剩下的1-ε的概率则进行开发(选取当前状态下效用值较大的那个动作)。ε一般取值较小,0.01即可。以此也可以看出,Q-learning并非每次迭代都沿当前Q值最高的路径前进。
(4)执行动作后,达到下一个状态s_和reward。
(5)算出q_pre(Q预测),就是一开始初始化的数值0
(6)算出q_target(Q实际),公式中R为执行此Action得到的Reward(视为眼前利益),γ为折扣因子(discount factor)。
折扣因子γ越大,所起到的作用就越大。但指什么呢?agent在对状态进行更新时,会考虑到眼前利益(R),和记忆中的利益()(他刚才在下一个状态下知道了执行某种动作会取得最大reward。这一部分被加了进来,变成了记忆。他要选的是更重视哪一部分)。指的便是记忆中的利益。它是指agent记忆里下一个状态的动作中效用值的最大值。如果agent之前在下一个状态的某个动作上吃过甜头(选择了某个动作之后获得了很多的奖赏),那么它就更希望提早地得知这个消息,以便下回在状态可以通过选择正确的动作继续进入这个吃甜头的状态。可以看出,γ越大,小鸟就会越重视以往经验,越小,小鸟只重视眼前利益(R)。(因为R是执行初始状态下的动作获得的奖赏,而是之后探索出来的,所以是长远利益)一般我们取0.9,能够充分地对外来奖励进行考虑。
(7)更新Q值。alpha 是一个权衡上一次学到结果和这一次学习结果的量,Q2 = Q1 + alpha*(q_target-q_pre)(上一回学习的Q值与这会学的的一部分),alpha的作用就是更重视哪一部分,如果alpha很大,就说明很重视后一部分刚才学的,那么想对的前一部分的结果就会变得不那么重要。
(8)接着迭代下一个。
参考:https://blog.csdn.net/sinat_32485497/article/details/75313499