关于人工智能:Torch从特征提取到模型的语音识别

4次阅读

共计 7585 个字符,预计需要花费 19 分钟才能阅读完成。

作者 |Ayisha D
编译 |VK
起源 |Towards Data Science

这篇文章中,咱们探讨从语音数据中提取的特色,以及基于这些特色构建模型的不同办法。

语音数字 (Spoken digits) 数据集是 Tensorflow 语音数据集的一个子集,它包含数字 0 - 9 之外的其余录音。在这里,咱们只关注辨认书面语数字。

数据集能够按如下形式下载。

data = download_url("http://download.tensorflow.org/data/speech_commands_v0.01.tar.gz", "/content/")

with tarfile.open('/content/speech_commands_v0.01.tar.gz', 'r:gz') as tar:
    tar.extractall(path='./data')
Downloading http://download.tensorflow.org/data/speech_commands_v0.01.tar.gz to /content/speech_commands_v0.01.tar.gz
HBox(children=(FloatProgress(value=1.0, bar_style='info', max=1.0), HTML(value='')))
digit = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
for x in digit:
    print(x, ":", len(os.listdir('/content/data/'+x)))

#均衡
zero :  2376
one :  2370
two :  2373
three :  2356
four :  2372
five :  2357
six :  2369
seven :  2377
eight :  2352
nine :  2364

评估指标

数字相当均衡,每个类有大概 2300 个样本。因而,准确度是评估模型性能的一个很好的指标。准确度是正确预测数与总预测数的比拟。

对于不均衡的数据集,这不是一个很好的性能度量,因为少数类可能会黯然失色。

循环学习率

在训练一个模型时,学习率逐步升高,以对训练进行微调。为了进步学习效率,能够采纳循环学习率。在这里,学习率在不同期间的最小值和最大值之间稳定,而不是枯燥降落。

初始训练率对模型的性能至关重要,低训练率可避免在训练开始时被卡住,随后的稳定克制了部分极小值的状况。

该我的项目有三种分类办法:

  1. 应用五个提取的特色进行 Logistic 回归剖析,准确率为 76.19%。
  2. 仅应用 MFCCs 的 Logistic 回归 - 准确率为 95.56%。
  3. CNN 应用 Mel 谱图 - 准确率为 95.81%。

通过扭转 epoch 和训练率对模型进行重复训练。暗藏层的数量和每个层中的节点也各不相同。这里形容了每种办法的最佳架构和超参数。因为训练和验证集划分的随机性,再训练的精确度可能略有不同。

我的项目的源代码在这里:https://github.com/AyishaR/Sp…

有五个.ipynb 文件:

  1. 特征提取 - 提取三种办法所需的 CSV 文件和特色。
  2. 特色可视化 - 在每个类中绘制特色图。
  3. Spokendigit 五个特色 - 应用五个提取的特色实现逻辑回归。
  4. Spokendigit MFFC- 应用 MFCC 实现逻辑回归。
  5. Spokendigit CNN- 应用 Mel 谱图实现 CNN。

1. 应用五个提取特色的 Logistic 回归

特色

提取的特色包含:

  • Mel Frequency Cepstral Coefficients (MFCCs)- 依据人类听觉零碎的响应(Mel 尺度)距离的频带组成声音的频谱示意的系数。
  • Chroma - 与 12 个不同的音高等级无关。
  • Mel spectrogram的平均值 - 基于 Mel 标度的 Mel 谱图。
  • Spectral Contrast- 示意谱的质心。
  • Tonnetz - 代表音调空间。

这些特色是大小为(20,)(12,)(128,)(7,)和(6,)的 NumPy 数组。这些连接起来造成一个大小为(173,)的特色数组。标签被附加到数组的头部,并写入每个记录的 CSV 文件中。

