基于 Python 的音乐流派分类

音乐就像一面镜子,它可以告诉人们很多关于你是谁,你关心什么,不管你喜欢与否。我们喜欢说“you are what you stream” - Spotify

Spotify 拥有 260 亿美元的净资产,是如今很受欢迎的音乐流媒体平台。它目前在其数据库中拥有数百万首歌曲,并声称拥有适合所有人的乐谱。Spotify 的 Discover Weekly 服务已成为千禧一代的热门话题。毋庸置疑,Spotify 已投入大量研究来改进用户查找和收听音乐的方式。机器学习是他们研究的核心,从 NLP 到协同过滤再到深度学习。根据歌曲的数字签名对一些因素进行分析,包括节奏、曲调、力度、可跳舞性等,以回答那个不可能的古老的第一次约会问题:你喜欢什么样的音乐?

公司现在使用音乐分类,要么能够向他们的客户推荐(例如 Spotify、Soundcloud),要么只是作为一种产品(例如 Shazam)。确定音乐流派是朝着这个方向迈出的第一步。机器学习技术已被证明在从大型数据池中提取趋势和模式方面非常成功。同样的原则也适用于音乐分析。

在本文中,我们将研究如何使用 Python 分析音频/音乐信号。然后,我们将利用学到的技能将音乐片段分类为不同的流派。

使用 Python 进行音频处理

声音以具有频率、频宽、分贝等参数的音频信号形式表示。典型的音频信号可以表示为振幅和时间的函数。

基于 Python 的音乐流派分类_第1张图片

这些声音有多种格式,使计算机可以读取和分析它们。比如:

  • mp3格式

  • WMA(Windows 媒体音频)格式

  • wav(波形音频文件)格式

音频库

Python 有一些很棒的音频处理库,例如 Librosa 和 PyAudio。还有用于一些基本音频功能的内置模块。

我们将主要使用两个库进行音频采集和播放:

1. Librosa

它是一个 Python 第三方库,用于分析一般的音频信号,但更适合音乐。它包括构建 MIR(音乐信息检索)系统的具体细节。它有很好的文档记录,还有很多示例和教程。

安装

pip install librosa
or
conda install -c conda-forge librosa

如果想要更多音频解码能力,您可以安装 FFmpeg,它附带许多音频解码器。

2.IPython.display.Audio

IPython.display.Audio 可让您直接在 jupyter notebook 中播放音频。

加载音频文件

import librosa
audio_path = '../


T08-violin.wav'
x , sr = librosa.load(audio_path)print(type(x), type(sr))
 print(x.shape, sr)
(396688,) 22050
这将返回一个音频时间序列作为一个 numpy 数组,默认采样率为 22KHZ 单声道。我们可以通过以下语句进行修改:

librosa.load(audio_path, sr=44100)

将采样率设置为 44.1KHz 


librosa.load(audio_path, sr=None)

禁用重采样功能

采样率是每秒传输的音频样本数,以 Hz 或 kHz 为单位。

播放音频

使用 IPython.display.Audio 播放音频

import IPython.display as ipd
ipd.Audio(audio_path)

这会在 jupyter notebook 中返回一个音频小部件,如下所示:

e522e6155f8781b9bfb7a599fc2ae402.png

音频小部件的屏幕截图

这个小部件在这里不起作用,但它会在你的笔记本上起作用。有兴趣的话,可以通过下述链接查看:https://soundcloud.com/parul-pandey-323138580/t08-violin?utm_source=cdn.embedly.com&utm_campaign=wtshare&utm_medium=widget&utm_content=https%253A%252F%252Fsoundcloud.com%252Fparul-pandey-323138580%252Ft08-violin

您甚至可以为音频示例使用 mp3 或 WMA 格式。

可视化音频

波形

我们可以使用 librosa.display.waveplot 绘制音频:


%matplotlib inline
import matplotlib.pyplot as plt
import librosa.display
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

基于 Python 的音乐流派分类_第2张图片

Spectrogram

