跳到正文
原文
Hugging Face:Blog(RSS)·· 2023-07-05精选AI 评分63

用 Transformers.js 制作浏览器端 ML 网页游戏 Doodle Dash 的教程

Making ML-powered web games with Transformers.js

AI 导读

Hugging Face 博客发布教程,讲解如何制作完全在浏览器中运行的实时 ML 网页游戏 Doodle Dash,灵感来自 Google 的 Quick, Draw!

推荐理由

作者完整走通从微调 MobileViT 到用 Transformers.js 在浏览器实时推理的全流程,方法可直接复用到自己的网页游戏项目。

正文 · AI 翻译

在这篇博客文章中,我将向你展示我是如何制作 Doodle Dash 的,这是一个由机器学习驱动的实时网页游戏,完全在你的浏览器中运行(得益于 Transformers.js)。本教程的目标是向你展示制作自己的机器学习网页游戏有多么简单……正好赶上即将到来的开源 AI 游戏开发挑战赛(2023 年 7 月 7 日至 9 日)。如果你还没有参加,快来加入吧!

快速链接

概述

在开始之前,让我们先聊聊我们将要创建的内容。这款游戏的灵感来自 Google 的 Quick, Draw! 游戏,在游戏中你会得到一个词语,神经网络有 20 秒的时间来猜测你在画什么(重复 6 次)。事实上,我们将使用他们的训练数据来训练我们自己的草图检测模型!你是不是也爱死开源了?😍

在我们的版本中,你将有一分钟的时间尽可能多地画出物品,一次一个提示。如果模型预测出正确的标签,画布将被清空,并给你一个新的词语。一直这样做,直到计时结束!由于游戏完全在你的浏览器中本地运行,我们完全不必担心服务器延迟。模型能够在你绘画时进行实时预测,速度高达每秒超过 60 次预测……🤯 哇!

本教程分为 3 个部分:

  1. 训练神经网络
  2. 使用 Transformers.js 在浏览器中运行
  3. 游戏设计

1. 训练神经网络

训练数据

我们将使用 Google Quick, Draw! 数据集的子集来训练我们的模型,该数据集包含 345 个类别、超过 500 万幅画作。以下是数据集中的一些样本:

Quick, Draw! dataset

模型架构

我们将微调 apple/mobilevit-small,这是一个轻量级且适合移动端的 Vision Transformer,已在 ImageNet-1k 上进行了预训练。它只有 560 万个参数(文件大小约 20 MB),是运行在浏览器中的完美候选!如需了解更多信息,请查看 MobileViT 论文以及下方的模型架构。

MobileViT archtecture

微调

Open In Colab

为了让这篇博客文章(相对)简短,我们准备了一个 Colab notebook,它将向你展示我们在数据集上微调 apple/mobilevit-small 所采取的确切步骤。从高层来看,这包括:

  1. 加载“Quick, Draw!”数据集。

  2. 使用 MobileViTImageProcessor 转换数据集。

  3. 定义我们的整理函数和评估指标。

  4. 使用 MobileViTForImageClassification.from_pretrained 加载预训练的 MobileVIT 模型。

  5. 使用 Trainer 和 TrainingArguments 辅助类训练模型。

  6. 使用 🤗 Evaluate 评估模型。

注意:你可以在 Hugging Face Hub 上这里找到我们微调后的模型。

2. 使用 Transformers.js 在浏览器中运行

什么是 Transformers.js?

Transformers.js 是一个 JavaScript 库,允许你直接在浏览器中运行 🤗 Transformers(无需服务器)!它的设计目标是在功能上等同于 Python 库,这意味着你可以使用非常相似的 API 运行相同的预训练模型。

在幕后,Transformers.js 使用 ONNX Runtime,因此我们需要将微调后的 PyTorch 模型转换为 ONNX。

将我们的模型转换为 ONNX

幸运的是,🤗 Optimum 库让将微调后的模型转换为 ONNX 变得非常简单!最简单(也是推荐)的方法是:

  1. 克隆 Transformers.js 仓库 并安装必要的依赖:

    git clone https://github.com/xenova/transformers.js.git
    cd transformers.js
    pip install -r scripts/requirements.txt
    
  2. 运行转换脚本(它底层使用 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 询问一些游戏名字的想法……不用说,它没有让我失望!

Game name suggestions by 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