たれぱんのびぼーろく

わたしの備忘録、生物学とプログラミングが多いかも

データのセットアップ・ロード in Python for 機械学習・ニューラルネットワーク

機械学習ニューラルネットワークにおいて、データを用意・ロードすることは簡単そうに見えて難しい。

  • corpusのダウンロード・展開
  • データの前処理・保存
  • データセット(processed corpusの部分集合)のセットアップ
  • datumのロード
  • アクセス順・バッチ化
  • 分散dataset

考えることいっぱい。
fileSystemからデータをメモリ上に展開 (ロード) しまくるとメモリ弾けるし、毎回のんびり前処理かけてたら日が暮れる。
並行して学習をする際に適切にデータを配分する必要もある。

コーパス ~ バッチの定義

コーパスを前処理してデータセットとし、データセットを変換してバッチテンソルとする.

        Preprocess           Transform
Corpus -----------> Dataset -----------> Batch

Corpus :: [any] = {i0, i1, ...}
Preprocess :: (i ∈ C' ⊂ Corpus) -> (x: any)
Dataset :: [any] = {Preprocess(i) | i ∈ C' ⊂ Corpus}
Transform :: (x ∈ Dataset) -> (x' :: T)
Batch :: [T] = {Transform(x) | x ∈ D' ⊂ Dataset}

分割の意義

(配布される)データ源としてのCorpus.
データを様々な特徴量へ事前変換 (preprocessing) したDataset.
Transformによる逐次変換とデータ型統一(テンソル化)、ここから得られるBatch.

変換: 事前 (preprocess) / 逐次 (transform)

逐次変換で都度異なるデータを生成可能 (例: clipping)
事前変換で生成したデータの型が異なっていても、逐次変換でテンソル化が可能 (T=100とT=120のデータを、length=40のランダム区間に逐次clip).

PyTorch

  • DataSet: datumの取り出しが可能なオブジェクト
  • DataLoader: Datasetから様々な設定でデータを取り出すようにできるiterable

Dataset

Datasetをベースクラスとする薄いデータwrapper。

のいずれかでデータ集合を表現する。
Datasetは抽象クラスになっており、実装者がデータセットごとに読み込み等を実装する。
Utilityとしてデータセットの結合(ConcatDataset for dataset / ChainDataset for iterSet)と分割(Subset / random_split)が提供されている。

corpusのダウンロードや前処理(preprocessing, データセット化と私は呼んでいる)をdatasetのinitに書くのがベストプラクティス.
new dataset()するだけでデータが手に入り、再利用性が高い.
augmentationを始めとする「feed時に逐次実行してほしい関数」はdataset内にtransformとして実装.

データロードのタイミングは実装次第。
__init__でon-memoryに置いて高速アクセスを可能にしてもいいし、__getitem__で逐次datumを読み込んでメモリ節約してもいい.

実装

torch.utils.data.Dataset
Dataset__add__ がmixed inされたMapping型
なので利用時は Dataset を継承してdatumを吐き出す __getitem__ と全長を返す __len__ を実装する。
__add__Dataset の合体を定義しており、暗示的に ConcatDataset を実行する。

DataLoader

index setの供給 (sampler) と、index setに基づくdatumのset化 (collate_fn).

samplerをいじれば同じindexを出したり、indexの出る順番にバイアス (weight random sample的な) をかけたりできる.
collate_fnをいじればバッチ化をやめたり、バッチの形を任意にいじったり、データ自体に手を入れたりできる.

デフォルトではshuffleフラグに基づいたランダムサンプル、データTensor化&バッチ化のcollate_fn.

デフォルトcollate_fnは自動Tensor化をしてくれるので便利だが、謎挙動に見えなくもないので頭の片隅に.

It automatically converts NumPy arrays and Python numerical values into PyTorch Tensors.