/ AI / 103浏览

【RL】DQN的简单实现

本文将实现一个简单的DQN(Deep Q-Network)Agent。DQN是深度强化学习中的一个经典算法,用于学习从环境状态到动作的映射,使得Agent能够在环境中做出正确的决策以获得最大的奖励。

Q-Learning 简述

首先来对QLearning进行简单的解释。

Q-learning是一种基于值迭代的强化学习算法,用于学习在给定环境中的最优策略。它的核心思想是通过更新Q值函数来学习如何在每个状态下选择最优动作,以最大化累积奖励。下面详细解释Q-learning算法及其数学公式:

  1. 算法描述:
    假设我们有一个由状态空间S和动作空间A组成的MDP(马尔可夫决策过程)。Q-learning算法使用一个Q值函数Q(s, a)来表示在状态s下采取动作a所能获得的累积奖励。该算法的主要步骤如下:
  • 初始化Q值函数Q(s, a)为任意初始值,对所有状态-动作对(s, a);
  • 不断与环境交互,从当前状态s开始,采取动作a,得到奖励r和下一个状态s’;
  • 更新Q值函数:Q(s, a) = Q(s, a) + α [r + γ max(Q(s’, a’)) – Q(s, a)],其中α是学习率,γ是折扣因子;
  • 将当前状态更新为下一个状态:s = s’;
  • 重复以上步骤直到收敛或达到预定迭代次数。
  1. 数学公式:
    Q-learning算法的核心更新规则由以下数学公式表示:

Q(s, a) = Q(s, a) + α [r + γ max(Q(s’, a’)) – Q(s, a)]

其中,

  • Q(s, a)表示在状态s下采取动作a所能获得的累积奖励(Q值);
  • α(0 ≤ α ≤ 1)是学习率,控制更新的步长,用于平衡新旧Q值的权重;
  • r是在当前状态s下采取动作a后获得的即时奖励;
  • γ(0 ≤ γ ≤ 1)是折扣因子,用于权衡当前奖励和未来奖励的重要性;
  • max(Q(s’, a’))是在下一个状态s’下所有可能动作a’的Q值的最大值。

更新公式表示了一个基于差分的更新过程,将当前的Q值逐步调整,使其逼近目标Q值,即即时奖励与下一状态的最大Q值的组合。

在Q-learning算法中,Agent通过不断与环境交互和更新Q值函数来学习最优策略。在学习过程中,Agent逐渐探索并学习到在每个状态下采取最优动作,从而使得累积奖励最大化。经过足够的迭代和训练,Q值函数将收敛到最优值,从而找到最优的策略。

而DQN就是用神经网络来拟合Q函数。

DQN实现

让我们逐步解释代码中的每个部分:

  1. 导入模块:
import time
import numpy as np
import tensorflow as tf
from collections import deque
import random

from tensorflow.keras.layers import Convolution2D, Flatten
from tensorflow.keras.layers import Dense

在这里,代码导入了一些必要的库和模块,包括时间处理、数组操作、TensorFlow框架、双端队列(deque)、随机数生成和Keras中的一些层。

  1. DQNAgent类:
class DQNAgent:
    def __init__(self, state_size, action_size):
        # ...
        # 初始化一些参数和变量
        # ...
        self.model = self._build_model()  # 创建DQN模型

    def _build_model(self):
        # ...
        # 创建DQN模型的结构并编译
        # ...

    def remember(self, state, action, reward, next_state, done):
        # ...
        # 存储经验回放的方法
        # ...

    def act(self, state, use_model=False):
        # ...
        # 根据当前状态选择动作的方法
        # ...

    def replay(self, batch_size):
        # ...
        # 更新神经网络的方法
        # ...
  1. 初始化方法:
