Deep Q-Network 学习笔记(一)

一、思路

 

                                     图 1.1

 

这里,先自己对那个例子的理解总结一下。

要解决的问题是:如上图 1.1 中有 5 个房间,分别被标记成 0-4,房间外可以看成是一个大的房间,被标记成 5,现在智能程序 Agent 被随机丢在 0-4 号 5 个房间中的任意 1 个,目标是让它寻找到离开房间的路(即:到达 5 号房间)。

图片描述如下:

                                   图 1.2

 

给可以直接移动到 5 号房间的动作奖励 100 分,即:图1.2中,4 到 5 、 1 到 5 和 5 到 5 的红线。

在其它几个可移动的房间移动的动作奖励 0 分

如下图:

                                   图 1.3

 

假设 Agent 当前的位置是在 2 号房间,这里就将 Agent 所在的位置做为“状态”,也就是 Agent 当前的状态是 2,当前 Agent 只能移动到 3 号房间,当它移动到 3 号房间的时候,状态就变为了 3,此时得到的奖励是 0 分。

而 Agent 根据箭头的移动则是一个“行为”

根据状态与行为得到的奖励可以组成以下矩阵。

                          图 1.4

同时,可以使用一个 Q 矩阵,来表示 Agent 学习到的知识,在图 1.4 中,“-1”表示不可移动的位置,比如从 2 号房间移动到 1 号房间,由于根本就没有门,所以没办法过去。

                    图 1.5

该 Q 矩阵就表示 Agent 在各种状态下,做了某种行为后自己给打的分,也就是将经验数据化,由于 Agent 还没有行动过,所以这里全是 0。

在 Q-Learning 算法中,计算经验得分的公式如下:

Q(state, action) = Q(state, action) + α(R(state, action) + Gamma * Max[Q(next state, all actions)] - Q(state, action))

当 α 的值是 1 时,公式如下:

Q(state, action) = R(state, action) + Gamma * Max[Q(next state, all actions)]

 

state: 表示 Agent 当前状态。

action: 表示 Agent 在当前状态下要做的行为。

next state: 表示 Agent 在 state 状态下执行了 action 行为后达到的新的状态。

Q(state, action): 表示 Agent 在 state 状态下执行了 action 行为后学习到的经验,也就是经验分数。

R(state, action): 表示 Agent 在 state 状态下做 action 动作后得到的即时奖励分数。

Max[Q(next state, all actions)]: 表示 Agent 在 next state 状态下,自我的经验中,最有价值的行为的经验分数。

Gamma: ,γ,表示折损率,也就是未来的经验对当前状态执行 action 的重要程度。

 

二、算法流程

Agent 通过经验去学习。Agent将会从一个状态到另一个状态这样去探索,直到它到达目标状态。我们称每一次这样的探索为一个场景(episode)。
每个场景就是 Agent 从起始状态到达目标状态的过程。每次 Agent 到达了目标状态,程序就会进入到下一个场景中。

1. 初始化 Q 矩阵,并将初始值设置成 0。

2. 设置好参数 γ 和得分矩阵 R。

3. 循环遍历场景(episode):

    (1)随机初始化一个状态 s。

    (2)如果未达到目标状态,则循环执行以下几步:

           ① 在当前状态 s 下,随机选择一个行为 a。

           ② 执行行为 a 得到下一个状态 s`。

           ③ 使用 Q(state, action) = R(state, action) + Gamma * Max[Q(next state, all actions)] 公式计算 Q(state, action) 。

           ④ 将当前状态 s 更新为 s`。

 

设当前状态 s 是 1, γ =0.8和得分矩阵 R,并初始化 Q 矩阵:

由于在 1 号房间可以走到 3 号房间和 5 号房间,现在随机选一个,选到了 5 号房间。

现在根据公式来计算,Agent 从 1 号房间走到 5 号房间时得到的经验分数 Q(1, 5) :

1.当 Agent 从 1 号房间移动到 5 号房间时,得到了奖励分数 100(即:R(1, 5) = 100)。

2.当 Agent 移动到 5 号房间后,它可以执行的动作有 3 个:移动到 1 号房间(0 分)、移动到 4 号房间(0 分)和移动到 5 号房间(0 分)。注意,这里计算的是经验分数,也就是 Q 矩阵,不是 R 矩阵

所以,Q(1, 5) = 100 + 0.8 * Max[Q(5, 1), Q(5, 4), Q(5, 5)] = 100 + 0.8 * Max{0, 0, 0} = 100 

 

在次迭代进入下一个episode:

随机选择一个初始状态,这里设 s = 3,由于 3 号房间可以走到 1 号房间、 2 号房间和 4 号房间,现在随机选一个,选到了 1 号房间。

步骤同上得:Q(3, 1) = 0 + 0.8 * Max[Q(1, 3), Q(1, 5)] = 0 + 0.8 * Max{0, 100} = 0 + 0.8 * 100 = 80

即:

 

三、程序实现

 先引入 numpy:

import numpy as np

初始化:

复制代码
# 动作数。
ACTIONS = 6

# 探索次数。
episode = 100

# 目标状态,即:移动到 5 号房间。
target_state = 5

# γ,折损率,取值是 0 到 1 之间。
gamma = 0.8

# 经验矩阵。
q = np.zeros((6, 6))


def create_r():
    r = np.array([[-1, -1, -1, -1, 0, -1],
                  [-1, -1, -1, 0, -1, 100.0],
                  [-1, -1, -1, 0, -1, -1],
                  [-1, 0, 0, -1, 0, -1],
                  [0, -1, -1, 1, -1, 100],
                  [-1, 0, -1, -1, 0, 100],
                  ])
    return r
复制代码

 

执行代码:

特别注意红色字体部分,当程序随机到不可移动的位置的时候,直接给于死亡扣分,因为这不是一个正常的操作,比如 从 4 号房间移动到 1 号房间,但这两个房间根本没有门可以直接到。

至于为什么不使用公式来更新,是因为,如果 Q(4, 5)和Q(1, 5)=100分,

当随机到(4, 1)时,Q(4, 1)的经验值不但没有减少,反而当成了一个可移动的房间计算,得到 79 分,即:Q(4, 1) = 79,

当随机到(2, 1)的次数要比(4, 5)多时,就会出现Q(4, 1)的分数要比Q(4, 5)高的情况,这个时候,MaxQ 选择到的就一直是错误的选择

复制代码
if __name__ == '__main__':
    r = create_r()

    print("状态与动作的得分矩阵:")
    print(r)

    # 搜索次数。
    for index in range(episode):

        # Agent 的初始位置的状态。
        start_room = np.random.randint(0, 5)

        # 当前状态。
        current_state = start_room

        while current_state != target_state:
            # 当前状态中的随机选取下一个可执行的动作。
            current_action = np.random.randint(0, ACTIONS)

            # 执行该动作后的得分。
            current_action_point = r[current_state][current_action]

            if current_action_point < 0:
                q[current_state][current_action] = current_action_point
            else:
                # 得到下一个状态。
                next_state = current_action

                # 获得下一个状态中,在自我经验中,也就是 Q 矩阵的最有价值的动作的经验得分。
                next_state_max_q = q[next_state].max()

                # 当前动作的经验总得分 = 当前动作得分 + γ X 执行该动作后的下一个状态的最大的经验得分
                # 即:积累经验 = 动作执行后的即时奖励 + 下一状态根据现有学习经验中最有价值的选择 X 折扣率
                q[current_state][current_action] = current_action_point + gamma * next_state_max_q

                current_state = next_state

    print("经验矩阵:")
    print(q)

    start_room = np.random.randint(0, 5)
    current_state = start_room

    step = 0

    while current_state != target_state:
        next_state = np.argmax(q[current_state])

        print("Agent 由", current_state, "号房间移动到了", next_state, "号房间")

        current_state = next_state

        step += 1

    print("Agent 在", start_room, "号房间开始移动了", step, "步到达了目标房间 5")
复制代码

下面是运行结果图:

 

完整代码:

复制代码
import numpy as np

# 动作数。
ACTIONS = 6

# 探索次数。
episode = 100

# 目标状态,即:移动到 5 号房间。
target_state = 5

# γ,折损率,取值是 0 到 1 之间。
gamma = 0.8

# 经验矩阵。
q = np.zeros((6, 6))


def create_r():
    r = np.array([[-1, -1, -1, -1, 0, -1],
                  [-1, -1, -1, 0, -1, 100.0],
                  [-1, -1, -1, 0, -1, -1],
                  [-1, 0, 0, -1, 0, -1],
                  [0, -1, -1, 1, -1, 100],
                  [-1, 0, -1, -1, 0, 100],
                  ])
    return r


