200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 说话人性别识别

说话人性别识别

时间:2020-05-21 04:54:16

相关推荐

说话人性别识别

让人类来分辨说话人的性别是件十分简单的事情,对于机器来说也不是什么难事,下面介绍使用BiRNN进行说话人性别识别。

1. 性别判定特征

说道男女声音的差异很多人第一反应就是音高,这里的音高指的是基音的频率,我们采用基音周期作为判决男声女声的特征之一,如下图所示。我们可以看到女性的基音周期和男性基音周期有一定的差别。

下一个特征我们使用常用于语音信号处理的梅尔频率倒谱系数,这里我们使用13个梅尔滤波器然后将输出结果进行一阶差分得到12维动态的梅尔频率倒谱系数,因此我们的MFCC特征总共有13+12=25维, 如下图所示。

我们再添加两个特征分别为谱质心和谱对比度特征。其中谱质心描述了声音的明亮度,具有阴暗、低沉品质的声音倾向有较多低频内容,谱质心相对较低,具有明亮、欢快品质的多数集中在高频,谱质心相对较高

谱对比度将频谱的每个帧都分为子带。对于每个子带,通过将顶部分位数的平均能量(峰值能量)与底部分位数的平均能量(谷能量)进行比较来估计能量对比。高对比度值通常对应于清晰的窄带信号,而低对比度值则对应于宽带噪声。

这样我们就有了用于判定说话人性别的特征集{基音周期, MFCC, 谱质心,谱对比度}一共32维。

2. 模型训练

在这个任务中静音帧部分的特征是没有意义的,因此我们需要对数据进行预处理删除样本中的静音部分。但是这会带来一个问题——数据集中的每个样本长度不一样。为了解决这个问题,我们需要使用Pytorch中的pad_sequence, pack_padded_sequence, pad_packed_sequence,下面简单介绍一下它们的用法。在Dataloader中有一个collate_fn的属性,默认的collate_fn函数是要求一个batch中的样本都具有相同size,但是我们的样本长度不一样,这里我们就需要自定义一个函数传给collate_fn。

def pad_collate(batch):x, y, lens = zip(*batch)x_pad = pad_sequence(x, batch_first=True, padding_value=0)return x_pad, torch.tensor(y, dtype=torch.float32), torch.tensor(lens)

这样每个batch的输出大小都是一样的,这里注意我们的每个batch包含三个内容,第一是用于检测性别的特征,第二是每个样本对应的标签,第三是每个样本的长度,以上就解决了数据加载过程中样本长度不一致的问题。

在模型前向传播的过程中,我们需要将样本特征和每个样本的长度使用pack_padded_sequence进行“打包”成batch,然后将神经网络的输出使用pad_packed_sequence进行“解包”得出真正的输出。因此我们的网络定义如下,使用了双向LSTM。这里我们就解决了BP过程中样本长度不一致的问题。

class GCNet(nn.Module):def __init__(self, in_dim=32, hidden_dim=64, n_layer=2, n_class=1):super(GCNet, self).__init__()self.n_layer = n_layerself.hidden_dim = hidden_dimself.lstm = nn.LSTM(in_dim, hidden_dim, n_layer, batch_first=True, bidirectional=True)self.classifier = nn.Linear(2 * hidden_dim, n_class)def forward(self, x, lens):lens = torch.as_tensor(lens, dtype=torch.int64)x = pack_padded_sequence(x, lens, batch_first=True,enforce_sorted=False)out, _ = self.lstm(x)out, lens = pad_packed_sequence(out, batch_first=True)out = out[:, -1, :]out = self.classifier(out)out = F.torch.sigmoid(out)return out

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。