【Python入门】Python做游戏——跳跃小鸟

本文介绍了如何使用Python和Keras通过卷积神经网络(CNN)实现跳跃小鸟游戏。游戏输入经过预处理,每帧图像与前几帧叠加形成多通道输入。神经网络模型包括多个卷积层,用于图像特征提取,再通过全连接层转换为动作指令。文章还提到了游戏运行的环境配置和训练模型的步骤。
摘要由CSDN通过智能技术生成

如何运行

  • 安装依赖
pip install keras
pip install pygame
pip install scikit-image
pip install h5py

作者使用的是theano训练的,训练好的模型文件要使用theano作为Keras的后端才能调用,在配置文件~/.keras/keras.json中(没有可创建)确认/修改backendtheano(如果没有安装tensorflow[Keras的另一可选后端]好像就不用管了),配置文件样式下文中卷积神经网络小节的补充里有。
要使用theano,我们还需要安装OpenBLAS。直接下载源码并解压,cd进目录,然后

sudo apt-get install gfortran
make FC=gfortran  
sudo make PREFIX=/usr/local install  

  • 下载源码并运行
git clone https://github.com/yanpanlau/Keras-FlappyBird.git
cd Keras-FlappyBird
python qlearn.py -m "Run"

我下载时目录中game/wrapped_flappy_bird.py文件的第144行,FPSCLOCK.tick(FPS)语句处缩进有点问题,删去现有缩进,打8个空格就好了,没问题就不用管了。

  • vmware虚拟机Ubuntu16.04+python3+只使用CPU+theano运行:

  • 如果想重新训练神经网络,删除**model.h5**文件然后运行命令qlearn.py -m "Train"
源码分析
  • 游戏输入及返回图像
import wrapped_flappy_bird as game
x_t1_colored, r_t, terminal = game_state.frame_step(a_t)

直接使用flappybird python版本的接口。
输入为a_t(1, 0)代表不跳,(0,1)代表跳)。
返回值为下一帧图像x_t1_colored和奖励reward+0.1表示存活,+1表示通过管道,-1表示死亡),奖励被控制在[-1,+1]来提高稳定性。terminal 是一个布尔值表示游戏是否结束。
奖励函数在game/wrapped_flappy_bird.py中的
def frame_step(self, input_actions)方法中修改。

为什么直接将游戏图像输入处理呢?我一开始没转过弯,其实图像中包含了全部的信息(声音信息在多数游戏里只是辅助,不影响游戏),而人在玩游戏时也是接受输入的图像信息,然后决策输出相应的操作指令。这里其实就是在模拟人的反馈过程,将这一过程描述为一个非线性函数,而该非线性函数我们将使用卷积神经网络来表达,大体上卷积实现了对图像特征的提取,神经网络实现了从特征到操作指令的转换。

  • 图像预处理

要素:

1.  将图片转换为灰阶
2.  裁剪图片尺寸到80x80像素
3.  每次堆积4帧,一起馈入神经网络。相当于一次输入一张'四通道'的图像。  
    (为什么要将4帧堆在一起?这是一种方法,为了让模型能推断出小鸟的速度信息。)
x_t1 = skimage.color.rgb2gray(x_t1_colored)
x_t1 = skimage.transform.resize(x_t1,(80,80))
x_t1 = skimage.exposure.rescale_intensity(x_t1, out_range=(0, 255)) # 调整亮度
#
x_t1 = x_t1.reshape(1, 1, x_t1.shape[0], x_t1.shape[1])
s_t1 = np.append(x_t1, s_t[:, :3, :, :], axis=1)
# axis=1 意味着在第二维上添加

x_t1是一个(1x1x80x80) 的单帧,s_t1是4帧的叠加,形状为(1x4x80x80)。输入设计为 (1x4x80x80)而不是(4x80x80)是为了Keras考虑。

补充

rescale_intensity

  • 卷积神经网络
    现在,将预处理后的图像输入神经网络。
def buildmodel():
    print("开始建模")
    model = Sequential()
    model.add(Convolution2D(32, 8, 8, subsample=(4,4),init=lambda shape, name: normal(shape, scale=0.01, name=name), border_mode='same', dim_ordering='th', input_shape=(img_channels,img_rows,img_cols)))
    model.add(Activation('relu'))
    model.add(Convolution2D(64, 4, 4, subsample=(2,2),init=lambda shape, name: normal(shape, scale=0.01, name=name), border_mode='same', dim_ordering='th'))
    mod
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值