侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

微信(小程序)  /  管理员 发布于 7年前   157

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

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

1.需要设备:

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

2.大致原理

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

3.训练过程

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

我是这样做的,找一个手机写个app监听按压屏幕时间,另一个手机玩游戏,然后两个手指同时按两个手机o(s□t)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] 

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

最后,开始训练:

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

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


  • 上一条:
    itchat和matplotlib的结合使用爬取微信信息的实例
    下一条:
    Django实现支付宝付款和微信支付的示例代码
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 微信模板消息改版后发送规则记录(微信订阅消息参数值内容限制说明)(1个评论)
    • 微信支付v3对接所需工具及命令(0个评论)
    • 2023年9月1日起:微信小程序必须备案才能上线运营(0个评论)
    • 腾讯官方客服回应了:微信好友上限约10000个!(1个评论)
    • 2023年做微信小程序的老铁注意:新增收费项、微信小程序获取手机号也收费了(2个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2017-10
    • 2018-01
    • 2020-03
    • 2021-06
    • 2021-10
    • 2022-03
    • 2023-02
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客