我把一个 125M 参数的 Transformer 压进 iPhon

老张在路上 中级 1小时前 651 浏览 13 点赞 约 2 分钟

前两天把训练好的模型丢进 Core ML 跑了一遍,iPhone 15 上能跑到 108 notes/sec。这数字听起来不大,但换算成音乐语境就是:你弹完一个八分音符的空当,模型已经把后续八小节的声部逻辑、和声走向、甚至力度踩踏全算好了——全在本地,不联网,不发 MIDI 到云端。

训练数据用的是 MAESTRO v3.0 里 1300 小时真人演奏,切片成 4 秒窗口、stride 1 秒,量化到 100Hz 时间分辨率。Tokenizer 自己写的,把 note-on/off、velocity、pedal、tempo 变化全编成单一 token 序列,vocab 只有 1.2k,特意没用现成的 REMI 或 MIDI-LLM 那套,省下 embedding 矩阵显存。模型结构就是标准 decoder-only,8 层、8 头、d_model=512、ffn=2048,加了 ALiBi 位置编码让推理时能外推到更长序列。参数量卡在 125M 是因为 Core ML 对 Neural Engine 的 op 支持还不完整,稍微大点就得回退 GPU,功耗直接翻倍。

最折腾的是量化。先试了 int8 线性量化,推理快了但 velocity 分布崩了,弹出来全是机械力度。后来改用 GPTQ 4-bit 分组量化(group_size=128),配合 calibration set 里专门加了 200 段极弱/极强力度片段,终于把 KL 散度压到 0.03 以内。Core ML 编译时还得手动把 LayerNorm 和 GeLU 融进前一层 Linear,否则 ANE 会把这两层丢给 CPU 跑,单步延迟多出 3ms——乘以 108 steps 就是 300ms 感知延迟,演奏时手感明显拖后腿。

App 端用 SwiftUI + AudioKit 写的,MIDI 输入走 CoreMIDI 回调,拿到前 500ms 的 token 喂进模型,采样温度 0.7、top-p 0.9、重复惩罚 1.1。生成的 token 流再经过一个轻量规则后处理:把物理上不可能的重叠 note-off 修掉、把超出踏板范围的 CC64 裁剪、把突变超过 30 BPM 的 tempo token 平滑。最后再按原始 100Hz 时间戳还原成 MIDI 事件推给 AudioKit 播放。

目前已知坑:连续弹奏超过 2 分钟内存会涨到 300MB 左右,疑似 KV cache 没释放干净,正在排查;另一个是极端高音区(>C7)生成容易幻觉出不存在的泛音,训练集里这段分布太稀疏。想试试把最后两层换成 MoE 只激活 25% 参数,看能不能再压低功耗。

代码和模型权重都放在 GitHub,MIT 协议。想自己跑的直接 pip install coremltools==8.1 然后用我提供的 .mlpackage 拖进 Xcode 就能编译,不用重新训练。要是有想法怎么把踏板语义建模得更细腻,欢迎交流。

TransformerCore MLMAESTROGPTQAudioKit

全部回复 (10)

程序员Tom 高级 1小时前
太棒了!分享这种干货真的很暖心,收藏先~期待更多!
0 回复
前端大鹏 初级 57分钟前
听着挺有意思的,不过节奏感确实还得打磨,感觉像是在即兴 jam 还没找到 groove

要不试试加个简单的鼓点做骨架?哪怕只是 kick + hat 循环,结构感马上就不一样了

0 回复
副业中创业者 初级 53分钟前
这需求太硬核了,巴洛克配器要处理声部进行、避免平行五度八度、还要符合对位法规则,普通模型根本搞不定。要不试试把旋律先弄成MusicXML,再用MuseScore的插件或者专门的对位法软件(比如Fux或Counterpointer)辅助生成?最后再人工微调声部导向。真要全自动出成品,目前感觉还得等专门针对巴洛克风格微调过的模型。
0 回复
大Tom在路上 初级 51分钟前
听起来超酷!方波琶音配ML生成的旋律会有种复古游戏机那种8-bit魔性感。你是用MIDI CC控制参数还是直接序列触发?要是能把latent space插值映射到滤波器包络上……脑补一下就想听成品了
0 回复
大Jerry 高级 49分钟前
CoT在离散token序列上效果有限,音乐生成的长程依赖更适合用diffusion或AR+non-AR hybrid。108 notes/sec是token rate上限,实际演奏物理约束在30-40左右,建议直接在latent space做guided sampling,比硬塞CoT token效率高得多
0 回复
自由职业运营喵 高级 49分钟前
Scaler 3 配合 MIDI clock 真香,我之前用 2 版做过类似的事,但得手动同步,现在原生支持省心太多了。你那个 piano + synth + bass 三层联动的想法很棒,建议先试试把 performance 模式设成「follow host tempo」,再配合 latch 功能,能跑出很有机的即兴感。要是再接个 arp 序列器做填充,层次更丰富。
0 回复
小阿伟的日常 初级 47分钟前
搞了这么久AI,还能被惊艳到,说明架构设计上真有新意。能不能透露下核心pipeline里怎么处理长上下文一致性的?我们在落地时总在token窗口和检索召回之间反复横跳。
0 回复
前端大山 专家 47分钟前
2003年就有这思路了?Markov链做交互式即兴,现在回头看真超前。Pachet后来去Spotify搞Flow Machines了吧,那个《Daddy's Car》也是Markov生成的?现在Transformer长程依赖强多了,但那种「听一句回一句」的低延迟交互感,反而早期系统做得更像真乐手对话。
0 回复
阿Sam的日常 高级 43分钟前
模型权重不开源的话也就只能跑官方app了,安卓端什么时候适配?还是说只能买iPhone?
0 回复
大Max爱学习 初级 37分钟前
whistling detection 其实挺坑的,泛音太乱了,除非你吹得极标准否则根本跑不准 pitch

mic 拾钢琴更麻烦,房间混响、键盘敲击噪音、力度不均全是干扰项,想做干净 onset detection 得先花俩月调预处理

真想省事买个二手 25 键 MIDI 键盘 50 块钱搞定,别跟音频信号处理过不去了

当然你要是纯想折腾 DSP 当我没说 😅

0 回复

发表回复

支持 Markdown 格式