语音识别数据预处理(添加噪音)和特征提取

0 前言

   在做ASR和KWS实验时,必不可少的需要对语音数据预处理,提取特征(业内常见是提取为MFCC),最后再喂入模型中。数据预处理可分为离线处理和在线处理:

  • 离线处理: 训练之前先对语音数据进行加噪音、调低\高音量、1.5倍速播放等(有人用工具audiomentations),然后再提取MFCC特征到特征文件里(特征文件格式.h5,.csv),训练时数据集从特征文件读取,不需要再预处理了.
      优点: 只需提取特征一次就可以多次训练,时间减少很多;
      缺点: 每个epoch喂入模型的数据特征都是一样的(提取到特征文件,其实特征就被写死了),变相的降低了数据集可增强的空间,模型泛化能力会降低;
  • 在线处理: 对数据进行预处理,然后提取MFCC特征,最后喂入模型中。每一个epoch都会进行预处理,再喂入模型;
      优点: 数据集可增强空间变大(相当于有epoch个数据集),模型泛化能力强;
      缺点: 训练时间长,显存消耗大;

后面章节将介绍语音预处理、特征提取到特征文件

1 语音预处理

语音预处理常用工具是librosa或者audiomentations,下面将介绍基于audiomentations的数据预处理;

1.1 audiomentations简介

audiomentations工具是一款GitHub开源的语音处理工具,主要有

  • AddGaussianNoise(min_amplitude=0.001, max_amplitude=0.015, p=0.5):随机添加高斯噪音
  • TimeStretch(min_rate=0.8, max_rate=1.25, p=0.5): 对时间维度 调整
  • PitchShift(min_semitones=-4, max_semitones=4, p=0.5) :对音调的调整
  • Shift(min_fraction=-0.5, max_fraction=0.5, p=0.5) : 在时间轴的滚动,主要是用到np.roll()函数

1.2 audiomentations增强语音数据

import audiomentations
import librosa

def audio_preprocessing(file):
	""" file为wav语音文件,返回离散语音数据 """
	data , sr = librosa.core.load(file)  #  语音流转为离散数值
	augmenter = Compose([
    	    AddGaussianNoise(min_amplitude=0.001, max_amplitude=0.015, p=0.5),
        	TimeStretch(min_rate=0.8, max_rate=1.25, p=0.5),
        	PitchShift(min_semitones=-4, max_semitones=4, p=0.5),
        	Shift(min_fraction=-0.5, max_fraction=0.5, p=0.5),
    	])
	return augmenter(audio, sample_rate=sr)  # 语音预处理,返回离散语音数据

2.特征提取到文件.h5

特征文件常见的有.h5,.npy, .txt, .csv等 ,前两种比较受欢迎,其读写速度都比较快,博客详细的介绍他们的性能;这里我采用.h5文件保存特征,但是.h5有一个问题,多线程读取一个文件时会出现报错:
在这里插入图片描述
据说.h5多线程本身的问题,因此需要用到多线程的需要注意。

2.1 节省空间小技巧

下面简单介绍下hdf5文件存储特征时,节省空间的小技巧。

  1. .h5文件数据保存格式默认是float64, 但实际上并不需要那么高精度,float32也足够了;
  2. 保存文件时采用gzip压缩格式,压缩级别设置到9;
  3. 最后就是chunks的设置,可以限定你文件都写都是放在一个块中,这个大大节约了空间;

2.2 语音数据特征提取为mel光谱图

博客详细的讲解了特征提取为MFCC的过程,这里简单介绍:

  1. 离散傅里叶变换FFT: FFT用于提取声音频谱信息,将语音流的时域序列转到频域表示;x轴为时间(每个点即表示一帧),y轴代表频率;
  2. 平方取功率谱;
  3. Mel滤波器: 将声音转换到Mel表示,更加符合人耳听觉特性(只对频率操作即可);
  4. 取对数增强低频数据;
  5. DCT离散余弦变换: 傅里叶的逆变换,得到系数向量,即倒谱系数;
  6. 偏微分: 偏微分可以丰富信息;
import librosa

def extract_feature_1(file):
	""" file 为 数组"""
	melspectrogram = librosa.feature.melspectrogram(y=file, sr=16000, n_fft=2048, hop_length=1024)  # mel滤波
	s =librosa.power_to_db(melspectrogram)  # 取对数
    mfcc = librosa.feature.mfcc(S=s, n_mfcc=20)  # MFCC,这里其实可以一步到位,去掉melspectrogram、power_to_db操作都可以
    mfcc_delta = librosa.feature.delta(mfcc)
    mfcc_delta_delta = librosa.feature.delta(mfcc_delta)  # 偏微分
    mfcc_comb = np.concatenate([mfcc, mfcc_delta, mfcc_delta_delta], axis=0)
    return mfcc_comb

DCT变换只提取了频谱的包络信息,损失了大量声音细节,特征也失去了,因此在深度学习中,采用特征更加丰富的Mel谱信息作为特征更优。下面我们定义只提取到mei谱的特征函数。

import librosa
def extract_feature(file):
	""" file 为 数组"""
	melspectrogram = librosa.feature.melspectrogram(y=file, sr=16000, n_fft=2048, hop_length=1024, n_mels=40)  # mel滤波
	mel =librosa.power_to_db(melspectrogram)  # 取对数
    return mel

2.3 特征提取到文件

假设数据特征shape(1,40, 101),若没有补0.

import h5py
import audio_preprocessing,extract_feature

def extract_feature_to_h5(data)
	"""data为数组,存储的为语音wav文件 """
	### 预处理 audio_preprocessing()
	audio_data = []
	for wav in data:
		audio_data.append(audio_preprocessing(wav))
	### 特征提取
	features = []
	for wav in audio_data:
		item = extract_feature(wav)
		item = np.pad(data, (0, max(0, in_len - item.shape[1])), "constant")  # 数据格式对齐(1,40,101)
		features.appen(item.reshape(1,40,101))
	### 特征保存到文件.h5
	h5_train = h5py.File("Train.h5", 'w')  # 新建一个Train.h5文件
	h5_data = h5_train.create_dataset("data", data=[[[]]], maxshape=(None, 40, 101), chunks=(1,  40, 101), compression="gzip", compression_opts=9)  # 在.h5文件中创建data 数据集,后续需要重新添加数据,因此数据集大小不能写死maxshape=(None,101,40)中None说明可以随时写入数据集。
	for i, item in  enumerate(features):
		h5_data .resize((i+1,40, 101))
		h5_data [i] = item
	h5_data.close()

你可能感兴趣的:(Deep,Learning)