Skip to content

Instantly share code, notes, and snippets.

@astellon
Created May 8, 2022 14:46
Show Gist options
  • Save astellon/c9d268bff17da7317cd3024c11b68c40 to your computer and use it in GitHub Desktop.
Save astellon/c9d268bff17da7317cd3024c11b68c40 to your computer and use it in GitHub Desktop.

LibriSpeechのWebDataset化

まとめ

  • Librispeechという約60GBぐらいの音声データセットを
  • webdatasetという形式に変換して
  • Disk I/Oを効率化する

アバウトな測定結果

consumer disk location not sharding sharding
Local Local (SSD) 10:00 5:30
Google Compute Engine Google Cloud Storage x 9:30

モチベーション

  • 深層学習では大規模なデータセットを扱う(100G-1Tオーダー)
  • テーブルデータとは異なり、マルチメディアデータはサンプルごとにファイル化されている
  • ディスクIOは遅い(latency/bandwidth)
  • ランダムアクセスは特に遅い(SSDだとマシ)
  • ネットワーク越しにファイルシステムがあると最悪

そこで、

  • 並列で読み込む
  • ファイルの局所化

で対処する。

WebDataset

WebDatasetはデータセットをtarファイルにまとめることでデータを局所化し、効率的にアクセスするためのミドルウェアを提供している、フォーマット兼ライブラリのようなもの。複数のtarファイルに分割することも可能で、主にネットワーク越しに並列でアクセスするような場合に有利である。

LibriSpeechのWebDataset化

LibriSpeechのデータセットクラスを使って書き込む。このとき書き込むのはメタデータと音声ファイル(.flac)のバイト列。一度読み込んで無圧縮にすると倍近くファイルが大きくなってしまい、IOの面でも不利(要検証)。

dataset = LibriSpeech(os.path.join(root, folder_in_archive), split)
sampler = torch.utils.data.RandomSampler(dataset)

dst = os.path.join(root, 'webdataset', 'shards', f'librespeech-{split}-%06d.tar')

with webdataset.ShardWriter(dst, maxsize=maxsize, maxcount=maxcount) as sink:
    for i in sampler:
    # dont need raw waveform
        fn, text, spk, chap, utter = dataset[i]

        with open(fn, 'rb') as f:
            data = f.read()

        sample = {
            "__key__": f'{basename(fn)}',
            "waveform.flac": data,
            "text.txt": text,
            "speaker.id": spk,
        }

        sink.write(sample)

WebDatasetの読み込み

WebDatasetでは標準で音声ファイルのデコードが上手くできない[^1]ので自分で用意する。pysoundfileを使ってメモリ上のflacフォーマットバイト列をデコード。

def flac_handler_soundfile(b):
    return torch.from_numpy(soundfile.read(io.BytesIO(b))[0])
    
url = "data/materials/webdataset/shards/librespeech-train-{000000..000058}.tar"
dataset = webdataset.WebDataset(url, shardshuffle=True) \
    .shuffle(1000) \
    .decode(webdataset.handle_extension("flac", flac_handler_soundfile)) \
    .to_tuple("waveform.flac", "speaker.id") \
    .map(transform) \
    .batched(16)

dataloader = torch.utils.data.DataLoader(dataset, num_workers=4, batch_size=None)

今後の目標

FFSVCに出たいので、環境構築・コード基盤構築を頑張る。

  • GCP上で学習
  • 任意長音声の評価
  • データ拡張パイプライン
  • Unsupervised Learning

[^1] : webdatasetでもtorchaudioを介してファイルを読むことは可能である。一方でtorchaudio.loadの引数がfile objectであるため、webdatasetでは一度/tmpに書き込んでからそれを読み込んでいる。今回はメモリ上のflacフォーマットバイト列を読むためにわざわざsoundfileを使ったが速度差があるのかは要検証。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment