机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

前言本篇将简要介绍强化学习的“自主学习Flappy Bird”实例读完本篇,你将了解:一、强化学习1.相关概念2.马尔可夫决策过程(MDP)(model base 模型)3.蒙特卡洛强化学习4.Q-learning算法5.深度强化学习(DRL)6.Deep Q Network(DQN)二、自主学习Flappy Bird1.程序基本框架(观察期、探索期、训练期)2.动作选择模块3.卷积神经网络-CNN4.Tensorflow&openCV库三、关于机器学习专栏的一点总结

前言

本篇将简要介绍强化学习的“自主学习Flappy Bird”实例
读完本篇,你将了解:

一、强化学习
1.相关概念
2.马尔可夫决策过程(MDP)(model base 模型)
3.蒙特卡洛强化学习
4.Q-learning算法
5.深度强化学习(DRL)
6.Deep Q Network(DQN)

二、自主学习Flappy Bird
1.程序基本框架(观察期、探索期、训练期)
2.动作选择模块
3.卷积神经网络-CNN
4.Tensorflow&openCV库

三、关于机器学习专栏的一点总结
1.无监督学习
2.监督学习
3.强化学习。

一、强化学习(增强学习)

1.定义

(1)程序或智能体(agent)通过与环境不断地进行交互学习一个从环境到动作的映射,学习的目标是使累计回报最大化

(2)是一种试错学习,因其在各种状态(环境)下需尽量尝试所有可以选择的动作,通过环境给出的反馈(奖励)来判断动作的优劣,最终获得环境和最优动作的映射关系(策略)

2.举例:吃豆游戏

(1)基本组件
①agent: 大嘴小怪物
②环境:整个迷宫中的所有信息
③奖励:agent每走一步,需要扣除1分,吃掉小球得10分,吃掉敌人得200分,被吃掉游戏结束。
④动作:在每种状态下,agent能够采用的动作,比如上下左右移动。
⑤策略:在每种状态下,采取最优的动作。
⑥学习目标:获得最优的策略,以使累计奖励最大(即Score )。

(2)图示
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

3.马尔可夫决策过程(MDP)(model base 模型)

机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

(1)马尔可夫决策过程(MarkovDecision Process)通常用来描述一个强化学习问题。
(2)智能体agent根据当前对环境的观察采取动作获得环境的反馈,并使环境发生改变的循环过程。

(3)基本元素
①s∈S:有限状态state集合,s表示某个特定状态
②a∈A:有限动作action集合,a表示某个特定动作
③T(S,a,S’)~Pr(s’|s,a):状态转移模型,根据当前状态s和动作a预测下一个状态s,Pr表示从s采取行动a转移到s‘的概率
④R(s,a):表示agent采取某个动作后的即时奖励,其他表现形式:R(s,a,s’),R(s)
⑤Policy π(s)->a:根据当前state来产生action,可表现为a=π(s)或π(a|s)=P(a|s),后者表示某种状态下执行某个动作的概率

(4)值函数
①状态值函数v表示执行策略π能得到的累计折扣奖励
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

整理后得
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

②状态动作值函数Q(s,a)表示在状态s下执行动作a能得到的累计折扣奖励
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

整理后得

机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

③最优值函数
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

(5)最优控制
在得到最优值函数之后,可以通过值函数的值得到状态s时应该采取的动作a
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

4.蒙特卡洛强化学习

(1)免模型学习
①在现实的强化学习任务中,环境的转移概率、奖励函数往往很难得知,甚至很难得知环境中有多少状态。
②若学习算法不再依赖于环境建模,则称为免模型学习,蒙特卡洛强化学习就是其中的一种。

(2)蒙特卡洛强化学习使用多次采样,然后求取平均累计奖赏作为期望累计奖赏的近似。
<s0,a0,s1,a1,r2,…,S(T-1),a(T-1),rT,ST>

(3)直接对状态动作值函数Q(s,a)进行估计,每采样一条轨迹,就根据轨迹中的所有“状态-动作”利用下面的公式对来对值函数进行更新。
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

(4)贪心策略
①每次采样更新完所有的“状态-动作”对所对应的Q(s,a),就需要更新采样策略n。但由于策略可能是确定性的,即一个状态对应一个动作,多次采样可能获得相同的采样轨迹,因此需要借助ε贪心策略
②如图
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

5.Q-learning算法

(1)蒙特卡洛强化学习算法需要采样一个完整的轨迹来更新值函数,效率较低,此外该算法没有充分利用强化学习任务的序贯决策结构。

(2)Q-learning算法结合了动态规划与蒙特卡洛方法的思想,使得学习更加高效。

(3)过程
①假设对于状态动作对(s,a)基于t次采样估算出其值函数为∶
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

②在进行t+1次采样后,依据增量更新得到:
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

③然后,将,替换成系数α(步长),得到:
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

④以γ折扣累计奖赏为例∶
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

⑤则值函数的更新方式如下:
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

(4)流程

机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)
注:请参考周志华老师《机器学习》一书

6.深度强化学习(DRL)

(1)传统强化学习:真实环境中的状态数目过多,求解困难。

(2)深度强化学习:将深度学习和强化学习结合在一起,通过深度神经网络直接学习环境(或观察)与状态动作值函数Q(s,a)之间的映射关系,简化问题的求解。

7.Deep Q Network(DQN)

(1)介绍
①是将神经网络(neural network)和Q-learning结合,利用神经网络近似模拟函数Q(s,a)
②输入是问题的状态(e.g.,图形),输出是每个动作a对应的Q值
③然后依据Q值大小选择对应状态执行的动作,以完成控制。

(2)神经网络的参数︰应用监督学习完成

(3)DQN学习过程
①状态s输入,获得所有动作对应的Q值Q(s,a)
②选择对应Q值最大的动作a’并执行
③执行后环境发生改变,并能够获得环境的奖励r
④利用奖励r更新Q(s,a’)——强化学习
⑤利用新的Q(s,a’)更新网络参数—监督学习
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

(4)讲解
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

二、自主学习Flappy Bird游戏项目分析

1.“自主学习Flappy Bird游戏”实例介绍

(1)深度强化学习
①2013年,Deep Mind团队在NIPS上发表《PlayingAtari with Deep Reinforcement Learning》一文,在该文中首次提出Deep Reinforcement Learning—词
②并且提出DQN(DeepQ-Network)算法,实现了从纯图像输入完全通过学习来玩Atari游戏。
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

(2)Atari游戏
①接下来的学习中,我们将通过python实现的一个开源的自主学习flappy bird游戏的小项目,更细致的讲解有关深度强化学习的实例应用。
②Flappy Bird游戏:由来自越南的独立游戏开发者开发的一款游戏。在游戏中,玩家需要点击屏幕控制小鸟跳跃,跨越由各种不同长度水管组成的障碍。
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

③Flappy Bird游戏和Atari游戏的操作方法很相似,同样可以使用DQN进行学习。

(3)自主学习Flappy Bird游戏
①目标:使用深度强化学习方法自主学习Flappy Bird游戏策略,达到甚至超过人类玩家的水平。
②技术路线:Deep Q-Network
③使用工具:tensorflow + pygame + cv2

2.Flappy Bird自主学习程序基本框架

(1)程序与模拟器交互
①训练过程也就是神经网络(agent)不断与游戏模拟器(Environment)进行交互
②通过模拟器获得状态,给出动作,改变模拟器中的状态,获得反馈,依据反馈更新策略的过程
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

(2)训练过程
①观察期(OBSERVE):程序与模拟器进行交互,随机给出动作,获取模拟器中的状态,将状态转移过程存放在D(Replay Memory)中
②探索期(EXPLORE):程序与模拟器交互的过程中,依据Replay Memory中存储的历史信息更新网络参数,并随训练过程降低随机探索率ε
③训练期(TRAIN):ε已经很小,不再发生改变,网络参数随着训练过程不断趋于稳定。

(3)整体框架——观察期
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

①打开游戏模拟器,不执行跳跃动作,获取游戏的初始状态
②根据ε贪心策略获得一个动作(由于神经网络参数也是随机初始化的,在本阶段参数也不会进行更新,所以统称为随机动作),并根据迭代次数减小ε的大小

③由模拟器执行选择的动作,能够返回新的状态和反馈奖励
④将上一状态s ,动作a,新状态s ‘,反馈r组装成( s , a , s’ ,r)放进Replay Memory中用作以后的参数更新
⑤根据新的状态s ‘,根据ε贪心策略选择下一步执行的动作,周而复始,直至迭代次数到达探索期

(4)整体框架——探索期
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

探索期与观察期的唯一区别在于会根据抽样对网络参数进行更新。

①迭代次数达到一定数目,进入探索期,根据当前状态s,使用ε贪心策略选择一个动作(可以是随机动作或者由神经网络选择动作),并根据迭代次数减小ε的值
②由模拟器执行选择的动作,能够返回新的状态和反馈奖励
③将上一状态s ,动作a,新状态s’,反馈r组装成( s , a , s’ ,r)放进Replay Memory中用作参数更新
④从Replay Memory中抽取一定量的样本,对神经网络的参数进行更新
⑤根据新的状态s ‘,根据s贪心策略选择下一步执行的动作,周而复始,直至迭代次数到达训练期

(5)整体框架——训练期
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

迭代次数达到一定数目,进入训练期,本阶段跟探索期的过程相同,只是在迭代过程中不再修改ε的值

(6)模拟器

①游戏模拟器
1)使用Python的Pygame模块完成的FlappyBird游戏程序
2)为了配合训练过程,在原有的游戏程序基础上进行了修改。
3)参考以下网址查看游戏源码:https://github.com/sourabhv/FlapPyBird

②图示通过模拟器获取游戏的画面。
③训练过程中使用连续4帧图像作为一个状态s ,用于神经网络的输入。
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

(7)动作选择模块
①动作选择模块︰为s贪心策略的简单应用,以概率ε随机从动作空间A中选择动作,以1-ε概率依靠神经网络的输出选择动作:
②如图
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)


③DQN∶用卷积神经网络对游戏画面进行特征提取,这个步骤可以理解为对状态的提取。

(8)卷积神经网络-CNN
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

展示卷积操作
①卷积核∶这里的卷积核指的就是移动中3*3大小的矩阵。
②卷积操作∶使用卷积核与数据进行对应位置的乘积并加和,不断移动卷积核生成卷积后的特征。

③池化操作∶对卷积的结果进行操作。最常用的是最大池化操作,即从卷积结果中挑出最大值,如选择一个2*2大小的池化窗口(操作如图示):
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

④卷积神经网络:把Image矩阵中的每个元素当做一个神经元,那么卷积核就相当于输入神经元和输出神经元之间的链接权重,由此构建而成的网络被称作卷积神经网络。

⑤Flappy Bird-深度神经网络

本实验中使用的深度神经网络结构就是多个卷积操作和池化操作的累加。
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

1)对采集的4张原始图像进行预处理,得到80804大小的矩阵;

2)使用32个884大小步长4的卷积核对以上矩阵进行卷积,得到202032大小的矩阵;
注:在tensorflow中使用4维向量表示卷积核[输入通道数,高度,宽度,输出通道数],对应于上面的[4,8,8,32],可以理解为32个884大小的卷积核;

3)对以上矩阵进行不重叠的池化操作,池化窗口为22大小,步长为2,得到101032大小的矩阵;
4)使用64个4
432大小步长为2的卷积核对以上矩阵进行卷积,得到5564的矩阵;
5)使用64个3
364大小步长为1的卷积核对以上矩阵进行卷积,得到5564的矩阵;
6)将输出的5
564大小的数组进行reshape,得到11600大小的矩阵;
7)在之后添加一个全连接层,神经元个数为512;
8)最后一层也是一个全连接层,神经元个数为2,对应的是就是两个动作的动作值函数;

