Tensorflowデータセットでトレーニング、テスト、検証セットを分割する – tfds

Tensorflow Datasets (通称 tfds) は、幅広い種類のデータセットへのラッパーとして機能するライブラリで、主に Tensorflow を用いた機械学習や深層学習のためにデータセットをロード、分割、準備する独自の関数を備えています。

注:Tensorflow Datasetsライブラリは、データの取得には使用されますが、データの前処理には使用されません。

その作業はTensorflow Data (tf.data) ライブラリに委ねられる。

Tensorflow Datasetsで取得したデータセットはすべて tf.data.Dataset オブジェクトにラップされているので、プログラムによって様々なデータセットを簡単に取得し、準備することができます! データセットをロードして知り合った後に行う最初のステップの1つが、train/test/validationの分割です。

このガイドでは、Tensorflow Datasetsをロードしてtrain/test/validation splitを実行する方法を学ぶ前に、トレーニング、テスト、検証セットとは何かを見ていきます。

トレーニングセットとテストセット

教師あり学習では、特徴量とその特徴量のラベルを別々のものとして、あるいは1つの Dataset として取得する必要があります。

すべてのデータに対してネットワークを学習させるのはいいのですが、同じデータに対してその精度をテストすることはできません。

なぜなら、そのようにモデルを評価すると、汎化ではなく、暗記に報酬を与えることになってしまうからです。

その代わりに、データの一部でモデルを学習させ、学習が終わったらその一部をテスト用に保留しておく。

この2つの比率は80/20が一般的で、これはかなり理にかなったデフォルトです。

データセットの大きさによっては、60/40や90/10など、異なる比率を選択することもできます。

テストセット内に多くのサンプルがある場合、それ専用のサンプルを大きな割合で用意する必要はない。

例えば、データセットの1%が1.000.000サンプルに相当する場合、テストにはそれ以上必要ないでしょう。

モデルやアーキテクチャによっては、テストセットが全く必要ないものもあります。

例えば、画像を生成するGenerative Adversarial Networks (GANs)を学習する場合、モデルのテストは実際のラベルと予測されたラベルを比較するほど簡単ではありません! 多くの生成モデル(音楽、テキスト、ビデオ)では、少なくとも現状では、人間が出力を判断する必要があり、その場合、テストセットは完全に冗長です。

テストセットは、テスト段階までモデルから切り離されるべきで、学習ではなく、推論にのみ使用されるべきです。

テストセットを定義して、モデルの精度を検証する最終段階まで「忘れてしまう」のが一般的なやり方です。

ということです。

バリデーションセット

検証セットは非常に重要であり、時には見落とされることもあるセットです。

検証セットは、イメージしやすいように、テストセットから「取り出した」ものと説明されることが多いが、実際には、別々のセットである。

分割比率に決まったルールはありませんが、テストセットと同じサイズか、少し小さめの検証セットを持つのが一般的で、75/15/10、70/15/15、70/20/10のような感じです。

検証セットは学習時に使用され、各エポックにおいてモデルをおおよそ検証します。

これは、モデルがうまく機能しているかどうかの「ヒント」を与えることで、モデルを更新するのに役立ちます。

さらに、モデルの実際のパフォーマンスをより正確に垣間見るために、エポックセット全体が終了するのを待つ必要がありません。

注:検証セットはトレーニングには使用されず、モデルはどの時点でも検証セットでトレーニングするわけではありません。

あるエポックでの性能を検証するために使用されます。

学習プロセスに影響を与えるので、モデルは間接的に検証集合で学習します。

したがって、テストでは完全に信頼することはできませんが、学習中に信念を更新するための良い近似/代用品となります。

これは、間違っているときは分かるが、正しい答えが何であるかは分からないことに似ている。

最終的には、間違っていることに気づいてから信念を更新することで、それが何であるかを 明確に教えられなくても、真実に近づくことができる。

検証セットは、間接的にあなたの知識を訓練します。

検証セットを使うことで、モデルが大幅にオーバーフィットし始めたことをリアルタイムで簡単に解釈でき、検証精度と学習精度の差に基づいて、自動的に学習を停止したり、学習率を更新したりするなどの対応を取ることができるようになります。

TensorflowデータセットによるTrain、Test、Validationセットの分割

tfdsモジュールのload()` 関数は、データセット名を指定してデータセットをロードします。

もし、ローカルマシンにダウンロードされていない場合は、プログレスバーを表示しながら自動的にデータセットをダウンロードします。

import tensorflow_datasets as tfds


# Load dataset
dataset, info = tfds.load("cifar10", as_supervised=True, with_info=True)


# Extract informative features
class_names = info.features["label"].names
n_classes = info.features["label"].num_classes


print(class_names) # ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
print(n_classes) # 10


load()関数に渡すことができるオプションの引数のひとつにsplit` があります。

新しい Split API では、データセットのどの部分を分割するかを定義することができます。

デフォルトでは、このデータセットでは 'train''test' のみの分割をサポートしています。

これがこのデータセットの「公式」な分割です。

これがこのデータセットの「公式」な分割です。

valid という分割はありません。

注:各データセットには「公式」の分割がある.train」だけの分割もあれば、「train」と「test」の分割、さらには「validation」の分割もある。

これは意図した分割であり、データセットが分割をサポートしている場合にのみ、その分割の文字列エイリアスを使用することができます。

もしデータセットが ‘train’ のみを含む場合は、問題なく学習データを train/test/valid に分割することができます。

これらは tfds.Split.TRAINtfds.Split.TEST 、そして tfds.Split.VALIDATION 列挙型に対応しており、以前のバージョンでは API を通じて公開されていました。

データセットを任意の数のセットにスライスすることができますが、通常は train_settest_setvalid_set の3つのセットを使用します。

test_set, valid_set, train_set = tfds.load("cifar10", 
                                           split=["test", "train[0%:20%]", "train[20%:]"],
                                           as_supervised=True, with_info=True)


print("Train set size: ", len(train_set)) # Train set size:  40000
print("Test set size: ", len(test_set))   # Test set size:  10000
print("Valid set size: ", len(valid_set)) # Valid set size:  10000


ここでは、'test' を分割して test_set に取り込みました。

train’split の 0 % から 20% までのスライスをvalid_setに、25 % 以降をtrain_set` に割り当てる。

これはセット自体のサイズによっても検証される。

パーセンテージの代わりに、絶対値やパーセンテージと絶対値の混在を使用することもできます。

# Absolute value split
test_set, valid_set, train_set = tfds.load("cifar10", 
                                           split=["test", "train[0:10000]", "train[10000:]"],
                                           as_supervised=True)


print("Train set size: ", len(train_set)) # Train set size:  40000
print("Test set size: ", len(test_set))   # Test set size:  10000
print("Valid set size: ", len(valid_set)) # Valid set size:  10000


# Mixed notation split
# 5000 - 50% (25000) left unassigned
test_set, valid_set, train_set = tfds.load("cifar10", 
                                           split=["train[:2500]", # First 2500 are assigned to `test_set`
                                           "train[2500:5000]",    # 2500-5000 are assigned to `valid_set`
                                           "train[50%:]"],        # 50% - 100% (25000) assigned to `train_set`
                                           as_supervised=True)


これはあまり一般的ではありませんが、集合がインターリーブされているためです。

train_and_test, half_of_train_and_test = tfds.load("cifar10", 
                                split=['train+test', 'train[:50%]+test'],
                                as_supervised=True)

print("Train+test: ", len(train_and_test))               # Train+test:  60000
print("Train[:50%]+test: ", len(half_of_train_and_test)) # Train[:50%]+test:  35000


これらの2つの集合は、現在、大きくインターリーブされています。

N個の集合に対する偶数分割

繰り返しますが、分割リストに分割を追加するだけで、任意の数の分割を作成することができます。

split=["train[:10%]", "train[10%:20%]", "train[20%:30%]", "train[30%:40%]", ...]


しかし、多くの分割を行う場合、特に偶数分割の場合は、 渡される文字列が非常に予測しやすくなります。

これは、文字列のリストを作成することで自動化することができます。

その際、文字列には等間隔 (たとえば 10%)を指定します。

まさにこの目的のために、 tfds.even_splits() 関数は、プレフィックス文字列と希望する分割数を与えて、文字列のリストを生成します。

import tensorflow_datasets as tfds


s1, s2, s3, s4, s5 = tfds.even_splits('train', n=5)
# Each of these elements is just a string
split_list = [s1, s2, s3, s4, s5]
print(f"Type: {type(s1)}, contents: '{s1}'")
# Type: <class 'str'="", contents: 'train[0%:20%]'


for split in split_list:
    test_set = tfds.load("cifar10", 
                                split=split,
                                as_supervised=True)
    print(f"Test set length for Split {split}: ", len(test_set))


この結果は

Test set length for Split train[0%:20%]:  10000
Test set length for Split train[20%:40%]:  10000
Test set length for Split train[40%:60%]:  10000
Test set length for Split train[60%:80%]:  10000
Test set length for Split train[80%:100%]:  10000


また、 split_list 全体を split 引数として渡すことで、ループの外側で複数の分割データセットを構築することもできます。

ts1, ts2, ts3, ts4, ts5 = tfds.load("cifar10", 
                                split=split_list,
                                as_supervised=True)


結論

このガイドでは、トレーニングセットとテストセットが何であるか、また検証セットの重要性について見てきました。

最後に、Tensorflow Datasets ライブラリの新しい Splits API を調べて、train/test/validation の分割を実行しました。

</class

タイトルとURLをコピーしました