Introduction
这次的作业是利用MLP完成语音识别的任务,具体的流程大体可以分成三个部分,第一是数据处理,将原始的numpy数组处理成torch的标准输入格式,第二部分是网络搭建,第三部分是调参+网络结构优化。
输入数据代表特征的一些细节指导书上写的很细了,这里不会说太多。
Part 1
原始文件的格式是这样的:
1 2 3 4 5 6 7 8 9 10 11 Data folder |--dev-clean |--test-clean |--train-clean-100 | |--mfcc | | |--0019-000198-000.npy | | |--0019-000198-001.npy | | |-- ... more files | |--transcript | | |--0019-000198-000.npy | | |--0019-000198-001.npy
具体可以看kaggle data ,下面我将展示npy文件的具体内容。首先介绍如何逐一读取训练集和测试集下的文件:
1 2 3 datapath = 'dev-clean' mfcc_list = os.listdir(f'{datapath} /mfcc' ) trans_list = os.listdir(f'{datapath} /transcript' )
利用os.listdir
方法就能得到该目录下的所有文件名,然后再去逐个读文件,这里演示单个文件:
1 2 3 idx = 0 mfcc = np.load(f'{datapath} /mfcc/{mfcc_list[idx]} ' ) trans = np.load(f'{datapath} /transcript/{mfcc_list[idx]} ' )[1 :-1 ]
这里对于trans
是把首尾两个元素去除了,因为对应的是<eos>
和<sos>
,并不表示音素,这样得到的mfcc
和trans
如下所示:
1 2 3 4 5 6 7 8 array([[ 1.24845963e+01 , -1.36812055e+00 , -1.42250881e-01 , ..., -4.10560369e-02 , -8.77164230e-02 , -1.29315346e-01 ], ..., [ 7.65058327e+00 , -5.13446569e-01 , -8.14266324e-01 , ..., -2.23895818e-01 , -1.85610950e-01 , -7.40890345e-03 ]], dtype=float32) array(['SIL' , .., 'S' , 'T' , 'T' , 'T' , 'T' , 'T' , 'OW' , 'OW' , ..., 'SIL' ], dtype='<U5' )
对trans
还需要进行编码处理,因为最后神经网络的输出是数字的形式,这里就直接利用已有的PHONEMES
建立映射即可:
1 2 3 4 5 6 7 8 9 PHONEMES = [ 'SIL' , 'AA' , 'AE' , 'AH' , 'AO' , 'AW' , 'AY' , 'B' , 'CH' , 'D' , 'DH' , 'EH' , 'ER' , 'EY' , 'F' , 'G' , 'HH' , 'IH' , 'IY' , 'JH' , 'K' , 'L' , 'M' , 'N' , 'NG' , 'OW' , 'OY' , 'P' , 'R' , 'S' , 'SH' , 'T' , 'TH' , 'UH' , 'UW' , 'V' , 'W' , 'Y' , 'Z' , 'ZH' , '<sos>' , '<eos>' ] phone_map = {lb:idx for idx, lb in enumerate (PHONEMES)}
最后的那两个标识符加上不加上都不影响,一共有效的音素是40个,对应0-39的映射,最后会被转换成one-hot encoding作为输出。
接下来就是完成本次作业需要的AudioDataset(torch.utils.data.Dataset)
,其实就是填写__init__
,__len__
,__getitem__
函数。下面就用训练集做演示说明三个函数具体需要完成的内容。
init函数
需要完成数据的初始化,也就是把原始的npy文件全读到self变量里,再处理成MLP输入的格式。需要完成的是对输入mfcc的padding,也就是单个训练音频数据前后补零,这样做的原因指导书有介绍,此外就是把训练集中的标签转为数字格式,之前已经提到了。
len函数
getitem函数
Part 2
模型的设置,目前的模型是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Network (torch.nn.Module ): def __init__ (self, context ): super (Network, self).__init__() input_size = (2 *context + 1 ) * 15 output_size = 40 self.model = torch.nn.Sequential( torch.nn.Linear(input_size, 2048 ), torch.nn.ReLU(), torch.nn.Linear(2048 , 648 ), torch.nn.ReLU(), torch.nn.Linear(648 , 128 ), torch.nn.ReLU(), torch.nn.Linear(128 , output_size) ) def forward (self, x ): out = self.model(x) return out
Part 3