def extract_features(files):
    data, sr = librosa.load('/content/data/'+files.File)
    mfccs = np.mean(librosa.feature.mfcc(y = data, sr=sr).T, axis = 0)
    stft = np.abs(librosa.stft(data))
    chroma = np.mean(librosa.feature.chroma_stft(S = stft, sr = sr).T, axis = 0)
    mel = np.mean(librosa.feature.melspectrogram(data, sr).T, axis = 0)
    contrast = np.mean(librosa.feature.spectral_contrast(S = stft, sr = sr).T, axis = 0)
    tonnetz = np.mean(librosa.feature.tonnetz(y = librosa.effects.harmonic(data), sr = sr).T, axis = 0)
    
    #print(mfccs.shape, stft.shape, chroma.shape, mel.shape, contrast.shape, tonnetz.shape)
    
    row =  np.concatenate((mfccs, chroma, mel, contrast, tonnetz), axis = 0).astype('float32')
    csvwriter.writerow(np.concatenate(([digit.index(files.Label)], row)))

模型

线性回归模型共有 1 个输出层、2 个暗藏层和 1 个带 ReLu 激活的输入层。

class SpokenDigitModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.l1 = nn.Linear(173, 1024)
        self.l2 = nn.Linear(1024, 512)
        self.l3 = nn.Linear(512, 64)
        self.l4 = nn.Linear(64, 10)

    def forward(self, x):
        x = F.relu(self.l1(x))
        x = F.relu(self.l2(x))
        x = F.relu(self.l3(x))
        x = self.l4(x)
        return x

    def training_step(self, batch):
        inputs, labels = batch
        outputs = self(inputs)
        loss = F.cross_entropy(outputs, labels)
        return loss

    def validation_step(self, batch):
        inputs, labels = batch
        outputs = self(inputs)
        loss = F.cross_entropy(outputs, labels)
        _, pred = torch.max(outputs, 1)
        accuracy = torch.tensor(torch.sum(pred==labels).item()/len(pred))
        return [loss.detach(), accuracy.detach()] 

训练

model = to_device(SpokenDigitModel(), device)
history = []
evaluate(model, val_dl)
{'accuracy': 0.10285229980945587, 'loss': 3.1926627159118652}
history.append(fit(model, train_dl, val_dl, 64, 0.01))
r = evaluate(model, val_dl)
yp, yt = predict_dl(model, val_dl)
print("Loss:", r['loss'], "\nAccuracy:", r['accuracy'], "\nF-score:", f1_score(yt, yp, average='micro'))
Loss:  2.0203850269317627 
Accuracy:  0.7619398832321167 
F-score:  0.7586644125105664

该模型在 CPU 上训练约 3 分钟,准确率为 76.19%。

plot(losses, 'Losses')

从最小值开始,最终验证损失缓缓变大。

plot(accuracies, 'Accuracy')

以上为准确率曲线

plot(last_lr, 'Last Learning Rate')

以上为每一 epoch 的学习率曲线

2. 仅应用 MFCCs 的 Logistic 回归

特色

该模型仅应用 Mel 频率倒谱系数(MFCCs)。这个特色是一个大小为(20,)的 NumPy 数组。它从蕴含上述所有特色的 CSV 文件中检索。

模型

线性回归模型共有 1 个输出层、2 个暗藏层和 1 个带 ReLu 激活的输入层。

class SpokenDigitModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.l1 = nn.Linear(20, 1024)
        self.l2 = nn.Linear(1024, 512)
        self.l3 = nn.Linear(512, 64)
        self.l4 = nn.Linear(64, 10)

    def forward(self, x):
        x = F.relu(self.l1(x))
        x = F.relu(self.l2(x))
        x = F.relu(self.l3(x))
        x = self.l4(x)
        return x

    def training_step(self, batch):
        inputs, labels = batch
        outputs = self(inputs)
        loss = F.cross_entropy(outputs, labels)
        return loss

    def validation_step(self, batch):
        inputs, labels = batch
        outputs = self(inputs)
        loss = F.cross_entropy(outputs, labels)
        _, pred = torch.max(outputs, 1)
        accuracy = torch.tensor(torch.sum(pred==labels).item()/len(pred))
        return [loss.detach(), accuracy.detach()] 

训练