⑥通过获得输入s,神经网络就能够:
1)输出Q(s,a1)和Q(s,a2)比较两个值的大小,就能够评判采用动作a1和a2的优劣,从而选择要采取的动作
2)在选择并执行完采用的动作后,模拟器会更新状态并返回回报值,然后将这个状态转移过程存储进D,进行采样更新网络参数。

(9)网络参数更新
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

①从D中抽取更新使用的样本;
②利用神经网络计算maxQ(s2, a’)和Qold(s1,a1);
③计算Qnew(s1,a1),并通过Qnew(s1,a1)和Qold(s1,a1)更新网络参数

3.相关库的介绍及安装

(1)相关库的简介

①TensorFlow
1)是谷歌2015年开源的一个人工智能学习系统。主要目的是方便研究人员开展机器学习和深度神经网络方面的研究,目前这个系统更具有通用性,也可广泛用于其他计算领域。
2)Tensorflow支持多种前端语言,包括Python(Python也是tensorflow支持最好的前端语言),因此一般大家利用python实现对tensorflow的调用。

②OpenCV
1)是一个开源的跨平台的计算机视觉库,实现了大量的图像处理和计算机视觉方面的通用算法。
2)本实验采用openev对采集的游戏画面进行预处理。

③Pygame
1)是一个跨平台的模块,专为电子游戏设计。
2)Pygame相当于是一款游戏引擎,用户无需编写大量的基础模块,而只需完成游戏逻辑本身就可以了。
3)本实验的模拟器根据pygame实现

(2)相关库的安装
①TensorFlow:在确保网络通畅的情况下,打开windows的DoS命令行窗口,使用pip命令安装:
pip install tensorflow

②OpenCV库安装:
1)在下载地址中找到opencv的相关下载链接,依据Python的具体版本下载对应的文件。
2)找到下载的文件的路径,打开windows的DOS命令行窗口,使用如下命令:
pip install opencv_python-3.2.0-cp35-cp35m-win_amd64.whl
3)如果未提示任何安装错误,则说明安装成功。

③Pygame库安装
1)在确保网络通畅的情况下,打开windows的DOS命令行窗口,使用如下命令:
pip install pygame

(3)测试
打开windows的DOS命令行窗口,进入Python命令行模式,导人包测试,如无错误,则说明安装成功

4.项目实战

(1)tensorflow基本使用

①理解TensorFlow:
1)使用图(graph)来表示计算任务;
2)在被称之为会话(Session)的上下文(context)中执行图;
3)使用tensor(张量)表示数据;
4)通过变量(Variable)维护状态;
5)使用feed和fetch可以为任意的操作(arbitrary operation)赋值或者从其中获取数据。

②TensorFlow是一个编程系统,使用图来表示计算任务。图中的节点被称作op (Operation ) , op可以获得0个或多个tensor,产生0个或多个tensor。

③每个tensor是一个类型化的多维数组。
④例如:可以将一组图像集表示成一个四维的浮点数组,四个维度分别是[batch,height,weight,channels]。
⑤图(graph)描述了计算的过程。为了进行计算,图必须在会话中启动,会话负责将图中的op分发到CPU或GPU上进行计算,然后将产生的tensor返回。在Python中,tensor就是numpy.ndarray对象。

⑥TensorFlow程序通常被组织成两个阶段:构建阶段和执行阶段。
1)构建阶段:op的执行顺序被描迹成一个图
2)执行阶段:使用会话执行图中的op。
3)例如:通常在构建阶段创建一个图来表示神经网络,在执行阶段反复执行图中的op训练神经网络。

import tensorflow as tf
mat1 = tf.constant([[3.,3.]]) #创建一个1*2的矩阵
mat2 = tf.constant([[2.,2.]]) #创建一个2*1的矩阵
product = tf.matmul(mat1,mat2) #创建op执行两个矩阵的算法
sess = tf.session() #启动默认图
res = sess.run(product) #在,默认图中执行op操作
print(res)
sess.close()

