系列文章目录

强化学习


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题 。


一、强化学习是什么?

强化学习是智能体(Agent)以“试错”的方式进行学习,通过与环境进行交互获得的奖赏指导行为,目标是使智能体获得最大的奖赏,强化学习不同于连接主义学习中的监督学习,主要表现在强化信号上,强化学习中由环境提供的强化信号是对产生动作的好坏作一种评价(通常为标量信号),而不是告诉强化学习系统RLS(reinforcement learning system)如何去产生正确的动作。由于外部环境提供的信息很少,RLS必须靠自身的经历进行学习。通过这种方式,RLS在行动-评价的环境中获得知识,改进行动方案以适应环境。
理解:强化学习其实就是和人一样,一开始是什么都不懂的,所谓吃一堑长一智,他像一个新生的孩子,它在不断的试错过程中慢慢知道了做什么有奖励,做什么对得到奖励会有一定的价值,做什么会被打。在这个过程中不会像监督学习一样有个师傅带你,完全需要自己去摸索,就像修仙宗门一样,有背景的宗门弟子是继承掌门之位(监督),创立宗门的人是开山立派(强化),必须一步一个脚印去不断成长。

其实强化学习吸引我的就是因为它主要使用在游戏上,例如:
在 Flappy bird 这个游戏中,我们需要简单的点击操作来控制小鸟,躲过各种水管,飞的越远越好,因为飞的越远就能获得更高的积分奖励。

机器有一个玩家小鸟——Agent
需要控制小鸟飞的更远——目标
整个游戏过程中需要躲避各种水管——环境
躲避水管的方法是让小鸟用力飞一下——行动
飞的越远,就会获得越多的积分——奖励
在这里插入图片描述

二、核心点(环境)

强化学习比较核心的步骤是环境,也就是强化学习的某个场景,一般就是游戏的游戏文件,因为如果去用Tkinter画环境太费时间了,所以直接导入相应的游戏库,可以让强化学习的核心点放在算法模型上。

安装方法

pip install gym

用法:

因为使用了环境的第三方库之后,学习方法编写好了,直接调用环境,并测试出环境的动作,奖励(这些在第三方库中都有返回,所以只需要调用就可以非常完好的兼容神经网络了),这个游戏是锤子,只有两个方向,为了让锤子立起来。
观测值,也就是对当前状态的观测评估值


env = gym.make('CartPole-v0') #调用游戏环境,v0为版本号
env = env.unwrapped #解压,也可以不解直接用的

print(env.action_space)#获得动作的种类
print(env.observation_space) #获得观测值情况
print(env.observation_space.high) #获得观测值最大值
print(env.observation_space.low) #最小值
#把可用内容放到神经网络中,传入动作数量,传入最开始的观测值,也就是对当前状态的观测评估值,作用是了解最开始处于环境的状态
RL = DeepQNetwork(n_actions=env.action_space.n,
                  n_features=env.observation_space.shape[0],
                  learning_rate=0.01, e_greedy=0.9,
                  replace_target_iter=100, memory_size=2000,
                  e_greedy_increment=0.001,)
total_steps = 0  # 总步骤

for i_episode in range(100):  # 训练100次
    # 重置观测值,从头开始
    observation = env.reset()
    ep_r = 0  # 对总价值记录
    while True:
        # 渲染环境,让程序跑起来
        env.render()
        # 选择动作
        action = RL.choose_action(observation)
        # 执行动作得到的的值,下一个状态的观测值,价值,完成情况,信息(没用到)
        observation_, reward, done, info = env.step(action)
        # 游戏中的reward是当锤柄趋于垂直的时候为1,偏移到一定程度或者锤子出了边界都是0,所以需要修改下价值,让神经网络更好的收敛
        # the smaller theta and closer to center the better
        # theta 越小,锤柄越靠近中心越好,
        # 在源码中找reward的情况
        x, x_dot, theta, theta_dot = observation_
        # 第一个是锤子靠两边边界越远价值高,偏离了就变小
        r1 = (env.x_threshold - abs(x)) / env.x_threshold - 0.8
        # 锤柄偏离度,在阈值内的角度,靠近垂直价值越高
        r2 = (env.theta_threshold_radians - abs(theta)) / env.theta_threshold_radians - 0.5
        reward = r1 + r2
        # 存储记忆库
        RL.store_transition(observation, action, reward, observation_)
        # 获得总的价值
        ep_r += reward
        # 当到达1000步才开始学习,1000之前都只存储记忆库
        if total_steps > 1000:
            RL.learn()
        # 如果当前动作导致游戏结束,这里游戏结束的规则是锤子移动超过边界,锤柄角度是否垂直
        if done:
            # 输出当前轮次,当前轮次获得的总价值,当前探索衰减率
            print('episode: ', i_episode,
                  'ep_r: ', round(ep_r, 2),
                  ' EPSILON: ', round(RL.epsilon, 2))
            break
        # 下一个观测值
        observation = observation_
        # 步骤计数
        total_steps += 1

RL.plot_cost()

在这里插入图片描述
在gym包中找到这个游戏的脚本,根据值去修改价值
在这里插入图片描述

小车上坡的例子

对比下锤子和小车的两个例子,看看代码的情况,小车的代码如下:


import gym
from RL_brain import DeepQNetwork

env = gym.make('MountainCar-v0')
env = env.unwrapped

print(env.action_space)
print(env.observation_space)
print(env.observation_space.high)
print(env.observation_space.low)

RL = DeepQNetwork(n_actions=3, n_features=2, learning_rate=0.001, e_greedy=0.9,
                  replace_target_iter=300, memory_size=3000,
                  e_greedy_increment=0.0002,)

total_steps = 0


for i_episode in range(10):

    observation = env.reset()
    ep_r = 0
    while True:
        env.render()

        action = RL.choose_action(observation)

        observation_, reward, done, info = env.step(action)

        position, velocity = observation_

        # the higher the better
        reward = abs(position - (-0.4))     # r in [0, 1]

        RL.store_transition(observation, action, reward, observation_)

        if total_steps > 1000:
            RL.learn()

        ep_r += reward
        if done:
            get = '| Get' if observation_[0] >= env.unwrapped.goal_position else '| ----'
            print('Epi: ', i_episode,
                  get,
                  '| Ep_r: ', round(ep_r, 4),
                  '| Epsilon: ', round(RL.epsilon, 2))
            break

        observation = observation_
        total_steps += 1

RL.plot_cost()

可以看到,除了获取reward的方式有些不同之外,几乎没得其他的区别,这里的reward我得去源码里参考参考评分的情况,去gym包目录搜索下,

在这里插入图片描述
再直接搜索reward
在这里插入图片描述
看了下,源码里写的reward标准有点,,,看截图就很好看出来,”你没上去就是-1,上去没价值,因为上去就是goal“,然后就测试了下,两个价值不同所得到的情况,源码里的价值很显然训练的很慢,主要是它没有一个价值标准,价值的作用就是告诉训练时,拿到价值越高离成功越近,这样学习能力才会更好。
在这里插入图片描述
查看两个观测值的最大最小值发现最大0.6,最小是-1.2,这是它的位置信息,那我获得奖励根据位置来不就好了?, reward = abs(position - (-0.4)) 让奖励也就是价值保持在一个固定的区间内,0,1之间

总结

一个好的环境要配一个比较合理的reward才能让模型训练的效果更好

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