特征提取 在Python中,一个单声道10kHz的波形文件表示为一个范围为-254到255的整数列表,每秒声音包含10000个整数。每个整数代表歌曲在对应时间点上的相对幅度。我们将分别从两首歌曲中分别提取一段时长60秒的片段,所以每个片段将由600000个整数表示。上面代码中的函数“read_wav”返回了这些整数列表。下面是从Eminem的《The Eminem Show》中一些歌曲中提取的10秒声音波形图: 
为了对比,下面是Paganini的《Violin Caprices》中的一些片段波形图: 
从上面两个图中可以看出,这些片段的波形结构差别很明显,但一般来看Eminem的歌曲波形图看起来都有些相似,《Violin Caprices》的歌曲也是这样。接下来,我们将从这些波形图中提取一些统计特征,这些特征将捕捉到歌曲之间的差异,然后通过这些歌曲听起来的相似性,我们使用机器学习技术将它们分组。
我们将要提取的第一组特征集是波形的统计矩(均值、标准差、偏态和峰态)。除了对幅度进行这些计算,我们还将对递增平滑后的幅度进行计算来获取不同时间尺度的音乐特性。我使用了长度分别为1、10、100和1000个样点的平滑窗,当然可能其他的值也能取得很好的结果。
分别利用上面所有大小的平滑窗对幅度进行相应计算。为了获取信号的短时变化量,我还计算了一阶差分幅度(平滑过的)的统计特性。
上面的特征在时间域给出了一个相当全面的波形统计总结,但是计算一些频率域的特征也是有帮助的。像嘻哈这种重低音音乐在低频部分有更多的能量,而经典音乐在高频部分占有更多的比例。
将这些特征放在一起,我们就得到了每首歌曲的42种不同特征。下面的Python代码从一系列幅度值计算了这些特征:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | def moments(x):
mean = x.mean()
std = x.var() * * 0.5
skewness = ((x - mean) * * 3 ).mean() / std * * 3
kurtosis = ((x - mean) * * 4 ).mean() / std * * 4
return [mean, std, skewness, kurtosis]
def fftfeatures(wavdata):
f = numpy.fft.fft(wavdata)
f = f[ 2 :(f.size / 2 + 1 )]
f = abs (f)
total_power = f. sum ()
f = numpy.array_split(f, 10 )
return [e. sum () / total_power for e in f]
def features(x):
x = numpy.array(x)
f = []
xs = x
diff = xs[ 1 :] - xs[: - 1 ]
f.extend(moments(xs))
f.extend(moments(diff))
xs = x.reshape( - 1 , 10 ).mean( 1 )
diff = xs[ 1 :] - xs[: - 1 ]
f.extend(moments(xs))
f.extend(moments(diff))
xs = x.reshape( - 1 , 100 ).mean( 1 )
diff = xs[ 1 :] - xs[: - 1 ]
f.extend(moments(xs))
f.extend(moments(diff))
xs = x.reshape( - 1 , 1000 ).mean( 1 )
diff = xs[ 1 :] - xs[: - 1 ]
f.extend(moments(xs))
f.extend(moments(diff))
f.extend(fftfeatures(x))
return f
|
|