2019-03-27 21:37:57 azeyeazeye 阅读数 927
  • 决胜AI-强化学习实战系列视频课程

    强化学习实战视频培训教程概况:强化学习是当下爆火的机器学习经典模型,系列课程从实例出发,形象解读强化学习如何完整一个实际任务。由基本概念过度到马尔科夫决策过程,通过实例演示如何通过迭代求解来得出来好的决策。举例讲解强化学习(Q-Learning)算法的原理以及如何将强化学习和深度学习进行结合。后通过让AI自动玩游戏的项目实战实例演示如何实现用强化学习和卷积神经网络打造DQN网络模型。

    7825 人正在学习 去看看 唐宇迪
2017-12-05 14:26:30 kwame211 阅读数 418
  • 决胜AI-强化学习实战系列视频课程

    强化学习实战视频培训教程概况:强化学习是当下爆火的机器学习经典模型,系列课程从实例出发,形象解读强化学习如何完整一个实际任务。由基本概念过度到马尔科夫决策过程,通过实例演示如何通过迭代求解来得出来好的决策。举例讲解强化学习(Q-Learning)算法的原理以及如何将强化学习和深度学习进行结合。后通过让AI自动玩游戏的项目实战实例演示如何实现用强化学习和卷积神经网络打造DQN网络模型。

    7825 人正在学习 去看看 唐宇迪

深度学习与强化学习

随着 DeepMind 公司的崛起,深度学习和强化学习已经成为了人工智能领域的热门研究方向。除了众所周知的 AlphaGo 之外,DeepMind 之前已经使用深度学习与强化学习的算法构造了能够自动玩 Atari 游戏的 AI,并且在即时战略游戏 StarCraft II 的游戏 AI 构建上做出了自己的贡献。虽然目前还没有成功地使用 AI 来战胜 StarCraft II 的顶尖职业玩家,但是 AI 却能够带给大家无穷的想象力和期待。

本篇 PPT 将会从强化学习的一些简单概念开始,逐步介绍值函数与动作值函数,以及 Q-Learning 算法。然后介绍深度学习中卷积神经网络的大致结构框架。最后将会介绍卷积神经网络是如何和强化学习有效地结合在一起,来实现一些简单的游戏 AI。

之前也写过一份PPT《当强化学习遇见泛函分析》,两份 PPT 有一些重复的地方,读者选择一些看即可。之前文章从强化学习的定义出发,一步一步地给读者介绍强化学习的简单概念和基本性质,并且会介绍经典的 Q-Learning 算法。文章的最后一节会介绍泛函分析的一些基本概念,并且使用泛函分析的经典定理 Banach Fixed Point Theorem 来证明强化学习中 Value Iteration 等算法的收敛性。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

2019-11-10 11:44:56 public669 阅读数 180
  • 决胜AI-强化学习实战系列视频课程

    强化学习实战视频培训教程概况:强化学习是当下爆火的机器学习经典模型,系列课程从实例出发,形象解读强化学习如何完整一个实际任务。由基本概念过度到马尔科夫决策过程,通过实例演示如何通过迭代求解来得出来好的决策。举例讲解强化学习(Q-Learning)算法的原理以及如何将强化学习和深度学习进行结合。后通过让AI自动玩游戏的项目实战实例演示如何实现用强化学习和卷积神经网络打造DQN网络模型。

    7825 人正在学习 去看看 唐宇迪

今天分享一个基于深度学习而开发的AI小游戏

简单介绍

这一款基于深度学习的五子棋小游戏的界面是使用Unity开发的,而网络结构是使用keras搭建的。

环境

笔者的环境如下

操作系统 windows 10
使用框架是keras

初始化界面

在这里插入图片描述

游戏界面

在这里插入图片描述

棋谱部分代码

using System;
using System.Collections;
using System.Collections.Generic;
using Wineforever;
using System.Linq;
using System.IO;
using UnityEngine;
using System.Diagnostics;
using System.Text;

