使用pytorch,在Windows系统下处理语音信号(附代码)
这篇博客以TIMIT数据集为例,在Windows系统下,使用pytorch自带的语音处理库,将语音文件处理成pytroch模型能直接加载训练的文件。
前言
- 语言信号处理好麻烦,github上好多ASR项目,Windows系统都运行不了,还要安装kalid,好麻烦,还好pytorch有自带的语音处理库。
- 处理好的数据已上传,可以直接加载到pytorch模型。
一、引入库
import os
import torch
import torchaudio
from collections import Counter, OrderedDict,defaultdict
from torch.utils.data import DataLoader
from nltk.tokenize import TweetTokenizer
import numpy as np
二、构建词汇表
语音识别,根据语音信号,得到一句话,词汇表用于将这句话变成一串数字
例如: I hate you -> 12 9 35
- 使用PTB的训练文件生成词汇表,代码如下(示例):
class OrderedCounter(Counter, OrderedDict): #这样定义的字典类型变量,会将输入的句子里的新单词添加到字典中,并记录该单词的出现次数
"""Counter that remembers the order elements are first encountered"""
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
def create_vocab(split):
tokenizer = TweetTokenizer(preserve_case=False) #分词,不区分大小写
w2c = OrderedCounter()
w2i = dict()
i2w = dict()
special_tokens = ['<pad>', '<unk>', '<sos>', '<eos>']
for st in special_tokens:
i2w[len(w2i)] = st
w2i[st] = len(w2i)
with open(split, 'r') as file:
for i, line in enumerate(file):
words = tokenizer.tokenize(line)
w2c.update(words) #这段程序将文件中出现过的所有单词加载到字典类型变量w2c中,并存储了他们出现的次数
for w, c in w2c.items():
if c > 3 and w not in special_tokens: #依次为出现次数大于3,且不是那4种特殊信号的单词分配序号
i2w[len(w2i)] = w
w2i[w] = len(w2i) #w2i格式为'cat':50这种,i2w为50:'cat'这种
return w2i,i2w
w2i,_ = create_vocab('ptb.train.txt')
得到的词汇表w2i如图所示,每个单词都有对应的数字。
具体可以参考这篇文献:Pytorch加载txt格式的数据集文件
三、处理TIMIT数据集
TIMIT数据集的各个文件夹以及文件名的详细介绍,参考这篇博客,解释的很清楚:语音识别数据集-TIMIT数据集-中文超详细解析
代码如下:
path = os.getcwd() #获取当前文件地址
train_path = path + '\\data\\TRAIN' #得到训练集和测试集的地址
test_path = path + '\\data\\TEST'
num = 0
for i in os.listdir(train_path): #这个和TIMIT数据集的组成有关,参考上面提到的TIMIT那篇博客
for j in os.listdir(train_path + str('\\') +i):
for k in os.listdir(train_path + str('\\') + i + str('\\') + j):
path = train_path + str('\\') + i + str('\\') + j + str('\\') + k
if '.WAV' in path: #加载训练集的每一个音频文件(WAV)
waveform,sample_rate = torchaudio.load('data\\TRAIN' + str('\\') + i + str('\\') + j + str('\\') + k) #得到音频文件的波形和采样率(都是16khz)
specgram = torchaudio.transforms.MelSpectrogram()(waveform) #得到MFCC频谱信号波形
with open('data\\TRAIN' + str('\\') + i + str('\\') + j + str('\\') + k[:-4]+ '.TXT', "r") as f:
data = f.read() #读出数据集里语音转换后的txt文件
data = data.split() #下面是因为,txt存储是这样的 0 4555 i hate you.我们只需要 i hate you 其余全部去掉
data_e = data[-1][:-1]#取出最后一个字母‘you.’ 并且删除'.' 只保留'you'
data = data[2:-1]#不要0 4555 和 you.
data.append(data_e)#将'you'加上,这样句子就从‘0 4555 i hate you.’变成'i hate you'
length = len(data) #句子的长度
target = [w2i.get(w, w2i['<unk>']) for w in data]#根据词汇表,将句子转换为数字
target = torch.from_numpy(np.asarray(target))
state = {'waveform':waveform,'txt':data,'length':length,'specgram':specgram,'target':target,'sample_rate':sample_rate}
torch.save(state,'train_data/'+str(num)+ '.cfg')
num = num + 1
num = 0
for i in os.listdir(test_path):
for j in os.listdir(test_path + str('\\') +i):
for k in os.listdir(test_path + str('\\') + i + str('\\') + j):
path = test_path + str('\\') + i + str('\\') + j + str('\\') + k
if '.WAV' in path:
waveform,sample_rate = torchaudio.load('data\\TEST' + str('\\') + i + str('\\') + j + str('\\') + k)
specgram = torchaudio.transforms.MelSpectrogram()(waveform)
with open('data\\TEST' + str('\\') + i + str('\\') + j + str('\\') + k[:-4]+ '.TXT', "r") as f:
data = f.read()
data = data.split()
data_e = data[-1][:-1]
data = data[2:-1]
data.append(data_e)
length = len(data)
target = [w2i.get(w, w2i['<unk>']) for w in data]
target = torch.from_numpy(np.asarray(target))
state = {'waveform':waveform,'txt':data,'length':length,'specgram':specgram,'target':target,'sample_rate':sample_rate}
torch.save(state,'test_data/'+str(num)+ '.cfg')
num = num + 1
- 对TMIT数据集处理,得到的训练集文件0.cfg-4619.cfg存放在train_data文件夹内; 得到的测试集文件0.cfg-1679.cfg存放在train_data文件夹内;
- 生成cfg文件含有六个属性
- waveform : 波形
- txt : 对应的文字
- target : 经过词汇表转换txt后的数字
- length : txt长度
- specgram: MFCC波形,一般使用MFCC做ASR,语音识别之特征参数提取(一)
- sample_rate:采样率
如图所示:
四、加载为能被批处理的tensor变量
data = defaultdict(dict)
for i in range(4620): #处理训练集和测试集
train_data = torch.load('train_data/'+str(i)+'.cfg')
inp = train_data['specgram']
if inp.size()[2] <= 256: #统一输入input的长度,短的填0,长的截断
zero = torch.zeros(1,128,256-inp.size()[2])
inp = torch.cat((inp,zero),dim=2)
else:
inp = inp[:,:,:256]
data[i]['input'] = inp.squeeze(0)
txt = train_data['txt']
length = train_data['length']
if length <= 15: #统一标签label的长度,短的填<pad>,长的截断
txt.extend(['<pad>'] * (15-length))
else:
txt = txt[:15]
target = [w2i.get(w, w2i['<unk>']) for w in txt]
target = torch.from_numpy(np.asarray(target))
data[i]['target'] = target
train_data_loader = DataLoader(
dataset= data,
batch_size= 64,#批处理大小
shuffle=True #是否打乱排序
)
data = defaultdict(dict)
for i in range(1680):
test_data = torch.load('test_data/'+str(i)+'.cfg')
inp = test_data['specgram']
if inp.size()[2] <= 256:
zero = torch.zeros(1,128,256-inp.size()[2])
inp = torch.cat((inp,zero),dim=2)
else:
inp = inp[:,:,:256]
data[i]['input'] = inp.squeeze(0)
txt = test_data['txt']
length = test_data['length']
if length <= 15:
txt.extend(['<pad>'] * (15-length))
else:
txt = txt[:15]
target = [w2i.get(w, w2i['<unk>']) for w in txt]
target = torch.from_numpy(np.asarray(target))
data[i]['target'] = target
test_data_loader = DataLoader(
dataset= data,
batch_size= 64,#批处理大小
shuffle=True #是否打乱排序
)
这样就得到了训练集和测试集的批处理的迭代器,输入为MFCC波形(input),输出为一串数字(target)(可通过词汇表w2i翻译)
如图所示:
总结
这篇博客以TIMIT数据集为例,在Windows系统下,使用pytorch自带的语音处理库,将语音文件处理成pytroch模型能直接加载训练的文件。
- 完整项目代码已上传:TIMIT-preprocess.zip