代码详解用Python给你喜欢的音乐分个类吧.docx
- 文档编号:28062931
- 上传时间:2023-07-08
- 格式:DOCX
- 页数:32
- 大小:511.88KB
代码详解用Python给你喜欢的音乐分个类吧.docx
《代码详解用Python给你喜欢的音乐分个类吧.docx》由会员分享,可在线阅读,更多相关《代码详解用Python给你喜欢的音乐分个类吧.docx(32页珍藏版)》请在冰豆网上搜索。
代码详解用Python给你喜欢的音乐分个类吧
代码详解:
用Python给你喜欢的音乐分个类吧
你喜欢什么样的音乐?
目前,很多公司实现了对音乐的分类,要么是为了向客户提供推荐(如Spotify、SoundCloud),要么只是作为一种产品(如Shazam)。
对音乐进行分类,首先要确定音乐类型。
事实证明,用机器学习技术从大量数据中找出音乐的各种潮流和类型是非常成功的。
音乐分析亦然。
本文我们将学习如何用Python进行音频/音乐信号分析以及之后如何用该技能对不同类型的音乐片段进行分类。
用Python处理音频
声音以音频信号的形式表示,音频信号具有频率、带宽、分贝等参数,音频信号一般可表示为振幅和时间的函数。
这些声音有多种格式,因此计算机可以对其进行读取和分析。
例如:
• mp3格式
• WMA(WindowsMediaAudio)格式
• wav(WaveformAudioFile)格式
音频库
Python有一些很好用的音频处理库,比如Librosa和PyAudio。
另外,还有一些基本的音频功能的内置模块。
我们将主要使用两个音频库进行音频采集和回放,如下:
1.Librosa
Librosa是一个Python模块,通常用于分析音频信号,但更适合音乐信号分析。
它包括构建一个音乐信息检索(MIR)系统的具体细节,目前,Librosa已充分实现文档化,并具有许多相关的示例和教程。
安装
pipinstalllibrosa
or
condainstall-cconda-forgelibrosa
可以安装附带很多音频解码器的ffmpeg(一个开源免费跨平台的视频和音频流方案)以提高音频解码功率。
2.IPython.display.Audio
IPython.display.Audio可以让用户直接在Jupyternotebook中播放音频。
音频包加载
importlibrosa
audio_path='../T08-violin.wav'
x,sr=librosa.load(audio_path)
print(type(x),type(sr))
print(x.shape,sr)
(396688,)22050
以上步骤的返回值为一段音频的时间序列,其默认采样频率(sr)为22KHZmono。
我们可将其改为:
librosa.load(audio_path,sr=44100)
可重新采样为44.1KHZ,
librosa.load(audio_path,sr=None)
或者不重新采样。
采样频率指音频每秒钟的采样样本数,以Hz或kHz表示。
音频播放
用Ipython.display.Audio播放音频。
importIPython.displayasipd
ipd.Audio(audio_path)
以上步骤的返回值为Jupyternotebook的一个音频插件。
如下:
这里的插件不起作用,不过放到你的notebooks上就可以了。
以下音频也可用mp3格式或WMA格式听。
可视化音频(VisualizingAudio)
波形音频(Waveform)
我们可以用librosa.display.waveplot来绘制音频。
%matplotlibinline
importmatplotlib.pyplotasplt
importlibrosa.display
plt.figure(figsize=(14,5))
librosa.display.waveplot(x,sr=sr)
上图显示了该段波形音频的振幅包络线(amplitudeenvelope)。
声谱图(spectrogram)
声谱图(spectrogram)是声音或其他信号的频率随时间变化时的频谱(spectrum)的一种直观表示。
声谱图有时也称sonographs,voiceprints,或者voicegrams。
当数据以三维图形表示时,可称其为瀑布图(waterfalls)。
在二维数组中,第一个轴是频率,第二个轴是时间。
我们可以用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()
纵轴显示的是频率(从0到10kHz),横轴显示的是音频的时间。
因为所有可见的波动都发生在频谱的底部,故这里将频率轴转换成对数轴。
librosa.display.specshow(Xdb,sr=sr,x_axis='time',y_axis='log')
plt.colorbar()
音频编写
用librosa.output.write_wav将NumPy数组保存到WAV文件中。
librosa.output.write_wav('example.wav',x,sr)
创建音频信号
现在让我们创建一个220HZ的音频信号。
由于音频信号是一个numpy数组,所以创建后需将其转换为音频函数。
importnumpyasnp
sr=22050#samplerate
T=5.0 #seconds
t=np.linspace(0,T,int(T*sr),endpoint=False)#timevariable
x=0.5*np.sin(2*np.pi*220*t)#puresinewaveat220Hz
Playingtheaudio
ipd.Audio(x,rate=sr)#loadaNumPyarray
Savingtheaudio
librosa.output.write_wav('tone_220.wav',x,sr)
然后,这就是你创建的第一个音频信号。
特征提取
每一个音频信号都有很多特征。
然而,我们必须提取出与我们试图解决的问题相关的特征。
提取特征以用于分析的过程称为特征提取。
接下来我们将详细研究其中几个特征。
过零率(ZeroCrossingRate)
过零率(zerocrossingrate)是一个信号符号变化的比率,即,在每帧中,语音信号从正变为负或从负变为正的次数。
这个特征已在语音识别和音乐信息检索领域得到广泛使用,通常对类似金属、摇滚等高冲击性的声音的具有更高的价值。
现在我们来计算示例音频片段的过零率:
#Loadthesignal
x,sr=librosa.load('../T08-violin.wav')
#Plotthesignal:
plt.figure(figsize=(14,5))
librosa.display.waveplot(x,sr=sr)
#Zoomingin
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))
频谱质心(SpectralCentroid)
频谱质心指示声音的“质心”位于何处,并按照声音的频率的加权平均值来加以计算。
假设现有两首歌曲,一首是蓝调歌曲,另一首是金属歌曲。
现在,与同等长度的蓝调歌曲相比,金属歌曲在接近尾声位置的频率更高。
所以蓝调歌曲的频谱质心会在频谱偏中间的位置,而金属歌曲的频谱质心则靠近频谱末端。
用librosa.feature.spectral_centroid计算出每一帧音频信号的频谱质心。
spectral_centroids=librosa.feature.spectral_centroid(x,sr=sr)[0]
spectral_centroids.shape
(775,)
#Computingthetimevariableforvisualization
frames=range(len(spectral_centroids))
t=librosa.frames_to_time(frames)
#Normalisingthespectralcentroidforvisualisation
defnormalize(x,axis=0):
returnsklearn.preprocessing.minmax_scale(x,axis=axis)
#PlottingtheSpectralCentroidalongthewaveform
librosa.display.waveplot(x,sr=sr,alpha=0.4)
plt.plot(t,normalize(spectral_centroids),color='r')
频谱质心在接近末端处有上升。
谱滚降(SpectralRolloff)
谱滚降(SpectralRolloff)是对信号形状的测量,表示的是在谱能量的特定百分比(如85%)时的频率。
librosa.feature.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')
梅尔频率倒谱系数(Mel-FrequencyCepstralCoefficients)
信号的梅尔频率倒谱系数(MFCC)是一个通常由10-20个特征构成的集合,可简明地描述频谱包络的总体形状,对语音特征进行建模。
这次我们使用一个简单的循环波。
x,fs=librosa.load('../simple_loop.wav')
librosa.display.waveplot(x,sr=sr)
用librosa.feature.mfcc计算出音频信号的梅尔频率倒谱系数:
mfccs=librosa.feature.mfcc(x,sr=fs)
printmfccs.shape
(20,97)
#Displaying theMFCCs:
librosa.display.specshow(mfccs,sr=sr,x_axis='time')
计算出该段超过97帧的音频的梅尔频率倒谱系数为20。
我们也可以给特征标上刻度,使其每个系数有相应的零均值和单位方差。
importsklearn
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')
ChromaFrequencies
色度特征是对音乐音频的一种有趣生动的表示,可将整个频谱投射到代表“八度”(在音乐中,相邻的音组中相同音名的两个音,包括变化音级,称之为八度。
)上12个不同的半音(或色度)的12进制上。
色度向量(chromavector)(维基百科)(FMP,p.123)是一个通常包含12个元素特征的向量,表示信号中每个音级{C,C#,D,D#,E,…,B}中的能量。
用librosa.feature.chroma_stft计算ChromaFrequencies。
#Loadignthefile
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')
案例分析:
对歌曲类型进行分类
以上我们对声学(听觉)信号及其特征和特征提取过程进行了概述,现在让我们用刚习得的技能来解决机器学习问题。
目标
本节,我们将尝试创建一个分类器将歌曲归为不同的类型。
假设这样一个场景:
出于某种原因,我们在硬盘上找到一堆随机命名的MP3文件,且文件里有音乐。
我们的任务是根据音乐类型将它们分到不同的文件夹中,如爵士、古典音乐、乡村音乐、流行音乐、摇滚乐和金属乐。
数据集
我们将用最常用的的GITZAN数据集进行案例研究。
G.Tzanetakis和P.Cook在2002年IEEETransactionsonaudioandSpeechProcessing中发表的著名论文:
Musicalgenreclassificationofaudiosignals(音频信号的音乐类型分类)中曾用到该数据集。
该数据集每30秒包含1000条音轨,共包含10个音乐类型,即布鲁斯、古典、乡村、迪斯科、嘻哈、爵士、雷鬼、摇滚、金属和流行音乐。
每种类型包含100段声频。
数据处理
在训练分类模型之前,我们须将原始数据从音频样本转换成更有意义的表示形式。
需将音频片段从.au格式转换为能与python的wave模块兼容的.wav格式,以读取音频文件。
不过我常用的是开源SoX模块。
soxinput.auoutput.wav
分类
特征提取(FeatureExtraction)
我们接下来需要从音频文件中提取出有意义的特征。
为了对音频片段进行分类,这里将选择5个特征,即梅尔频率倒谱系数(Mel-FrequencyCepstralCoefficients),频谱质心(SpectralCentroid),过零率(ZeroCrossingRate),ChromaFrequencies,谱滚降(SpectralRoll-off)。
然后将所有特征附加到.csv文件中,以便使用分类算法。
分类(Classification)
提取出特征后,用现有的分类算法将歌曲分为不同的类型。
你可以直接用声谱图进行分类,也可以在提取特征后使用分类模型。
无论采用哪种方式,都要在模型上进行大量的实验。
你可以进行试验和改进结果。
建议试试CNN模型,它(在声谱图上)的精确度更高。
音乐类型分类的笔记
导入库
In[0]:
#featureextractoringandpreprocessingdata
importlibrosa
importpandasaspd
importnumpyasnp
importmatplotlib.pyplotasplt
%matplotlibinline
importos
fromPILimportImage
importpathlib
importcsv
#Preprocessing
fromsklearn.model_selectionimporttrain_test_split
fromsklearn.preprocessingimportLabelEncoder,StandardScaler
#Keras
importkeras
importwarnings
warnings.filterwarnings('ignore')
音乐和特征提取
数据集
我们用GTZANgenrecollection数据集进行分类。
数据集包含10中音乐类型。
如下:
• 布鲁斯
• 古典
• 乡村
• 迪斯科
• 嘻哈
• 爵士
• 金属乐
• 流行音乐
• 雷鬼
• 摇滚
每一种音乐类型包含100首歌曲。
共计1000首歌曲。
音频的声谱图提取
In[0]:
cmap=plt.get_cmap('inferno')
plt.figure(figsize=(10,10))
genres='bluesclassicalcountrydiscohiphopjazzmetalpopreggaerock'.split()
forgingenres:
pathlib.Path(f'img_data/{g}').mkdir(parents=True,exist_ok=True)
forfilenameinos.listdir(f'./MIR/genres/{g}'):
songname=f'./MIR/genres/{g}/{filename}'
y,sr=librosa.load(songname,mono=True,duration=5)
plt.specgram(y,NFFT=2048,Fs=2,Fc=0,noverlap=128,cmap=cmap,sides='default',mode='default',scale='dB');
plt.axis('off');
plt.savefig(f'img_data/{g}/{filename[:
-3].replace(".","")}.png')
plt.clf()
将所有的音频文件转换成相应的声谱图,以方便提取特征。
声谱图特征提取
我们将提取以下特征:
• 梅尔频率倒谱系数(Mel-frequencycepstralcoefficients(MFCC))(20个)
• 频谱质心(SpectralCentroid)
• 过零率(ZeroCrossingRate)
• ChromaFrequencies
• 谱滚降(SpectralRoll-off)
In[0]:
header='filenamechroma_stftrmsespectral_centroidspectral_bandwidthrolloffzero_crossing_rate'
foriinrange(1,21):
header+=f'mfcc{i}'
header+='label'
header=header.split()
将数据写入csv文件
In[0]:
file=open('data.csv','w',newline='')
withfile:
writer=csv.writer(file)
writer.writerow(header)
genres='bluesclassicalcountrydiscohiphopjazzmetalpopreggaerock'.split()
forgingenres:
forfilenameinos.listdir(f'./MIR/genres/{g}'):
songname=f'./MIR/genres/{g}/{filename}'
y,sr=librosa.load(songname,mono=True,duration=30)
chroma_stft=librosa.feature.chroma_stft(y=y,sr=sr)
spec_cent=librosa.feature.spectral_centroid(y=y,sr=sr)
spec_bw=librosa.feature.spectral_bandwidth(y=y,sr=sr)
rolloff=librosa.feature.spectral_rolloff(y=y,sr=sr)
zcr=librosa.feature.zero_crossing_rate(y)
mfcc=librosa.feature.mfcc(y=y,sr=sr)
to_append=f'{filename}{np.mean(chroma_stft)}{np.mean(rmse)}{np.mean(spec_cent)}{np.mean(spec_bw)}{np.mean(rolloff)}{np.mean(zcr)}'
foreinmfcc:
to_append+=f'{np.mean(e)}'
to_append+=f'{g}'
file=open('data.csv','a',newline='')
withfile:
writer=csv.writer(file)
writer.writerow(to_append.split())
以上数据已被提取并写入data.csv文件。
用Pandas进行数据分析
In[6]:
data=pd.read_csv('data.csv')
data.head()
Out[6]:
5行×28列
In[7]:
data.shape
Out[7]:
(1000,28)
In[0]:
#Droppingunneccesarycolumns
data=data.drop(['filename'],axis=1)
对标签进行编码
In[0]:
genre_list=data.iloc[:
-1]
encoder=LabelEncoder()
y=encoder.fit_transform(genre_list
给特征栏标上刻度
In[0]:
scaler=StandardScaler()
X=scaler.fit_transform(np.array(data.iloc[:
:
-1],dtype=float))
将数据分为训练集和测试集
In[0]:
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 代码 详解 Python 给你 喜欢 音乐 分个类吧