强化学习(一) K臂老虎机python实现

强化学习(一) K臂老虎机python实现

前言: 在本科毕业设计中使用Sarsa算法做了机械臂的运动控制,受限于时间,没有深入研究。现在研究生开学已经一月有余,利用课余时间系统的学习Sutton编写的《强化学习》第二版。课余时间真的太少(如果有中科大的老师逛到这,少布置点作业吧,球球了)。学习全程单打独斗,如有错误,恳请指正。

1. 贪心算法+乐观初始值10臂赌博机

下面这个程序中,10个动作的收益符合正态分布,均值依次从-10到9,价值初始值均为0。这也算是一种乐观初始值。后续的实验表面,乐观初始值对这个初级模型的影响非常大,如果初始值不够乐观甚至有些“悲观”,往往不能训练出正确结果。

# 10臂赌博机,采样平均策略,贪心算法
import numpy as np
import matplotlib.pyplot as plt
import random


def choose(a):  # 动作选择函数,返回动作编号
    max_act = np.max(a)
    max_array = np.where(a == max_act)[0]
    # 如果有多个最大价值,随机选
    if max_array.size > 1:
        return np.random.choice(max_array)
    else:
        return max_array[0]


def r_func(x):  # 奖励函数
    # 返回相应动作的奖励,所有动作奖励符合正态分布
    # 均值=相应动作的编号-10,标准差(方差的算数平方根)均为1
    a = int(np.random.normal(x - 10, 1, 1))
    return a


# 初始化价值Q和迭代轮数N
Q = np.zeros(10)
N = 0
# 总收益
r_all = [0]
for i in range(10000):
    act = choose(Q)
    r = r_func(act)
    N = N + 1
    # 计算平均收益序列
    k = r_all[i] + r
    k = k / N
    r_all.append(k)
    Q[act] = Q[act] + (r - Q[act]) / N

# 输出最大价值动作
print(Q)
e = np.max(Q)
print(np.where(Q == e)[0])
plt.plot(range(10000), r_all[1:100001])
plt.show()

输出如下:

[-1.8        -2.         -1.28571429 -3.         -8.         -0.75242984
 -0.73172197 -0.7350572  -1.         -0.66035183]
[9]

2. e-贪心算法

将动作选择函数改为如下所示:

def choose_e(a):  # e-贪心算法动作选择函数,返回动作编号
    ee = 0.2
    rand_e = random.random()
    if rand_e < ee:  # 随机选择
        return random.randint(0, 9)
    else:  # 贪心选择
        max_act = np.max(a)
        # 注意where函数的用法,括号内是条件式,
        # 返回一个元胞,一个是aaray,另一个是数据格式
        max_array = np.where(a == max_act)[0]

        # 如果有多个最大价值,随机选
        if max_array.size > 1:
            return np.random.choice(max_array)
        else:
            return max_array[0]

两者平均收益对比如图所示,其中黄色为贪心算法,红色为e-贪心算法
平均收益对比

3. softmax算法

需新增四个全局变量:

# softmax,初始化概率H矩阵
H = np.ones(10)
# 指数HH矩阵
HH = np.ones(10)
# 累积收益标量
r_all2 = 0
# softmax步长
n = 0.1

动作选择函数设计:十个动作被选择的概率归一化之后,[0,1]刚好按十个动作的概率叠加和被划分为10个区间。随机产生[0,1]之间的浮点数,按顺序插入这个区间,浮点数区间中的索引值即为动作编号。
程序如下:

def choose_softmax(H):
    # 归一化
    h = sum(H)
    HP = H / h
    print(h)
    # 将[0,1]这一区间划分为各个动作的概率之比
    H2 = np.zeros(11)
    for t in range(10):
        H2[t + 1] = H2[t] + HP[t]
    H2 = H2[1:11]
    # 生成随机数并查看它在数组中的位置
    e = random.random()
    # 这里要用赋值覆盖原array,不然值不变
    H2 = np.append(H2, e)
    H2.sort()
    # 本次选择的动作编号 = 随机值在H2矩阵的坐标
    return np.where(H2 == e)[0]

在奖励函数中得到奖励,并根据公式更新指数HH数组。

def r_func_softmax(x):  # 奖励函数
    a = np.random.normal(x, 1, 1)
    global N, r_all2, H
    for i in range(10):
        if i == x:
            HH[i] = HH[i] + n * (a - r_all2 / N) * (1 - H[i])
        else:
            HH[i] = HH[i] - n * (a - r_all2 / N) * H[i]
        H[i] = pow(math.e, HH[i])
    r_all2 += a
    return r_all2

在softmax的训练中没有再使用乐观初始值,即价值初值为0,10个动作对应奖励的正态分布的均值=动作自身的编号。训练结果如下:
在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值