这些天,想必大家最不缺的是假期....
正好可以趁这段时间学习学习,于是我还是沉下心搞了一下技术研究,接下来就说说从年前宅到现在折腾的东西吧。
一言蔽之:学习了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
主要兼容的代码包括以下两部分:
- 把原tfjs中的self和this换成小游戏的全局变量GameGlobal
- 底部加上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去做个智能识别口罩,然后推送真假货建议或使用建议信息的小程序,但模型训练难度太高,于是被否了。
现在还一直在想怎么做点跟疫情相关的技术研究,有想法的同学可以留言建议咯。
最后,
病毒无情,人间有情,愿我们在彼此隔离间迈过这道坎~