pytorch加载语音类自定义数据集的方法教程


Posted in Python onNovember 10, 2020

前言

pytorch对一下常用的公开数据集有很方便的API接口,但是当我们需要使用自己的数据集训练神经网络时,就需要自定义数据集,在pytorch中,提供了一些类,方便我们定义自己的数据集合

  • torch.utils.data.Dataset:所有继承他的子类都应该重写  __len()__  , __getitem()__ 这两个方法
    •  __len()__ :返回数据集中数据的数量
    •   __getitem()__ :返回支持下标索引方式获取的一个数据
  • torch.utils.data.DataLoader:对数据集进行包装,可以设置batch_size、是否shuffle....

第一步

自定义的 Dataset 都需要继承 torch.utils.data.Dataset 类,并且重写它的两个成员方法:

  • __len()__:读取数据,返回数据和标签
  • __getitem()__:返回数据集的长度
from torch.utils.data import Dataset


class AudioDataset(Dataset):
 def __init__(self, ...):
 """类的初始化"""
 pass

 def __getitem__(self, item):
 """每次怎么读数据,返回数据和标签"""
 return data, label

 def __len__(self):
 """返回整个数据集的长度"""
 return total

注意事项:Dataset只负责数据的抽象,一次调用getiitem只返回一个样本

案例:

文件目录结构

  • p225
    • ***.wav
    • ***.wav
    • ***.wav
    • ...
  • dataset.py

目的:读取p225文件夹中的音频数据

class AudioDataset(Dataset):
 def __init__(self, data_folder, sr=16000, dimension=8192):
 self.data_folder = data_folder
 self.sr = sr
 self.dim = dimension

 # 获取音频名列表
 self.wav_list = []
 for root, dirnames, filenames in os.walk(data_folder):
 for filename in fnmatch.filter(filenames, "*.wav"): # 实现列表特殊字符的过滤或筛选,返回符合匹配“.wav”字符列表
 self.wav_list.append(os.path.join(root, filename))

 def __getitem__(self, item):
 # 读取一个音频文件,返回每个音频数据
 filename = self.wav_list[item]
 wb_wav, _ = librosa.load(filename, sr=self.sr)

 # 取 帧
 if len(wb_wav) >= self.dim:
 max_audio_start = len(wb_wav) - self.dim
 audio_start = np.random.randint(0, max_audio_start)
 wb_wav = wb_wav[audio_start: audio_start + self.dim]
 else:
 wb_wav = np.pad(wb_wav, (0, self.dim - len(wb_wav)), "constant")

 return wb_wav, filename

 def __len__(self):
 # 音频文件的总数
 return len(self.wav_list)

注意事项:19-24行:每个音频的长度不一样,如果直接读取数据返回出来的话,会造成维度不匹配而报错,因此只能每次取一个音频文件读取一帧,这样显然并没有用到所有的语音数据,

第二步

实例化 Dataset 对象

Dataset= AudioDataset("./p225", sr=16000)

如果要通过batch读取数据的可直接跳到第三步,如果你想一个一个读取数据的可以看我接下来的操作

# 实例化AudioDataset对象
train_set = AudioDataset("./p225", sr=16000)

for i, data in enumerate(train_set):
 wb_wav, filname = data
 print(i, wb_wav.shape, filname)

 if i == 3:
 break
 # 0 (8192,) ./p225\p225_001.wav
 # 1 (8192,) ./p225\p225_002.wav
 # 2 (8192,) ./p225\p225_003.wav
 # 3 (8192,) ./p225\p225_004.wav

第三步

如果想要通过batch读取数据,需要使用DataLoader进行包装

为何要使用DataLoader?

  • 深度学习的输入是mini_batch形式
  • 样本加载时候可能需要随机打乱顺序,shuffle操作
  • 样本加载需要采用多线程

pytorch提供的 DataLoader 封装了上述的功能,这样使用起来更方便。

DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, num_workers=0, collate_fn=default_collate, pin_memory=False, drop_last=False)

参数:

  • dataset:加载的数据集(Dataset对象)
  • batch_size:每个批次要加载多少个样本(默认值:1)
  • shuffle:每个epoch是否将数据打乱
  • sampler:定义从数据集中抽取样本的策略。如果指定,则不能指定洗牌。
  • batch_sampler:类似于sampler,但每次返回一批索引。与batch_size、shuffle、sampler和drop_last相互排斥。
  • num_workers:使用多进程加载的进程数,0代表不使用多线程
  • collate_fn:如何将多个样本数据拼接成一个batch,一般使用默认拼接方式
  • pin_memory:是否将数据保存在pin memory区,pin memory中的数据转到GPU会快一些
  • drop_last:dataset中的数据个数可能不是batch_size的整数倍,drop_last为True会将多出来不足一个batch的数据丢弃