Spectrogram是声音或其他信号随时间变化的频率频谱的直观表示。频谱图有时称为声谱图、声纹或语音图。当数据以 3D 图表表示时,它们可能被称为瀑布图。在二维数组中,第一个轴是频率,第二个轴是时间。

我们可以使用 librosa.display.specshow 显示频谱图。


X = librosa.stft(x)
Xdb = librosa.amplitude_to_db(abs(X))
plt.figure(figsize=(14, 5))
librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='hz')
plt.colorbar()

基于 Python 的音乐流派分类_第3张图片

垂直轴显示频率(从 0 到 10kHz),水平轴显示剪辑的时间。由于所有动作都发生在频谱底部,我们可以将频率轴转换为对数轴。


librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='log')
plt.colorbar()

基于 Python 的音乐流派分类_第4张图片

写入音频文件

librosa.output.write_wav 可以将 NumPy 数组保存到 WAV 文件。


librosa.output.write_wav('example.wav', x, sr)

创建音频信号

现在让我们创建一个 220Hz 的音频信号。音频信号可以是一个 numpy 数组,因此我们将创建一个数组并将其传递给音频函数。


import numpy as np
sr = 22050 # sample rate
T = 5.0    # seconds
t = np.linspace(0, T, int(T*sr), endpoint=False) # time variable
x = 0.5*np.sin(2*np.pi*220*t)# pure sine wave at 220 Hz
Playing the audio
ipd.Audio(x, rate=sr) # load a NumPy arraySaving the audio
librosa.output.write_wav('tone_220.wav', x, sr)

所以,此处我们便创建好了第一个声音信号。

特征提取

每个音频信号都包含许多特征。但是,我们必须提取与我们要解决的问题相关的特征。提取特征以将其用于分析的过程称为特征提取。让我们详细研究一些功能。

Zero-Crossing Rate

Zero-Crossing Rate 是符号随信号变化的速率,即信号从正变为负或反向的速率。此功能已大量用于语音识别和音乐信息检索。对于金属和摇滚中的高打击乐声音,它通常具有更高的值。

基于 Python 的音乐流派分类_第5张图片


# Load the signal
x, sr = librosa.load('../T08-violin.wav')
#Plot the signal:
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

基于 Python 的音乐流派分类_第6张图片


# Zooming in
n0 = 9000
n1 = 9100
plt.figure(figsize=(14, 5))
plt.plot(x[n0:n1])
plt.grid()

上述显示有 6 个零交叉点。让我们用 librosa 验证一下。


zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)
print(sum(zero_crossings))
6

Spectral Centroid

它代表了声音的“质心”所在位置,并计算声音中存在的频率的加权平均值。考虑两首歌曲,一首来自蓝调类型,另一首属于金属。现在,与整个长度相同的布鲁斯风格歌曲相比,金属歌曲在结尾处有更高的频率。因此,布鲁斯歌曲的频谱质心将位于其频谱中间附近的某个位置,而金属歌曲的频谱质心将接近其末端。

librosa.feature.spectral_centroid 函数可以计算每个帧的Spectral Centroid:


spectral_centroids = librosa.feature.spectral_centroid(x, sr=sr)[0]
spectral_centroids.shape
(775,)
# Computing the time variable for visualization
frames = range(len(spectral_centroids))
t = librosa.frames_to_time(frames)# Normalising the spectral centroid for visualisation
def normalize(x, axis=0):
    return sklearn.preprocessing.minmax_scale(x, axis=axis)#Plotting the Spectral Centroid along the waveform
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_centroids), color='r')

基于 Python 的音乐流派分类_第7张图片

Spectral Rolloff

它是信号形状的度量。它表示总频谱能量的百分比(例如 85%)低于该频率。

librosa.feature.spectral_rolloff 可以计算每一帧的Spectral Rolloff:


spectral_rolloff = librosa.feature.spectral_rolloff(x+0.01, sr=sr)[0]
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_rolloff), color='r')

基于 Python 的音乐流派分类_第8张图片

Mel-Frequency Cepstral Coefficients

MFCC 是一小组特征(通常约为 10-20),简明地描述了频谱包络的整体形状。它可以模拟人声的特征。

基于 Python 的音乐流派分类_第9张图片


x, fs = librosa.load('../simple_loop.wav')
librosa.display.waveplot(x, sr=sr)

librosa.feature.mfcc 可以计算音频信号的 MFCC:


mfccs = librosa.feature.mfcc(x, sr=fs)
print mfccs.shape
(20, 97)
#Displaying  the MFCCs:
librosa.display.specshow(mfccs, sr=sr, x_axis='time')

基于 Python 的音乐流派分类_第10张图片

这里 mfcc 在 97 帧上计算了 20 个 MFCC 。

我们还可以执行特征缩放,使得每个系数维度具有零均值和单位方差:


import sklearn
mfccs = sklearn.preprocessing.scale(mfccs, axis=1)
print(mfccs.mean(axis=1))
print(mfccs.var(axis=1))
librosa.display.specshow(mfccs, sr=sr, x_axis='time')

基于 Python 的音乐流派分类_第11张图片

Chroma features

Chroma features 是音乐音频的一种有趣而强大的表示,其中整个频谱被投射到 12 个 bins 上,代表音乐八度音阶的 12 个不同的半音(或色度)。

librosa.feature.chroma_stft 可以帮我们计算:


# Loadign the file
x, sr = librosa.load('../simple_piano.wav')
hop_length = 512
chromagram = librosa.feature.chroma_stft(x, sr=sr, hop_length=hop_length)
plt.figure(figsize=(15, 5))
librosa.display.specshow(chromagram, x_axis='time', y_axis='chroma', hop_length=hop_length, cmap='coolwarm')

基于 Python 的音乐流派分类_第12张图片

案例研究:将歌曲分为不同的流派。

在对声学信号、其特征及其特征提取过程进行了概述之后,是时候利用我们新开发的技能来处理机器学习问题了。

我们将尝试建立一个分类器模型来将歌曲分类为不同的流派。让我们假设一个场景,由于某种原因,我们在硬盘上发现了一堆随机命名的 MP3 文件,这些文件被认为包含音乐。我们的任务是根据音乐流派将它们分类到不同的文件夹中,例如爵士、古典、乡村、流行、摇滚和金属类。

数据集

我们将使用著名的 GITZAN 数据集进行案例研究。该数据集被 G. Tzanetakis 和 P. Cook 在 IEEE Transactions on Audio and Speech Processing 2002 中发表的著名流派分类论文“音频信号的音乐流派分类”中使用。

该数据集包含 1000 个音轨,每个音轨长 30 秒。它包含十种流派:蓝调、古典、乡村、迪斯科、嘻哈、爵士、雷鬼、摇滚、金属和流行。每个流派包含 100 个声音片段。

数据预处理

在训练分类模型之前,我们必须将原始数据从音频样本转换为更有意义的表示形式。音频片段需要从 .au 格式转换为 .wav 格式,使其兼容 python 的 wave 模块读取音频文件。我使用开源 SoX 库进行转换。


sox input.au output.wav

分类

特征提取

然后我们需要从音频文件中提取有意义的特征。我们将选择五个特征来对我们的音频剪辑进行分类,即Mel-Frequency Cepstral Coefficients, Spectral Centroid, Zero Crossing Rate, Chroma Frequencies, Spectral Roll-off.。然后将所有特征附加到 .csv 文件中,以便可以使用分类算法。

分类

一旦提取了特征,我们就可以使用现有的分类算法将歌曲分类为不同的流派。您可以直接使用频谱图图像进行分类,也可以提取特征并在其上使用分类模型。

尾记

音乐流派分类是音乐信息检索的众多分支之一。从这里,您可以对音乐数据执行其他任务,例如节拍跟踪、音乐生成、推荐系统、音轨分离和乐器识别等。音乐分析是一个多元化的领域,也是一个有趣的领域。音乐会话以某种方式代表用户的时刻。找到这些时刻并描述它们是数据科学领域的一项有趣挑战。

·  END  ·

HAPPY LIFE

基于 Python 的音乐流派分类_第13张图片

你可能感兴趣的:(python,分类,ffmpeg,开发语言,数据挖掘)