开发者生态
morning
Show HN:我训练了一个 125M 模型来在设备上自动完成钢琴演奏
2026-08-21
1 阅读
约7分钟阅读
simedw
字号:
TL;DR:我训练了一个 125M 参数的转换器来实时自动完成钢琴演奏(在 iPhone 15 上约为 108 个音符/秒)。最大的改进来自于找到正确的 MIDI 表示、积极清理训练数据以及在训练后添加 DPO。大约一年前,我开始琢磨一个想法:将我的 MIDI 钢琴连接到我的手机,弹奏一些东西,然后让人工智能为我自动完成这首歌。想想 GitHub Copilot,但它是针对钢琴的。结果发现这是一个比我预想的更深的兔子洞。经过十四次实验,我终于可以高兴地写下来了。您的浏览器不支持视频标签。马铃薯质量的视频,因为好的手机正忙于运行 MIDI 模型。如果您有 MIDI 键盘和 iPhone/iPad,可以在此处免费使用 RollTab 应用程序。一些声音样本 每个音频都以简短的提示开始,然后是模型的延续。神奇宝贝,托盘镇(8 音符提示) 您的浏览器不支持音频标签。最终幻想 VI,Terra 主题(16 音符提示) 您的浏览器不支持音频标签。致爱丽丝(16 音符提示) 您的浏览器不支持音频标签。 MIDI 文件中有什么? MIDI 文件与 MP3 或其他音频格式有很大不同。它不是存储录制的声音,而是将音乐存储为一系列事件:以一定的音高和速度按下琴键,释放琴键,延音踏板改变状态等等。其他事件包括切换乐器或改变音量。这些事件通常被组织成多个轨道。流行音乐或游戏 MIDI 可能有旋律、和弦、贝斯、鼓、弦乐和几个合成器部分。这个项目的重点是钢琴的延续,所以我主要保留了类似钢琴的材料,并删除或减少了其余的。如何对音乐进行代币化?为了训练变压器进行这些表演,我首先需要将 MIDI 事件转换为模型可以读取和预测的离散序列。最明显的映射是为每个 MIDI 事件创建一个标记:NOTE_ON_60_80 # {pitch}_{velocity} NOTE_OFF_60 # {pitch} TIME_SHIFT_12 # {time step} 如果将音高和速度直接包含在 NOTE_ON 标记中,词汇量会快速增长。有 128 个 MIDI 音高和 128 个力度值,因此简单的组合音符词汇表最多有:仅用于音符开始和音符结束的标记。在实践中,您可能会提高速度,但基本问题仍然存在:许多组合很少见,并且模型必须从稀疏标记中学习大量结构。一个常见的改进是用语法来分解表示:[NOTE_ON, PITCH, VELOCITY] | [注意_关闭,音调] | [TIME_SHIFT, DURATION] 现在输出空间更小:NOTE_ON / NOTE_OFF / TIME_SHIFT PITCH:128 个值 VELOCITY:~16 DURATION:~100 您可以在生成过程中通过屏蔽无效的下一个标记来强制执行语法。在 NOTE_ON 之后,只有音高标记有效。投球后,只有速度令牌有效。这保证了语法上有效的输出。我尝试了音符开/音符关风格的表示,但我的模型往往会漂移。他们会忘记发出音符,留下悬挂的音符,或者忘记活动状态。这对我的目标尤其不利:在笔记本电脑或手机上接近实时运行的小型模型。我尝试的另一种表示更接近:[NOTE, PITCH, VELOCITY, DURATION] | [TIME_SHIFT, DURATION] 这可以避免音符漂移,因为音符持续时间是明确的。当没有演奏音符时,时移标记使播放头前进。这在音乐上效果更好,但速度很慢。一个音符大约需要四个自回归变压器步骤。它也会快速烧毁上下文窗口。最终的表示 我最终确定的表示是: 注意(音调、增量开始、持续时间、速度) 最终版本中没有单独的 TIME_SHIFT 事件。静音由下一个音符的 delta_onset 表示:自上一个音符开始以来的时间。例如:NOTE(C4,delta = 0,duration = 12,velocity = 80)NOTE(D4,delta = 24,duration = 12,velocity = 80)意味着:播放C4,在下一个音符开始之前等待24个时间步,然后播放D4。和弦表示为 delta_onset = 0 的多个音符,按音高排序:NOTE(C4, delta=24,uration=24,velocity=80)NOTE(E4,delta=0,duration=24,velocity=78)NOTE(G4,delta=0,duration=24,velocity=82)它也不是一个扁平的令牌流,如:NOTE、PITCH、DELTA、DURATION、VELOCITY 而不是花费四次 Transformer 通道生成音符的属性,Transformer 一次将音乐推进一个完整的音符。实际上,这使得大型模型在 iPhone 上达到约 108 个音符/秒,远高于人类现场演奏所需的速度。在内部,每个注释都有五个分类字段,每个字段都有自己的词汇表,并且时间量化为固定步骤。 [event_type、pitch_id、delta_id、duration_id、velocity_id] 每个字段都有自己的嵌入。音符标记是所有嵌入的总和: note = event_type_embedding [ NOTE ] +itch_embedding [
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