装 CubeMX 这件事本身真不复杂,复杂的是装完之后想跑 Cube.AI 那一步。我身边不少人卡在几个很具体的位置:扩展包列表里翻不到 X-CUBE-AI、找到了但是灰色的勾不上、Analyze 转半天弹出不支持的算子、生成代码后一编译几百行重复定义。折腾两轮之后就把 STM32 上跑神经网络归到"玄学"那一类去了。其实它一点都不玄学,出问题的地方高度集中在版本对齐、Python 环境和安装路径这三件事上,把这三件事理顺,后面基本一次过。
这篇就把整条链路从头到尾走一遍:CubeMX 本体怎么装、Java 和芯片包怎么处理、X-CUBE-AI 扩展包怎么挂到工程里、模型怎么喂进去做 Analyze 和 Validate、生成的代码在工程里长什么样、以及我实际踩过的那些坑是怎么一个个定位出来的。适合刚上手 STM32 的同学,也适合已经在用 CubeMX 配外设、现在想往边缘 AI 上延伸的人。
1. CubeMX 与 Cube.AI 到底各管一段什么活
1.1 三个组件的分工:图形配置器、固件包、AI 扩展包
很多人第一次装的时候容易把这三样东西混成一件事,结果下载了一堆东西还是用不起来。拆开看其实很清晰。
STM32CubeMX是一个基于 Java 的图形化配置工具。它本身不含任何芯片驱动代码,只负责"生成配置":你在界面上点时钟树、点引脚复用、勾外设,它把结果翻译成初始化代码和一个.ioc工程文件。它还有第二个身份:扩展包和芯片包的管理器。X-CUBE-AI 就是通过它下载和挂载的,这一点后面会展开。
STM32Cube MCU Package(也就是大家常说的"芯片包"或"固件包",比如 STM32CubeF1、STM32CubeH7)是真正的 HAL 库、LL 库、中间件、例程集合。CubeMX 生成代码时把这里面的 HAL 源文件复制或引用到你的工程里。没有它,CubeMX 界面能打开,但生成代码会直接报错。
X-CUBE-AI是扩展包(Expansion Package),它提供一个 C 运行时库加一套代码生成器。你给它一个训练好的模型文件,它把模型解析、量化、内存排布,最后吐出一份纯 C 的推理代码,包含网络参数数组和几个调用函数。这份代码运行时不依赖任何 Python,也不需要操作系统,裸机就能跑。
三者的关系是:CubeMX 是调度中心,芯片包提供外设底座,X-CUBE-AI 提供神经网络这一层。
1.2 一次成功的安装,长什么样
我给自己定了一个验收标准,达到这三条才算装好:
- CubeMX 能新建工程,选中一颗具体型号(比如 STM32F103C8T6),生成代码后在 IDE 里零报错编译通过;
- 扩展包管理器里能看到 X-CUBE-AI,并且版本号是彩色可勾选状态;
- 新建工程时 Additional Software 里勾上 X-CUBE-AI,生成后工程目录里出现 Middlewares/ST/AI 这一层。
这三条里最容易被忽略的是第一条。很多人 EDA 装完就直接冲 AI,结果连最基础的芯片包都没装全,后面出一堆莫名其妙的报错,排查方向全跑偏了。所以我会建议老老实实先做一个点灯工程,把"安装"和"可用"这两件事分开验证。
1.3 为什么说这套环境是很多 STM32 项目的通用底座
顺带说一句,为什么值得花时间把 CubeMX 这套环境配利索。因为一旦装好,你顺手能配出来的东西非常杂:SPI 加 DMA 去读芯片数据、ADC 多通道配 DMA 搬运、定时器输入捕获测频率、FDCAN 收发、USART 加 DMA 做伺服电机 485 通信、TouchSensing 触摸按键、FreeRTOS 多任务、以太网加协议栈……这些配置在 CubeMX 里都是勾选加填参数的事,不用去啃寄存器手册。
我手头一个鱼缸控制器就是这么攒出来的:温度采集走 I2C,水位检测走 ADC,水泵和加热棒走 GPIO 加 PWM,屏幕走 UART,任务调度丢给 FreeRTOS。整个过程外设部分没写几行底层代码。等这套底座稳了,再往里塞一个 Cube.AI 推理任务,技术栈是连续的,不需要另起炉灶。
2. CubeMX 本体安装:把下载、Java、芯片包一次理顺
2.1 下载渠道与账号
CubeMX 官方只在一个地方放安装包,需要登录账号才能下载。Windows 是.exe安装器,Linux 是免安装的.zip,macOS 是.dmg。版本别追新也别用太老的,我的经验是选当前稳定版往前一到两个小版本最省事,因为最新版刚发的时候扩展包生态往往还没跟上。
下载的时候有个细节:官网会同时列出完整安装包和"仅安装器"。完整包体积大,但它把一些公共组件都打进去了,如果你网络环境一般,建议直接下完整包,少一次在线拉取就少一个失败点。
2.2 Java 运行时这件事,Windows 和 Linux 差别很大
CubeMX 是 Java 程序,这一点在 Windows 上基本无感——安装器会带一个自带的 JRE,装完双击就能开。真正麻烦的是 Linux。
Linux 下解压完直接运行./STM32CubeMX,如果系统里没有 JRE,它会静默退出或者只闪一下终端。我一般这样处理:
# 先看有没有 Java java -version # 没有的话装一个(以 Debian/Ubuntu 系为例) sudo apt update sudo apt install openjdk-17-jre -y # 如果 CubeMX 目录里有自带的 jre,把路径显式指过去 export PATH=$PWD/jre/bin:$PATH官方文档写的要求是 Java 8 以上,实测 11 和 17 都能跑起来。但要提醒一句:如果你用的是老版本 CubeMX,配 Java 17 有可能在打开某些对话框时闪退,这时候换 Java 11 通常就好了,不用去追根因,换版本是最快的路。
提示:Linux 下如果
./STM32CubeMX提示找不到主类,先看当前目录下有没有jre文件夹,有的话直接改启动脚本里的JAVA_HOME指向它,比在系统里装 Java 更干净。
2.3 芯片包:装在哪儿、怎么改路径、离线怎么导入
芯片包默认下载到用户目录下的仓库文件夹里,Windows 一般在C:\Users\你的用户名\STM32Cube\Repository,Linux 在~/.stm32cubemx附近。这个默认路径有两个风险:一是用户名带中文或空格,二是 C 盘空间不够。
改路径的位置在Help → Updater Settings,里面有个 Repository Folder,改成纯英文、无空格、空间充足的路径,比如D:/STM32/Repository。这一步看着琐碎,但它是后面 X-CUBE-AI 各种诡异报错的重要源头之一,因为转换工具在调用外部程序时对路径里的特殊字符很敏感。
离线导入是另一个实用技能。公司内网或者断网环境里,可以从官网单独下固件包(.zip或.pack),然后在扩展包管理器里选 "From Local",指到本地文件即可。导入完记得回去看一眼 Repository 目录下是不是真的多了对应系列文件夹,有时候导入成功但目录是空的,那说明包没解压完整。
2.4 用最小工程验证安装结果
装完先别急着写代码,跑一个最小闭环:
- 新建工程,选一颗手头有的芯片型号,比如 F103C8T6;
- 只改两处:RCC 时钟源选外部晶振,SYS 调试口改成 Serial Wire(否则烧一次程序后调试口就锁了);
- Project Manager 里选工具链,工程名和路径都用纯英文;
- 生成代码,在 IDE 里编译。
编译通过说明 HAL 和芯片包这条路是通的。这一步的价值在于,它把"工具链问题"和"AI 问题"提前隔离开了。后面 AI 出任何问题,你都知道底座是好的,排查范围直接砍掉一半。
3. X-CUBE-AI 扩展包的安装与工程挂载
3.1 在扩展包管理器里找到它
X-CUBE-AI 不在默认展示的那一页。打开Help → Manage embedded software packages,默认停在 STM32Cube MCU Packages 这一栏,你要手动切到 "STMicroelectronics" 或 "X-CUBE" 分类下,才能看到 X-CUBE-AI 的条目。
看到条目之后,版本选择上有讲究。列表里通常有多个版本,能勾选的是兼容当前 CubeMX 的,灰色的说明和当前工具链不匹配。我的建议是不要硬追最新,选一个次新的稳定版本。新版本刚出的时候对模型算子的支持范围、Python 依赖版本都可能刚改过,容易踩到边界。
勾选安装后它会去在线拉取,体积不小,网速不好的时候会卡在进度条。这时候看下 Repository 目录里Packs子文件夹,如果有一个.part之类的临时文件在涨,说明还在下,别急着点取消。
3.2 本地 Python 与 stm32ai 工具链的配置
这是整个流程里最容易被跳过、也最容易出问题的一环。
X-CUBE-AI 的模型解析和代码生成,底层靠的是一个叫stm32ai的命令行工具,它是 Python 写的。安装扩展包的过程中,CubeMX 会问你要不要配置本地环境,选项大致是三种:用云端服务、用本地 Python、或者你已经自己装好了。
我强烈建议用本地 Python,理由是可控。云端方案省事,但每次分析模型都要上传,模型稍微大一点就超时,调试阶段非常难受。
本地配置的具体做法:
# 1. 建一个独立的虚拟环境,别污染系统 Python python -m venv d:/stm32ai-env d:/stm32ai-env/Scripts/activate # Linux 下是 source d:/stm32ai-env/bin/activate # 2. 在 CubeMX 的扩展包配置界面里,把 Python 解释器路径指到 # d:/stm32ai-env/Scripts/python.exe # 然后点 Install,它会自动 pip 安装对应版本的 stm32ai wheel # 3. 装完在命令行验证 stm32ai --version第二条里那个"点 Install"是关键动作,很多人只改了路径没点安装,然后 Analyze 的时候一直失败,还以为是模型的问题。
Python 版本上,3.8 到 3.11 之间相对安全。3.12 刚出来那阵子,一些轮子文件还没跟上,会出现 pip 装不上的情况。如果你系统里默认是 3.12,开个虚拟环境换成 3.10 往往更省时间。
注意:虚拟环境的路径同样要纯英文无空格。放在中文目录下,pip 装 wheel 时可能报编码错误,而报错信息本身还会乱码,特别难排查。
3.3 勾选进工程之后要注意什么
模型工具配好之后,回到 CubeMX 主界面,在Additional Software一栏里勾上 X-CUBE-AI,然后选好工作模式。这时候有三个决策点:
- 是只生成运行时,还是同时生成验证代码。调试阶段我建议勾上验证代码,后面做板端验证要用;产品阶段再去掉,能省一点 Flash。
- 内存分配方式。默认是激活缓冲固定分配,如果你的网络比较大,要改成动态分配或者手动指定地址。
- 网络编译模式。有的版本提供"每次生成时重新解析模型"和"用已解析好的中间文件"两种,前者慢但稳,后者快但模型改了容易忘同步。
还有一个细节:X-CUBE-AI 在工程里是靠.ioc文件记录状态的,你手动改过Middlewares目录里的内容,重新生成时会被覆盖。所以自定义的推理逻辑一定写在Core/Src或者自己新建的目录里,别改生成目录。
3.4 三个让扩展包"变灰"的隐形原因
实际遇到的扩展包不可用,九成出在下面三个地方:
| 现象 | 根因 | 处理方式 |
|---|---|---|
| 列表里能看到但勾选框灰色 | 版本与当前 CubeMX 不兼容 | 换一个稍旧的版本,或升级 CubeMX |
| 能勾选但安装到一半失败 | 网络中断,包没下全 | 删掉 Repository 里的残留文件重下 |
| 装完但工程里看不到 AI 中间件 | .ioc里没勾选 | 在 Additional Software 里手动勾上再重新生成 |
第三个我见过好几次,用户以为"装好就等于用上",其实安装和挂载是两回事,必须回到工程里勾一次。
4. 模型进 Cube.AI:Analyze、Validate 与量化取舍
4.1 模型格式与导出时的常见问题
X-CUBE-AI 支持的输入格式,主流是 TFLite(.tflite)和 ONNX(.onnx)。早期的 Keras.h5也能吃,但新版本里对 Keras 3 的兼容性变差了,很多环境里直接解析失败。如果你手上只有 Keras 模型,我的习惯是先转成 TFLite 再喂进去,稳得多。
导出环节有几个坑值得单独提:
- 动态 batch 维。导出时 batch 维必须固定成 1,STM32 上不会跑批处理,保留
None会让解析器直接报错。 - 不必要的前后处理。模型里如果夹了归一化层、Resize 层、NMS 这种算子,很多时候解析器不支持。正确做法是把这些留在 MCU 侧的 C 代码里手写,模型只保留纯推理部分。
- 算子版本。同一个算子在不同 TFLite 版本里签名不一样,用太新的算子集导出的模型,旧版转换工具认不出来。导出时把算子版本往低里设一档,成功率明显提高。
4.2 Analyze 面板的数字怎么读
把模型拖进去点 Analyze,出来的那张表信息量很大,但很多人只看最后一行"OK"就往下走了。其实这几个数字决定了后面会不会翻车。
权重(weights)是网络参数占用的空间,默认会以常量数组的形式编译进 Flash。这个数字如果接近你芯片的 Flash 上限,就得考虑量化压缩。
激活缓冲(activations)是推理过程中间张量需要的内存,跑在 RAM 里。这是最容易爆的一项。很多视觉模型权重才几百 KB,激活却要几 MB,STM32F1 这种小 RAM 的片子直接没戏。
MACC是乘加运算次数,衡量计算量。这个数除以你的主频再乘个经验系数,大致能估出单次推理耗时。比如 100 MACC、主频 72 MHz,数量级上就是几十毫秒的级别。
每层明细也要扫一眼,如果某一层单独占了总激活内存的一大半,通常是全连接层或者大卷积核,这就是后面优化的抓手。
4.3 桌面验证与板端验证的分工
X-CUBE-AI 提供两级验证,很多人只做第一级就上板了,结果对不上又回头查。
桌面验证(Validate on Desktop)在 PC 上跑。它用随机输入分别喂给原模型和转换后的 C 代码(在 PC 上模拟执行),比较两边输出的相似度。这一步验证的是"转换过程有没有引入错误"。如果这一步就不过,说明模型里有算子被错误处理了,别往下走,先改模型结构。
板端验证(Validate on Target)需要把生成的工程烧进真实芯片,通过串口和 PC 通信。PC 发测试数据,板子跑推理,结果回传比对。这一步验证的是"目标平台上的数值精度和内存排布有没有问题"。
两级的区别很重要:桌面过了不代表板端能过。浮点模型在 MCU 上用单精度跑,累积误差比 PC 上的双精度大,某些对数值敏感的模型(比如很深的分类网络)在板端会出现相似度下降。这时候 int8 量化反而可能更稳,因为定点运算两边行为一致。
4.4 int8 与 float32:什么时候必须量化
选精度这件事,我的判断顺序是这样的:
先看 RAM。如果激活内存超出芯片可用 RAM 的一半以上,直接上 int8,别犹豫。int8 量化模型的激活内存通常是 float32 的四分之一,权重也是四分之一。
再看速度。int8 在 Cortex-M4 及以上(带 DSP 指令的核)上有明显加速,因为可以用 SIMD 指令一次算多个。在 M0/M0+ 上没有这个优势,甚至可能更慢。
最后看精度要求。分类任务对量化掉点容忍度高,回归任务(比如预测一个连续值)就敏感得多。如果是做电机控制、传感器融合这类回归,我一般保留 float32,用 H7 或者 U5 这种有 FPU 的片子。
需要明确一点:Cube.AI 不负责量化训练。它要求你喂进去的模型本身已经量化好了(TFLite 全整型量化)。如果你给的是 float 模型,转换出来的就是 float 推理。想做量化,得在训练侧用 TensorFlow 的量化感知训练或者训练后量化工具先处理一遍。
5. 生成代码拆解:AI 中间件在工程里的真实样子
5.1 目录结构逐层说明
点下 Generate Code 之后,工程里多出来的东西主要在这几个位置:
Middlewares/ST/AI/ Inc/ 运行时对外头文件,ai_platform.h 之类 Lib/ 预编译好的静态库,按内核和工具链分目录 X-CUBE-AI/ App/ app_x-cube-ai.c 应用层入口,你主要改这里 app_x-cube-ai.h <model>.c 网络结构和权重数组 <model>.h 对外 API 声明 <model>_data*.h 权重数据(可能拆成多个文件) Lib/ 可选,验证相关Middlewares/ST/AI/Lib里的库文件是分工具链的,比如 GCC 版、MDK 版、IAR 版各一套,CubeMX 会根据你选的工具链自动引用对应的那份。如果你中途换了 IDE,记得重新生成一次,否则链接阶段会找不到符号。
5.2 app_x-cube-ai.c 里必须看懂的四个函数
生成的代码在app_x-cube-ai.c里有两组函数:一组是MX_X_CUBE_AI_Init()和MX_X_CUBE_AI_Process(),被主程序调用;另一组是对网络的封装,大致形如:
/* 创建网络实例,同时指定激活缓冲区 */ ai_error ai_model_create(ai_handle *network, const ai_handle activations, const ai_size activations_size); /* 初始化,绑定权重和缓冲区 */ ai_error ai_model_init(ai_handle network); /* 执行一次推理 */ ai_error ai_model_run(ai_handle network, const ai_buffer *input, ai_buffer *output); /* 释放 */ ai_error ai_model_destroy(ai_handle network);对应的生命周期是:create一次,init一次,run可以反复调,程序结束或者要换模型时destroy。
这个顺序不能乱。我见过有人在循环里反复 create,结果内存一点点漏掉,跑几分钟就死机。正确写法是把 create 和 init 放在MX_X_CUBE_AI_Init()里,run放在MX_X_CUBE_AI_Process()里,主循环里只调 Process。
激活缓冲区本身是一个静态数组,名字形如AI_MODEL_DATA_ACTIVATIONS,长度是生成的宏AI_MODEL_DATA_ACTIVATIONS_SIZE_BYTES。这个数组不能太小,也不能在运行时被别的代码踩。
5.3 输入输出的喂数与取数
输入输出通过ai_buffer结构访问,关键是别自己猜数据格式,一定要问生成代码要:
ai_buffer *in = ai_model_get_inputs(network); ai_buffer *out = ai_model_get_outputs(network); /* 输入数据布局:通常是 [1, H, W, C] 或者 [1, C, H, W], 跟导出时框架的惯例有关,onxx 常是 NCHW,tflite 常是 NHWC */ memcpy(in->data, sensor_frame, in->size); if (ai_model_run(network, in, out).type != AI_ERROR_NONE) { /* 出错处理 */ } /* 结果在 out->data 里,类型由 out->format 描述 */这里最容易翻车的是通道顺序。同样的模型,ONNX 导出是 NCHW,TFLite 导出是 NHWC,如果你的输入图像在 MCU 侧是按行扫描存的,喂进去前得做一次转置,否则结果会非常离谱但又不报错——你会以为是模型精度问题,其实是数据摆错了。
取结果的时候同理,out->data是一块裸内存,是 float 还是 int8 取决于模型。int8 量化模型的输出还带一个 scale 和 zero_point,要还原成实际物理量,得自己做(q - zero_point) * scale。这个参数可以从验证报告或者模型元数据里拿到。
5.4 内存不够时的三种搬移思路
RAM 溢出是这一步最常见的硬伤。按优先级,我一般这么处理:
第一,换 int8。激活和权重同时变四分之一,往往一步就解决了。
第二,把激活缓冲挪到外部 RAM。H7、U5 这类有外部存储接口的片子,可以把AI_MODEL_DATA_ACTIVATIONS的链接地址指到 SDRAM 区域,改 scatter file 或者 linker script 即可。代价是访问速度慢,推理耗时会涨,如果外部存储是 QSPI 走 cache 的还好,纯 SDRAM 不加 cache 会明显拖慢。
第三,拆网络。有些版本支持把网络分块,中间结果落盘或者落到另一块缓冲。这个方案复杂,一般只在实在没办法的时候用。
顺带提醒,别忘给栈留空间。AI 运行时有些函数会在栈上放临时变量,栈太小会出现那种"跑几十次才崩一次"的随机故障,特别难查。我一般把主栈从默认的 1 KB 调到 4 KB 起步,网络大了再往上加。
6. 报错排查链路:我实际踩过的六个坑
6.1 扩展包列表里没有 X-CUBE-AI 或不可勾选
排查顺序是这样的:
第一步,确认 CubeMX 的版本。在Help → About里看版本号,然后对照扩展包列表里能看到的 X-CUBE-AI 最高版本。如果列表里压根没有 X-CUBE-AI 这一项,多半是 CubeMX 太老,或者 Repository 路径指向了一个空目录。
第二步,去 Updater Settings 里确认 Repository Folder 是不是可写。有时候软件装在了 C 盘,用户权限受限,下载会静默失败。
第三步,看Connection设置。如果配了代理(合法的企业网络代理),而代理需要认证,下载会一直挂在那儿。这种情况在扩展包管理器界面里通常没什么明显提示,只看到进度条不动。
6.2 Analyze 报不支持的算子
这类报错信息一般会明确告诉你哪一层的哪个算子不支持,比如某个自定义激活函数、某个变形的 Reshape。处理办法有三条,按代价从低到高:
- 改模型:把不支持的算子换成等价的基础算子组合,比如自定义激活换成 ReLU 或 LeakyReLU;
- 挪出去:把这一层从前处理里挪到生成之后,用 C 代码手写一个算子函数,嵌在
run前面; - 升级或降级工具:有些算子是在某个版本才开始支持的,换个版本可能就过了。
6.3 生成后编译报重复定义或 RAM 溢出
重复定义一般是ai_platform相关符号在两个地方都定义了,常见原因是重复勾选了扩展包,或者工程里同时留了新旧两份模型文件。检查Middlewares/ST/AI和X-CUBE-AI两个目录,看有没有同名文件。
RAM 溢出会在链接阶段报错,信息里会写着哪个段超了多少字节。这时候先看 map 文件,确认是哪块缓冲占了大头,再按 5.4 的思路处理。有个小技巧:把激活缓冲用__attribute__((section(".ai_ram")))单独放到一个段里,链接脚本里给它一个明确的区域,出错时定位会快很多。
6.4 板端 Validate 连不上
板端验证走串口,连不上通常是这几个原因:
- 串口号选错,尤其是插了好几个 USB 转串口设备的时候;
- 波特率不匹配,CubeMX 里配的 UART 参数和验证工具里选的不一致;
- 串口被别的软件占着,比如开着的串口助手;
- 验证代码没生成进工程,或者生成了但没被调用。
我习惯先用串口助手手动发几个字节,确认物理链路是通的,再回到 CubeMX 里点验证。这样能把"硬件问题"和"配置问题"分开。
6.5 板端结果和 PC 对不上
如果桌面验证过了、板端不过,按这个顺序查:
先看输入数据的排布是不是和桌面验证时一致,通道顺序错了会直接导致结果发散。再看栈大小,栈溢出会随机破坏结果。然后看编译器优化等级,-O0和-Ofast在浮点运算上会有细微差别,极端情况下会把相似度从 0.999 拉到 0.95,这时候换个中间等级通常就稳了。
还有一种情况是时钟配置不对。CubeMX 生成的时钟树如果没配外部晶振,实际主频可能不是你以为的那个值,导致某些依赖时序的外设出问题——虽然推理本身不依赖时序,但如果数据是从 ADC 或 SPI 来的,源头就不对了。
6.6 Keil/CubeIDE 链接脚本与栈大小
不同工具链的默认配置差别挺大。CubeIDE(GCC)默认栈可能只有 1 KB,Keil 的启动文件里栈大小写在汇编里,改的位置完全不一样。
CubeIDE 改的地方在链接脚本(.ld文件)里的_Min_Stack_Size和_Min_Heap_Size;Keil 在startup_xxx.s文件开头,找Stack_Size这个符号。改完记得重新生成一次工程,否则 CubeMX 可能会覆盖掉。
还有一点:AI 运行时库有些版本需要在链接选项里加数学库-lm。CubeIDE 通常自动带,Keil 和 Makefile 工程可能要手动加。
7. 把环境用顺手之后的一些体会
踩完这一整轮,我的最大感受是:CubeMX 加 Cube.AI 这条链路本身设计得挺完整,坑基本都不在功能上,而在"环境"上。版本、路径、Python 环境、内存配置,这四样东西只要有一个不对,表现出来都是同一句含糊的报错。所以我现在的习惯是先花十分钟把版本对应关系理清楚——CubeMX 版本、X-CUBE-AI 版本、Python 版本、模型框架版本,四个都记在工程 README 里。后面换电脑或者过半年再回来,不用重新猜。
另一个实用习惯是把.ioc文件和模型文件一起放进版本管理,但Middlewares和X-CUBE-AI这两个生成目录加进忽略列表。生成的东西不进仓库,什么时候要什么时候重新生成,工程会干净很多。
最后一件事,如果你只是想先感受一下在 MCU 上跑网络是什么体验,别一上来就选视觉模型。找个输入是几维特征的小网络,比如三轴加速度做动作识别、几路传感器数据做异常检测,模型小、依赖少、内存压力小,整条链路走通一次,后面换成大模型只是参数调整的事。我当初就是拿一个输入 6 维、输出 3 类的全连接网络跑通的第一次验证,全程不到半天,比死磕大模型快得多。