public static class ai{
    public struct Point
    {
        public int X;
        public int Y;
    }
    public static Point move()
    {
        var root = System.IO.Directory.GetCurrentDirectory();
        //调用预测脚本
        System.Console.InputEncoding = System.Text.Encoding.UTF8;
        System.Diagnostics.Process exep = new System.Diagnostics.Process();
        exep.StartInfo.UseShellExecute = false;
        exep.StartInfo.FileName = "cmd.exe";
        exep.StartInfo.RedirectStandardInput = true;
        exep.Start();
        exep.StandardInput.WriteLine("cd /d "+ root);
        exep.StandardInput.WriteLine("python predict.py");
        exep.StandardInput.WriteLine("exit()");
        exep.WaitForExit();
        //分析输出信息
        var policy_dic = Wineforever.String.client.LoadFromSheet(root + "\\policy.wf")["Policy"];//预测落子
        //var eva = double.Parse(Wineforever.String.client.LoadFromSheet(System.AppDomain.CurrentDomain.BaseDirectory + "Assets\\eva.wf")["Evaluation"][0]);//胜率指数
        var policy_list = policy_dic.Select((i => double.Parse(i))).ToList();
        var sorted = policy_list.Select((x, i) => new KeyValuePair<double, int>(x, i)).OrderByDescending(x => x.Key).ToList();
        //var policy_sorted = sorted.Select(i => i.Key).ToList();
        var policy_index = sorted.Select(i => i.Value).ToList();
        //转换成落子坐标
        var Move = new Point();
        for (int i = 0; i < 361; i++)
        {
            int index = policy_index[i];
            int Y = index % 19, X = index / 19;
            if (GameObject.Find("board").GetComponent<logic>().Board_State[X,Y] == -1)
            {
                Move.X = X;
                Move.Y = Y;
                break;
            }
        }
        return Move;
    }
}

网络结构

网络结构就很简单了,使用keras搭建四层卷积层,输入的尺寸是4x19x19

ef create_model():
    lr = 1e-4
    policy_net = Sequential()
    policy_net.add(Convolution2D(filters=32,kernel_size=(5,5),padding='same', data_format="channels_first", activation="relu",kernel_regularizer=l2(lr),input_shape=(4,19,19)))
    policy_net.add(Convolution2D(filters=64,kernel_size=(3,3),padding='same', data_format="channels_first", activation="relu",kernel_regularizer=l2(lr)))
    policy_net.add(Convolution2D(filters=128,kernel_size=(3,3),padding='same', data_format="channels_first", activation="relu",kernel_regularizer=l2(lr)))
    policy_net.add(Convolution2D(filters=4,kernel_size=(1,1),padding='same', data_format="channels_first", activation="relu",kernel_regularizer=l2(lr)))
    policy_net.add(Flatten())
    policy_net.add(Dense(361,activation="softmax",kernel_regularizer=l2(lr)))
    adam = Adam(lr=2e-4)
    policy_net.compile(optimizer=adam,loss='categorical_crossentropy')
    policy_net.save('policy_model.h5')

训练

使用命令:

python train.py

测试

在文件夹下点击gobang.exe即可

说明

项目中我已经将tarin的一部分数据放在Assets下的train中了,数据的数量比较的少,大概只用三四百个数据的样子,这里呢,当你完整和AI玩一盘游戏后所产生的对战数据也会被保存在train的目录下,这样即可为后面的训练提供数据的基础。训练时,它的loss下降的是很漫长的,这里提供的模型,是经过使用了30000条数据经过大概三天的时间训练而来的。大家在这个模型的基础上继续训练,会有一个相对好的结果。但是呢,这个AI现在的棋力还是很弱的,暂时性的只是学会了如何下棋,想要达到打败普通人还是很难的。想要达到一个很好的效果,还是需要花费大量的时间和资源进行训练。

总结

由于笔者的水平有限,在表述上有不准确的地方,还请谅解。。。
源码地址:https://github.com/huzixuan1/AI_Gomoku
有问题欢迎添加1017190168讨论交流

2019-09-02 11:22:23 wangwei19871103 阅读数 242
  • 决胜AI-强化学习实战系列视频课程

    强化学习实战视频培训教程概况:强化学习是当下爆火的机器学习经典模型,系列课程从实例出发,形象解读强化学习如何完整一个实际任务。由基本概念过度到马尔科夫决策过程,通过实例演示如何通过迭代求解来得出来好的决策。举例讲解强化学习(Q-Learning)算法的原理以及如何将强化学习和深度学习进行结合。后通过让AI自动玩游戏的项目实战实例演示如何实现用强化学习和卷积神经网络打造DQN网络模型。

    7825 人正在学习 去看看 唐宇迪

深度强化学习

深度强化学习可以理解为深度学习和强化学习的结合体,有个大神说AI=RL+DL,就是这个意思,Deep Mind用这个技术玩游戏,下围棋,一时间引领了AI的潮流。
在这里插入图片描述

强化学习

先说说强化学习,简单来说就是你有一个智能体,他会观察环境,然后做出相应的行为,然后环境反馈给他一个奖励,环境随之也会发生变化,然后智能体继续观察环境做出行为,继续这个循环,如果环境反馈的奖励是好的,那智能体就知道刚才的行为是对的,以后要多这样做,如果反馈的奖励是不好的,那就说明刚才的行为不好,以后要少做,举个例子,如果机器看到桌子上有水杯,然后采取了打翻水杯的行为,然后地球爷爷说你这样做不好,浪费水源,于是机器就知道了,刚才的行为是不好的,以后不能做了,于是他下次看到水杯就不会这样了。:
在这里插入图片描述
如果他发现地上有水,他采取了拖地的动作,把水拖干净了,然后地球爷爷说他真好,谢谢,于是下次他再看到地上有水,就会去拖地,因此他可能就学会看到地上有水就去拖地了。总结来说就是我们的智能体会希望去得到最大的奖励:
在这里插入图片描述
再举个下围棋的例子,机器看到的是棋谱,然后做出下一步棋:
在这里插入图片描述
然后人类选手继续走:
在这里插入图片描述
大多数情况下其实没有奖励,落子下去什么都没发生,只有当棋下完了,赢或者输才有奖励,这个奖励是很稀疏的,那到底每一步要怎么下棋才算好呢,是个值得讨论的问题,或许我们应该把一局当整体来看:
在这里插入图片描述

与监督学习的区别

监督学习来下围棋就是你看到什么情况,下什么棋,但是情况太多了,我们并不能知道所有情况该怎么下棋比较好,这样的下棋就好像有个老师在教你一样,看到什么做什么。

强化学习就不一样了,他下围棋只看整一局最后是输了还是赢了,来决定遇到什么样的情况应该做什么,是自己根据经验来学习的,当然在训练的时候不可能人去陪着下,会训练两个智能体相互下棋。AlphaGo其实是监督学习和强化学习的结合体:
在这里插入图片描述

训练语音对话机器人

举一个语音对话的机器人的例子,如果我们用监督学习,那就是让机器看到什么,就说什么,都是有标准答案的。如果是强化学习的话就是跟机器对话,然后根据机器的回答,来告诉他这个回答好不好,好的话就给他正奖励,不好的就负奖励,他为了让奖励越大,会学着用好的回答来进行对话:
在这里插入图片描述
当然用人工的方法去跟机器对话来训练他是不太现实的,那得训练多久啊,所以一般都是训练两个代理,让他们相互对话,但是这样可能会出现最后两个人就一直说同一句话的情况,因为双方给相互的奖励都比较大,所以就这么无限循环了:
在这里插入图片描述
所以传统的做法就是预先定义一些规则,什么样的是好的,什么样的是不好的对话:
在这里插入图片描述

更多的应用

比如交互式搜索的例子,可以用强化学习来训练,比如人说一个词让机器来搜索,如果机器不确定是什么,就会反问人,这样就可以给他低分,如果机器直接把结果给他,他觉得这个结果又多好,就给多高的分:
在这里插入图片描述
当然还有其他的应用,比如开直升机,自动驾驶,给谷歌机房节电,文子生成等等:
在这里插入图片描述

玩游戏的例子

强化学习最多的应用是在让机器玩游戏,我们知道现在围棋,星际,dota,德扑都已经被机器给玩爆了,我们来看看一般的强化学习是怎么做的,其实OpenAI已经开源了很多强化学习玩游戏的环境和框架,可以用来学习。其实机器玩游戏跟人是一样的,他也是看画面,也就是一堆像素点,然后来学习要用什么动作来获得最高分数:
在这里插入图片描述
我们来看这个太空入侵的例子,这个游戏技术的条件就是所有外星人被消灭,或者自己的飞船被外星人消灭,机器看到的跟我们看到的一样,都是这么一副图,左上角的是分数,中间的是外心人,下面的是掩体和自己的飞船:
在这里插入图片描述
强化学习的过程应该是这样的,首先机器看到s1s_1这个状态,然后他采取动作a1a_1右移,得到的奖励r1r_1是0,状态变为了s2s_2,然后他采取动作a2a_2射击,得到的奖励r2r_2是5,状态变为了s3s_3,通常游戏也包含很多随机元素,或许你消灭一个外星人得到的分数可能是4,也可能是3:
在这里插入图片描述如此反复下去直到最后一次采取aTa_T,获得的奖励是rTr_T,游戏结束,这个整个过程我们叫做一个episode,也就是一个开始到结束的一个过程。我们希望最大化机器每次游戏的过程的累计奖励:
在这里插入图片描述

强化学习的难点:

