- AI 应用
- 机器学习
- 计算机视觉
- 前端
【免费下载链接】teachable-machine-v1
Explore how machine learning works, live in the browser. No coding required.
本篇技术指南以仓库根目录 README.md 为骨架,完整覆盖 Teachable Machine 实验项目的定位、依赖安装、项目构建、本地开发、代码规范与本地 HTTPS 运行等全部开发实操内容,并结合 package.json 的脚本配置与 src/ 目录下的核心源码,深入剖析“摄像头输入 → 机器学习 → 输出”这条完整流水线的底层实现,帮助读者在掌握启动本项目的同时,理解一个纯浏览器端、无需写代码即可训练图像分类器的最小可运行架构。
Teachable Machine 是一个运行在浏览器中的机器学习实验:用户无需编写任何代码,只需通过摄像头提供示例,就能实时训练出一个图像分类器,并让机器以 GIF、声音或语音的方式做出回应。这个项目由 Google Creative Lab 与 Støj、Use All Five 以及 PAIR 团队合作完成,基于 TensorFlow.js 构建,所有训练均在本地设备上进行,图像不会上传到任何服务器。本指南将带你从零搭建本地开发环境,并深入到源码层面理解其“训练—预测—输出”的完整链路。
一、项目定位:不写代码的机器学习实验
README 开篇即给出了项目的核心定位:让任何人都能更轻松地探索机器学习,实时运行在浏览器中,无需编码。它不是一个正式的产品,而是一个实验性质的 Web 应用——用户打开页面、点击授权摄像头、按住彩色按钮采集若干示例,机器就能学会区分不同的手势或物体,并触发对应的输出。
从技术选型看,实验基于 TensorFlow.js 构建(package.json 中声明了@tensorflow/tfjs@0.11.7、@tensorflow-models/mobilenet@0.1.1与@tensorflow-models/knn-classifier@0.1.0),即:用 MobileNet 做特征提取,用 KNN 分类器做增量学习。这也解释了为何“无需编码”——训练过程本质上是往 KNN 分类器里持续添加当前帧的特征向量。
README 还提到,项目方同时发布了 boilerplate 版本(googlecreativelab/teachable-machine-boilerplate),可作为开发者二次开发自己项目的起点——如果你想把“摄像头 + 迁移学习”这套范式复用到自己的 Web 项目中,可以直接参考该模板,而本仓库则是完整、可直接运行和改造的成品实验。
二、安装依赖:yarn
README 给出的第一步是安装依赖:
yarn该命令等价于npm install,会依据 package.json 与仓库中的 yarn.lock 安装全部依赖。核心依赖清单如下(版本号以当前仓库为准):
| 依赖 | 版本 | 用途 |
|---|---|---|
@tensorflow/tfjs | 0.11.7 | TensorFlow.js 运行时,提供tf.fromPixels等 API |
@tensorflow-models/mobilenet | 0.1.1 | 预训练 MobileNet,用于图像特征提取 |
@tensorflow-models/knn-classifier | 0.1.0 | KNN 分类器,承担“训练样本 + 实时分类” |
gifler | git 指定 v0.3.0 | 在 Canvas 上播放 GIF 动画 |
gsap | ^1.20.2 | 界面动画(按钮、箭头、置信度条的补间动画) |
browserify/budo | ^14.4.0 / ^10.0.3 | 打包与本地开发服务器(端口 3000) |
cpx/concurrently | — | 静态资源拷贝与多任务并行 |
stylus/nib | ^0.54.5 / ^1.1.2 | 样式编译(.styl→style.css) |
openssl | ^1.1.0 | 本地 HTTPS 证书生成工具 |
此外,browserify配置通过babelify转换器配合babel-preset-es2015将 ES2015 源码转译成浏览器可执行的bundle.js,这是整个构建链的编译基础。
三、构建项目:yarn build
README 给出的第二个命令是:
yarn build这条命令在 package.json 中被定义为四个串行子任务的组合:
"build": "npm run html-copy && npm run style-build && npm run assets-copy && npm run browserify"各子任务职责如下:
| 脚本 | 命令 | 作用 |
|---|---|---|
html-copy | cpx "html/**/*.html" "public/" --clean | 将 html/index.html 拷贝到public/,构建前先清理旧文件 |
style-build | stylus -c -u nib style/main.styl -o public/style.css | 以压缩模式(-c)编译 style/main.styl 为public/style.css |
assets-copy | cpx "assets/**/*" "public/assets/" --clean | 将 assets/ 下的图片、音频、SVG 等资源拷贝到public/assets/ |
browserify | browserify src/index.js -o public/bundle.js | 以 src/index.js 为入口,打包出浏览器端public/bundle.js |
构建产物统一输出到public/目录,该目录正是 app.yaml 中 Google App Engine 静态部署所指向的目录(static_files: public/index.html、public/bundle.js、public/style.css等)。也就是说,yarn build产出的public/目录既是本地预览的基础,也是线上部署的直接输入。
四、启动本地开发服务器:yarn run watch
README 提供的开发命令是:
yarn run watch对应脚本:
"watch": "npm run style-build && concurrently \"npm run assets-watch\" \"npm run html-watch\" \"npm run budo\" \"npm run style-watch\""它先用style-build完成一次样式初始编译,然后用concurrently并行启动四个监听任务:
assets-watch:监听 assets/ 目录,变化时自动重新拷贝;html-watch:监听 html/ 目录,变化时自动重新拷贝;budo:budo src/index.js:bundle.js --port=3000 --live -v --dir=public -o,启动开发服务器,默认端口 3000,--live支持浏览器自动刷新,--dir=public指定静态文件根目录;style-watch:stylus -m -w -u nib style/main.styl -o public/style.css,以监听模式实时编译样式(-m为非压缩模式,便于调试)。
启动后访问http://localhost:3000即可打开实验页面。若是在localhost本机环境下,摄像头权限可直接获得;而如果希望从局域网 IP 或其他域名访问并启用摄像头,则必须走 HTTPS,这正是下一节要解决的问题。
五、本地 HTTPS:摄像头权限的前提条件
README 明确指出:https 是获取摄像头权限的必要条件——当不在localhost上工作时,必须使用 HTTPS(现代浏览器安全策略要求getUserMedia仅在安全上下文https://或http://localhost下可用)。
第 1 步:生成自签名证书
按 README 给出的两条命令生成密钥与证书:
openssl genrsa -out server.key 2048 openssl req -new -x509 -sha256 -key server.key -out server.cer -days 365 -subj /CN=YOUR_IP- 第一条生成 2048 位的 RSA 私钥
server.key; - 第二条基于该私钥生成自签名 X.509 证书
server.cer,有效期为 365 天,/CN=YOUR_IP处应替换为你实际访问时使用的 IP 地址(例如192.168.1.100)。
第 2 步:启动 HTTPS 开发服务器
yarn run watch-https对应脚本:
"watch-https": "npm run style-build && concurrently \"npm run assets-watch\" \"npm run html-watch\" \"npm run budo-https\" \"npm run style-watch\""其中budo-https是关键差异:
"budo-https": "budo src/index.js:bundle.js --ssl --cert=server.cer --key=server.key --port=3000 --live -v --dir=public -o"它通过--ssl启用 HTTPS,并加载第 1 步生成的server.cer与server.key,端口同样是 3000。
第 3 步:访问并接受安全提示
浏览器访问https://YOUR_IP:3000(把YOUR_IP替换成你的局域网 IP),由于证书是自签名的,浏览器会弹出“不安全”的隐私提示,点击“继续前往/接受风险”即可进入页面并正常使用摄像头。README 原话是:“accept the insecure privacy notice, and proceed”。
六、代码规范与提交前检查
README 在 Code Styles 一节中规定了三条质量约束,它们全部由 package.json 落实:
- pre-commit 钩子:仓库配置了
"pre-commit": ["eslint", "stylint"],会在每次git commit前自动运行两项检查,存在错误时会阻止提交; yarn eslint:运行eslint src,检查 src/ 下 ES6 代码的错误与警告(对应devDependencies中的eslint@^4.3.0);yarn stylint:运行stylint style,检查 style/ 下 Stylus 样式文件的错误与警告(对应stylint@^1.5.9)。
两个脚本的完整定义如下:
"eslint": "eslint src", "stylint": "stylint style"源码中也能看到与规范呼应的痕迹:例如 src/ai/WebcamClassifier.js 顶部有/* eslint-disable camelcase, max-lines */注释,因为 TensorFlow.js 的 API 与 KNN 使用不符合默认 camelcase 约定,属于针对特定文件的合理豁免。
七、从源码看整体架构:输入 → 学习 → 输出
项目的页面结构(见 html/index.html)分为三大区块:#input-section(Input)、#learning-section(Learning)、#output-section(Output),左右两侧用“电线”SVG 串联,形成直观的“机器”隐喻。入口 src/index.js 在页面加载后依次实例化这些模块:
BrowserUtils:检测浏览器类型与 WebGL/getUserMedia兼容性,并按 Chrome/Safari/Firefox 显示不同的“开启摄像头”引导文案(见 src/ui/components/BrowserUtils.js);LaunchScreen与Wizard:首屏引导与带配音的教学向导;InputSection→CamInput→WebcamClassifier:负责请求摄像头并启动分类器;LearningSection→LearningClass:负责三个类别的训练按钮、样本计数与置信度显示;OutputSection:负责 GIF / Sound / Speech 三种输出之间的切换与触发;Recording:支持把“训练过程 + 输出画面”录制成 10 秒 WebM 视频分享(见 src/ui/modules/Recording.js)。
值得一提的是,src/index.js中还实现了对 IE/Edge 的NodeList.prototype.forEachshim,并在移动端通过localStorage记住“是否使用后置摄像头”(isBackFacingCam),这些细节体现了项目对兼容性的处理。
7.1 输入:WebcamClassifier与摄像头
src/ui/components/CamInput.js 创建了 src/ai/WebcamClassifier.js 实例并挂载其<video>元素。摄像头通过navigator.mediaDevices.getUserMedia获取,其中:
- 桌面端:
video: true,并在 Chrome 下同时请求音频流(用于后续录制视频时合成音轨); - 移动端:根据
GLOBALS.isBackFacingCam设置facingMode为environment(后置)或user(前置)。
视频帧统一被缩放为227×227的输入尺寸(IMAGE_SIZE = 227,见 WebcamClassifier 顶部常量),这与 MobileNet 的标准输入规格一致。
7.2 学习:按住即采集样本
页面提供green / purple / orange三个类别按钮(见 src/config.js 中的classNames数组与colors配色)。用户按住按钮时(LearningClass.buttonDown→webcamClassifier.buttonDown),分类器进入“训练采集”状态:每一帧都被送入 MobileNet 提取特征并加入 KNN 分类器,同时把最近 8 帧的缩略图画进示例查看器 Canvas(见WebcamClassifier.animate())。松开按钮即停止采集。
关于样本数量,src/ui/modules/LearningClass.js 的setSamples()中写有推荐值:
let recommendedNumSamples = (GLOBALS.inputType === 'cam') ? 30 : 10;即摄像头输入建议每个类别至少 30 个样本;html/index.html 的 FAQ 也明确建议“每个类别至少采集 30 张图像”,并提醒注意按压/松开按钮的时刻以及多角度、多变化的采集策略。训练不足时,src/ui/modules/Wizard.js 还会给出“至少 30 个样本效果最佳”的提示。
7.3 输出:三种回应方式
用户可以在 Output 区块自由切换三种输出(见 src/ui/modules/OutputSection.js 与 html/index.html 的output__selector__option):
- GIF(src/outputs/GIFOutput.js):每个类别对应一个 Giphy GIF,可点击缩略图进入 Giphy 搜索重新选择;搜索接口每次返回
numResults = 10条、支持offset分页与 “Load more” 加载更多;GIF 播放由gifler+ src/ui/components/GifCanvas.js 在 Canvas 上完成; - Sound(src/outputs/SoundOutput.js):内置 23 个 mp3 音效(位于 assets/outputs/sound/sounds/),三个类别的默认音效分别为
birds.mp3、guitar_1.mp3、trombone.mp3;点击输入框可通过 src/outputs/sound/SoundSearch.js 按关键字过滤并重新指定音效,也可删除置为 “Nothing”; - Speech(src/outputs/SpeechOutput.js):基于 Web Speech API 的 src/outputs/speech/TextToSpeech.js 实现,默认说出 "Hello" / "Awesome" / "Yes"(单条消息限 25 字符),使用
Google US English Female语音、rate = 0.9、lang = 'en-US',可直接编辑文本框自定义机器“说的话”。
八、核心原理:MobileNet 特征提取 + KNN 增量学习
src/ai/WebcamClassifier.js 是本项目机器学习的核心,其原理可以概括为两层:
- 特征提取层:使用 MobileNet 预训练模型,把每一帧 227×227 的图像转成高维特征向量。关键调用是:
const logits = this.mobilenetModule.infer(img, 'conv_preds');- 分类层:使用 KNN 分类器对特征向量做增量式“训练”与“预测”:
// 训练:把一个样本加入指定类 this.classifier.addExample(logits, newMappedIndex); // 预测:返回各类别置信度 const response = await this.classifier.predictClass(logits);由于没有对神经网络进行梯度更新,整个过程是“迁移学习 + 最近邻”式的轻量方案——不需要标签文件、不需要训练轮次,因此能够在浏览器里实现“按住按钮几秒即完成训练”的即时反馈。
源码中还有一个值得注意的细节——类别索引重映射。注释说明:当不从未知索引 0 开始时,mobilenetModule/knnClassifier会返回 -1,因此train/predict通过mappedButtonIndexes数组把页面上的 0–2 类别索引与 KNN 内部索引解耦,确保只训练第三个类别时也能保留索引 2。
性能方面,分类器以requestAnimationFrame驱动推理循环,并设置了MEASURE_TIMING_EVERY_NUM_FRAMES = 20:每 20 帧用performance.now()测量一次单帧推理耗时(lastFrameTimeMs),在 Safari 等慢速环境下据此节流置信度更新,避免动画卡顿。
值得一提的是仓库中还保留了一个早期的 SqueezeNet 实现 src/ai/squeezenet.js(从 Google Cloud Storage 加载 checkpoint,含完整的 fire 模块卷积网络),以及配套的 ImageNet 预处理 shader src/ai/imagenet_util.js。从当前入口 src/index.js 的引用链看,线上运行使用的是WebcamClassifier的 MobileNet + KNN 方案,SqueezeNet 属于历史版本残留——这从侧面反映了该项目从deeplearn.js迁移到 TensorFlow.js 的演进痕迹。
九、全局配置:GLOBALS与三类别设定
src/config.js 集中定义了全项目的全局配置,是理解“为什么是三个类别、为什么是这几个颜色”的关键:
classNames: ['green', 'purple', 'orange', 'red'], colors: { 'green': '#2baa5e', 'purple': '#c95ac5', 'orange': '#dd4d31', 'red': '#e8453c' }, numClasses: 3, micThreshold: 25, classesTrained: {'green': false, 'purple': false, 'orange': false}, audioContext: new AudioContext(), isBackFacingCam: falsenumClasses = 3对应页面上三个训练按钮(第四个red仅存在于配置数组中,未启用);micThreshold: 25是与麦克风相关的阈值配置;classesTrained记录每个类别是否已训练(在 src/ui/modules/LearningClass.js 中当样本数达到推荐值时被置为true)。配色(含 25% 透明度的rgbaColors)同时驱动按钮、置信度条、LED 灯泡与输出边框的视觉统一。
十、部署与浏览器兼容
10.1 Google App Engine 部署
app.yaml 采用runtime: python27的 App Engine 标准环境配置:静态文件(index.html、fb.html、style.css、bundle.js及图片音频资源)直接由 GAE 提供,动态接口/share-video由 main.py 中的ShareVideohandler 处理——它通过urlfetch换取 Facebook access token,并将前端录制的 WebM 视频 multipart 上传到 Facebook Graph API。环境变量FB_CLIENT_SECRET需要在 GAE 控制台配置,用于鉴权。也就是说,整个项目前端纯静态、后端只有一个分享接口,模型推理完全发生在用户浏览器内。
10.2 浏览器兼容策略
src/ui/components/BrowserUtils.js 通过 UA 检测区分 Chrome / Safari / Firefox / Edge / IE 与移动端,并进一步检查navigator.mediaDevices.getUserMedia与 WebGL 支持情况(webglSupport()尝试创建 webgl 上下文),最终得出isCompatible结论。html/index.html 的#is-not-compatible区块会在不兼容环境(如旧版 Android)下提示用户改用桌面 Chrome 访问。
结语
本文以 README.md 的开发脉络为主线,完整还原了 Teachable Machine v1 从yarn安装、yarn build构建、yarn run watch本地开发到自签名证书 +watch-https启用摄像头的全部操作步骤,并顺带讲解了 eslint/stylint/pre-commit 的工程约束。在此基础上,通过 package.json、src/ 源码与 app.yaml 的交叉印证,厘清了“MobileNet 提取特征 + KNN 增量学习”的核心原理、三类别训练的交互机制,以及 GIF / 声音 / 语音三种输出的实现路径。如果你想把“零代码训练浏览器端分类器”的范式移植到自己的项目中,建议以 README 提到的 boilerplate 模板为起点,以本仓库的WebcamClassifier为参考实现。
该项目并非 Google 官方产品,而是 Støj、Use All Five、Creative Lab 与 PAIR 团队协作的实验成果(见 README 的 Credit 一节)——它的价值不在于生产级精度,而在于以极低的门槛和极高的可玩性,向所有人展示“机器学习到底是怎么工作的”。
- AI 应用
- 机器学习
- 计算机视觉
- 前端
【免费下载链接】teachable-machine-v1
Explore how machine learning works, live in the browser. No coding required.
相关推荐
Teachable Machine v1:零代码AI模型训练全攻略
Teachable Machine v1:零代码AI模型训练全攻略 你是否想过,不需要写一行代码就能训练属于自己的AI模型?Teachable Machine
AI 应用机器学习计算机视觉前端Teachable Machine v1终极指南:浏览器内AI模型训练全流程解析
Teachable Machine v1终极指南:浏览器内AI模型训练全流程解析 Teachable Machine v1是一款革命性的浏览器端AI工具,让任何
AI 应用机器学习计算机视觉前端SpiceAI数据联邦查询:如何在单一SQL中连接60+数据源
SpiceAI数据联邦查询:如何在单一SQL中连接60+数据源 在当今数据驱动的时代,企业数据通常分散在各种不同的数据源中,从关系型数据库到云存储,从API服务
后端大模型人工智能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考