轻松实现TensorFlow微信跳一跳的AI


Posted in Python onJanuary 05, 2018

作为python和机器学习的初学者,目睹了AI玩游戏的各种风骚操作,心里也是跃跃欲试。

然后发现微信跳一跳很符合需求,因为它不需要处理连续画面(截屏太慢了)和复杂的操作,很适合拿来练手。于是…这个东西诞生了,目前它一般都可以跳到100多分,发挥好了能上200。

1.需要设备:

Android手机,数据线
ADB环境
Python环境(本例使用3.6.1)
TensorFlow(本例使用1.0.0)

2.大致原理

使用adb模拟点击和截屏,使用两层卷积神经网络作为训练模型,截屏图片作为输入,按压毫秒数直接作为为输出。

3.训练过程

最开始想的用强化学习,然后发现让它自己去玩成功率太!低!了!,加上每次截屏需要大量时间,就放弃了这个方法,于是考虑用自己玩的数据作为样本喂给它,这样就需要知道每次按压的时间。

我是这样做的,找一个手机写个app监听按压屏幕时间,另一个手机玩游戏,然后两个手指同时按两个手机o(?□?)o

4.上代码

首先,搭建模型:

第一层卷积:5*5的卷积核,12个featuremap,此时形状为96*96*12
池化层:4*4 max pooling,此时形状为24*24*12
第二层卷积:5*5的卷积核,24个featuremap,此时形状为20*20*24
池化层:4*4 max pooling,此时形状为5*5*24
全连接层:5*5*24连接到32个节点,使用relu激活函数和0.4的dropout率
输出:32个节点连接到1个节点,此节点就代表按压的时间(单位s)

# 输入:100*100的灰度图片,前面的None是batch size,这里都为1 
x = tf.placeholder(tf.float32, shape=[None, 100, 100, 1]) 
# 输出:一个浮点数,就是按压时间,单位s 
y_ = tf.placeholder(tf.float32, shape=[None, 1]) 
 
# 第一层卷积 12个feature map 
W_conv1 = weight_variable([5, 5, 1, 12], 0.1) 
b_conv1 = bias_variable([12], 0.1) 
# 卷积后为96*96*12 
 
h_conv1 = tf.nn.relu(conv2d(x, W_conv1) + b_conv1) 
h_pool1 = max_pool_4x4(h_conv1) 
# 池化后为24*24*12 
 
# 第二层卷积 24个feature map 
W_conv2 = weight_variable([5, 5, 12, 24], 0.1) 
b_conv2 = bias_variable([24], 0.1) 
# 卷积后为20*20*24 
 
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) 
h_pool2 = max_pool_4x4(h_conv2) 
# 池化后为5*5*24 
 
# 全连接层5*5*24 --> 32 
W_fc1 = weight_variable([5 * 5 * 24, 32], 0.1) 
b_fc1 = bias_variable([32], 0.1) 
h_pool2_flat = tf.reshape(h_pool2, [-1, 5 * 5 * 24]) 
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) 
 
# drapout,play时为1训练时为0.6 
keep_prob = tf.placeholder(tf.float32) 
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) 
# 学习率 
learn_rate = tf.placeholder(tf.float32) 
 
# 32 --> 1 
W_fc2 = weight_variable([32, 1], 0.1) 
b_fc2 = bias_variable([1], 0.1) 
y_fc2 = tf.matmul(h_fc1_drop, W_fc2) + b_fc2 
 
# 因输出直接是时间值,而不是分类概率,所以用平方损失 
cross_entropy = tf.reduce_mean(tf.square(y_fc2 - y_)) 
train_step = tf.train.AdamOptimizer(learn_rate).minimize(cross_entropy)

其次,获取屏幕截图并转换为模型输入:

# 获取屏幕截图并转换为模型的输入 
def get_screen_shot(): 
  # 使用adb命令截图并获取图片,这里如果把后缀改成jpg会导致TensorFlow读不出来 
  os.system('adb shell screencap -p /sdcard/jump_temp.png') 
  os.system('adb pull /sdcard/jump_temp.png .') 
  # 使用PIL处理图片,并转为jpg 
  im = Image.open(r"./jump_temp.png") 
  w, h = im.size 
  # 将图片压缩,并截取中间部分,截取后为100*100 
  im = im.resize((108, 192), Image.ANTIALIAS) 
  region = (4, 50, 104, 150) 
  im = im.crop(region) 
  # 转换为jpg 
  bg = Image.new("RGB", im.size, (255, 255, 255)) 
  bg.paste(im, im) 
  bg.save(r"./jump_temp.jpg") 
 
  img_data = tf.image.decode_jpeg(tf.gfile.FastGFile('./jump_temp.jpg', 'rb').read()) 
  # 使用TensorFlow转为只有1通道的灰度图 
  img_data_gray = tf.image.rgb_to_grayscale(img_data) 
  x_in = np.asarray(img_data_gray.eval(), dtype='float32') 
 
  # [0,255]转为[0,1]浮点 
  for i in range(len(x_in)): 
    for j in range(len(x_in[i])): 
      x_in[i][j][0] /= 255 
 
  # 因为输入shape有batch维度,所以还要套一层 
  return [x_in]

以上代码过程大概是这样:

轻松实现TensorFlow微信跳一跳的AI

最后,开始训练:

