🐕

huggingface datasets に LLM 学習用の dataset(コーパス) を追加するメモ(めんどいんであまり推奨しない)

2023/10/08に公開

huggingface datasets とは?

pytorch dataloader みたいなものです.

https://huggingface.co/docs/datasets/dataset_script

中身的には git lfs です.

  • repo にはデータセットローダスクリプトだけ置いて, スクリプトで別サーバーの storage を見るようにする
  • huggingface dataset の repo 自体にデータセットを追加する
    • データサイズは unlimited!

の2つのやりかたがあります. 今回は後者をとします.

でも huggingface datasets あんまり推奨しない...

圧縮後 50 GB(展開時 150 GB) くらいでも, 内部ではダウンロードのキャッシュと, 展開ファイルのキャッシュ, その他があるため, 展開時データサイズ * 1.5 くらい必要になります.

git lfs 遅いし, upload もなんどかしないとうまくいかないしで... あんまり推奨しません...

とりあえず以下は参考までです.

データセットのファイルレイアウト

https://huggingface.co/docs/datasets/share

https://huggingface.co/docs/datasets/repository_structure#split-name-keywords

サポートされているファイル拡張子と split フォルダ名であれば, 自動でフォルダをスキャンしていい感じにしてくれるようです.
今(2023/10)だと

  • train
  • validation
  • test

でフォルダを作りそれぞれにデータセットを置くのがよいでしょう.
必要に応じて README.md のメタデータで明示的にファイルパスを指定することもできます.

https://discuss.huggingface.co/t/how-to-split-main-dataset-into-train-dev-test-as-datasetdict/1090/6

のようにデータセットロード時に分ける手もあります.

validation, test(holdout) の割合

LLM データセット用では, ある程度任意とは思われます. あんまり多くても非効率かも?(e.g. train の 10% とか)

https://github.com/Cerebras/modelzoo/blob/97bdaf4460ace1681ad437b07ba33f0e179f5ca4/modelzoo/transformers/data_processing/slimpajama/preprocessing/shuffle_holdout.py#L110

SlimPajama ではそれぞれ 0.17% でした.

データセットのアップロード

git lfs でやります. ただ lfs add とかだけでもファイルが GB 単位だと数分かかったりするので(hash を求めている?)結構やりずらいです.

さらに, アップロードも不都合があります.

huggingface datasets へのアップロードメモ
https://zenn.dev/syoyo/articles/67691c8641020c

頻繁に connection 切れたりするので注意ください.

データサイズが大きいと遅い

streamling で読むにしても, メタデータをまずは読み込むようでデータセットのサイズが大きい(500 GB or more)と最初の起動時で結構数分またされます.

また, local folder を参照する場合でも一旦 ~/.huggingface のキャッシュにファイル群が作られるため, 領域が二倍以上必要になります.

iterate や配列アクセスするとハングする

大きめの dataset(50GB or more) を python 的に iterate や配列アクセスすると, 内部でコピーやら作るのか実質無限に時間がかかってハングします...

from datasets import load_dataset

dataset = load_dataset("mydata")
DatasetDict({
    train: Dataset({
        features: ['text', 'label'],
        num_rows: 85300000
    })
    validation: Dataset({
        features: ['text', 'label'],
        num_rows: 1066
    })
    test: Dataset({
        features: ['text', 'label'],
        num_rows: 1066
    })
})

ここで split ごとになんか処理したいなーと

for split in dataset:
  ...

とか,

# 最初の要素にアクセス
dataset["train"]["text"][0]

とかすると数時間かかっても処理したままになります.

split 取得は dataset.keys(), 各要素アクセスは dataset.map あたりでやるしかないようです.

マルチプロセスでロード

num_proc でいけます.

https://huggingface.co/docs/datasets/loading#multiprocessing

shard 化?

shard 化するとダウンロードが複数化できるようですが... 要検証

Discussion