【项目实战】AUTOVC 代码解析 —— make_metadata.py

AUTOVC 代码解析 —— make_metadata.py

  简介

       本项目一个基于 AUTOVC 模型的语音转换项目,它是使用 PyTorch 实现的(项目地址)。
       
        AUTOVC 遵循自动编码器框架,只对自动编码器损耗进行训练,但它引入了精心调整的降维和时间下采样来约束信息流,这个简单的方案带来了显著的性能提高。(详情请参阅 AUTOVC 的详细介绍)。
       
       由于 AUTOVC 项目较大,代码较多。为了方便学习与整理,将按照工程文件的结构依次介绍。
       
       本文将介绍项目中的 make_metadata.py 文件:为训练生成说话人嵌入和元数据。
       

  函数解析

      main

          该函数的作用是: 为训练生成说话人嵌入和元数据

          输入参数:

          输出参数:

          代码详解:

		
		# 调用 model_bl 中的 D_VECTOR 创建说话人嵌入网络模型,输入数据大小为 80 ,LSTM 隐藏单元数为 768 , 输出数据大小为 256 ;
		# 使用 model.eval 方法,将模块设置为评估模式。该设置仅对模型中某些模块有影响,例如 Dropout , BatchNorm 等;
		# 使用 model.cuda 方法,移动所有的模型参数并缓存到 GPU ;
		# 需注意:这也会生成相关的参数并缓冲不同的对象。因此,如果模块将在GPU上运行,那么它应该在构建优化器之前被调用。
		C = D_VECTOR(dim_input=80, dim_cell=768, dim_emb=256).eval().cuda()
		# 加载预训练的说话人编码器模型
		c_checkpoint = torch.load('3000000-BL.ckpt')
		# 创建一个有序字典
		new_state_dict = OrderedDict()
		# 遍历加载的预训练说话人编码模型对应部分
		for key, val in c_checkpoint['model_b'].items():
		    # 截取 key 值,使命名一致
		    new_key = key[7:]
		    # 添加训练好的 Tensor 至有序字典中
		    new_state_dict[new_key] = val
		
		# 将顺序字典中的 Tensor 加载到上文创建的说话人编码模型中
		C.load_state_dict(new_state_dict)
		
		# 为语句数量赋值 10
		num_uttrs = 10
		# 为修建长度赋值 128
		len_crop = 128
		
		# 提供含有梅尔谱图的文件目录
		rootDir = './spmel'
		# 获取含有梅尔谱图文件目录的子目录列表
		dirName, subdirList, _ = next(os.walk(rootDir))
		# 打印含有梅尔谱图文件目录名
		print('Found directory: %s' % dirName)
		
		
		# 创建说话人列表
		speakers = []
		# 遍历含有梅尔谱图文件目录的子目录列表
		for speaker in sorted(subdirList):
		    # 打印当前说话人
		    print('Processing speaker: %s' % speaker)
		    # 创建说话列表
		    utterances = []
		    # 将当前说话人插入说话列表
		    utterances.append(speaker)
		    # 查找当前说话人目录下的所有文件名
		    _, _, fileList = next(os.walk(os.path.join(dirName,speaker)))
		    
		    # 构建说话人嵌入
		    # 当存在的语句数量少于设定的语句数量时警告
		    assert len(fileList) >= num_uttrs
		    # 打乱顺序:从 [0, 10) 中随机抽取 10 个数字组成数组,要求数字不能重复
		    idx_uttrs = np.random.choice(len(fileList), size=num_uttrs, replace=False)
		    
		    embs = []
		    # 循环次数为设定的语句数量
		    for i in range(num_uttrs):
		        # 按上文生成的随机顺序加载该说话人的语句(梅尔谱图数据)
		        tmp = np.load(os.path.join(dirName, speaker, fileList[idx_uttrs[i]]))
		        # 源代码有问题,确少维度参数,会报错
		        # 这里是将选择的语句编号删除,留下未选择的语句编号
		        # candidates = np.delete(np.arange(len(fileList)), idx_uttrs)
		        candidates = np.delete(np.arange(len(fileList)), idx_uttrs[i], None)
		        # 如果当前的语句太短,选择另一个语句
		        while tmp.shape[0] < len_crop:
		            # 从剩下的语句编号中随机抽取一个
		            idx_alt = np.random.choice(candidates)
		            # 将选择的语句加载,覆盖 tmp
		            tmp = np.load(os.path.join(dirName, speaker, fileList[idx_alt]))
		            # 源代码有误,缺少维度参数,处理方式与上文一致
		            # 将选择的语句编号从剩余语句编号数组中删除
		            # candidates = np.delete(candidates, np.argwhere(candidates==idx_alt))
		            candidates = np.delete(candidates, np.argwhere(candidates == idx_alt), None)
		        
		        # 取左边界,建议第二个参数写成 high=tmp.shape[0]-len_crop
		        left = np.random.randint(0, tmp.shape[0]-len_crop)
		        # 新增一个维度(据说是要求以批量的形式输入),从左边界截取设定的修建长度,保留其他维度全部数据
		        # 使用上述截取出的 numpy 数组创建 Tensor,并将参数移至 GPU
		        melsp = torch.from_numpy(tmp[np.newaxis, left:left+len_crop, :]).cuda()
		        # 将得到的 Tensor 作为输入,使用先前创建的说话人嵌入模型计算说话人编码
		        emb = C(melsp)
		        # 将计算的说话人编码从当前计算图分离,并压缩掉维数为 1 的维度
		        # 接着将 GPU Tensor 转换为 CPU Tensor ,再转换为 numpy 数组
		        # 最后,将得到的说话人编码添加进说话人编码列表
		        embs.append(emb.detach().squeeze().cpu().numpy())     
		    
		    # 将说话人编码列表中的说话人编码取平均值,得到该说话人的平均说话人编码,并添加进说话列表中
		    utterances.append(np.mean(embs, axis=0))
		    
		    # 创建文件列表
		    # 按顺序遍历该说话人语句文件(梅尔频谱数据)
		    for fileName in sorted(fileList):
		        # 将该说话人的语句文件名添加进说话列表中
		        utterances.append(os.path.join(speaker,fileName))
		    
		    # 在说话人列表中添加该说话人的说话列表(说话信息:人名,说话人编码,说话文件) 
		    speakers.append(utterances)
		    
		# 创建训练文件,以二进制打开文件,并写入
		with open(os.path.join(rootDir, 'train.pkl'), 'wb') as handle:
		    # Python中的Pickle模块实现了基本的数据序列与反序列化
		    # dump()方法能序列化对象,将对象保存到文件中去
		    pickle.dump(speakers, handle)


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值