Qwen2-Audio-7B 🤖 | 🤗 | Qwen-Audio-7B-Instruct 🤖 | 🤗 | Demo 🤖 | 🤗
论文链接–https://arxiv.org/abs/2407.10759
代码链接–github.com/QwenLM/Qwen2-Audio
Qwen2-Audio作为一个大规模音频语言模型,Qwen2-Audio能够接受各种音频信号输入,并根据语音指令执行音频分析或直接响应文本。我们引入两种不同的音频交互模式:
- 语音聊天:用户可以自由地与Qwen 2-Audio进行语音交互,无需文字输入;
- 音频分析:用户可以在交互过程中提供音频和文本指令进行分析;
- 多语言支持:该模型支持超过8种语言和方言,例如:中文、英语、粤语、法语、意大利语、西班牙语、德语和日语。
Qwen 2-Audio是一个大规模的音频语言模型,它能够接受各种音频信号输入,并对语音指令进行音频分析或直接的文本响应。与复杂的分层标签相比,我们通过利用不同数据和任务的自然语言提示简化了预训练过程,并进一步扩大了数据量。我们提升了Qwen 2-Audio的语音追踪能力,并实现了语音聊天和音频分析两种不同的音频交互模式。在语音聊天模式下,用户可以自由地与Qwen 2-Audio进行语音交互,无需文字输入。在音频分析模式下,用户可以在交互过程中提供音频和文本指令进行分析。请注意,我们不使用任何系统提示来在语音聊天和音频分析模式之间切换。 Qwen 2-Audio能够智能地理解音频中的内容,并按照语音命令做出适当的响应。例如,在同时包含声音、多说话者对话和语音命令的音频片段中,Qwen 2-Audio可以直接理解命令并提供对音频的解释和响应。
介绍
音频是人类和其他生物之间互动和交流的重要媒介,承载着丰富的信息内容。 全面理解各种形式的音频信号对于实现通用人工智能 (AGI) 至关重要。Qwen2-Audio主要重点是增强其指令跟踪能力。 Qwen2-Audio 是一种大型音频语言模型 (LALM),旨在处理音频和文本输入以生成文本输出。 与之前的模型相比,Qwen2-Audio 显着扩展了训练数据集。 为了减少训练前和训练后阶段之间的差距,我们通过直接使用自然语言提示各种数据和任务来简化预训练过程,如下图所示。 遵循大语言模型(OpenAI,2023;Qwen,2023)的实践,我们进一步进行指令调优和直接偏好优化,使模型的输出与人类偏好保持一致。
Qwen2-Audio 以两种不同的模式运行:音频分析和语音聊天。 这两种模式从功能上有所区别,但用户在使用过程中无需区分。 在音频分析模式下,用户可以利用Qwen2-Audio来分析多种音频类型,包括语音、声音、音乐或各种混合音频形式。 命令可以通过音频或文本发出,Qwen2-Audio 将自动识别音频中的命令片段。 相反,在语音聊天模式下,用户可以与 Qwen2-Audio 进行交互,就好像它是一个会话代理一样,进行不受限制的对话。 提供音频交互,用户可以随时切换到文本交互。 例如,如果用户输入一个音频剪辑,其中初始部分是键盘打字的声音,然后用户询问“这是什么声音?”在口语中,Qwen2-Audio 预计会直接回复“这是键盘的声音”。
方法
模型架构
Qwen2-Audio的训练过程如图2所示,其中包含音频编码器和大语言模型。 给定配对数据(𝒂,𝒙),其中𝒂和𝒙表示音频序列和文本序列,训练目标是最大化下一个文本词符的概率为:
以音频表示和先前文本序列 𝒙<t 为条件,其中 θ 和 ϕ 分别表示大语言模型和音频编码器的可训练参数。
与Qwen-Audio不同的是,Qwen2-Audio的音频编码器的初始化是基于Whisper-large-v3模型。 为了预处理音频数据,我们将其重新采样到 16kHz 的频率,并使用 25ms 的窗口大小和 10ms 的跳跃大小将原始波形转换为 128 通道梅尔频谱图。 此外,还合并了步长为 2 的池化层,以减少音频表示的长度。 因此,编码器输出的每一帧大约对应于原始音频信号的 40ms 片段。 Qwen2-Audio 仍然采用大型语言模型 Qwen-7B 作为其基础组件。 Qwen2-Audio的总参数为8.2B参数。
预训练
在预训练阶段,我们用自然语言提示替换分层标签。 如图2所示。 我们发现使用语言提示可以提高更好的泛化能力和更好的指令跟随能力。
有监督微调
Qwen2-Audio的彻底预训练使模型对音频内容有了全面的理解。 在此基础上,我们采用基于指令的微调技术来提高模型与人类意图保持一致的能力,从而形成交互式聊天模型。 我们的初步研究强调了 SFT 数据的质量和复杂性对模型性能的关键影响。 因此,收集了一组精心策划的高质量 SFT 数据,并实施了严格的质量控制程序。
我们考虑两种不同的人类互动模式:
- 音频分析:在音频分析模式下,用户可以灵活地让 Qwen2-Audio 分析各种音频。 用户指令可以通过音频或文本给出。该模式常用于音频文件的离线分析。
- 语音聊天:在语音聊天模式下,鼓励用户与Qwen2-Audio进行语音对话,提出各种问题。 请随意将其视为您的语音聊天助手。该模式常用于与 LALM 的在线交互。
为了一致性和模型统一性,两种交互模式都经过联合训练,用户在使用过程中不会出现模式差异化,也无需使用单独的系统提示在不同模式之间切换。 两种模式在实际使用中是无缝结合的。
直接偏好优化(DPO)
我们采用 DPO (Rafailov 等人, 2024) 来进一步优化模型以遵循人类偏好。 通过获取带有三元组数据(𝒙,𝒚𝒘,𝒚𝒍)的数据集𝒟,其中𝒙是带有输入音频的输入序列,𝒚𝒘和𝒚𝒍 分别是人工注释的好响应和坏响应,我们对模型 𝒫θ 进行如下优化:
其中𝒫ref表示用𝒫θ初始化的参考模型,σ表示sigmoid函数,β是超参数。 图2说明了Qwen2-Audio的三阶段训练过程。
实验
在实践中,我们发现之前的许多测试数据集都非常有限,无法充分反映现实场景中的性能,例如一些SLU(口语理解)和SER(语音情感识别)数据集。 因此,我们主要直接在AIR-Bench上评估性能。 我们发现 AIR-Bench 的分数更符合实际的用户交互体验。 同时,为了评估Qwen2-Audio的通用理解能力,如表1所示,我们仍然进行了涵盖各种任务的综合评估,即自动语音识别(ASR)、语音识别-文本翻译(S2TT)、语音情感识别(SER)、语音分类(VSC)。 评估是在 13 个数据集上进行的。 评估数据集被严格排除在训练数据之外,以避免数据泄露。 我们比较的模型包括开源模型和可调用的 API,例如 Gemini。
表2:自动语音识别 (ASR)、语音到文本翻译 (S2TT)、语音情绪识别 (SER)、声音分类 (VSC) 和 AIR-Bench 聊天基准测试的结果。 请注意,对于 Qwen2-Audio,Fleurs 的结果是零样本,而 Common Voice 的结果不是零样本。
案例:
结论:
在本文中,我们提出了 Qwen2-Audio,它建立在 Qwen-Audio 分析各种类型音频的能力之上,同时还被赋予了语音交互能力。 在预训练阶段,我们针对不同的数据和任务利用自然语言提示,进一步扩大了数据量。 在SFT阶段,我们通过提高SFT数据的数量、质量和复杂性来增强Qwen2-Audio与人类交互的一致性,从而实现无缝的语音和文本交互。 此外,我们还通过 DPO 阶段提高了 Qwen2-Audio 的响应质量。 在不同基准上测试的客观指标证明了 Qwen2-Audio 在音频理解和对话能力方面的熟练程度。 论文中的案例也说明了Qwen2-Audio流畅灵活的语音交互能力。
补充:语音/文本嵌入融合
Qwen-audio-chat模型如何将音频特征与文本提示无缝融合,通过特征编码、位置标记和信息整合,提升模型的跨模态理解能力。
系统会提取音频的特征,然后对文本提示进行嵌入(Embedding)处理。具体来说,它通过将音频特征转换成一个三维向量(如[1,56,4096]),并将这个向量嵌入到文本提示中。例如,考虑到一个文本提示信息,其中包括标记转换为ID的过程,随后是与音频特征的结合,即在文本中通过和标签指明音频的开始与结束位置。
在融合过程中,系统通过ID定位到这些标签所代表的位置,并用音频特征向量A替换掉文本提示中的“Audio_path/audio_name.flac”相对应的向量表示。这样,音频特征就被有效地融合到文本提示中,形成了一个语言模型能够理解的向量表示。
// A code block
<|im_start|>system
You are a helpful assistant.<|im_end|>
<|im_start|>user
Audio 1:<audio>Audio_path/audio_name.flac</audio>
what does the person say?<|im_end|>
<|im_start|>assistant
代码实现:
// An highlighted block
bos_pos = torch.where(input_ids == self.config.audio['audio_start_id'])
eos_pos = torch.where(input_ids == self.config.audio['audio_start_id'] + 1)
audio_pos = torch.stack((bos_pos[0], bos_pos[1], eos_pos[1]), dim=1)
if audios is not None:
for idx, (i, a, b) in enumerate(audio_pos):
hidden_states[i][a : b+1] = audios[idx]
output_shape = input_shape + (hidden_states.size(-1),)