while True: 
 
  ………… 
 
  # 每训练100个保存一次 
  if train_count % 100 == 0: 
    saver_init.save(sess, "./save/mode.mod") 
 
  …………   
  
  sess.run(train_step, feed_dict={x: x_in, y_: y_out, keep_prob: 0.6, learn_rate: 0.00005})

训练所用数据是直接从采集好的文件中读取的,由于样本有限(目前采集了800张图和对应800个按压时间,在github上train_data文件夹里),并且学习率太大又会震荡,只能用较小学习率反复学习这些图片。

5.总结

1.样本的按压时间大都分布在300ms到900ms之间,刚开始训练的时候发现不论什么输入,输出都一直很谨慎的停留在600左右,还以为这种方法不可行。不过半个小时后再看发现已经有效果了,对于不同的输入,输出值差距开始变大了。所以…相信卷积网络的威力,多给它点耐心。

2.由于我自己最多玩到100多分,后面的数据没法采集到,所以当后面物体变得越来越小时,这个AI也会变得容易挂掉。理论上说让它自己探索不会有这个瓶颈,只是截屏时间实在难以忍受。

3.目前还是初级的版本,有很多可以优化的地方,比如说识别左上角的分数,如果某次跳跃得分较高,那么可以把这次的学习率增大;检测特殊物体,比如超市音乐盒,就停留几秒再进行下一次跳跃,等等。

下面是github地址,源码加注释总共不到300行:
https://github.com/zhanyongsheng/LetsJump

更多内容大家可以参考专题《微信跳一跳》进行学习。

Python 相关文章推荐
利用python求解物理学中的双弹簧质能系统详解
Sep 29 Python
python3利用smtplib通过qq邮箱发送邮件方法示例
Dec 03 Python
python模块smtplib学习
May 22 Python
Python中类的创建和实例化操作示例
Feb 27 Python
Python3+PyInstall+Sciter解决报错缺少dll、html等文件问题
Jul 15 Python
django2笔记之路由path语法的实现
Jul 17 Python
Python中关于浮点数的冷知识
Sep 22 Python
PYTHON发送邮件YAGMAIL的简单实现解析
Oct 28 Python
PyTorch中Tensor的数据统计示例
Feb 17 Python
基于Python中Remove函数的用法讨论
Dec 11 Python
Django中ORM的基本使用教程
Dec 22 Python
pycharm进入时每次都是insert模式的解决方式
Feb 05 Python
OpenCV-Python实现轮廓检测实例分析
Jan 05 #Python
django2 快速安装指南分享
Jan 05 #Python
Python实现改变与矩形橡胶的线条的颜色代码示例
Jan 05 #Python
用python制作游戏外挂
Jan 04 #Python
Python学习之Anaconda的使用与配置方法
Jan 04 #Python
Windows下Anaconda的安装和简单使用方法
Jan 04 #Python
Python+OpenCV让电脑帮你玩微信跳一跳
Jan 04 #Python
You might like
PHP执行zip与rar解压缩方法实现代码
2010/12/05 PHP
PHP页面实现定时跳转的方法
2014/10/31 PHP
WordPress中编写自定义存储字段的相关PHP函数解析
2015/12/25 PHP
Zend Framework入门教程之Zend_Mail用法示例
2016/12/08 PHP
ThinkPHP框架实现定时执行任务的两种方法分析
2018/09/04 PHP
理运用命名空间让js不产生冲突避免全局变量的泛滥
2014/06/15 Javascript
js控制页面的全屏展示和退出全屏显示的方法
2015/03/10 Javascript
javascript编程异常处理实例小结
2015/11/30 Javascript
基于javascript实现图片切换效果
2016/04/17 Javascript
Bootstrap实现水平排列的表单
2016/07/04 Javascript
js实现截图保存图片功能的代码示例
2017/02/16 Javascript
Bootstrap Table 删除和批量删除
2017/09/22 Javascript
javaScript中的空值和假值
2017/12/18 Javascript
微信小程序如何连接Java后台
2019/08/08 Javascript
NodeJs实现简易WEB上传下载服务器
2019/08/10 NodeJs
Python实现基本线性数据结构
2016/08/22 Python
Python 使用with上下文实现计时功能
2018/03/09 Python
Python实现简单http服务器
2018/04/12 Python
PyQt5每天必学之切换按钮
2020/08/20 Python
Python直接赋值、浅拷贝与深度拷贝实例分析
2019/06/18 Python
一篇文章搞定Python操作文件与目录
2019/08/13 Python
python实现猜拳小游戏
2020/04/05 Python
Python 类的私有属性和私有方法实例分析
2019/09/29 Python
python json load json 数据后出现乱序的解决方案
2020/02/27 Python
python pandas dataframe 去重函数的具体使用
2020/07/20 Python
全球酒店预订网站:Hotels.com
2016/08/10 全球购物
英国户外装备和冒险服装零售商:alloutdoor
2018/01/30 全球购物
新加坡交友网站:be2新加坡
2019/04/10 全球购物
屈臣氏马来西亚官网:Watsons马来西亚
2019/06/15 全球购物
某个公司的Java笔面试题
2016/03/11 面试题
教师对学生的评语
2014/04/28 职场文书
教师批评与自我批评剖析材料
2014/10/16 职场文书
入党积极分子十八届四中全会思想汇报
2014/10/23 职场文书
整改落实情况汇报材料
2014/10/29 职场文书
公司规章制度范本
2015/08/03 职场文书
Apache Pulsar结合Hudi构建Lakehouse方案分析
2022/03/31 Servers