Press "Enter" to skip to content

探索用人工智能生成音乐的世界

介绍

利用人工智能生成音乐已经成为一个有价值的领域,改变了音乐的创作和欣赏方式。本项目介绍了在音乐创作中应用人工智能的概念和目的。我们旨在探索使用人工智能算法生成音乐的过程以及其潜力。

探索用人工智能生成音乐的世界 四海 第1张

我们的项目专注于理解和实施促进音乐创作的人工智能技术。人工智能可以通过学习大量音乐作品,并利用特殊的数学规则来理解音乐中的模式、节奏和结构,然后根据所学习的内容创作新的曲调。通过对音乐数据进行训练,我们使人工智能系统能够学习和产生新的原创作品。我们还将研究人工智能生成音乐的最新发展,特别是Meta的MusicGen。

通过探索人工智能在音乐生成中的范围,本项目旨在激发音乐家、研究人员和音乐爱好者探索这一创新技术的可能性。让我们一起踏上这段音乐之旅,揭示人工智能可以生成的旋律。

学习目标

通过参与这个项目,我们将获得新的技术技能,并了解如何实施人工智能算法来构建创新应用程序。在项目结束时,我们将:

  1. 了解人工智能在音乐创作中的应用。我们将学习训练人工智能模型进行音乐创作的基本概念和技术。
  2. 学习如何收集和准备与音乐模型训练相关的音乐数据。我们将探索如何收集.mp3文件并将其转换为MIDI文件,利用诸如Spotify的Basic Pitch之类的工具。
  3. 我们还将了解构建用于音乐生成的人工智能模型的步骤。此外,我们将学习适用于该任务的模型架构及其相关性,并亲自体验训练模型的过程,包括确定epoch数和批量大小。
  4. 我们将花时间探索评估训练模型性能的方法。然后,我们将学习如何分析指标并评估生成的音乐作品的质量,以衡量模型的效果并找出改进的方向。
  5. 最后,我们将探索使用训练好的人工智能模型生成新的音乐作品的过程。

本文作为数据科学博文发布。

项目描述

本项目旨在探索利用人工智能生成音乐的有趣领域。我们旨在研究人工智能技术如何创造独特的音乐作品。通过利用机器学习算法,我们的目标是训练一个能够在各种音乐流派中产生旋律和和声的人工智能模型。

该项目的重点是收集各种类型的音乐数据,特别是.mp3文件,这些文件将成为训练人工智能模型的基础。这些文件将经过预处理,使用专门的工具(如Spotify的Basic Pitch)将它们转换为MIDI格式。这种转换是必要的,因为MIDI文件提供了人工智能模型可以轻松解释的音乐元素的结构化表示。

随后的阶段涉及构建专门用于音乐生成的人工智能模型。使用准备好的MIDI数据训练模型,旨在捕捉音乐中的潜在模式和结构。

进行性能评估以评估模型的熟练程度。这将涉及生成音乐样本并评估其质量,以优化流程并提高模型产生创意音乐的能力。

本项目的最终成果将是使用训练好的人工智能模型生成原创作品的能力。这些作品可以通过后期处理技术进一步改进,以丰富其音乐性和连贯性。

问题陈述

本项目致力于解决音乐创作工具的可访问性有限的问题。传统的音乐创作方法可能繁琐,并需要专业知识。此外,产生新颖和独特的音乐概念可能是一个巨大的挑战。本项目的目标是利用人工智能来克服这些障碍,为音乐创作提供无缝解决方案,即使对于非音乐家也是如此。通过开发一个能够作曲旋律和和声的人工智能模型,本项目旨在民主化音乐创作过程,让音乐家、爱好者和新手释放他们的创造潜力,并轻松创作独特的作品。

音乐生成使用人工智能的简要历史

人工智能在创作音乐方面的故事可以追溯到20世纪50年代,最早是由计算机帮助创作的Illiac Suite for String Quartet。然而,直到最近几年,人工智能在这个领域才真正开始展现出色。如今,人工智能可以创作各种类型的音乐,从古典音乐到流行音乐,甚至可以创作模仿著名音乐家风格的音乐。

探索用人工智能生成音乐的世界 四海 第2张

近年来,人工智能在创作音乐方面取得了非常先进的进展。最近,Meta推出了一款名为MusicGen的新型AI音乐创作工具。MusicGen基于强大的Transformer模型,可以猜测和创作音乐片段,类似于语言模型猜测句子中的下一个字母。它使用一个名为EnCodec的音频分词器,将音频数据分解为较小的部分,以便进行简单处理。

MusicGen的一个特殊功能是它能够同时处理文本描述和音乐提示,从而实现艺术表达的流畅混合。利用20000小时的允许音乐数据集,确保其创作与听众产生共鸣。此外,像OpenAI这样的公司还开发了MuseNet和Jukin Media的Jukin Composer等能够在各种风格和类型中创作音乐的AI模型。此外,AI现在可以创作几乎与人类创作的音乐相同的音乐,使其成为音乐界的强大工具。

伦理考虑

探索用人工智能生成音乐的世界 四海 第3张

讨论AI生成的音乐的伦理方面在探索这一领域时至关重要。一个相关的关注领域涉及潜在的版权和知识产权侵权问题。训练AI模型使用大量的音乐数据集,可能导致生成的作品与现有作品相似。尊重版权法,并适当地归属原始艺术家,以维护公平的实践,是至关重要的。

此外,AI生成的音乐的出现可能会扰乱音乐产业,给在一个充斥着AI作品的环境中寻求认可的音乐家带来挑战。在利用AI作为创作工具和保护人类音乐家的艺术个性之间取得平衡是一个重要的考虑因素。

数据收集与准备

为了这个项目的目的,我们将尝试使用AI生成一些原创的器乐音乐。个人而言,我是Fluidified、MusicLabChill和FilFar等知名器乐音乐频道的忠实粉丝,它们在YouTube上有各种心情的优秀音轨。从这些频道汲取灵感,我们将尝试创作类似风格的音乐,并最终在YouTube上分享。

为了组装我们项目所需的数据,我们专注于收集与我们期望的音乐风格相匹配的相关.mp3文件。通过在在线平台和网站上进行广泛探索,我们发现了合法且免费提供的器乐音乐音轨。这些音轨是我们数据集的宝贵资产,包含了丰富多样的旋律和和声,丰富了我们模型的训练过程。

一旦我们成功获取了所需的.mp3文件,我们将它们转换为MIDI文件。MIDI文件以数字格式表示音乐作品,能够通过我们的模型进行高效的分析和生成。为了进行这种转换,我们依赖Spotify的Basic Pitch提供的实用和用户友好的功能。

借助Spotify的Basic Pitch,我们上传所获取的.mp3文件,启动转换过程。该工具利用先进的算法解析音频内容,提取关键的音乐元素,如音符和结构,生成相应的MIDI文件。这些MIDI文件是我们音乐生成模型的基石,使我们能够操纵和产生新颖、创新的作品。

模型架构

为了开发我们的音乐生成模型,我们使用了专门为此目的量身定制的一种特殊架构。所选的架构包括两个LSTM(长短期记忆)层,每个层包含256个单元。LSTM是一种适用于处理序列数据的递归神经网络(RNN),因其内在的时间特性而成为生成音乐的优秀选择。

第一个LSTM层处理固定长度为100的输入序列,由sequence_length变量确定。通过返回序列,该层有效地保留了音乐数据中存在的时间关系。为了防止过拟合和提高模型对新数据的适应性,还加入了一个dropout率为0.3的dropout层。

第二个LSTM层不返回序列,接收来自前一层的输出,并进一步学习音乐中的复杂模式。最后,一个具有softmax激活函数的全连接层生成下一个音符的输出概率。

构建模型

在建立了我们的模型架构之后,让我们直接开始构建同样的模型。为了读者的方便,我们将代码分解成几个部分,并解释每个部分的作用。

我们首先导入了一些为我们的项目提供有用功能的必要库。除了常规操作所需的常用库外,我们还将使用tensorflow进行深度学习,使用music21进行音乐处理。

import numpy as np
import os
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dropout, Dense
from tensorflow.keras.utils import to_categorical
from music21 import converter, instrument, stream, note, chord
from google.colab import files

加载和处理MIDI文件

接下来,我们定义了存放MIDI文件的目录。代码遍历目录中的每个文件,提取音符和和弦,并将它们存储供进一步处理。我们使用music21库中的“converter”模块来解析MIDI文件并获取音乐元素。为了进行实验,我们首先使用一个MIDI文件来训练模型,然后使用五个MIDI文件进行比较。

# 存放MIDI文件的目录
midi_dir = "/content/Midi Files"

notes = []

# 处理目录中的每个MIDI文件
for filename in os.listdir(midi_dir):
    if filename.endswith(".midi"):
        file = converter.parse(os.path.join(midi_dir, filename))

        # 在MIDI文件中查找所有音符和和弦
        try:
            # 如果MIDI文件有乐器部分
            s2 = file.parts.stream()
            notes_to_parse = s2[0].recurse()
        except:
            # 如果MIDI文件只有音符(没有和弦或乐器部分)
            notes_to_parse = file.flat.notes

        # 从音符和和弦中提取音高和持续时间信息
        for element in notes_to_parse:
            if isinstance(element, note.Note):
                notes.append(str(element.pitch))
            elif isinstance(element, chord.Chord):
                notes.append('.'.join(str(n) for n in 
                element.normalOrder))

# 打印音符的数量和一些示例音符
print("音符总数:", len(notes))
print("示例音符:", notes[:10])
Source: Google Colab Notebook

将音符映射到整数

为了将音符转换为我们的模型可以处理的数值序列,我们创建一个字典,将每个唯一的音符或和弦映射到相应的整数。这一步骤允许我们以数值格式表示音乐元素。

# 创建一个字典,将唯一的音符映射到整数
unique_notes = sorted(set(notes))
note_to_int = {note: i for i, note in 
enumerate(unique_notes)}

生成输入和输出序列

为了训练我们的模型,我们需要创建输入和输出序列。这是通过在音符列表上滑动一个固定长度的窗口来完成的。输入序列由前面的音符组成,输出序列是下一个音符。这些序列被存储在不同的列表中。

# 将音符转换为数值序列
sequence_length = 100  # 每个输入序列的长度
input_sequences = []
output_sequences = []

# 生成输入/输出序列
for i in range(0, len(notes) - sequence_length, 1):
    # 提取输入序列
    input_sequence = notes[i:i + sequence_length]
    input_sequences.append([note_to_int[note] for 
    note in input_sequence])

    # 提取输出序列
    output_sequence = notes[i + sequence_length]
    output_sequences.append(note_to_int[output_sequence])

调整和归一化输入序列

在将输入序列提供给我们的模型之前,我们将其调整为与LSTM层预期的输入形状相匹配。此外,我们通过将它们除以唯一音符的总数来归一化序列。这一步骤确保输入值在模型有效学习的适当范围内。

# 调整和归一化输入序列
num_sequences = len(input_sequences)
num_unique_notes = len(unique_notes)

# 调整输入序列
X = np.reshape(input_sequences, (num_sequences, sequence_length, 1))
# 归一化输入序列
X = X / float(num_unique_notes)

One-Hot编码输出序列

表示下一个要预测的音符的输出序列将转换为一种One-Hot编码格式。这种编码允许模型理解下一个音符在可用音符中的概率分布。

# 对输出序列进行One-Hot编码
y = to_categorical(output_sequences)

定义RNN模型

我们使用tensorflow.keras.models模块的Sequential类来定义我们的RNN(循环神经网络)模型。该模型由两个LSTM(长短期记忆)层组成,后面跟着一个dropout层以防止过拟合。最后一层是一个带有softmax激活函数的Dense层,用于输出每个音符的概率。