返回:数据加载器

案例:

# 实例化AudioDataset对象
train_set = AudioDataset("./p225", sr=16000)
train_loader = DataLoader(train_set, batch_size=8, shuffle=True)

for (i, data) in enumerate(train_loader):
 wav_data, wav_name = data
 print(wav_data.shape) # torch.Size([8, 8192])
 print(i, wav_name)
 # ('./p225\\p225_293.wav', './p225\\p225_156.wav', './p225\\p225_277.wav', './p225\\p225_210.wav',
 # './p225\\p225_126.wav', './p225\\p225_021.wav', './p225\\p225_257.wav', './p225\\p225_192.wav')

我们来吃几个栗子消化一下:

栗子1

这个例子就是本文一直举例的,栗子1只是合并了一下而已

文件目录结构

  • p225
    • ***.wav
    • ***.wav
    • ***.wav
    • ...
  • dataset.py

目的:读取p225文件夹中的音频数据

import fnmatch
import os
import librosa
import numpy as np
from torch.utils.data import Dataset
from torch.utils.data import DataLoader


class Aduio_DataLoader(Dataset):
 def __init__(self, data_folder, sr=16000, dimension=8192):
 self.data_folder = data_folder
 self.sr = sr
 self.dim = dimension

 # 获取音频名列表
 self.wav_list = []
 for root, dirnames, filenames in os.walk(data_folder):
  for filename in fnmatch.filter(filenames, "*.wav"): # 实现列表特殊字符的过滤或筛选,返回符合匹配“.wav”字符列表
  self.wav_list.append(os.path.join(root, filename))

 def __getitem__(self, item):
 # 读取一个音频文件,返回每个音频数据
 filename = self.wav_list[item]
 print(filename)
 wb_wav, _ = librosa.load(filename, sr=self.sr)

 # 取 帧
 if len(wb_wav) >= self.dim:
  max_audio_start = len(wb_wav) - self.dim
  audio_start = np.random.randint(0, max_audio_start)
  wb_wav = wb_wav[audio_start: audio_start + self.dim]
 else:
  wb_wav = np.pad(wb_wav, (0, self.dim - len(wb_wav)), "constant")

 return wb_wav, filename

 def __len__(self):
 # 音频文件的总数
 return len(self.wav_list)


train_set = Aduio_DataLoader("./p225", sr=16000)
train_loader = DataLoader(train_set, batch_size=8, shuffle=True)


for (i, data) in enumerate(train_loader):
 wav_data, wav_name = data
 print(wav_data.shape) # torch.Size([8, 8192])
 print(i, wav_name)
 # ('./p225\\p225_293.wav', './p225\\p225_156.wav', './p225\\p225_277.wav', './p225\\p225_210.wav',
 # './p225\\p225_126.wav', './p225\\p225_021.wav', './p225\\p225_257.wav', './p225\\p225_192.wav')

注意事项:

  1. 27-33行:每个音频的长度不一样,如果直接读取数据返回出来的话,会造成维度不匹配而报错,因此只能每次取一个音频文件读取一帧,这样显然并没有用到所有的语音数据,
  2. 48行:我们在__getitem__中并没有将numpy数组转换为tensor格式,可是第48行显示数据是tensor格式的。这里需要引起注意

栗子2

相比于案例1,案例二才是重点,因为我们不可能每次只从一音频文件中读取一帧,然后读取另一个音频文件,通常情况下,一段音频有很多帧,我们需要的是按顺序的读取一个batch_size的音频帧,先读取第一个音频文件,如果满足一个batch,则不用读取第二个batch,如果不足一个batch则读取第二个音频文件,来补充。

我给出一个建议,先按顺序读取每个音频文件,以窗长8192、帧移4096对语音进行分帧,然后拼接。得到(帧数,帧长,1)(frame_num, frame_len, 1)的数组保存到h5中。然后用上面讲到的 torch.utils.data.Dataset 和 torch.utils.data.DataLoader 读取数据。

具体实现代码:

第一步:创建一个H5_generation脚本用来将数据转换为h5格式文件:

第二步:通过Dataset从h5格式文件中读取数据

import numpy as np
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
import h5py

def load_h5(h5_path):
 # load training data
 with h5py.File(h5_path, 'r') as hf:
 print('List of arrays in input file:', hf.keys())
 X = np.array(hf.get('data'), dtype=np.float32)
 Y = np.array(hf.get('label'), dtype=np.float32)
 return X, Y


class AudioDataset(Dataset):
 """数据加载器"""
 def __init__(self, data_folder):
 self.data_folder = data_folder
 self.X, self.Y = load_h5(data_folder) # (3392, 8192, 1)

 def __getitem__(self, item):
 # 返回一个音频数据
 X = self.X[item]
 Y = self.Y[item]

 return X, Y

 def __len__(self):
 return len(self.X)


