最近看完了 Willi Richert的《机器学习系统设计》。书虽然有点薄但也比较全,内容感觉有点偏文本处理,里面介绍了一些文本处理的方法和工具。综合起来看作为机器学习入门还是挺不错的,这里就简单记一下我做的笔记,方便回顾。书中的代码可以通过它说到的网站下载,这里是第7部分笔记。

第九章 声音的分类

由于这本书的重点在文本数据的处理上,对于声音和图像数据,这里各用了一章的内容来介绍,这一章的目的是对于音频文件,分析他的音乐体裁,音乐体裁有很多,例如爵士乐(jazz),古典音乐(classical),乡村音乐(country),流行音乐(pop),摇滚乐(rock)和金属音乐(metal)。这里使用的是GTZAN的数据集,它是一个经常用于乐曲体裁分类任务的数据集,它包含十种体裁。为了简化问题,这里选用其中的六种:古典,爵士,乡村,流行,摇滚和金属音乐。 我们可以在 http://opihi.cs.uvic.ca/sound/genres.tar.gz 下载这个数据集。音轨是22050Hz(每秒22050次读入)单声道WAV格式的。MP3格式是一种有损音乐压缩格式,因为它将人耳听不到的部分截掉了。这种方法有利于存储,但对于分类来说并不是很好,可以用sox来进行格式转换。转换成WAV格式还有另一个好处,就是可以直接使用scipy读取数据。

要快速获得对不同体裁的乐曲的印象,一个比较便捷的方式是绘制乐曲的声谱图,对于matplotlib来说,可以直接使用specgram()函数来进行绘制:

1
2
3
4
5
6
>>> import scipy
>>> from matplotlib.pyplot import specgram
>>> sample_rate, X = scipy.io.wavfile.read(wave_filename)
>>> print sample_rate, X.shape
22050, (661794,)
>>> specgram(X, Fs=sample_rate, xextent=(0,30))

FFT对声音信号的处理

提取频率强度的一个方法是使用快速傅立叶变幻(Fast Fourier Transform, FFT)得到。scipy中已经实现了fft算法,可以直接将上面我们的到的X数据传入scipy.fft()中进行计算。

对于分类器,我们使用逻辑回归分类器(书中说逻辑回归用于情感分析,但实际上在情感分析部分使用的是贝叶斯分类器)。对于多分类问题,通常使用混淆矩阵(confusion matrix)来评估正确率。混淆矩阵在sklearn中已经实现,可以直接调用得到混淆矩阵的一个数组,但我们也可以用matplotlib来对其实现可视化,代码可以参考下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred) # 这个cm就是我们要的矩阵

from matplotlib import pylab

#这个函数用来将cm矩阵可视化
def plot_confusion_matrix(cm, genre_list, name, title):
pylab.clf()
pylab.matshow(cm, fignum=False, cmap='Blues', vmin=0, vmax=1.0)
ax = pylab.axes()
ax.set_xticks(range(len(genre_list)))
ax.set_xticklabels(genre_list)
ax.xaxis.set_ticks_position("bottom")
ax.set_yticks(range(len(genre_list)))
ax.set_yticklabels(genre_list)
pylab.title(title)
pylab.colorbar()
pylab.grid(False)
pylab.show()

通过测试,我们发现使用FFT进行提取频率的方法在这里表现的并不是很好,这就让我们想到,有没有跟好的方法来进行音频的特征提取呢?

ROC 受试者工作特征曲线

我们已经知道,正确率并不一定能反映出一个分类器的真正效果,我们之前考准确-召回曲线对分类器的效果有了一个更深入的了解,这里还有一个类似它的标准,叫做受试者工作特征曲线(Reveiver Operator Characteristic,ROC),它也衡量了分类器的类似方面,P/R曲线和ROC曲线的主要区别在于,P/R曲线更适合正类别比负类别更重要的人物,或者说正例数目比负例数目小得多的人物。信息检索或者欺诈检测就是它的典型应用领域。另一方面,ROC曲线对于分类器的一般效果提供了一个更好的描述。有一篇很好的论文可以详细了解下这两种标准的关系:The Relationship Between Precision-Recall and ROC Curves, Jesse Davis and Mark Goadrich, ICML 2006。

MFCC 梅尔倒频谱系数

对于音频数据的体裁分类问题,有一个专门的会议在研究,这个会议是由音乐信息检索国际协会(International Society for Music Information Retrieval, ISMIR)组织的。在他们的会议中,有一个技术已经成功用于很多工作中了,它叫做 梅尔倒频谱系数(Mel Frequency Cepstral Coefficient, MFCC),梅尔倒频谱会对声音的功率谱进行编码。对于MFCC来说,有人已经做了一个实现,叫做Talkbox Scikit。我们可以从https://pypi.python.org/pypi/scikits.talkbox 安装。之后,调用mfcc()函数即可计算MFCC系数。

1
2
3
4
5
>>> from scikits.talkbox.features import mfcc
>>> sample_rate, X = scipy.io.wavfile.read(fn)
>>> ceps, mspec, spec = mfcc(X)
>>> print(ceps.shape)
(4135, 13)

用于分类的数据存储在ceps里,他对乐曲的4135帧中的每一帧都有13个系数(mfcc()函数的nceps参数默认值)。可以截取一段用来进行分类,而无须把全部数据进行处理分类。使用MFCC参数后,分类器的效果明显的到了改善。