第一,可能有奖励的延迟,因为我们每次只是射击之后才能会获得奖励,然后会认为射击这个动作是好的,然后可能一直采取射击了,但是其实射击之前的一系列移动对射击是有帮助的。我们希望机器能有一点未来的眼光,有些动作或许现在没奖励,但是对未来的奖励有所帮助。同样在下围棋也是一样,短期的牺牲可能会换来更多长期的奖励。

第二,如果没有进行射击动作而得到奖励,机器可能只会左右移动了,永远都不会去射击,这个就是个问题,我们希望机器能够去探索未知的世界,希望他有有好奇心,那样才可以学到更多的东西。
在这里插入图片描述

强化学习比较新的方法

强化学习一般分为基于策略的和基于价值的,具体本篇先介绍下基于策略的,当时比较好的方法是A3C,就是一个分布式结合策略和价值的改进版,听说很厉害:
在这里插入图片描述
一些相关文章:
在这里插入图片描述

强化学习基于策略的方法

我们说机器学习其实就是在找一个方法,有个输入,有个输出,强化学习也一样,我们要找到一个方法π\pi,你把环境当做输入,然后行动当做输出,至于要怎么样的输出才是好的,就看环境给予你的奖励:
在这里插入图片描述
我们知道深度学习的基本步骤,我们可以把要找的方法用神经网络来学出来,我们可以记这个方法叫Actor,暂时叫演员吧:
在这里插入图片描述
我们可以把所观察的到环境用向量表示,然后输入到一个神经网络,输出希望就是不同动作的概率,然后我们选择概率最大的那个来行动,比如太空入侵的例子,我们可以把看到的像素画面当做一个向量或者矩阵作为输入,经过神经网络训练后输出应该采取的行为的分布,选择可能性最大的那个,我们之用神经网络来训练出这个Actor也是因为神经网络的泛化能力强:
在这里插入图片描述
然后我们进行第二步,找出最好的那个方法:
在这里插入图片描述
那怎么来衡量一个Actor的好坏呢,我们用目标函数,就像我们在监督学习的时候一样,我们希望输出的分布和真实的分布越接近越好,希望损失越小越好:
在这里插入图片描述
我们先用参数θ\theta初始化这个神经网络actor,然后用这个actor去玩游戏,在s1s_1的时候采取了a1a_1获得的奖励reward是r1r_1,环境变成了s2s_2,然后采取a2a_2获得的奖励reward是r2r_2,环境变成了s3s_3,以此类推,直到游戏结束,我们把功总得奖励记作RθR_\theta。因为游戏具有随机性,这个是设计游戏的时候做的,所以或许同样的actor也会得到不同的RθR_\theta,所以我们取RθR_\theta的期望,记作Rθ\overline R_\theta,我们可以用Rθ\overline R_\theta来衡量actor的好坏,这个很好理解,即游戏中采取的行为直接影响游戏得分好坏:
在这里插入图片描述
我们定义每一局游戏即从游戏开始到结束,为τ={s1,a1,r1,s2,a2,r2,...,sT,aT,rT}\tau=\{s_1,a_1,r_1,s_2,a_2,r_2,...,s_T,a_T,r_T\},也就是一局游戏过程的序列,因为τ\tau是基于参数为θ\theta的神经网络的输出,每个τ\tau出现的概率就是P(τθ)P(\tau|\theta),所以我们的期望Rθ\overline R_\theta就是:
在这里插入图片描述
但是我们没办法穷举每一局游戏,我们只能进行采样,我们用actor去玩N局游戏,然后进行采样:
在这里插入图片描述
然后我们可以将期望近似为采样的均值,也就是将所有采样到的N局游戏奖励求和再取平均:
在这里插入图片描述
接下来我们就是要找出最好的actor:
在这里插入图片描述
我们要优化的就是期望,我们希望期望越大越好,我们可以用梯度上升法更新参数,其实原理跟梯度下降类似,只是一个是越大越好,一个是越小越好,具体可以看下图,还是比较好理解的:
在这里插入图片描述
我们前面定义了期望:
在这里插入图片描述
因为奖励是游戏本身设定的,我们可能是不知道的,所以梯度只作用于概率上那部分上:
在这里插入图片描述
因为要log,所以进行变换:
在这里插入图片描述
因为我们知道:
在这里插入图片描述
所以期望就是:
在这里插入图片描述
然后近似于N次采样:
在这里插入图片描述