⑦交互式会话(InteractiveSession):
为了方便使用Ipython之类的Python交互环境,可以使用交互式会话(InteractiveSession)来代替Session,使用类似Tensor.run()Operation.eval()来代替Session.run(),避免使用一个变量来持有会话。

import tensorflow as tf
sess = tf.InteractiveSession #创建交互式会话
a = tf.Variable([1.0,2.0]) #创建变量数组
b = tf.constant([3.0,4.0]) #创建常量数组
sess.run(tf.global_variables_initializer())#变量初始化
res = tf.add(a,b)#创建加法操作
print(res.eval())#执行操作并输出结果

(2)Feed操作:
①前面的例子中,数据均以变量或常量的形式进行存储。
②Tensorflow还提供了Feed机制,该机制可以临时替代图中任意操作中的tensor。
③最常见的用例是使用tf.placeholder()创建占位符,相当于是作为图中的输人
④然后使用Feed机制向图中占位符提供数据进行计算,具体使用方法见接下来的样例。

import tensorflow as tf
sess = tf.InteractiveSession()#创建交互式会话
input1 = tf.placeholder(tf.float32)#创建占位符
input2 = tf.placeholder(tf.float32)
res = tf.mul(input1,input2)#创建乘法操作
res.eval(feed_dict={input1:[7.],input2:[2.]})#求值

(3)自主学习flappy bird实例程序编写
①建立工程,导入相关工具包
②设置超参数
③创建深度神经网络
④训练深度神经网络
⑤开启整个训练过程(创建交互式会话)

#建立工程,导入相关工具包
import cv2 #导入opencv
import sys
import tensorflow as tf
sys.path.append("game/") #添加game目录到系统环境变量
from pygame import wrapped_flappy_bird as game#加载游戏
import random #加载随机模块
import numpy as np
from collections import deque#导入双端队列

#设置超参数
GAME = 'bird'#设置游戏名称
ACTIONS = 2#设置游戏动作数目
GAMMA = 0.99 #设置增强学习更新公式中的累计折扣因子
OBSERVE = 10000 #观察期,1万次迭代(随机指定动作获得d)
EXPLORE = 2000000 #探索期
FINAL_EPSILON = 0.0001#设置ε的最小值
INITIAL_EPSILON = 0.1#设置ε贪心策略中ε的初始值
REPLAY_MEMORY = 50000#设置容量
BATCH = 32 #设置每次网络参数更新时用的样本数目
FRAME_PER_ACTION = 1 #设置几帧图像进行一次动作


# 创建深度神经网络
#首先定义一个函数用于生成形状为shape的张量(高维数组)
def weight_variable(shape):
    initial = tf.truncated_normal(shape,stddev=0.01)#张量中的初始化数值服从正态分布,且方差为0.01
    return tf.Variable(initial)
#生成另一个函数用于生成偏置项,初始值为0.01
def bias_variable(shape):
    initial = tf.constant(0.01,shape = shape)
    return tf.Variable(initial)
#定义卷积操作,实现卷积核W在数据x上卷积操作
def conv2d(x,W,stride):
    return tf.nn.conv2d(x,W,strides=[1,stride,stride,1],padding = "SAME")#strides为卷积核的移动步长,padding为卷积的一种模式,参数为same表示滑动范围超过边界时
#定义池化函数,调用max_pool执行最大池化操作,大小为2*2,stride步长为2
def max_pool_2x2(x):
    return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")

