您好,登錄后才能下訂單哦!
pytorch如何實現加載語音類的數據集?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
pytorch對一下常用的公開數據集有很方便的API接口,但是當我們需要使用自己的數據集訓練神經網絡時,就需要自定義數據集,在pytorch中,提供了一些類,方便我們定義自己的數據集合
第一步
自定義的 Dataset 都需要繼承 torch.utils.data.Dataset 類,并且重寫它的兩個成員方法:
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文件夾中的音頻數據
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?
pytorch提供的 DataLoader 封裝了上述的功能,這樣使用起來更方便。
DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, num_workers=0, collate_fn=default_collate, pin_memory=False, drop_last=False)
參數:
返回:數據加載器
案例:
# 實例化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文件夾中的音頻數據
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')
注意事項:
栗子2
相比于案例1,案例二才是重點,因為我們不可能每次只從一音頻文件中讀取一幀,然后讀取另一個音頻文件,通常情況下,一段音頻有很多幀,我們需要的是按順序的讀取一個batch_size的音頻幀,先讀取第一個音頻文件,如果滿足一個batch,則不用讀取第二個batch,如果不足一個batch則讀取第二個音頻文件,來補充。
我給出一個建議,先按順序讀取每個音頻文件,以窗長8192、幀移4096對語音進行分幀,然后拼接。得到(幀數,幀長,1)(frame_num, frame_len, 1)的數組保存到h6中。然后用上面講到的 torch.utils.data.Dataset 和 torch.utils.data.DataLoader 讀取數據。
具體實現代碼:
第一步:創建一個H5_generation腳本用來將數據轉換為h6格式文件:
第二步:通過Dataset從h6格式文件中讀取數據
import numpy as np from torch.utils.data import Dataset from torch.utils.data import DataLoader import h6py def load_h6(h6_path): # load training data with h6py.File(h6_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_h6(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.h6") 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]) # ...
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。