那接下来怎么求这个梯度呢,我们知道P(τθ)P(\tau|\theta)是怎么来的:
在这里插入图片描述
在这里插入图片描述
我们看到跟θ\theta相关的就是中间连乘的那部分,因为你每次在某个时间t状态下采取的行动,是基于你的actor πθ\pi _\theta的,比如下面的例子,某个时刻t的状态下,要开火的概率是0.7:
在这里插入图片描述
因为有连乘,所以我们取log,得到:
在这里插入图片描述
所以梯度就跟中间累加项有关:
在这里插入图片描述
于是:
在这里插入图片描述
在这里插入图片描述
R(τn)R(\tau^n)作用于每一个梯度,所以可以乘进去,得:
在这里插入图片描述
我们的梯度上升是这样:
在这里插入图片描述
因此我们希望奖励的期望梯度越大越好,当R(τn)R(\tau^n)是正的时候,我们希望提高p(atnstn,θ)p(a_t ^n|s_t ^n,\theta),反之当R(τn)R(\tau^n)是负的时候,我们希望减小p(atnstn,θ)p(a_t ^n|s_t ^n,\theta),这样就才可以使得奖励的期望梯度尽可能的大:
在这里插入图片描述
这边为什么是考虑某一局游戏的奖励R(τn)R(\tau^n),而不是某个时间点的奖励呢τtn\tau_t ^n,因为如果仅仅考虑某个时间点,比如开火的时候,得到了奖励,那他就越提高开火的概率,训练之后可能会一直乱开火。

我们来看这个式子,为什么最后要是取log,其实我们把他还原回去,可以看到其实是除以了概率:
在这里插入图片描述
为什么要做这件事呢,因为加入某个状态在很多局游戏里出现,采取a的奖励是2,采取b的奖励1,但是会采取b的次数多,因为我们的梯度是会进行求和,所以算出来最后可能他会选择b,但是事实a应该是更好的,所以我们要把这个次数的影响给消除点,我们除以概率就可以了,比如下图a出现的概率是1/4,b出现的概率是3/4,把奖励除以对应的概率,最后算出来会提升a的概率从,所以可能选择a的概率大:
在这里插入图片描述
其实还有个问题,我们的R(τn)R(\tau^n)一直是正的,理论上好像没问题,比如下图的a,b,c三个概率,如果都是正的,假设a,c的奖励大,b的小,那三个概率都应该增加,但是概率大的其实反而概率是会减少的,因为概率的和是1,其他增加了多少了,增加少的就会减少:
在这里插入图片描述
但是实际上你可能没采样的a,然后导致a的概率降低了:
在这里插入图片描述
这个其实是有问题的,或许a是更好的选择,那怎么避免这种情况呢,我们可以设定一个门槛,一个基线b,超过他的我们才会把概率提高,这样b,c的概率也就不一定提高,a也不一定降低了:
在这里插入图片描述

总结

本篇主要介绍强化学习的基本概念和基于策略的方法,还有一些要注意的地方,其实挺值得我们思考的,也是我们今后可以优化的地方,其他的方法再后面会介绍。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵,图片来自李宏毅课件,侵删。

2017-11-17 06:43:52 Uwr44UOuQcNsUQb60zk2 阅读数 5866
  • 决胜AI-强化学习实战系列视频课程

    强化学习实战视频培训教程概况:强化学习是当下爆火的机器学习经典模型,系列课程从实例出发,形象解读强化学习如何完整一个实际任务。由基本概念过度到马尔科夫决策过程,通过实例演示如何通过迭代求解来得出来好的决策。举例讲解强化学习(Q-Learning)算法的原理以及如何将强化学习和深度学习进行结合。后通过让AI自动玩游戏的项目实战实例演示如何实现用强化学习和卷积神经网络打造DQN网络模型。

    7825 人正在学习 去看看 唐宇迪


本文通过一种简单的 Catch 游戏介绍了深度强化学习的基本原理,并给出了完整的以 Keras 为前端的 TensorFlow 代码实现,是入门深度强化学习的不错选择。


GitHub 链接:https://github.com/JannesKlaas/sometimes_deep_sometimes_learning/blob/master/reinforcement.ipynb


去年,DeepMind 的 AlphaGo 以 4-1 的比分打败了世界围棋冠军李世乭。超过 2 亿的观众就这样看着强化学习(reinforce learning)走上了世界舞台。几年前,DeepMind 制作了一个可以玩 Atari 游戏的机器人,引发轩然大波。此后这个公司很快被谷歌收购。


很多研究者相信,强化学习是我们创造通用人工智能(Artificial General Intelligence)的最佳手段。这是一个令人兴奋的领域,有着许多未解决的挑战和巨大的潜能。