# 创建深度神经网络之定义网络结构(具体参数可回顾之前的框架)
def createNetwork(): #定义深度神经网络的参数和偏置
    #第一个卷积层
    W_conv1 = weight_variable([8,8,4,32])
    b_conv1 = bias_variable([32])
    # 第二个卷积层
    W_conv2 = weight_variable([4,4,32,64])
    b_conv2 = bias_variable([64])
    # 第三个卷积层
    W_conv3 = weight_variable([3,3,64,64])
    b_conv3 = bias_variable([64])
    #第一个全连接层
    W_fc1 = weight_variable([1600,512])
    b_fc1 = bias_variable([512])
    # 第二个全连接层
    W_fc2 = weight_variable([512,ACTIONS])
    b_fc2 = bias_variable([ACTIONS])
    #输入层
    s = tf.placeholder("float",[None,80,80,4])#placeholder用于占位,可用作网络的输入
    #隐藏层(对各层进行连接)
    h_conv1 = tf.nn.relu(conv2d(s,W_conv1,4) + b_conv1)
    h_pool1 = max_pool_2x2(h_conv1)

    h_conv2 = tf.nn.relu(conv2d(h_pool1,W_conv2,2) + b_conv2)
    h_conv3 = tf.nn.relu(conv2d(h_conv2, W_conv3, 1) + b_conv3)

    h_conv3_flat = tf.reshape(h_conv3,[-1,1600])

    h_fc1 = tf.nn.relu(tf.matmul(h_conv3_flat,W_fc1)+b_fc1)

    #输出层
    readout = tf.matmul(h_fc1,W_fc2)+b_fc2


#训练深度神经网络
def tarinNetwork(s,readout,h_cf1,sess):
    #定义损失函数
    a = tf.placeholder("float,"[None,ACTIONS])
    y = tf.placeholder("float,"[None])
    readout_action = tf.reduce_sum(tf.multiply(readout,a),reduction_indices=1)

    cost = tf.reduce_mean(tf.square(y-readout_action))
    train_step = tf.train.AdamOptimizer(1e-6).minimize(cost)

    #开启游戏模拟器,会打开一个窗口,实时显示游戏的信息
    game_state = game.GameState()

    #创建双端队列用于存放relay memory
    D = deque()

    #获取游戏的初始状态,设置动作为不执行跳跃,并将初始状态修改成80*80*4大小
    #此处需用OpenCV对图像进行预处理
    do_nothing = np.zeros(ACTIONS)
    do_nothing[0] = 1 #不执行跳跃
    x_t,r_0,terminal = game_state.frame_step(do_nothing)
    x_t = cv2.cvtColor(cv2.resize(x_t,(80,80)),cv2.COLOR_BGR2GRAY)
    ret,x_t = cv2.threshold(x_t,1,255,cv2.THRESH_BINARY) #将像素值大于等于1的像素点处理成255,也就是黑白二值图
    s_t = np.stack((x_t,x_t,x_t,x_t),axis=2) #构造4阵的原始输入

    #用于加载或保存网络参数
    saver = tf.train.Saver()
    sess.run(tf.initializer_all_variables())
    checkpoint = tf.train.get_checkpoint_state("saved_networks")
    if checkpoint and checkpoint.model_checkpoint_path:
        saver.restore(sess,checkpoint.model_checkpoint_path)
        print("Successfully loaded:",checkpoint.model_checkpoint_path)
    else:
        print("could not find old network weights")

    #开始训练
    epsilon = INITIAL_EPSILON
    t = 0
    while "flappy bird" !="angry bird":
        #使用epsilon贪心策略选择一个动作
        readout_t = readout.eval(feed_dict={s:[s_t]})[0]
        a_t = np.zeros([ACTIONS])
        action_index = 0
        if t%FRAME_PER_ACTION==0:
            #执行一个随机动作
            if random.random()<= epsilon:
                print("---------Random Action---------")
                action_index = random.randrange(ACTIONS)
                a_t[random.randrange(ACTIONS)]=1
            #由神经网络计算的Q(s,a)值选择对应的动作
            else:
                action_index = np.argmax(readout_t)
                a_t[action_index]=1
        else:
            a_t[0] = 1 #不执行跳跃动作
    #随游戏的进行,不断降低epsilon,减少随机动作
    if epsilon>FINAL_EPSILON and t>OBSERVE:
        epsilon-=(INITIAL_EPSILON-FINAL_EPSILON)/EXPLORE
    #执行选择的动作,并获得下一状态及回报
    x_t1_colored,r_t,terminal = game_state.frame_step(a_t)
    x_t1 = cv2.cvtColor(cv2.resize(x_t1_colored,(80,80)),cv2.COLOR_BGR2GRAY)

    ret,x_t1 = cv2.threshold(x_t1,1,255,cv2.THRESH_BINARY)
    x_t1 = np.reshape(x_t1,(80,80,1))
    s_t1 = np.append(x_t1,s_t[:,:,:3],axis=2)

    #将状态转移过程存储到D中,用于更新参数时采样
    D.append((s_t,a_t,r_t,s_t1,terminal))
    if len(D)>REPLAY_MEMORY:
        D.popleft()

    #过了观察期,才会进行网络参数的更新
    if t>OBSERVE:
        # 从D中随机采样,用于参数更新
        minibatch = random.sample(D,BATCH)

    # 分别将当前状态、采取的动作、获得的回报、下一状态分组存放
    s_j_batch = [d[0] for d in minibatch]
    a_batch = [d[1] for d in minibatch]
    r_batch = [d[2] for d in minibatch]
    s_j1_batch = [d[3] for d in minibatch]

    #计算Q(s,a)的新值
    y_batch = []
    readout_j1_batch = readout.eval(feed_dict={s: s_j1_batch})
    for i in range(0,len(minibatch)):
        terminal = minibatch[i][4]
        #如果游戏结束,则只有反馈值
        if terminal:
            y_batch.append(r_batch[i])
        else:
            y_batch.append(r_batch[i]+GAMMA*np.max(readout_j1_batch[i]))
    #使用梯度下降更新网络参数
    train_step.run(feed_dict={
        y:y_batch,
        a:a_batch,
        s:s_j_batch}
    )
    #状态发生改变,用于下次循环
    s_t = s_t1
    t +=1
    #每进行10000次迭代,保留一下网络参数
    if t%10000==0:
        saver.save(sess,'saved_networks/'+GAME+'-dqn',gloabl_step=t)

    #打印游戏信息
    state = ""
    if t<=OBSERVE:
        state = "observe"
    elif t > OBSERVE and t<= OBSERVE+EXPLORE:
        state = "explore"
    else:
        state = "train"
    print("TIMESTEP",t,"/STATE/",state,\
          "/EPSILON",epsilon,"/ACTION",action_index,"/REMARD",r_t,\
          "/Q_MAX %"%np.max(readout_t))


