长假慢学,用TensorFlow做了个AI游戏

2020-07-24 10:54:26 浏览数 (1)

这些天,想必大家最不缺的是假期....

正好可以趁这段时间学习学习,于是我还是沉下心搞了一下技术研究,接下来就说说从年前宅到现在折腾的东西吧。

一言蔽之:学习了tensorflow

年末给自己定了一个“研究人工智能”的目标,为什么呢?毕竟现在说自己会写代码的人很多,但会人工智能编程的人却不多吧,学习人工智能,这完全符合我的“信息不对称”论。

那么,为什么是tensorflow(以下简称为tf)呢?因为它简单呀!(后来发现其实也挺难),而且它有js版本,会做网页开发的前端同学基本看看demo就能知道它在干嘛,也能马上做出一两个相关demo。

注.以下是tensorflow.js的官方定义:

Tensorflow.js 是一个基于 deeplearn.js 构建的库,可直接在浏览器环境中创建深度学习模型。使用它可以在浏览器上创建 CNNs,RNNs 等,并使用客户端的 GPU 处理能力训练这些模型。 Google,公众号:TensorFlowTensorFlow.js 入门指南

于是,拧起袖子,说干就干。但问题来了,干什么呢?每次要创造或者学习什么东西,我都习惯给自己定一个简单直接的场景,并具象化成一个载体。

做点没人做过的事:把tf用在小游戏上,做个手绘识别游戏。

老规矩,先上实例,依然搞了个游戏,不过这次做的是跨平台版本。

微信小游戏版(待发布,要体验可以单独联系):

字节小游戏版:

可能是小游戏中鲜有的、用了tensorflow的游戏?

其实,google早在普通小程序上给过tf的应用方案,但在小游戏上却没怎么提及过,何不给小游戏一个tf案例呢?于是,作为一个完全没接触过tf开发的程序员,我开始找demo去研究代码。后来,在网上发现一个外国牛人对google开源手绘数据集的应用:

代码语言:javascript复制
https://medium.com/tensorflow/train-on-google-colab-and-run-on-the-browser-a-case-study-8a45f9b1474e

里面阐述的内容大概是关于怎么利用手绘数据集,然后通过tf去训练模型的,与此同时,大牛还提供了一个web版的手绘识别demo。

结合文章,我发现其实把这个demo移植到微信小游戏中,应该是不难的,但因为我要做的是游戏,所以一般会用上游戏引擎,于是我试着用cocos creator(以下简称为ccc)去呈现这个demo。

其实还是有点麻烦的,最终花了一些时间去实现了一个可运行的网页版:

当我喜出望外,觉得这是一件简单的事情时,马上就晴天霹雳了,我在ccc中以微信小游戏发布,

然后在手机上试着运行,发现是报错的。

构造一个小游戏可用的tfjs

这是为什么呢?经过一定时间的摸索,发现官方的tf用了一个叫Fetch的方法,该方法在微信小游戏中并不兼容。

注.关于fetch的定义如下:

Fetch API 已经作为现代浏览器中异步网络请求的标准方法,其使用 Promise 作为基本构造要素。 公众号:前端大全认识 Fetch API

Fetch的作用说白了就是要简化请求,那么兼容方案就不难了,甚至也不用我主动去写兼容代码,因为google给普通小程序提供的Fetch兼容代码是适用于小游戏的:

代码语言:javascript复制
https://cdn.jsdelivr.net/npm/fetch-wechat@0.0.3/dist/fetch_wechat.js

于是通过终端中执行命令行,可得到最新版的tfjs:

代码语言:javascript复制
npm install @tensorflow/tfjs

在上述最右侧目录中找到tf.js,然后结合上述的Fetch兼容代码,我们就可以做出一份能在小游戏中适用的tfjs。

代码语言:javascript复制
https://github.com/minijoe/tfjsForMinigame/blob/master/tf.js

主要兼容的代码包括以下两部分:

  1. 把原tfjs中的self和this换成小游戏的全局变量GameGlobal
  1. 底部加上Fetch代码

这样,我们就得到了一个可用的tfjs,需要提醒的是,字节小游戏中的webgl版本跟tfjs貌似是不兼容的,这时候可以试试把backend调整成cpu模式(当然会慢一点了)。

使用google手绘数据集构建模型数据

很早之前Google就开源了一个非常棒的数据集---涂鸦数据集,其中涉及300多种物体, 包含5000 万张矢量画数据,这些数据全部开源给开发者,数量量极其庞大:

代码语言:javascript复制
https://github.com/googlecreativelab/quickdraw-dataset

借助于这个数据集,可用 Keras 框架在谷歌 Colab 免费提供的 GPU 上训练模型(Google云盘上的Colab Notebooks可运行脚本)。

具体可以参考这个帖子:

代码语言:javascript复制
https://medium.com/tensorflow/train-on-google-colab-and-run-on-the-browser-a-case-study-8a45f9b1474e

实际上,关键是要生成model.json和group1-shard1of1,这是tf.loadLayerModel所需要的模型数据。

tf要实现“某个图片在已有模型数据中的匹配度”目的,所遵循的逻辑有以下3步:

1.利用tf.loadLayersModel加载训练好的模型数据

代码语言:javascript复制
tf.loadLayersModel('http://xxx/model.json').then(model => {
    model.predict(tf.zeros([1, 28, 28, 1]))
    cc.game.model=model
})

2.读取并整理传进来的图片数据

代码语言:javascript复制
function preprocess(imgData) {
    //注意,1.5.2的tf不能直接传入图片数据,要整理一下
    var data={
        width:imgData.width,
        height:imgData.height,
        data:new Uint8Array(imgData.data)
    }
    return tf.tidy(() => {
        var tensor = tf.browser.fromPixels(data, 1)
        const resized = tf.image.resizeBilinear(tensor, [28, 28]).toFloat()
        const offset = tf.scalar(255.0);
        const normalized = tf.scalar(1.0).sub(resized.div(offset));
        const batched = normalized.expandDims(0)
        return batched
    })
}

3.计算匹配度

代码语言:javascript复制
const pred = cc.game.tfModel.predict(preprocess(imgData)).dataSync()

这句代码会得到传进来的图片数据在模型数据中的匹配排序,只要取出前几名就能判断出传进来的图片跟什么物体相似。

基于这个,就能做出只能识别手绘图的游戏逻辑了。

评估游戏主逻辑可行性后,我切换到灵魂画师的角色,理一下逻辑,游戏交互和视觉就出来了:

利用ipad的Procreate App,用apple pencil手绘一下logo和弹框、按钮之类的素材。

在ccc中嵌套视觉素材。

再补充关卡相关的页面和数据,调整一下难度,一个游戏的开发就完成了。

最后,个人对于字节互动的小游戏有点好奇,于是顺带就移植了一个版本,最终给微信和字节都做了版本。

结项~

这年春节很不平常,但对于想要学习和创作的我来说,其实是更多时间去折腾了。

本文只是基于应用层面简单的挂靠了一下AI概念,但愿还是能给想要在小游戏领域做AI的同学一点启发。

讲完了。

ps.最近一直在想能不能用技术去帮忙抗疫,昨晚就跟另一个朋友在聊,能不能用tf去做个智能识别口罩,然后推送真假货建议或使用建议信息的小程序,但模型训练难度太高,于是被否了。

现在还一直在想怎么做点跟疫情相关的技术研究,有想法的同学可以留言建议咯。

最后,

病毒无情,人间有情,愿我们在彼此隔离间迈过这道坎~

0 人点赞