def get_next_action():
    # # 获得当前可执行的动作集合。
    # actions = np.where(r[current_state] >= 0)[0]
    #
    # # 获得可执行的动作数。
    # action_count = actions.shape[0]
    #
    # # 随机选取一个可执行的动作。
    # next_action = np.random.randint(0, action_count)
    #
    # # 执行动作,获得下一个状态。
    # next_state = actions[next_action]
    next_action = np.random.randint(0, ACTIONS)

    return next_action


if __name__ == '__main__':
    r = create_r()

    print("状态与动作的得分矩阵:")
    print(r)

    # 搜索次数。
    for index in range(episode):

        # Agent 的初始位置的状态。
        start_room = np.random.randint(0, 5)

        # 当前状态。
        current_state = start_room

        while current_state != target_state:
            # 当前状态中的随机选取下一个可执行的动作。
            current_action = get_next_action()

            # 执行该动作后的得分。
            current_action_point = r[current_state][current_action]

            if current_action_point < 0:
                q[current_state][current_action] = current_action_point
            else:
                # 得到下一个状态。
                next_state = current_action

                # 获得下一个状态中,在自我经验中,也就是 Q 矩阵的最有价值的动作的经验得分。
                next_state_max_q = q[next_state].max()

                # 当前动作的经验总得分 = 当前动作得分 + γ X 执行该动作后的下一个状态的最大的经验得分
                # 即:积累经验 = 动作执行后的即时奖励 + 下一状态根据现有学习经验中最有价值的选择 X 折扣率
                q[current_state][current_action] = current_action_point + gamma * next_state_max_q

                current_state = next_state

    print("经验矩阵:")
    print(q)

    start_room = np.random.randint(0, 5)
    current_state = start_room

    step = 0

    while current_state != target_state:
        next_state = np.argmax(q[current_state])

        print("Agent 由", current_state, "号房间移动到了", next_state, "号房间")

        current_state = next_state

        step += 1

    print("Agent 在", start_room, "号房间开始移动了", step, "步到达了目标房间 5")
复制代码
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Prioritized Replay 是 Deep Q-Network (DQN) 中的一种重要改进算法。在传统的 DQN 算法中,模型训练是基于经验回放技术的。简单来说,就是将之前的一些观察和动作的经验随机地从经验池中抽取出来进行训练。但是,这种随机抽样并没有考虑到每个经验的重要性。有些经验虽然出现的次数很少,但是对模型的训练影响很大。因此,如果我们能够对经验进行优先级的排序,就能够更加有效地训练模型。 在 Prioritized Replay 算法中,我们使用了一个优先级队列来对经验进行排序。每个经验的优先级是根据其对模型训练的贡献来计算的。具体来说,每个经验的优先级为: $P_i = |\delta_i| + \epsilon$ 其中 $|\delta_i|$ 表示当前状态下真实 Q 值与估计 Q 值之差的绝对值,$\epsilon$ 是一个很小的常数,避免了某些经验的优先级为 0。这个公式的意思是,我们更倾向于选择那些真实 Q 值与估计 Q 值之差较大的经验进行训练。 在进行经验回放时,我们根据经验的优先级从优先级队列中抽取出经验。我们还需要一个重要的参数 $\alpha$,它表示优先级的重要程度。在优先级队列中,每个经验的优先级 $P_i$ 都会被赋予一个权重 $w_i$,它表示该经验在训练中的重要性。这个权重的计算公式为: $w_i = (\frac{1}{N} \frac{1}{P_i})^{\alpha}$ 其中 $N$ 是经验池中经验的总数,$\alpha$ 是一个超参数,控制优先级的重要程度。这个公式的意思是,优先级较高的经验在训练中得到的权重也较高,从而更加有效地更新模型。 需要注意的是,在 Prioritized Replay 算法中,我们对经验进行了优先级排序,但是这并不意味着我们只选择优先级高的经验进行训练。为了保证训练的稳定性,我们还需要引入一个随机因素,以一定的概率从优先级较低的经验中进行抽样。 总之,Prioritized Replay 算法通过对经验进行优先级排序,从而更加有效地训练模型。它是 DQN 算法的一个重要改进,被广泛地应用于深度强化学习领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值