零基础入门语音识别-食物声音识别 Task1学习笔记

理解赛题

赛题简介

这次的赛题是针对若干种不同食物的咀嚼声音数据进行模型训练,完成语音分类的任务。比赛地址:零基础入门语音识别-食物声音识别

数据概况

赛题的数据来自Eating Sound Collection,数据集中包含20种不同食物的咀嚼声音。通过观察数据文件可以看到,声音类别包括芦荟、汉堡、卷心菜、蜜饯、胡萝卜、薯条、巧克力、弗雷西、葡萄、软糖、冰淇淋、果冻、面条、泡菜、比萨、排骨、鲑鱼、汤、鸡翅等20种,音频格式都为.wav。
这就可以看出赛题的第一个重点,就是如何对这些音频文件进行读取,并把它们转换为能够进行深度学习计算的格式。

评估标准

赛题对结果的评估指标是准确率(Accuracy)。其定义是: 对于给定的测试数据集,分类器正确分类的样本数与总样本数之比。这是相对简单直接的评估标准,正确分类的样本数占总样本的比例越高,准确率就越高,进而赛题得分也就越高。

baseline学习

baseline是调用了librosa库进行音频文件处理,然后计算数据的梅尔频谱(mel spectrogram),并把它作为特征输出。
通过对梅尔频谱的相关学习我了解到这个baseline的思路便是将音频文件转换为波形图或频谱图,把音频分类变成图像分类去做。同时也明白了这个baseline为什么要用CNN进行建模。

下面是baseline中关于特征提取的代码

def extract_features(parent_dir, sub_dirs, max_file=10, file_ext="*.wav"):
    c = 0
    label, feature = [], []
    for sub_dir in sub_dirs: # 跳过第一个值,即跳过母文件夹
        for fn in tqdm(glob.glob(os.path.join(parent_dir, sub_dir, file_ext))[:max_file]): # 遍历数据集的所有文件(glob.glob查找文件)
            label_name = fn.split('/')[-2]
            label.extend([label_dict[label_name]])
            X, sample_rate = librosa.load(fn,res_type='kaiser_fast')
            mels = np.mean(librosa.feature.melspectrogram(y=X,sr=sample_rate).T,axis=0) # 计算梅尔频谱(mel spectrogram),并把它作为特征
            feature.extend([mels])
            
    return [feature, label]

查看一下特征:

# 获取特征
X = np.vstack(data[:, 0])
print(X)
print('X的特征尺寸是:',X.shape)

是这样的:(是一个1000行128列的特征矩阵)

[[9.5909061e+00 8.9241543e+00 5.4195790e+00 ... 2.2222184e-05
  2.9802143e-06 3.4577468e-07]
 [1.4151512e+00 2.0132339e+00 2.0210712e+00 ... 8.3886343e-06
  1.1541566e-06 1.6960963e-07]
 [3.9026089e+01 1.9351940e+01 2.8977978e+00 ... 2.0131629e-04
  3.0025676e-05 3.8540197e-06]
 ...
 [6.8946503e-02 2.4784628e-01 3.6950496e-01 ... 9.6918857e-06
  1.9629206e-06 1.8803826e-07]
 [1.9795325e-01 7.4999809e-01 1.3888948e+00 ... 1.9261705e-04
  2.6337708e-05 2.9368146e-06]
 [2.3339033e-01 1.6757719e-01 6.4574160e-02 ... 5.9617403e-05
  8.2187262e-06 1.3610829e-06]]
  X的特征尺寸是: (1000, 128)

关于标签,baseline有一个处理是

# 在Keras库中:to_categorical就是将类别向量转换为二进制(只有0和1)的矩阵类型表示
Y = to_categorical(Y)

这样将原有的向量数据转换为独热编码的形式,而这样做的原因应该是为了符合CNN输出的需要,因为多分类cnn网络的输出通常是softmax层,是一个概率分布。

输出看看

Y
print(Y.shape)
array([[1., 0., 0., ..., 0., 0., 0.],
       [1., 0., 0., ..., 0., 0., 0.],
       [1., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 1.],
       [0., 0., 0., ..., 0., 0., 1.],
       [0., 0., 0., ..., 0., 0., 1.]], dtype=float32)
(1000, 20)

对了,后续对训练集和测试集也有一个处理

X_train = X_train.reshape(-1, 16, 8, 1)
X_test = X_test.reshape(-1, 16, 8, 1)

根据了解也是为了CNN而进行处理的,把输入数据转换为CNN需要的shape。

最后则是搭建CNN网络进行数据训练预测的过程。但这里面的逻辑和各种参数我还没有完全搞懂,在接下来的学习中我会更深入理解代码里面的含义并尝试进行调参修改,对模型进行优化。

跑通baseline结果

在这里插入图片描述

总结

经过这两天的学习,已经初步了解语音识别是怎么一回事。作为一个小白,在这个过程中新接触的东西很多,也很懵懂。但是我也已经感受到这两天的些许进步,即使微不足道,但也足够令人充满动力。
在学习baseline的过程中也有很多令我感叹的地方,特别是以图像代替音频来进行处理的思路十分有趣,也让我明白自己在这方面的知识远远不够,至少我还不会想到原来还可以这么做哈哈哈。我需要学习更多,这很难,但希望自己能坚持下去,加油!

参考资料
【1】神经网路中one-hot有什么作用?为什么要使用to_categorical?

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