记录:简单实现CliffWalking环境下的Q-learning和Sarsa方法

本文仅做记录,因本人Python尚未精通,强化学习更是一知半解,但跟着周博磊老师的《强化学习纲要》系列课程学习一段时间,照猫画虎用Python写出在CliffWalking下寻找最优路径的Q-learning和Sarsa方法。如您需要学习相关内容,请移步B站周博磊老师的《强化学习纲要》课程和在GitHub上的代码,附链接:周博磊的个人空间_哔哩哔哩_bilibili,本文内容仅做记录以及方便后续完善,对您可能并无帮助。

其中,Q-learning方法的代码如下,为了方便后续调用将其写成类。

class QLearning(object):
    def __init__(self, cfg):
        self.gamma = cfg.gamma
        self.epsilon_start = cfg.epsilon_start
        self.epsilon_end = cfg.epsilon_end
        self.epsilon_decay = float(cfg.epsilon_decay)
        self.q_table = defaultdict(lambda: np.zeros(cfg.action_dim))
        self.learning_rate = cfg.learning_rate
        self.sample_count = 0
        self.action_dim = cfg.action_dim
        self.state_dim = cfg.state_dim
        self.env = cfg.env
        self.train_eps = cfg.train_eps



    def train(self):
        eps_rewards = []
        for _ in range(self.train_eps):
            state = self.env.reset()
            ep_total_reward = 0
            while True:
                action = epsilon_greedy(state)
                next_state, reward, done, _ = self.env.step(action)
                ep_total_reward += reward
                if done:
                    self.q_table[state][action] += self.learning_rate * reward
                    break
                else:
                    td_target = reward + self.gamma * np.argmax(self.q_table[next_state])
                    td_error = td_target - self.q_table[state][action]
                    self.q_table[state][action] += self.learning_rate * td_error
                state = next_state
            eps_rewards.append(ep_total_reward)
        return eps_rewards

cfg参数是为了方便保存训练过程中的各项参数,可以在cfg类中根据实际需求进行修改。其中train方法是开始Q-learning方法训练,会返回每次agent尝试之后所得到的回报值,方便后续分析使用。

Sarsa方法和Q-learning方法比较相似,所不同的地方是Sarsa方法更为保守是在同一个策略中不断进行优化,而Q-learning方法则有更为激进的探索策略因此会较快找到最优策略,同时会导致在相同的训练回合中其平均回报值可能会更低(有更高的概率掉入悬崖而获得-100的回报),但是当贪婪策略中的epsilon选择的更小时(换言之Sarsa也激进起来),两种策略会得到相同的最优策略。

class Sarsa(object):
    def __init__(self, cfg):
        self.gamma = cfg.gamma
        self.epsilon_start = cfg.epsilon_start
        self.epsilon_end = cfg.epsilon_end
        self.epsilon_decay = float(cfg.epsilon_decay)
        self.q_table = defaultdict(lambda: np.zeros(cfg.action_dim))
        self.learning_rate = cfg.learning_rate
        self.sample_count = 0
        self.action_dim = cfg.action_dim
        self.state_dim = cfg.state_dim
        self.env = cfg.env
        self.train_eps = cfg.train_eps

    def train(self):
        eps_rewards = []
        for _ in range(self.train_eps):
            state = self.env.reset()
            ep_total_reward = 0
            while True:
                action = epsilon_greedy(state)
                next_state, reward, done, _ = self.env.step(action)
                ep_total_reward += reward
                next_action = epsilon_greedy(next_state)
                if done:
                    self.q_table[state][action] += self.learning_rate * reward
                    break
                else:
                    td_target = reward + self.gamma * self.q_table[next_state][next_action]
                    td_error = td_target - self.q_table[state][action]
                    self.q_table[state][action] += self.learning_rate * td_error
                state = next_state
            eps_rewards.append(ep_total_reward)
        return eps_rewards

差别不大,仅在训练中选取下一个策略时有不同。

最后是两种方法都要涉及到的epsilon-greedy方法,这个比较简单,周博磊老师提供的和书上的稍微有些差别,不过影响不大。

def epsilon_greedy(self, state):
    epsilon = self.epsilon_start - (self.epsilon_start - self.epsilon_end) * (
            self.sample_count / self.epsilon_decay)
    if np.random.random() < epsilon:
        return np.random.randint(self.action_dim)
    else:
        return np.argmax(self.q_table[state])

以上是初学时较为浅薄的认知,同时在RCPSP问题中更重要的是如何设计动作、状态和回报值,当规模较小时以上两种方法可以胜任,但解决效率并不高,因此,要将强化学习应用于RCPSP问题中应该要尝试深度强化学习方法,用神经网络取代这两种表格型方法以此更好的解决大规模的问题。目前相关方向文献很少,学习进度较慢,同时研究方向也有可能转向制造类项目中集成供应商选择的高效能项目调度问题,不过强化学习和神经网络只是方法和工具,后续会继续学习,若有新的感受在及时记录。2022.5.4

你可能感兴趣的:(嚯茶,python,机器学习,深度学习)