强化学习起初看似非常有挑战性,但其实要入门并不困难。在这篇文章中,我们将创造一个基于 Keras 的简单机器人,使它能玩 Catch 游戏。


Catch 游戏



原始的 Catch 游戏界面


Catch 是一个非常简单的街机游戏,你可能在孩提时代玩过它。游戏规则如下:水果从屏幕的顶部落下,玩家必须用一个篮子抓住它们;每抓住一个水果,玩家得一分;每漏掉一个水果,玩家会被扣除一分。这里的目标是让电脑自己玩 Catch 游戏。不过,我们不会使用这么漂亮的游戏界面。相反,我们会使用一个简单的游戏版本来简化任务:



简化的 Catch 游戏界面


玩 Catch 游戏时,玩家要决定三种可能的行为。玩家可以将篮子左移、右移或保持不动。这个决定取决于游戏的当前状态。也就是说,取决于果子掉落的位置和篮子的位置。我们的目标是创造这样一个模型:它能在给定游戏屏幕内容的情况下,选择导致得分最高的动作。


这个任务可以被看做一个简单的分类问题。我们可以让游戏专家多次玩这个游戏,并记录他们的行为。然后,可以通过选择类似于游戏专家的「正确」动作来训练模型。


但这实际上并不是人类学习的方式。人类可以在无指导的情况下,自学像 Catch 这样的游戏。这非常有用。想象一下,你如果每次想学习像 Catch 一样简单的东西,就必须雇佣一批专家玩这个游戏上千次!这必然非常昂贵而缓慢。

而在强化学习中,模型不会根据标记的数据训练,而是通过以往的经历。


深度强化学习


强化学习受行为心理学启发。我们并不为模型提供「正确的」行为,而是给予奖励和惩罚。该模型接受关于当前环境状态的信息(例如计算机游戏屏幕)。然后,它将输出一个动作,就像游戏手柄一样。环境将对这个动作做出回应,并提供下一个状态和奖惩行为。


据此,模型学习并寻找最大化奖励的行为。


实际上,有很多方式能够做到这一点。下面,让我们了解一下 Q-Learning。利用 Q-Learning 训练计算机玩 Atari 游戏的时候,Q-Learning 曾引起了轰动。现在,Q-Learning 依然是一个有重大意义的概念。大多数现代的强化学习算法,都是 Q-Learning 的一些改进。


理解 Q-Learning


了解 Q-Learning 的一个好方法,就是将 Catch 游戏和下象棋进行比较。


在这两种游戏中,你都会得到一个状态 S。在象棋中,这代表棋盘上棋子的位置。在 Catch 游戏中,这代表水果和篮子的位置。


然后,玩家要采取一个动作,称作 A。在象棋中,玩家要移动一个棋子。而在 Catch 游戏中,这代表着将篮子向左、向右移动,或是保持在当前位置。据此,会得到一些奖励 R 和一个新状态 S'。

Catch 游戏和象棋的一个共同点在于,奖励并不会立即出现在动作之后。


在 Catch 游戏中,只有在水果掉到篮子里或是撞到地板上时你才会获得奖励。而在象棋中,只有在整盘棋赢了或输了之后,才会获得奖励。这也就是说,奖励是稀疏分布的(sparsely distributed)。大多数时候,R 保持为零。


产生的奖励并不总是前一个动作的结果。也许,很早之前采取的某些动作才是获胜的关键。要弄清楚哪个动作对最终的奖励负责,这通常被称为信度分配问题(credit assignment problem)。


由于奖励的延迟性,优秀的象棋选手并不会仅通过最直接可见的奖励来选择他们的落子方式。相反,他们会考虑预期未来奖励(expected future reward),并据此进行选择。例如,他们不仅要考虑下一步是否能够消灭对手的一个棋子。他们也会考虑那些从长远的角度有益的行为。


在 Q-Learning 中,我们根据最高的预期未来奖励选行动。我们使用 Q 函数进行计算。这个数学函数有两个变量:游戏的当前状态和给定的动作。因此,我们可以将其记为 Q(state,action)。在 S 状态下,我们将估计每个可能的动作 A 所带来的的回报。我们假定在采取行动 A 且进入下一个状态 S' 以后,一切都很完美。


对于给定状态 S 和动作 A,预期未来奖励 Q(S,A)被计算为即时奖励 R 加上其后的预期未来奖励 Q(S',A')。我们假设下一个动作 A' 是最优的。


由于未来的不确定性,我们用 γ 因子乘以 Q(S',A')表示折扣:

