用 Transformers.js 制作浏览器端 ML 网页游戏 Doodle Dash 的教程
Making ML-powered web games with Transformers.js
Hugging Face 博客发布教程,讲解如何制作完全在浏览器中运行的实时 ML 网页游戏 Doodle Dash,灵感来自 Google 的 Quick, Draw!
作者完整走通从微调 MobileViT 到用 Transformers.js 在浏览器实时推理的全流程,方法可直接复用到自己的网页游戏项目。
在这篇博客文章中,我将向你展示我是如何制作 Doodle Dash 的,这是一个由机器学习驱动的实时网页游戏,完全在你的浏览器中运行(得益于 Transformers.js)。本教程的目标是向你展示制作自己的机器学习网页游戏有多么简单……正好赶上即将到来的开源 AI 游戏开发挑战赛(2023 年 7 月 7 日至 9 日)。如果你还没有参加,快来加入吧!
快速链接
- 演示: Doodle Dash
- 源代码: doodle-dash
- 加入游戏开发挑战赛: Open Source AI Game Jam
概述
在开始之前,让我们先聊聊我们将要创建的内容。这款游戏的灵感来自 Google 的 Quick, Draw! 游戏,在游戏中你会得到一个词语,神经网络有 20 秒的时间来猜测你在画什么(重复 6 次)。事实上,我们将使用他们的训练数据来训练我们自己的草图检测模型!你是不是也爱死开源了?😍
在我们的版本中,你将有一分钟的时间尽可能多地画出物品,一次一个提示。如果模型预测出正确的标签,画布将被清空,并给你一个新的词语。一直这样做,直到计时结束!由于游戏完全在你的浏览器中本地运行,我们完全不必担心服务器延迟。模型能够在你绘画时进行实时预测,速度高达每秒超过 60 次预测……🤯 哇!
本教程分为 3 个部分:
1. 训练神经网络
训练数据
我们将使用 Google Quick, Draw! 数据集的子集来训练我们的模型,该数据集包含 345 个类别、超过 500 万幅画作。以下是数据集中的一些样本:
模型架构
我们将微调 apple/mobilevit-small,这是一个轻量级且适合移动端的 Vision Transformer,已在 ImageNet-1k 上进行了预训练。它只有 560 万个参数(文件大小约 20 MB),是运行在浏览器中的完美候选!如需了解更多信息,请查看 MobileViT 论文以及下方的模型架构。
微调
为了让这篇博客文章(相对)简短,我们准备了一个 Colab notebook,它将向你展示我们在数据集上微调 apple/mobilevit-small 所采取的确切步骤。从高层来看,这包括:
使用
MobileViTImageProcessor转换数据集。使用
MobileViTForImageClassification.from_pretrained加载预训练的 MobileVIT 模型。使用
Trainer和TrainingArguments辅助类训练模型。使用 🤗 Evaluate 评估模型。
注意:你可以在 Hugging Face Hub 上这里找到我们微调后的模型。
2. 使用 Transformers.js 在浏览器中运行
什么是 Transformers.js?
Transformers.js 是一个 JavaScript 库,允许你直接在浏览器中运行 🤗 Transformers(无需服务器)!它的设计目标是在功能上等同于 Python 库,这意味着你可以使用非常相似的 API 运行相同的预训练模型。
在幕后,Transformers.js 使用 ONNX Runtime,因此我们需要将微调后的 PyTorch 模型转换为 ONNX。
将我们的模型转换为 ONNX
幸运的是,🤗 Optimum 库让将微调后的模型转换为 ONNX 变得非常简单!最简单(也是推荐)的方法是:
克隆 Transformers.js 仓库 并安装必要的依赖:
git clone https://github.com/xenova/transformers.js.git cd transformers.js pip install -r scripts/requirements.txt运行转换脚本(它底层使用
Optimum):python -m scripts.convert --model_id <model_id>其中
<model_id>是你要转换的模型名称(例如Xenova/quickdraw-mobilevit-small)。
设置我们的项目
让我们先用 Vite 搭建一个简单的 React 应用:
npm create vite@latest doodle-dash -- --template react
接下来,进入项目目录并安装必要的依赖:
cd doodle-dash
npm install
npm install @xenova/transformers
然后你可以通过运行以下命令启动开发服务器:
npm run dev
在浏览器中运行模型
运行机器学习模型是计算密集型的,因此在单独的线程中执行推理非常重要。这样我们就不会阻塞主线程,主线程用于渲染 UI 和响应你的绘画手势 😉。Web Workers API 让这变得非常简单!
在 src 目录中创建一个新文件(例如 worker.js)并添加以下代码:
import { pipeline, RawImage } from "@xenova/transformers";
const classifier = await pipeline("image-classification", 'Xenova/quickdraw-mobilevit-small', { quantized: false });
const image = await RawImage.read('https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/blog/ml-web-games/skateboard.png');
const output = await classifier(image.grayscale());
console.log(output);
现在我们可以通过在 App 组件中添加以下代码,在 App.jsx 文件中使用这个 worker:
import { useState, useEffect, useRef } from 'react'
// ... rest of the imports
function App() {
// Create a reference to the worker object.
const worker = useRef(null);
// We use the `useEffect` hook to set up the worker as soon as the `App` component is mounted.
useEffect(() => {
if (!worker.current) {
// Create the worker if it does not yet exist.
worker.current = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module'
});
}
// Create a callback function for messages from the worker thread.
const onMessageReceived = (e) => { /* See code */ };
// Attach the callback function as an event listener.
worker.current.addEventListener('message', onMessageReceived);
// Define a cleanup function for when the component is unmounted.
return () => worker.current.removeEventListener('message', onMessageReceived);
});
// ... rest of the component
}
你可以通过运行开发服务器(使用 npm run dev)、访问本地网站(通常是 http://localhost:5173/)并打开浏览器控制台来测试一切是否正常。你应该会看到模型的输出被记录到控制台。
[{ label: "skateboard", score: 0.9980043172836304 }]
哇哦! 🥳 虽然上面的代码只是最终产品的一小部分,但它展示了其机器学习部分是多么简单!剩下的只是让它看起来好看并添加一些游戏逻辑。
3. 游戏设计
在本节中,我将简要讨论游戏设计过程。提醒一下,你可以在 GitHub 上找到该项目的完整源代码,因此我不会详细讨论代码本身。
利用实时性能
在浏览器中执行推理的主要优势之一是我们可以在实时(每秒超过 60 次)进行预测。在最初的 Quick, Draw! 游戏中,模型每隔几秒才做出一次新预测。我们可以在我们的游戏中做同样的事情,但那样我们就无法利用它的实时性能了!因此,我决定重新设计主游戏循环:
- 我们的版本不是六个 20 秒的回合(每个回合对应一个新词),而是让玩家在 60 秒内尽可能正确地画出涂鸦(一次一个提示)。
- 如果你遇到一个无法画出的词,你可以跳过它(但这会花费你剩余时间中的 3 秒)。
- 在最初的游戏中,由于模型每隔几秒就会做出一次猜测,它可以慢慢地将标签从列表中划掉,直到最终猜对。在我们的版本中,我们改为降低模型对前
n个错误标签的分数,随着用户继续绘画,n会随时间增加。
生活质量改进
原始数据集包含 345 个不同的类别,由于我们的模型相对较小(约 20MB),它有时无法正确猜测某些类别。为了解决这个问题,我们移除了一些词,这些词要么:
- 与其他标签过于相似(例如,“barn”与“house”)
- 太难理解(例如“动物迁徙”)
- 太难画出足够的细节(例如“大脑”)
- 有歧义(例如“蝙蝠”)
经过筛选后,我们仍然剩下超过 300 个不同的类别!
额外福利:想名字
本着开源开发的精神,我决定向 Hugging Chat 询问一些游戏名字的想法……不用说,它没有让我失望!
我喜欢“Doodle Dash”的头韵(建议 #4),所以我决定采用它。谢谢 Hugging Chat!🤗
希望你喜欢和我一起构建这个游戏!如果你有任何问题或建议,可以在 Twitter、GitHub 或 🤗 Hub 上找到我。另外,如果你想改进这个游戏(游戏模式?道具?动画?音效?),欢迎 fork 这个项目并提交 pull request!我很想看看你能做出什么!
PS:别忘了加入 Open Source AI Game Jam!希望这篇博客文章能启发你用 Transformers.js 构建自己的网页游戏!😉 游戏 Jam 见!🚀
来源:Hugging Face:Blog(RSS) · huggingface.co


