本文打算使用自制的西瓜数据集进行深度学习的模型训练.
通过对手部敲击西瓜的音频进行分析,进行快速傅里叶变换提取频域特征,使用一维卷积神经网络模型进行模型训练,构建西瓜成熟度检测模型.
目录
一. 数据集预处理
1.数据采集
使用进行模型训练的音频数据集,是自己采买西瓜进行录制的.
在进行采集音频的时候,根据敲击西瓜的方式分为了,拍 ( P ),弹 ( T ),敲 ( Q ).
关于西瓜信息:
采集的西瓜音频总共有939条.
数据集一共包含158个西瓜样本,每个西瓜有若干条音频数据.
其中选取86个西瓜样本作为训练集,36个测试集,36个验证集,
基本上数据比例为6:2:2
西瓜 | 八分熟 | 成熟 | 过熟 | 偏生 | 总和 |
---|---|---|---|---|---|
西瓜个数 | 25 | 76 | 31 | 26 | 158 |
音频数 | 145 | 440 | 192 | 162 | 939 |
标签 | 0 | 1 | 2 | 3 |
2.数据预处理
因为自行采集的数据集,每个音频时长在6~30S之间,里面含有多个敲击信号.要对数据进行预处理.
2.1端点检测
端点检测详解链接: 使用matlab进行双门限法的端点检测
端点检测:是指从包含语音的一段信号中确定出语音的起始点和结束点位置.
意义:不仅可以增加样本数量,而且能够减少网络训练过程中不必要的计算,提升模型训练的准确率.
双参数双门限端点检测效果图
从图中可以看出,经过端点检测处理后,样本个数变多了,信号长度大幅度缩减.
值得注意的是:
1.音频时间不要过短.
假设采样频率为16kHZ,每一个数据样本要提取频域信号前1000个数据代表该信号,则要保证至少截取的每一个音频时长为0.0625s.(当然每个截取的音频里至少包含一个激励信号)
采样频率=每单位时间采样点数=采样点数/采样时间
2.阈值的设置要合理
因为音频数量过多,需要进行批量处理.在进行批量处理之前,对于阈值的设置要合理.
假设仅使用单参数的双门限法,也就是根据短时能量法来进行端点检测,根据音频的短时平均能量(或其它参数)设置阈值(amp1和amp2),使激励信号可以被正常找到.
合理设置阈值找到有效激励信号
2.2数据增强
如果在进行了对音频进行了端点检测之后,数据量不够,还可以进行其他的数据增强.(端点检测也算数据增强了)
在进行数据增强时,最好只做一些小改动,使得增强数据和源数据存在较小差异即可,切记不能改变原有数据的结构,不然将产生“脏数据”,通过对音频数据进行数据增强,能有助于模型避免过度拟合并变得更加通用.
对音频进行的改变如下:加噪,波形拉伸,高音修正.
加噪
添加的噪声为均值为0,标准差为1的高斯白噪声.
#####增加噪声#####
def add_noise(data):
# 0.02为噪声因子
wn = np.random.normal(0, 1, len(data))
return np.where(data != 0.0, data.astype('float64') + 0.02 * wn, 0.0).astype(np.float32)
波形拉伸
在不影响音高的情况下改变声音的速度/持续时间.
#####波形拉伸#####
def time_stretch(x, rate):
# rate:拉伸的尺寸,
# rate > 1 加快速度
# rate < 1 放慢速度
return librosa.effects.time_stretch(x, rate)
高音修正
音高修正只改变音高而不影响音速.
#####音高修正#####
def pitch_shifting(x, sr, n_steps, bins_per_octave=12):
# sr: 音频采样率
# n_steps: 要移动多少步
# bins_per_octave: 每个八度音阶(半音)多少步
return librosa.effects.pitch_shift(x, sr, n_steps, bins_per_octave=bins_per_octave)
实例
import librosa
import numpy as np
import matplotlib.pyplot as plt
import soundfile as sf
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示符号
fs = 16000
wav_data, y = librosa.load(r"C:\Users\Administrator\Desktop\test\10_28_1190001.wav", sr=fs, mono=True)
#####1.增加噪声#####
def add_noise(data):
# 0.02为噪声因子
wn = np.random.normal(0, 1, len(data))
return np.where(data != 0.0, data.astype('float64') + 0.02 * wn, 0.0).astype(np.float32)
#####3.波形拉伸#####
def time_stretch(x, rate):
# rate:拉伸的尺寸,
# rate > 1 加快速度
# rate < 1 放慢速度
return librosa.effects.time_stretch(x, rate)
#####4.音高修正#####
def pitch_shifting(x, sr, n_steps, bins_per_octave=12):
# sr: 音频采样率
# n_steps: 要移动多少步
# bins_per_octave: 每个八度音阶(半音)多少步
return librosa.effects.pitch_shift(x, sr, n_steps, bins_per_octave=bins_per_octave)
data_noise = add_noise(wav_data)
data_stretch = time_stretch(wav_data, rate=2)
data_pitch2 = pitch_shifting(wav_data, fs, n_steps=-6, bins_per_octave=12) # 向下移三音(如果bins_per_octave为12,则六步)
# 绘图
plt.subplot(2, 2, 1)
plt.title("波形图", fontsize=15)
time = np.arange(0, len(wav_data)) * (1.0 / fs)
plt.plot(time, wav_data)
plt.xlabel('秒/s', fontsize=15)
plt.ylabel('振幅', fontsize=15)
plt.subplot(2, 2, 2)
plt.title("加噪", fontsize=15)
plt.plot(time, data_noise)
plt.xlabel('秒/s', fontsize=15)
plt.ylabel('振幅/Hz', fontsize=15)
plt.subplot(2, 2, 4)
plt.title("高音修正", fontsize=15)
plt.plot(time, data_pitch2)
plt.xlabel('秒/s', fontsize=15)
plt.ylabel('振幅/Hz', fontsize=15)
plt.subplot(2, 2, 3)
plt.title("波形拉伸", fontsize=15)
time = np.arange(0, len(data_stretch)) * (1.0 / fs)
plt.plot(time, data_stretch)
plt.xlabel('秒/s', fontsize=15)
plt.ylabel('振幅/Hz', fontsize=15)
plt.tight_layout()
plt.show()
2.3快速傅里叶变换(FFT)
对端点检测(或者数据增强)后得到的信号进行快速傅里叶变换,得到其幅频特性.提取频域信号前1000个数据(或者更多)代表该信号.
从物理的角度去看待傅立叶变换,它其实是帮助我们改变传统的时间域分析信号的方法转到从频率域分析问题的思维,下面的一幅立体图形可以帮助我们更好得理解这种角度的转换:
最前面的时域信号在经过傅立叶变换的分解之后,变为了不同正弦波信号的叠加,我们再去分析这些正弦波的频率,可以将一个信号变换到频域.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了.这就是很多信号分析采用FFT变换的原因.另外,FFT可以将一个信号的频谱提取出来,这在频谱分析方面也是经常用的.
对于计算机来说只有离散和有限长度的数据才能被处理,对于其它的变换类型只有在数学演算中才能用到,在计算机面前我们只能用DFT方法,而FFT也只不过是DFT的一种快速的算法.
关于如何实现fft,numpy中有一个fft的库.
具体程序实例如下: