音乐流媒体服务的兴起使得音乐无处不在。我们在上下班的时候听音乐,锻炼身体,工作或者只是放松一下。
这些服务的一个关键特性是播放列表,通常按流派分组。这些数据可能来自出版歌曲的人手工标注。但这并不是一个很好的划分,因为可能是一些艺人想利用一个特定流派的流行趋势。更好的选择是依靠自动音乐类型分类。与我的两位合作者张伟信(Wilson Cheung)和顾长乐(Joy Gu)一起,我们试图比较不同的音乐样本分类方法。特别是,我们评估了标准机器学习和深度学习方法的性能。我们发现特征工程是至关重要的,而领域知识可以真正提高性能。
在描述了所使用的数据源之后,我对我们使用的方法及其结果进行了简要概述。在本文的最后一部分,我将花更多的时间来解释googlecolab中的TensorFlow框架如何通过TFRecord格式在GPU或TPU运行时高效地执行这些任务。所有代码都在这里,我们很高兴与感兴趣的人分享我们更详细的报告。
数据源
预测一个音频样本的类型是一个监督学习问题。换句话说,我们需要包含标记示例的数据。FreeMusicArchive是一个包含相关标签和元数据的音频片段库,最初是在2017年的国际音乐信息检索会议(ISMIR)上为论文而收集的。
我们将分析重点放在所提供数据的一小部分上。它包含8000个音频片段,每段长度为30秒,分为八种不同类型之一:
- Hip-Hop
- Pop
- Folk
- Experimental
- Rock
- International
- Electronic
- Instrumental
每种类型都有1000个代表性的音频片段。采样率为44100hz,这意味着每个音频样本有超过100万个数据点,或者总共超过10个数据点。在分类器中使用所有这些数据是一个挑战,我们将在接下来的章节中详细讨论。
有关如何下载数据的说明,请参阅存储库中包含的自述文件。我们非常感谢Michaël Defferrard、Kirell Benzi、Pierre Vandergheynst、Xavier Bresson将这些数据整合在一起并免费提供,但我们只能想象Spotify或Pandora Radio拥有的数据规模所能提供的见解。有了这些数据,我们可以描述各种模型来执行手头的任务。
模型说明
我会尽量减少理论上的细节,但会尽可能地链接到相关资源。另外,我们的报告包含的信息比我在这里能包含的要多得多,尤其是关于功能工程的信息。
标准机器学习
我们使用了Logistic回归、k-近邻(kNN)、高斯朴素贝叶斯和支持向量机(SVM):支持向量机(SVM)通过最大化训练数据的裕度来寻找最佳决策边界。核技巧通过将数据投影到高维空间来定义非线性边界
kNN根据k个最近的训练样本的多数票分配一个标签
naivebayes根据特征预测不同类的概率。条件独立性假设大大简化了计算
Logistic回归还利用Logistic函数,通过对概率的直接建模来预测不同类别的概率
深度学习
对于深入学习,我们利用TensorFlow框架。我们根据输入的类型建立了不同的模型。对于原始音频,每个示例是一个30秒的音频样本,或者大约130万个数据点。这些浮点值(正或负)表示在某一时刻的波位移。为了管理计算资源,只能使用不到1%的数据。有了这些特征和相关的标签(一个热点编码),我们可以建立一个卷积神经网络。总体架构如下:
- 一维卷积层,其中过滤器结合来自偶然数据的信息
- MaxPooling层,它结合了来自卷积层的信息
- 全连接层,创建提取的卷积特征的线性组合,并执行最终的分类
- Dropout层,它帮助模型泛化到不可见的数据
另一方面,光谱图作为音频样本的视觉表示。这启发了将训练数据视为图像,并通过迁移学习利用预先训练的模型。对于每个例子,我们可以形成一个矩阵的Mel谱图。如果我们正确计算尺寸,这个矩阵可以表示为224x224x3图像。这些都是利用MobileNetV2的正确维度,MobileNetV2在图像分类任务上有着出色的性能。转移学习的思想是使用预先训练的模型的基本层来提取特征,并用一个定制的分类器(在我们的例子中是稠密层)代替最后一层。这是因为基本层通常可以很好地泛化到所有图像,即使它们没有经过训练。
模型结果
我们使用20%的测试集来评估我们模型的性能。我们可以将结果汇总到下表中:
在谱图中应用迁移学习的卷积神经网络是性能最好的,尽管SVM和Gaussian naivebayes在性能上相似(考虑到后者的简化假设,这本身就很有趣)。我们在报告中描述了最好的超参数和模型体系结构。
我们对训练和验证曲线的分析突出了过度拟合的问题,如下图所示(我们的大多数模型都有类似的图表)。目前的特征模式有助于我们确定这一问题。我们为此设计了一些解决方案,可以在本项目的未来迭代中实现:
- 降低数据的维数:PCA等技术可用于将提取的特征组合在一起,并限制每个示例的特征向量的大小
- 增加训练数据的大小:数据源提供更大的数据子集。我们将探索范围限制在整个数据集的10%以下。如果有更多的计算资源可用,或者成功地降低数据的维数,我们可以考虑使用完整的数据集。这很可能使我们的方法能够隔离更多的模式,并大大提高性能
- 在我们的搜索功能时请多加注意:FreeMusicChive包含一系列功能。当我们使用这些特性而不是我们自己的特性时,我们确实看到了性能的提高,这使我们相信我们可以希望通过领域知识和扩展的特征集获得更好的结果
TensorFlow实现
TensorFlow是一个非常强大的工具,可以在规模上构建神经网络,尤其是与googlecolab的免费GPU/TPU运行时结合使用。这个项目的主要观点是找出瓶颈:我最初的实现非常缓慢,甚至使用GPU。我发现问题出在I/O过程(从磁盘读取数据,这是非常慢的)而不是训练过程。使用TFrecord格式可以通过并行化来加快速度,这使得模型的训练和开发更快。
在我开始之前,有一个重要的注意事项:虽然数据集中的所有歌曲都是MP3格式,但我将它们转换成wav文件,因为TensorFlow有更好的内置支持。请参考GitHub上的库以查看与此项目相关的所有代码。代码还假设您有一个Google云存储桶,其中所有wav文件都可用,一个上载元数据的Google驱动器,并且您正在使用googlecolab。尽管如此,将所有代码调整到另一个系统(基于云的或本地的)应该相对简单。
初始设置
这个项目需要大量的库。这个requirements.txt存储库中的文件为您处理安装,但您也可以找到下面的详细列表。
#importlibrariesimportpandasaspdimporttensorflowastffromIPython.displayimportAudioimportosimportmatplotlib.pyplotaspltimportnumpyasnpimportmathimportsysfromdatetimeimportdatetimeimportpickleimportlibrosaimportastimportscipyimportlibrosa.displayfromsklearn.model_selectionimporttrain_test_splitfromsklearn.preprocessingimportLabelEncoderfromtensorflowimportkerasfromgoogle.colabimportfileskeras.backend.clear_session() tf.random.set_seed(42) np.random.seed(42)
第一步是挂载驱动器(数据已上传的位置),并使用存储音频文件的GCS存储桶进行身份验证。从技术上讲,数据也可以上传到GCS,这样就不需要安装驱动器了,但我自己的项目就是这样构建的。
#mountthedrive#adaptedfromhttps://colab.sandbox.google.com/notebooks/io.ipynb#scrollTo=S7c8WYyQdh5ifromgoogle.colabimportdrivedrive.mount('/content/drive') #loadthemetadatatoColabfromDrive, willgreatlyspeeduptheI/Oprocesszip_path_metadata="/content/drive/My Drive/master_degree/machine_learning/Project/fma_metadata.zip"!cp"{zip_path_metadata}" . !unzip-qfma_metadata.zip!rmfma_metadata.zip#authenticateforGCSaccessif'google.colab'insys.modules: fromgoogle.colabimportauthauth.authenticate_user()
我们还存储了一些变量以备将来使用,例如。
#setsomevariablesforcreatingthedatasetAUTO=tf.data.experimental.AUTOTUNE#usedintf.data.DatasetAPIGCS_PATTERN='gs://music-genre-classification-project-isye6740/fma_small_wav/*/*.wav'GCS_OUTPUT_1D='gs://music-genre-classification-project-isye6740/tfrecords-wav-1D/songs'#prefixforoutputfilenames, firsttypeofmodelGCS_OUTPUT_2D='gs://music-genre-classification-project-isye6740/tfrecords-wav-2D/songs'#prefixforoutputfilenames, secondtypeofmodelGCS_OUTPUT_FEATURES='gs://music-genre-classification-project-isye6740/tfrecords-features/songs'#prefixforoutputfilenames, modelsbuiltwithextractedfeaturesSHARDS=16window_size=10000#numberofrawaudiosampleslength_size_2d=50176#numberofdatapointstoformtheMelspectrogramfeature_size=85210#sizeofthefeaturevectorN_CLASSES=8DATA_SIZE= (224,224,3) #requireddatasizefortransferlearning