def __init__(self, state_size, action_size):
    self.state_size = state_size
    self.action_size = action_size
    self.memory = deque(maxlen=2000)  # 用于存储经验回放的经验存储器
    self.gamma = 0.95  # 折扣因子
    self.epsilon = 0.95  # 探索因子
    self.epsilon_decay = 0.995  # 探索因子的衰减率
    self.epsilon_min = 0.01  # 探索因子的最小值
    self.learning_rate = 0.0001  # 学习率
    self.model = self._build_model()

这是DQNAgent类的初始化方法。它设置了Agent的初始状态,包括状态空间大小(state_size)、动作空间大小(action_size)、经验回放存储器(memory)、折扣因子(gamma,用于考虑未来奖励的重要性)、探索因子(epsilon,用于控制随机探索的概率)、探索因子的衰减率(epsilon_decay,探索因子随时间逐渐减小)、探索因子的最小值(epsilon_min,最小探索概率)和学习率(learning_rate,用于更新神经网络的参数)。

  1. 构建DQN模型的方法:
def _build_model(self):
    model = tf.keras.Sequential()
    model.add(Convolution2D(32, 8, (4, 4), activation='relu',
                            input_shape=self.state_size))
    model.add(Convolution2D(64, 4, (2, 2), activation='relu'))
    model.add(Convolution2D(64, 3, (1, 1), activation='relu'))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dense(self.action_size))

    model.compile(loss='mse', optimizer=tf.keras.optimizers.Adam(lr=self.learning_rate))
    return model

这个方法定义了DQN模型的结构,使用了卷积层和全连接层构建神经网络。输入是环境状态(state),输出是动作空间的Q值。这个方法还编译了模型,指定了均方误差(MSE)作为损失函数,并使用Adam优化器进行参数更新。

  1. 存储经验回放的方法:
def remember(self, state, action, reward, next_state, done):
    self.memory.append((state, action, reward, next_state, done))

这个方法用于将Agent在环境中的经验(状态、动作、奖励、下一个状态和完成标志)存储到经验回放存储器中。经验回放是DQN算法中的一项重要技术,用于从存储的经验中随机抽取一批数据来进行训练,以减少数据之间的相关性。

  1. 根据当前状态选择动作的方法:
def act(self, state, use_model=False):
    if not use_model:
        print("Using random action.")
        if np.random.rand() <= self.epsilon:
            time.sleep(0.1)
            return random.randrange(self.action_size)
    q_values = self.model.predict(state)
    return np.argmax(q_values[0])

这个方法根据当前状态(state)选择一个动作(action)。如果use_model为False,那么Agent会以一定的概率(由epsilon控制)随机选择动作,以进行探索。如果use_model为True,那么Agent将根据当前模型预测的Q值选择最优的动作。

  1. 更新神经网络的方法:
def replay(self, batch_size):
    minibatch = random.sample(self.memory, batch_size)
    for state, action, reward, next_state, done in minibatch:
        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.epsilon > self.epsilon_min:
        self.epsilon *= self.epsilon_decay

读到这你可能有疑问,DQN不是应该有两个网络吗?DQN中的两个网络具有相同网络结构,只是参数不同。这里其实就是用上一次更新的模型来预测,然后进行一步更新。因此这里其实是其他DQN实现中把两个网络复制更新的步长设为1。

这个方法用于更新神经网络的参数,以减小预测值与目标值之间的差距。首先,从经验回放存储器中随机采样一个批次的经验(minibatch)。

然后,对于每个经验,计算目标Q值。如果游戏没有结束(done为False),目标Q值是当前奖励加上折扣因子乘以下一个状态的最大Q值;如果游戏结束(done为True),目标Q值就是当前奖励。接着,根据目标Q值和当前状态,更新模型的参数。最后,如果当前探索因子大于最小探索因子,就按照衰减率逐渐减小探索因子。

Eysent
音色克隆流程——采集自己的声音并训练AI唱歌
音色克隆流程——采集自己的声音并训练AI唱歌

0

  1. This post has no comment yet

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注