轻松实现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调用cmd命令行制作刷博器
Jan 13 Python
Python中针对函数处理的特殊方法
Mar 06 Python
Python的Django框架中自定义模版标签的示例
Jul 20 Python
python使用str & repr转换字符串
Oct 13 Python
Python基于回溯法子集树模板解决最佳作业调度问题示例
Sep 08 Python
python模块smtplib实现纯文本邮件发送功能
May 22 Python
win8下python3.4安装和环境配置图文教程
Jul 31 Python
python查看文件大小和文件夹内容的方法
Jul 08 Python
在django-xadmin中APScheduler的启动初始化实例
Nov 15 Python
python 利用toapi库自动生成api
Oct 19 Python
浅析Python 中的 WSGI 接口和 WSGI 服务的运行
Dec 09 Python
关于的python五子棋的算法
May 02 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 COOKIE设置为浏览器进程
2009/06/21 PHP
Notice: Trying to get property of non-object problem(PHP)解决办法
2012/03/11 PHP
php计算到指定日期还有多少天的方法
2015/04/14 PHP
yii2.0数据库迁移教程【多个数据库同时同步数据】
2016/10/08 PHP
jQuery实现的Email中的收件人效果(按del键删除)
2011/03/20 Javascript
关于eval 与new Function 到底该选哪个?
2013/04/17 Javascript
js获取php变量的实现代码
2013/08/10 Javascript
webapp框架AngularUI的demo改造之路
2014/12/21 Javascript
JS实现图片产生波纹一样flash效果的方法
2015/02/27 Javascript
JavaScript按值删除数组元素的方法
2015/04/24 Javascript
浅析Javascript匿名函数与自执行函数
2016/02/06 Javascript
原生JS实现匀速图片轮播动画
2016/10/18 Javascript
微信小程序 教程之引用
2016/10/18 Javascript
js 开发之autocomplete="off"在chrom中失效的解决办法
2017/09/28 Javascript
30分钟快速实现小程序语音识别功能
2018/11/27 Javascript
Vue.js实现tab切换效果
2019/07/24 Javascript
vue实现输入一位数字转汉字功能
2019/12/13 Javascript
element日历calendar组件上月、今天、下月、日历块点击事件及模板源码
2020/07/27 Javascript
基于Python实现一个简单的银行转账操作
2016/03/06 Python
python 简单备份文件脚本v1.0的实例
2017/11/06 Python
使用python将大量数据导出到Excel中的小技巧分享
2018/06/14 Python
python pandas生成时间列表
2019/06/29 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
基于Keras中Conv1D和Conv2D的区别说明
2020/06/19 Python
python 两种方法删除空文件夹
2020/09/29 Python
python list等分并从等分的子集中随机选取一个数
2020/11/16 Python
pycharm 复制代码出现空格的解决方式
2021/01/15 Python
SCDKey德国:全球领先的数字游戏市场
2019/04/09 全球购物
美国时尚大码女装购物网站:Avenue
2019/05/24 全球购物
Clos19英国:高档香槟、葡萄酒和烈酒在线购物平台
2020/07/10 全球购物
淘宝中秋节活动方案
2014/01/31 职场文书
英语专业职业生涯规划范文
2014/03/05 职场文书
大学生党员承诺书
2014/05/20 职场文书
不错的求职信范文
2014/07/20 职场文书
2014年财务工作自我评价
2014/09/23 职场文书
小学教师岗位职责
2015/04/02 职场文书