#开启整个训练过程(创建交互式会话)
def playGame():
    sess = tf.InteractiveSession()
    s,readout,h_fc1 = createNetwork()
    tarinNetwork(s,readout,h_fc1,sess)

if __name__=="_main_":
    playGame()

5.训练结果展示

(1)训练参数加载
①参数训练完成后,修改程序中的超参数INITIAL EPSILON=0,即不使用随机动作,直接由神经网络输出动作。
②saved networks文件夹下,保存了最近几次检查点保留的网络参数,只需使用tf.train.Saver(加载参数就可以使用了。
③修改checkpoint配置文件,加载保存的网络参数,默认加载最后一次保存的参数。修改完成,运行程序即可。

(2)结果展示
机器学习应用——强化学习&课程总结 实例 “自主学习Flappy Bird游戏”(MDP&蒙特卡洛强化学习&Q-learning&DRL&DQN)

三、课程总结

1.主要内容

(1)无监督学习(Unsupervised Learning )
(2)监督学习(Supervised Learning)
(3)强化学习(Reinforeement Learning,增强学习)

2.无监督学习

(1)无监督学习的两大任务
利用无标签的数据学习数据的分布或数据与数据之间的关系被称作无监督学习。
①聚类(clustering)
②降维(Dimension Reduction )

(2)聚类(clustering)
①聚类(clustering),就是根据数据的“相似性”将数据分为多类的过程。
②估算两个不同样本之间的相似性,通常使用的方法就是计算两个样本之间的“距离”
③最常用的就是欧式距离,此外还有马氏距离,曼哈顿距离,余弦距离等。

(3)Sklearn vs.聚类
①scikit-learn库提供的常用聚类算法函数包含在sklearn.cluster模块中,如:K-Means,DBSCAN等。
②我们在前面的讲解中通过实例具体讲解了K-Means,DBSCAN这些经典的聚类函数的在sklearn中的使用方法,也简单介绍了他们的算法思想。
③对大多数聚类算法来说,需要指定聚类的数目,DBSCAN是少数不需要指定聚类数目的算法之一。
④K-means:对簇中心的初始化比较敏感。
⑤DBSCAN:它可以发现使用K均值不能发现的许多簇,但不适合密度变化太大的数据,而且对于高维数据,该方法也有问题,因为密度定义比较困难。

(4)降维
①降维,就是在保证数据所具有的代表性特性或者分布的情况下,将高维数据转化为低维数据的过程。
②sklearn库提供多种降维算法,被封装在sklearn.decomposition模块中,在前面的学习中我们也展示了PCA和NMF在鸢尾花数据集和人脸数据集上的特征提取过程的相关操作。
③注意:降维方法通常用于高维数据集的探索与可视化,降维过的数据可以为其他任务作数据准备。

3.监督学习

(1)监督学习的两大任务
利用一组带有标签的数据,学习从输人到输出的映射,然后将这种映射关系应用到未知数据上,达到分类或回归的目的。

(2)分类
①输入:—组有标签的训练数据(也称观察和评估),标签表明了这些数据(观察)的所署类别。
②分类模型根据这些训练数据,训练自己的模型参数,学习出一个适合这组数据的分类器
③当有新数据(非训练数据)需要进行类别判断,就可以将这组新数据作为输人送给学好的分类器进行判断。

(3)Sklearn vs.聚类
①在分类学习个单元我们重点介绍了kNN、朴素贝叶斯、决策树模型的基本思想,通过对分类问题的实例编写,实现了对不同分类算法的调用,并进行了实验对比。
②初学者经常会将分类问题和聚类问题混淆,而训练数据有无标签是区别这两个问题的关键,在将实际问题转换为学习问题的过程中,需要大家判断准确,选择合适的机器学习算法。

(4)回归
①是一种统计学上分析数据的方法,目的在于了解两个或多个变数间是否相关、研究其相关方向与强度,并建立数学模型以便观察特定变数来预测研究者感兴趣的变数。
②回归方法常被用来进行如股票趋势预测,交通流量预测这种带有时序信息的数据分析上。

(5)Sklearn vs.回归
①回归函数主要分为两类,线性回归和非线性回归。线性回归函数主要封装在sklearn.linear_model模块中,如普通线性回归、岭回归、Lasso。
②注意:sklearn中非线性回归是通过利用sklearn.preprocessing模块生成原始数据的非线性特征,在调用线性回归模型将这些非线性特征按线性方式进行拟合实现的。

4.强化学习

(1)传统强化学习模型(model-based, model-free )
(2)深度强化学习的基本思路
(3)TensorFlow的简单使用技巧
(4)以Tensorflow实现Flappy bird游戏的自主学习的实例,通过实例的学习,可以掌握利用Tenforlow构造深度神经网络,并进行训练以解决实际问题的能力。

总结

关于强化学习,核心在于对基本CNN神经网络的理解h饿使用,在此仅用最基础的CNN结构为例,其余便不多做赘述。关于代码之中的一些改进问题,由于用到库中的其他方法,且本人能力有限,大家感兴趣可自行查阅官网API。

关于Tensorflow库的版本问题,由于1和2两个版本函数差异较大,在用到某些函数出现bug时可以百度查找一下,部分函数被删除,部分使用方法有所改变。

两点问题:
(1)代码运行需要基础数据支撑,py的自带库中有些内含所需数据,有些则没有,本篇并未放上数据txt文件,只是为了展示无监督学习的体系流程以作演示
(2)在库的包导入若发生问题,看看版本更新问题,以及部分包在近年来命名和函数有所调整,各位客官可面向百度

代码非原创,内容乃网课课件整理所得。
如有问题,欢迎指正!

机器学习专栏的所有内容至此就结束啦,完结撒花~

版权声明:本文为博主柠檬茶@原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/qq_51308373/article/details/122669769

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2022年1月24日
下一篇 2022年1月24日

相关推荐