model = to_device(SpokenDigitModel(), device)
history = []
evaluate(model, val_dl)
{'accuracy': 0.08834186941385269, 'loss': 8.290132522583008}
history.append(fit(model, train_dl, val_dl, 128, 0.001))
r = evaluate(model, val_dl)
yp, yt = predict_dl(model, val_dl)
print("Loss:", r['loss'], "\nAccuracy:", r['accuracy'], "\nF-score:", f1_score(yt, yp, average='micro'))
Loss:  0.29120033979415894 
Accuracy:  0.9556179642677307 
F-score:  0.9556213017751479

该模型在 CPU 上训练约 10 分钟,准确率为 95.56%。

mfcc 是基于 Mel 尺度的,在 Mel 尺度中,频率是依据人的听觉反馈而不是线性尺度来分组的。人耳是一个通过考验的语音识别系统,因而 Mel 尺度给出了很好的后果。

另一方面,mfcc 容易受到背景噪声的影响,因而在解决洁净的语音数据(无噪声或最小噪声)时成果最好。

plot(losses, 'Losses')

以上是验证集损失曲线

plot(accuracies, 'Accuracy')

以上是验证集准确率曲线

plot(last_lr, 'Last Learning Rate')

以上是每个 epoch 最初学习率的曲线

3. 应用 Mel 谱图图像的 CNN。

特色

该模型应用了 Mel 谱图。Mel 谱图是将频率转换为 Mel 标度的谱图。这些特色从录音中提取并存储在驱动器中。这花了 4.5 个多小时。

def extract_mel(f, label):
    
    data, sr = librosa.load('/content/data/'+label+'/'+f)
    
    fig = plt.figure(figsize=[1,1])
    ax = fig.add_subplot(111)
    ax.axes.get_xaxis().set_visible(False)
    ax.axes.get_yaxis().set_visible(False)
    ax.set_frame_on(False)
    
    S = librosa.feature.melspectrogram(y=data, sr=sr)
    librosa.display.specshow(librosa.power_to_db(S, ref=np.max), x_axis='time', y_axis='mel', fmin=50, fmax=280)
    file  = '/content/drive/My Drive/Dataset/spokendigit/'+label+'/' + str(f[:-4]) + '.jpg'
    plt.savefig(file, dpi=500, bbox_inches='tight',pad_inches=0)
    
    plt.close()

模型

class SpokenDigitModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.network = nn.Sequential(nn.Conv2d(3, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),

            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),

            nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.AdaptiveAvgPool2d(1),

            nn.Flatten(), 
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Linear(64, 10),
            nn.Sigmoid())

    def forward(self, x):
        return self.network(x)

    def training_step(self, batch):
        inputs, labels = batch
        outputs = self(inputs)
        loss = F.cross_entropy(outputs, labels)
        return loss

    def validation_step(self, batch):
        inputs, labels = batch
        outputs = self(inputs)
        loss = F.cross_entropy(outputs, labels)
        _, pred = torch.max(outputs, 1)
        accuracy = torch.tensor(torch.sum(pred==labels).item()/len(pred))
        return [loss.detach(), accuracy.detach()] 

训练

model = to_device(SpokenDigitModel(), device)
history = []
evaluate(model, val_dl)
{'accuracy': 0.09851787239313126, 'loss': 2.3029427528381348}
history.append(fit(model, train_dl, val_dl, 128, 0.001))
r = evaluate(model, val_dl)
yp, yt = predict_dl(model, val_dl)
print("Loss:", r['loss'], "\nAccuracy:", r['accuracy'], "\nF-score:", f1_score(yt, yp, average='micro'))
Loss:  1.492598056793213 
Accuracy:  0.9581243991851807 
F-score:  0.9573119188503804

该模型在 Colab GPU 上训练约 5 小时,准确率为 95.81%。

高准确率能够再次归因于 Mel 标度。

plot(losses, 'Losses')

以上是验证集损失曲线

plot(accuracies, 'Accuracy')

以上是验证集准确度曲线

plot(last_lr, 'Last Learning Rate')

以上是每个 epoch 最初学习率的曲线

参考

  • https://musicinformationretri…
  • https://github.com/jurgenarias/Portfolio/tree/master/Voice%20Classification/Code
  • https://arxiv.org/abs/1506.01186
  • https://en.wikipedia.org/wiki…

原文链接:https://towardsdatascience.co…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

正文完
 0