如果你写过read或load音频文件的程序,你会发现,音频数组和采样率通常会同时出现。如果你不知道采样率是什么,可以看看这篇文章。
作为一个炼丹师,对参数的敏感已经成为条件反射,很自然会想到的一个问题是:采样率会影响模型的识别结果吗?答:会的。
除了采样率,音频的属性还有采样深度、通道数等,音频的格式也各种各样,比如wav、mp3、flac等,这些会影响模型的识别吗?答:都会,但影响程度不一样。
采样率
采样率,简单地说,就是每秒采样的数量。语音识别场景常见的采样率有8000、16000、32000等。以采样率16000为例,一秒钟的语音(假设单通道)就是一个长度为1.6w的数组。
如果给你一个长1.6w的数组,不告诉你采样率,你没法确定这段语音的时长是多少。那这跟模型有什么关系呢?或者说,采样率怎么影响语音识别模型呢?
如果用采样率1.6w的语音训练一个模型,而测试集语音的采样率是8k,那测试集的语音每两秒被模型当做一秒,相当于语速加快了一倍,这会导致什么样的后果呢?
想象一下你在房间里背诵古文,你妈进来问你在念什么,你说古文。你妈二话不说上来就是一耳光,敢叫我滚?你很委屈,你明明说了两个字,却因为语速太快,她以为你只说了一个字。
所以,训练集和测试集的采样率一定要统一。
统一成多少比较好呢?没有固定的标准,语音识别一般用16000。如果追求精度,那就用高采样率;如果追求效率,就用低采样率。
采样深度
在图像识别任务中,图像输入模型之前,要进行归一化处理,最简单的方式就是image/255,因为像素取值范围是0~255。
在语音识别任务中,同样也要对语音进行归一化处理。与图像识别的区别在于,语音样本的取值范围是不固定的,这取决于采样深度。
如果采样深度是16位,那么语音样本的取值范围是 [ − 2 15 , 2 15 − 1 ] [-2^{15}, 2^{15}-1] [−215,215−1],简单的归一化就是 a u d i o / 2 15 audio/2^{15} audio/215;相应的,32位的采样深度对应的取值范围是 [ − 2 31 , 2 31 − 1 ] [-2^{31}, 2^{31}-1] [−231,231−1],归一化便是 a u d i o / 2 31 audio/2^{31} audio/231。
所以,采样深度影响语音数据归一化。
不过,很多时候read或load出来的语音数据本身就是[-1,1]之间的浮点数,这是因为已经做了归一化处理。
通道数
语音识别一般都是用单通道的语音,如果你的音频是多通道的,就要转成单通道。
多通道怎么转单通道?理想的情况是,你要识别的语音就在一个通道里,并且你知道在哪个通道,那么就把这个通道的数据提出来就好了,这样还可以避免其它通道无关信息对识别的干扰。
理想的情况通常不存在,实际情况是语音在各个通道里面都出现,或者你不知道哪个通道会出现语音,不过处理方式也简单粗暴,就是把各通道的数值取平均,得到一个通道。
音频格式
音频的格式有很多种,mp3、wav、flac、ogg等。我们知道,不同格式的音频的编码是不一样的。这对语音识别有没有影响呢?比如,用mp3音频训练的模型,再用wav的音频测试,会不会因为格式不同导致准确率低或者模型完全听不懂呢?答:几乎不会。
我们知道,同一张图的jpg和png两种格式,虽然编码方式不一样,但是解码后展示出来的图是差不多的,一般肉眼看不出什么差别。用png图片训练模型,用jpg图像测试模型,完全没问题。
音频也是一样,用wav音频训练模型,用MP3音频测试模型,也是没有问题。
最后
推荐一个可以修改音频采样率、采样深度、通道数的python脚本:
https://github.com/wapping/SpeechUtils/blob/master/audio/reset.py
支持多种格式的音频,支持单个或批量音频转换。
脚本依赖pydub库,而pydub依赖ffmpeg,所以要安装pydub和ffmpeg。