train_set = AudioDataset("./speaker225_resample_train.h5")
train_loader = DataLoader(train_set, batch_size=64, shuffle=True, drop_last=True)


for (i, wav_data) in enumerate(train_loader):
 X, Y = wav_data
 print(i, X.shape)
 # 0 torch.Size([64, 8192, 1])
 # 1 torch.Size([64, 8192, 1])
 # ...

我尝试在__init__中生成h5文件,但是会导致内存爆炸,就很奇怪,因此我只好分开了,

参考

总结

到此这篇关于pytorch加载语音类自定义数据集的文章就介绍到这了,更多相关pytorch加载语音类自定义数据集内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python使用in操作符时元组和数组的区别分析
May 19 Python
Django使用HttpResponse返回图片并显示的方法
May 22 Python
学生信息管理系统python版
Oct 17 Python
使用python Fabric动态修改远程机器hosts的方法
Oct 26 Python
自适应线性神经网络Adaline的python实现详解
Sep 30 Python
使用apiDoc实现python接口文档编写
Nov 19 Python
python pygame实现滚动横版射击游戏城市之战
Nov 25 Python
Python cookie的保存与读取、SSL讲解
Feb 17 Python
基于PyTorch的permute和reshape/view的区别介绍
Jun 18 Python
Python logging日志库空间不足问题解决
Sep 14 Python
python把一个字符串切开的实例方法
Sep 27 Python
pandas求平均数和中位数的方法实例
Aug 04 Python
sublime3之内网安装python插件Anaconda的流程
Nov 10 #Python
python+excel接口自动化获取token并作为请求参数进行传参操作
Nov 10 #Python
python request 模块详细介绍
Nov 10 #Python
解决使用Pandas 读取超过65536行的Excel文件问题
Nov 10 #Python
python各种excel写入方式的速度对比
Nov 10 #Python
Python 使用xlwt模块将多行多列数据循环写入excel文档的操作
Nov 10 #Python
详解vscode实现远程linux服务器上Python开发
Nov 10 #Python
You might like
destoon安全设置中需要设置可写权限的目录及文件
2014/06/21 PHP
codeigniter中实现一次性加载多个view的方法
2015/03/20 PHP
在CentOS上搭建LAMP+vsftpd环境的简单指南
2015/08/01 PHP
PHP学习记录之数组函数
2018/06/01 PHP
Yii2框架配置文件(Application属性)与调试技巧实例分析
2019/05/27 PHP
突发奇想的一个jquery插件
2010/11/19 Javascript
关于jQuery中的end()使用方法
2011/07/10 Javascript
javascript函数以及基础写法100多条实用整理
2013/01/13 Javascript
jquery 实现密码框的显示与隐藏示例代码
2013/09/18 Javascript
JS实现局部选择打印和局部不选择打印
2014/04/03 Javascript
js单独获取一个checkbox看其是否被选中
2014/09/22 Javascript
浅谈JavaScript 执行环境、作用域及垃圾回收
2016/05/31 Javascript
JavaScript中闭包之浅析解读(必看篇)
2016/08/25 Javascript
自己封装的一个简单的倒计时功能实例
2016/11/23 Javascript
JavaScript Ajax实现异步通信
2016/12/14 Javascript
令按钮悬浮在(手机)页面底部的实现方法
2017/05/02 Javascript
vue 利用路由守卫判断是否登录的方法
2018/09/29 Javascript
vue组件中的样式属性scoped实例详解
2018/10/30 Javascript
Vue2(三)实现子菜单展开收缩,带动画效果实现方法
2019/04/28 Javascript
layui-table获得当前行的上/下一行数据的例子
2019/09/24 Javascript
[00:32]DOTA2上海特级锦标赛 COL战队宣传片
2016/03/04 DOTA
python转换摩斯密码示例
2014/02/16 Python
全面解析Python的While循环语句的使用方法
2015/10/13 Python
Python实现KNN邻近算法
2021/01/28 Python
Python实现改变与矩形橡胶的线条的颜色代码示例
2018/01/05 Python
利用python将图片版PDF转文字版PDF
2019/05/03 Python
pandas中遍历dataframe的每一个元素的实现
2019/10/23 Python
印尼第一大家居、生活和家具电子商务:Ruparupa
2019/11/25 全球购物
网页设计个人找工作求职信
2013/11/28 职场文书
实习生个人的自我评价
2013/12/08 职场文书
车间副主任岗位职责
2013/12/24 职场文书
《乌塔》教学反思
2014/02/17 职场文书
公司司机岗位职责范本
2014/03/03 职场文书
2015年质量管理工作总结范文
2015/05/18 职场文书
食品卫生管理制度
2015/08/06 职场文书
Django一小时写出账号密码管理系统
2021/04/29 Python