Q(S,A) = R + γ * max Q(S',A')


象棋高手擅长在心里估算未来回报。换句话说,他们的 Q 函数 Q(S,A)非常精确。大多数象棋训练都是围绕着发展更好的 Q 函数进行的。玩家使用棋谱学习,从而了解特定动作如何发生,以及给定的动作有多大可能会导致胜利。但是,机器如何评估一个 Q 函数的好坏呢?这就是神经网络大展身手的地方了。


最终回归


玩游戏的时候,我们会产生很多「经历」,包括以下几个部分:

  • 初始状态,S
  • 采取的动作,A
  • 获得的奖励,R
  • 下一状态,S'

这些经历就是我们的训练数据。我们可以将估算 Q(S,A)的问题定义为回归问题。为了解决这个问题,我们可以使用神经网络。给定一个由 S 和 A 组成的输入向量,神经网络需要能预测 Q(S,A)的值等于目标:R + γ * max Q(S',A')。


如果我们能很好地预测不同状态 S 和不同行为 A 的 Q(S,A),我们就能很好地逼近 Q 函数。请注意,我们通过与 Q(S,A)相同的神经网络估算 Q(S',A')。


训练过程


给定一批经历 <S,A,R,S'>,其训练过程如下:


1、对于每个可能的动作 A'(向左、向右、不动),使用神经网络预测预期未来奖励 Q(S',A');

2、选择 3 个预期未来奖励中的最大值,作为 max Q(S',A');

3、计算 r + γ * max Q(S',A'),这就是神经网络的目标值;

4、使用损失函数(loss function)训练神经网络。损失函数可以计算预测值离目标值的距离。此处,我们使用 0.5 * (predicted_Q(S,A)—target)² 作为损失函数。


在游戏过程中,所有的经历都会被存储在回放存储器(replay memory)中。这就像一个存储 <S,A,R,S'> 对的简单缓存。这些经历回放类同样能用于准备训练数据。让我们看看下面的代码:

        class ExperienceReplay(object):
    """
    During gameplay all the experiences < s, a, r, s’ > are stored in a replay memory. 
    In training, batches of randomly drawn experiences are used to generate the input and target for training.
    """
    def __init__(self, max_memory=100, discount=.9):
        """
        Setup
        max_memory: the maximum number of experiences we want to store
        memory: a list of experiences
        discount: the discount factor for future experience
        
        In the memory the information whether the game ended at the state is stored seperately in a nested array
        [...
        [experience, game_over]
        [experience, game_over]
        ...]
        """
        self.max_memory = max_memory
        self.memory = list()
        self.discount = discount

    def remember(self, states, game_over):
        #Save a state to memory
        self.memory.append([states, game_over])
        #We don't want to store infinite memories, so if we have too many, we just delete the oldest one
        if len(self.memory) > self.max_memory:
            del self.memory[0]

    def get_batch(self, model, batch_size=10):
        
        #How many experiences do we have?
        len_memory = len(self.memory)
        
        #Calculate the number of actions that can possibly be taken in the game
        num_actions = model.output_shape[-1]
        
        #Dimensions of the game field
        env_dim = self.memory[0][0][0].shape[1]
        
        #We want to return an input and target vector with inputs from an observed state...
        inputs = np.zeros((min(len_memory, batch_size), env_dim))
        
        #...and the target r + gamma * max Q(s’,a’)
        #Note that our target is a matrix, with possible fields not only for the action taken but also
        #for the other possible actions. The actions not take the same value as the prediction to not affect them
        targets = np.zeros((inputs.shape[0], num_actions))
        
        #We draw states to learn from randomly
        for i, idx in enumerate(np.random.randint(0, len_memory,
                                                  size=inputs.shape[0])):
            """
            Here we load one transition <s, a, r, s’> from memory
            state_t: initial state s
            action_t: action taken a
            reward_t: reward earned r
            state_tp1: the state that followed s’
            """
            state_t, action_t, reward_t, state_tp1 = self.memory[idx][0]
            
            #We also need to know whether the game ended at this state
            game_over = self.memory[idx][1]

            #add the state s to the input
            inputs[i:i+1] = state_t
            
            # First we fill the target values with the predictions of the model.
            # They will not be affected by training (since the training loss for them is 0)
            targets[i] = model.predict(state_t)[0]
            
            """
            If the game ended, the expected reward Q(s,a) should be the final reward r.
            Otherwise the target value is r + gamma * max Q(s’,a’)
            """
            #  Here Q_sa is max_a'Q(s', a')
            Q_sa = np.max(model.predict(state_tp1)[0])
            
            #if the game ended, the reward is the final reward
            if game_over:  # if game_over is True
                targets[i, action_t] = reward_t
            else:
                # r + gamma * max Q(s’,a’)
                targets[i, action_t] = reward_t + self.discount * Q_sa
        return inputs, targets
      