# 定义RNN模型
model = Sequential()
model.add(LSTM(256, input_shape=(X.shape[1], X.shape[2]), 
return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(256))
model.add(Dense(y.shape[1], activation='softmax'))

编译和训练模型

通过指定损失函数和优化器来编译模型。然后,我们使用给定的批量大小对输入序列(X)和输出序列(y)进行特定次数的训练。

# 编译模型
model.compile(loss='categorical_crossentropy', optimizer='adam')

# 第4步:训练模型
model.fit(X, y, batch_size=64, epochs=100)

音乐生成

一旦我们训练了模型,我们可以生成新的音乐序列。我们定义了一个名为generate_music的函数,它接受三个输入:训练好的模型、种子序列和长度。它使用模型根据先前的音符预测序列中的下一个音符,并重复这个过程来生成所需长度的音乐。

首先,我们创建种子序列的副本,以防止对原始序列进行任何修改。这个种子序列作为生成音乐的初始点。

然后,我们进入一个循环,循环次数为length。在每次迭代中,执行以下步骤:

  1. 将生成的序列转换为numpy数组。
  2. 通过添加一个额外的维度来重塑输入序列,以匹配模型期望的输入形状。
  3. 通过将输入序列除以唯一音符的总数来归一化输入序列。这确保值在模型有效工作的适当范围内。

在归一化输入序列之后,使用模型预测下一个音符的概率。model.predict方法以输入序列为输入,并返回预测的概率。

为了选择下一个音符,使用np.random.choice函数,该函数根据获得的概率随机选择一个索引。这种随机性为生成的音乐引入了多样性和不可预测性。

所选的索引表示新的音符,将其附加到生成的序列中。然后通过移除第一个元素来更新生成的序列,以保持所需的长度。循环完成后,返回生成的序列,表示新生成的音乐。

种子序列和所需的生成长度需要进行设置以生成音乐。种子序列应该是模型训练过的有效输入序列,生成长度确定生成的音乐应包含的音符数量。

# 生成新的音乐
def generate_music(model, seed_sequence, length):
    generated_sequence = seed_sequence.copy()

    for _ in range(length):
        input_sequence = np.array(generated_sequence)
        input_sequence = np.reshape(input_sequence, (1, len(input_sequence), 1))
        input_sequence = input_sequence / float(num_unique_notes)  # 归一化输入序列

        predictions = model.predict(input_sequence)[0]
        new_note = np.random.choice(range(len(predictions)), p=predictions)
        generated_sequence.append(new_note)
        generated_sequence = generated_sequence[1:]

    return generated_sequence

# 设置种子序列和生成音乐的长度
seed_sequence = input_sequences[0]   # 用您自己的种子序列替换
generated_length = 100  # 用所需生成音乐的长度进行替换

generated_music = generate_music(model, seed_sequence, generated_length)
generated_music

# 上述代码的输出
[1928,
 1916,
 1959,
 1964,
 1948,
 1928,
 1190,
 873,
 1965,
 1946,
 1928,
 1970,
 1947,
 1946,
 1964,
 1948,
 1022,
 1945,
 1916,
 1653,
 873,
 873,
 1960,
 1946,
 1959,
 1942,
 1348,
 1960,
 1961,
 1971,
 1966,
 1927,
 705,
 1054,
 150,
 1935,
 864,
 1932,
 1936,
 1763,
 1978,
 1949,
 1946,
 351,
 1926,
 357,
 363,
 864,
 1965,
 357,
 1928,
 1949,
 351,
 1928,
 1949,
 1662,
 1352,
 1034,
 1021,
 977,
 150,
 325,
 1916,
 1960,
 363,
 943,
 1949,
 553,
 1917,
 1962,
 1917,
 1916,
 1947,
 1021,
 1021,
 1051,
 1648,
 873,
 977,
 1959,
 1927,
 1959,
 1947,
 434,
 1949,
 553,
 360,
 1916,
 1190,
 1022,
 1348,
 1051,
 325,
 1965,
 1051,
 1917,
 1917,
 407,
 1948,
 1051]

后处理

生成的输出是一个表示生成音乐中音符或和弦的整数序列。为了听到生成的输出,我们需要通过反转之前创建的映射来将其转换回音乐,以获取原始的音符或和弦。为此,我们首先创建一个名为int_to_note的字典,其中整数是键,对应的音符是值。

接下来,我们创建一个名为output_stream的流来存储生成的音符和和弦。这个流充当一个容器,用于保存构成生成音乐的音乐元素。

然后,我们遍历生成的音乐序列中的每个元素。每个元素都是一个表示音符或和弦的数字。我们使用int_to_note字典将数字转换回其原始的音符或和弦字符串表示。

如果模式是一个和弦,可以通过存在点号或为数字来识别,我们将模式字符串拆分成单独的音符。对于每个音符,我们创建一个note.Note对象,赋予它一个钢琴乐器,并将其添加到音符列表中。最后,我们从音符列表中创建一个chord.Chord对象,表示这个和弦,并将其附加到output_stream中。

如果模式是一个单独的音符,我们为该音符创建一个note.Note对象,赋予它一个钢琴乐器,并直接将其添加到output_stream中。

一旦生成音乐序列中的所有模式都被处理完毕,我们将output_stream写入一个名为’generated_music.mid’的MIDI文件中。最后,我们使用files.download函数从Colab下载生成的音乐文件。

# 将音符到整数的映射反转回去
int_to_note = {i: note for note, i in note_to_int.items()}

# 创建一个流来保存生成的音符/和弦
output_stream = stream.Stream()

# 将模型输出转换为音符/和弦
for pattern in generated_music:
    # 模式是一个数字,所以我们将其转换回音符/和弦字符串
    pattern = int_to_note[pattern]

    # 如果模式是一个和弦
    if ('.' in pattern) or pattern.isdigit():
        notes_in_chord = pattern.split('.')
        notes = []
        for current_note in notes_in_chord:
            new_note = note.Note(int(current_note))
            new_note.storedInstrument = instrument.Piano()
            notes.append(new_note)
        new_chord = chord.Chord(notes)
        output_stream.append(new_chord)
    # 如果模式是一个音符
    else:
        new_note = note.Note(pattern)
        new_note.storedInstrument = instrument.Piano()
        output_stream.append(new_note)

# 将流写入MIDI文件
output_stream.write('midi', fp='generated_music.mid')

# 从Colab下载生成的音乐文件
files.download('generated_music.mid')

最终输出

现在,是时候听一下我们的AI生成音乐的成果了。您可以在下面找到听音乐的链接。

老实说,最初的结果可能听起来像是一个有限经验的人演奏乐器。这主要是因为我们只使用了一个MIDI文件来训练我们的模型。然而,我们可以通过重复这个过程并使用更大的数据集来训练我们的模型,从而提高音乐的质量。在这种情况下,我们将使用五个MIDI文件来训练我们的模型,这些文件都是相似风格的器乐音乐。

从扩展数据集生成的音乐的质量差异非常明显。这清楚地表明,将模型训练在更多样化的MIDI文件上会显著提高生成音乐的质量。这强调了增加训练数据集的规模和多样性对于获得更好的音乐结果的重要性。

限制

虽然我们成功地使用了一个复杂的模型生成了音乐,但这种系统的扩展存在一些限制。

  1. 有限的数据集:生成的音乐的质量和多样性取决于用于训练的数据集的种类和规模。有限的数据集可能限制了我们的模型从中学习的音乐理念和风格的范围。
  2. 创造力差距:虽然AI生成的音乐能够产生令人印象深刻的结果,但它缺乏人类作曲家赋予他们作品的创造力和情感深度。由AI生成的音乐可能听起来机械化,或者缺少使音乐真正引人入胜的微妙细节。
  3. 数据依赖性:生成的音乐受到用于训练的输入MIDI文件的影响。如果训练数据集存在偏见或特定的模式,生成的音乐可能会展示相似的偏见或模式,限制其独创性。
  4. 计算要求:使用AI模型进行训练和生成音乐可能需要大量的计算资源和时间。它需要强大的硬件和高效的算法来训练复杂的模型,并在合理的时间范围内生成音乐。
  5. 主观评估:评估AI生成音乐的质量和艺术价值可能是主观的。不同人对音乐的美学和情感影响可能有不同的观点,这使得建立普遍的评估标准变得具有挑战性。

结论

在这个项目中,我们踏上了使用人工智能生成音乐的迷人旅程。我们的目标是探索人工智能在音乐创作中的能力,并释放其在创造独特音乐作品方面的潜力。通过实施人工智能模型和深度学习技术,我们成功地生成了与输入的MIDI文件风格相近的音乐。该项目展示了人工智能在音乐创作的创造过程中辅助和启发的能力。

关键点

以下是这个项目的一些关键点:

  1. 我们了解到人工智能可以作为创作过程中有价值的助手,为音乐家和作曲家提供新的观点和创意。
  2. 训练数据集的质量和多样性极大地影响人工智能生成的音乐输出。策划一个全面而多样化的数据集对于实现更原创和多样化的作品至关重要。
  3. 虽然人工智能生成的音乐显示出了潜力,但它无法取代人类作曲家所带来的艺术和情感深度。最佳的方法是将人工智能作为一种协作工具,来补充人类的创造力。
  4. 探索人工智能生成的音乐引发了重要的伦理考虑,例如版权和知识产权。尊重这些权利并营造一个对人工智能和人类艺术家都有益的健康和支持性的环境是至关重要的。
  5. 这个项目加强了对人工智能生成音乐领域持续学习的重要性。及时了解进展并拥抱新技术使我们能够推动音乐表达和创新的界限。

常见问题

本文中显示的媒体不归Analytics Vidhya所有,仅由作者自行决定使用。

Leave a Reply

Your email address will not be published. Required fields are marked *