定义模型


现在让我们定义这个利用 Q-Learning 学习 Catch 游戏的模型。我们使用 Keras 作为 Tensorflow 的前端。我们的基准模型是一个简单的三层密集网络。这个模型在简单版的 Catch 游戏当中表现很好。你可以在 GitHub 中找到它的完整实现过程。


你也可以尝试更加复杂的模型,测试其能否获得更好的性能。

        num_actions = 3  # [move_left, stay, move_right]
hidden_size = 100 # Size of the hidden layers
grid_size = 10 # Size of the playing field

def baseline_model(grid_size,num_actions,hidden_size):
    #seting up the model with keras
    model = Sequential()
    model.add(Dense(hidden_size, input_shape=(grid_size**2,), activation='relu'))
    model.add(Dense(hidden_size, activation='relu'))
    model.add(Dense(num_actions))
    model.compile(sgd(lr=.1), "mse")
    return model
      


探索


Q-Learning 的最后一种成分是探索。日常生活的经验告诉我们,有时候你得做点奇怪的事情或是随机的手段,才能发现是否有比日常动作更好的东西。


Q-Learning 也是如此。总是做最好的选择,意味着你可能会错过一些从未探索的道路。为了避免这种情况,学习者有时会添加一个随机项,而未必总是用最好的。我们可以将定义训练方法如下:

        def train(model,epochs):
    # Train
    #Reseting the win counter
    win_cnt = 0
    # We want to keep track of the progress of the AI over time, so we save its win count history
    win_hist = []
    #Epochs is the number of games we play
    for e in range(epochs):
        loss = 0.
        #Resetting the game
        env.reset()
        game_over = False
        # get initial input
        input_t = env.observe()
        
        while not game_over:
            #The learner is acting on the last observed game screen
            #input_t is a vector containing representing the game screen
            input_tm1 = input_t
            
            #Take a random action with probability epsilon
            if np.random.rand() <= epsilon:
                #Eat something random from the menu
                action = np.random.randint(0, num_actions, size=1)
            else:
                #Choose yourself
                #q contains the expected rewards for the actions
                q = model.predict(input_tm1)
                #We pick the action with the highest expected reward
                action = np.argmax(q[0])

            # apply action, get rewards and new state
            input_t, reward, game_over = env.act(action)
            #If we managed to catch the fruit we add 1 to our win counter
            if reward == 1:
                win_cnt += 1        
            
            #Uncomment this to render the game here
            #display_screen(action,3000,inputs[0])
            
            """
            The experiences < s, a, r, s’ > we make during gameplay are our training data.
            Here we first save the last experience, and then load a batch of experiences to train our model
            """
            
            # store experience
            exp_replay.remember([input_tm1, action, reward, input_t], game_over)    
            
            # Load batch of experiences
            inputs, targets = exp_replay.get_batch(model, batch_size=batch_size)
  
            # train model on experiences
            batch_loss = model.train_on_batch(inputs, targets)
            
            #sum up loss over all batches in an epoch
            loss += batch_loss
        win_hist.append(win_cnt)
    return win_hist
      


我将这个游戏机器人训练了 5000 个 epoch,结果表现得很不错!



Catch 机器人的动作


正如你在上述动图中看到的那样,机器人可以抓住从天空中掉落的苹果。为了将这个模型学习的过程可视化,我绘制了每一个 epoch 的胜利移动平均线,结果如下:


接下来做什么?现在,你已经对强化学习有了初步的直觉了解。我建议仔细阅读该教程的完整代码。你也可以试验看看。


你可能还想看看 Arthur Juliani 的系列介绍(https://medium.com/emergent-future/simple-reinforcement-learning-with-tensorflow-part-0-q-learning-with-tables-and-neural-networks-d195264329d0)。如果你需要一个更加正式的入门课,可以看看

Stanford's CS 234:http://web.stanford.edu/class/cs234/index.html

Berkeley's CS 294:http://rll.berkeley.edu/deeprlcourse/

或是 David Silver's lectures from UCL:http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching.html

训练你的强化学习技能最好是通过 OpenAI's Gym(https://gym.openai.com/envs/),它使用标准化的应用程序界面(API)提供了一系列训练环境


没有更多推荐了,返回首页