Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

tf.data: TensorFlow giriş ardışık düzenleri oluşturun

TensorFlow.org'da görüntüleyin Google Colab'de çalıştırın Kaynağı GitHub'da görüntüleyin Defteri indirin

tf.data API, basit, yeniden kullanılabilir parçalardan karmaşık girdi ardışık tf.data oluşturmanıza olanak tanır. Örneğin, bir görüntü modelinin ardışık düzeni, dağıtılmış bir dosya sistemindeki dosyalardan verileri toplayabilir, her görüntüye rastgele pertürbasyonlar uygulayabilir ve rastgele seçilen görüntüleri eğitim için bir grup halinde birleştirebilir. Bir metin modeli için boru hattı, ham metin verilerinden sembollerin çıkarılmasını, bunları bir arama tablosu ile tanımlayıcıların gömülmesini ve farklı uzunluklardaki dizilerin bir araya toplanmasını içerebilir. tf.data API, büyük miktarda veriyi işlemeyi, farklı veri biçimlerinden okumayı ve karmaşık dönüşümler gerçekleştirmeyi mümkün kılar.

tf.data API, her bir öğenin bir veya daha fazla bileşenden oluştuğu bir dizi öğeyi temsil eden birtf.data.Dataset soyutlaması sunar. Örneğin, bir görüntü ardışık düzeninde bir öğe, görüntüyü ve etiketini temsil eden bir çift tensör bileşenine sahip tek bir eğitim örneği olabilir.

Veri kümesi oluşturmanın iki farklı yolu vardır:

  • Bir veri kaynağı , bellekte veya bir veya daha fazla dosyada depolanan verilerden bir Dataset oluşturur.

  • Bir veri dönüşümü , bir veya daha fazlatf.data.Dataset nesnesinden bir veri kümesi oluşturur.

import tensorflow as tf
import pathlib
import os
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

np.set_printoptions(precision=4)

Temel mekanik

Bir giriş ardışık düzeni oluşturmak için bir veri kaynağıyla başlamalısınız. Örneğin, bellekteki verilerden bir Dataset oluşturmak için tf.data.Dataset.from_tensors() veya tf.data.Dataset.from_tensor_slices() . Alternatif olarak, girdi verileriniz önerilen TFRecord biçimindeki bir dosyada saklanıyorsa, tf.data.TFRecordDataset() kullanabilirsiniz.

Bir Dataset nesnesine sahip olduğunuzda,tf.data.Dataset nesnesinde yöntem çağrılarını zincirleyerek onu yeni bir Dataset dönüştürebilirsiniz . Örneğin, Dataset.map() gibi öğe başına dönüşümleri ve Dataset.map() gibi çok öğeli dönüşümleri Dataset.batch() .tf.data.Dataset tam listesi içintf.data.Dataset belgelerine bakın.

Dataset nesnesi bir Python yinelenebilirdir. Bu, öğelerini bir for döngüsü kullanarak tüketmeyi mümkün kılar:

dataset = tf.data.Dataset.from_tensor_slices([8, 3, 0, 8, 2, 1])
dataset
<TensorSliceDataset shapes: (), types: tf.int32>
for elem in dataset:
  print(elem.numpy())
8
3
0
8
2
1

Veya iter kullanarak açıkça bir Python yineleyicisi oluşturarak ve next öğelerini kullanarak öğelerini tüketerek:

it = iter(dataset)

print(next(it).numpy())
8

Alternatif olarak, veri kümesi öğeleri, tek bir sonuç üretmek için tüm öğeleri azaltan reduce dönüşümü kullanılarak tüketilebilir. Aşağıdaki örnek, tamsayılardan oluşan bir veri kümesinin toplamını hesaplamak için reduce dönüşümünün nasıl kullanılacağını gösterir.

print(dataset.reduce(0, lambda state, value: state + value).numpy())
22

Veri kümesi yapısı

Veri kümesi her biri aynı (iç içe) bir yapıya sahip ve yapısı tek tek bileşenleri herhangi bir tip gösterilebilen ait olabilmektedir öğeleri içeren tf.TypeSpec de dahil olmak üzere, tf.Tensor , tf.sparse.SparseTensor ,tf.RaggedTensor , tf.TensorArray , veyatf.data.Dataset .

Dataset.element_spec özelliği, her bir öğe bileşeninin türünü incelemenizi sağlar. Özellik, tf.TypeSpec nesnelerinin iç içe geçmiş bir yapısını döndürür; bu, tek bir bileşen, bileşenlerin bir demeti veya bileşenlerin iç içe geçmiş bir demeti olabilen öğenin yapısıyla tf.TypeSpec . Örneğin:

dataset1 = tf.data.Dataset.from_tensor_slices(tf.random.uniform([4, 10]))

dataset1.element_spec
TensorSpec(shape=(10,), dtype=tf.float32, name=None)
dataset2 = tf.data.Dataset.from_tensor_slices(
   (tf.random.uniform([4]),
    tf.random.uniform([4, 100], maxval=100, dtype=tf.int32)))

dataset2.element_spec
(TensorSpec(shape=(), dtype=tf.float32, name=None),
 TensorSpec(shape=(100,), dtype=tf.int32, name=None))
dataset3 = tf.data.Dataset.zip((dataset1, dataset2))

dataset3.element_spec
(TensorSpec(shape=(10,), dtype=tf.float32, name=None),
 (TensorSpec(shape=(), dtype=tf.float32, name=None),
  TensorSpec(shape=(100,), dtype=tf.int32, name=None)))
# Dataset containing a sparse tensor.
dataset4 = tf.data.Dataset.from_tensors(tf.SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4]))

dataset4.element_spec
SparseTensorSpec(TensorShape([3, 4]), tf.int32)
# Use value_type to see the type of value represented by the element spec
dataset4.element_spec.value_type
tensorflow.python.framework.sparse_tensor.SparseTensor

Dataset kümesi dönüşümleri, herhangi bir yapının veri kümelerini destekler. Kullanırken Dataset.map() , ve Dataset.filter() her bir elemanı için bir işlev geçerli dönüşümler, eleman yapısı fonksiyonunun bağımsız değişkenler belirler:

dataset1 = tf.data.Dataset.from_tensor_slices(
    tf.random.uniform([4, 10], minval=1, maxval=10, dtype=tf.int32))

dataset1
<TensorSliceDataset shapes: (10,), types: tf.int32>
for z in dataset1:
  print(z.numpy())
[4 6 7 3 1 1 6 7 3 7]
[6 6 1 7 3 8 9 8 9 4]
[2 3 2 2 7 1 8 8 5 9]
[6 6 7 8 8 9 2 3 7 8]

dataset2 = tf.data.Dataset.from_tensor_slices(
   (tf.random.uniform([4]),
    tf.random.uniform([4, 100], maxval=100, dtype=tf.int32)))

dataset2
<TensorSliceDataset shapes: ((), (100,)), types: (tf.float32, tf.int32)>
dataset3 = tf.data.Dataset.zip((dataset1, dataset2))

dataset3
<ZipDataset shapes: ((10,), ((), (100,))), types: (tf.int32, (tf.float32, tf.int32))>
for a, (b,c) in dataset3:
  print('shapes: {a.shape}, {b.shape}, {c.shape}'.format(a=a, b=b, c=c))
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)

Giriş verilerini okuma

NumPy dizilerini tüketmek

Daha fazla örnek için NumPy dizilerini yükleme konusuna bakın.

Tüm giriş verileriniz belleğe sığıyorsa, bunlardan bir Dataset oluşturmanın en basit yolu, onları tf.Tensor nesnelerine dönüştürmek ve Dataset.from_tensor_slices() kullanmaktır.

train, test = tf.keras.datasets.fashion_mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 1s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step

images, labels = train
images = images/255

dataset = tf.data.Dataset.from_tensor_slices((images, labels))
dataset
<TensorSliceDataset shapes: ((28, 28), ()), types: (tf.float64, tf.uint8)>

Python jeneratörlerini tüketmek

tf.data.Dataset olarak kolayca alınabilen diğer bir yaygın veri kaynağı da python oluşturucudur.

def count(stop):
  i = 0
  while i<stop:
    yield i
    i += 1
for n in count(5):
  print(n)
0
1
2
3
4

Dataset.from_generator yapıcısı, python oluşturucuyu tamamen işlevsel birtf.data.Dataset .

Yapıcı, bir yineleyici değil, giriş olarak çağrılabilir bir alır. Bu, sona ulaştığında jeneratörü yeniden başlatmasına izin verir. args argümanlar olarak iletilen isteğe bağlı bir argüman argümanını alır.

output_types için bağımsız değişkeni gereklidir tf.data bir inşa tf.Graph dahili ve grafik kenarları gerektirir tf.dtype .

ds_counter = tf.data.Dataset.from_generator(count, args=[25], output_types=tf.int32, output_shapes = (), )
for count_batch in ds_counter.repeat().batch(10).take(10):
  print(count_batch.numpy())
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24  0  1  2  3  4]
[ 5  6  7  8  9 10 11 12 13 14]
[15 16 17 18 19 20 21 22 23 24]
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24  0  1  2  3  4]
[ 5  6  7  8  9 10 11 12 13 14]
[15 16 17 18 19 20 21 22 23 24]

output_shapes argümanı gerekli değildir, ancak birçok tensorflow işlemi bilinmeyen dereceye sahip tensörleri desteklemediğinden şiddetle tavsiye edilir. Belirli bir eksenin uzunluğu bilinmiyorsa veya değişkense, bunu output_shapes None olarak output_shapes .

Ayrıca output_shapes ve output_types output_shapes diğer veri kümesi yöntemleriyle aynı iç içe geçme kurallarını izlediğine dikkat etmek önemlidir.

İşte her iki yönü de gösteren bir örnek oluşturucu, ikinci dizinin bilinmeyen uzunlukta bir vektör olduğu dizilerin demetlerini döndürür.

def gen_series():
  i = 0
  while True:
    size = np.random.randint(0, 10)
    yield i, np.random.normal(size=(size,))
    i += 1
for i, series in gen_series():
  print(i, ":", str(series))
  if i > 5:
    break
0 : [-1.8423 -0.1016  0.2763  0.815   0.0137  0.1228  0.0773]
1 : [ 0.4419  0.6819 -0.576 ]
2 : [-0.8961 -0.8613 -0.5917  0.7749 -0.2283  0.4406 -2.4833  0.1952  0.9962]
3 : []
4 : [0.2609 0.854  2.96  ]
5 : []
6 : [ 1.0899 -0.377   0.4295 -1.835  -0.4915 -0.0435 -0.6999 -0.9527]

İlk çıktı bir int32 , ikincisi ise float32 .

İlk öğe bir skaler, şekil () ve ikincisi, bilinmeyen uzunlukta bir vektördür (None,)

ds_series = tf.data.Dataset.from_generator(
    gen_series, 
    output_types=(tf.int32, tf.float32), 
    output_shapes=((), (None,)))

ds_series
<FlatMapDataset shapes: ((), (None,)), types: (tf.int32, tf.float32)>

Artık normal birtf.data.Dataset gibi kullanılabilir. Değişken şekilli bir veri kümesini toplu Dataset.padded_batch kullanmanız Dataset.padded_batch .

ds_series_batch = ds_series.shuffle(20).padded_batch(10)

ids, sequence_batch = next(iter(ds_series_batch))
print(ids.numpy())
print()
print(sequence_batch.numpy())
[12  0 21 20 19  2 13  6 16 15]

[[ 0.6409  0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-0.3158 -1.1566  0.5766  0.2067  0.2566 -0.7567  0.      0.      0.    ]
 [ 1.703   0.      0.      0.      0.      0.      0.      0.      0.    ]
 [ 1.577   0.      0.      0.      0.      0.      0.      0.      0.    ]
 [ 0.      0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-1.1427  1.779   1.5403  0.428  -0.0309  0.8038 -0.4779  0.3646 -0.3527]
 [-1.0069  0.6749 -1.4268  0.0887  0.4798  0.769   0.5454  0.      0.    ]
 [-0.3393  0.5725 -0.8578 -3.5323 -0.9053  0.261  -1.7785  0.5377 -0.4388]
 [ 0.5343  1.609  -0.9407  1.1031  0.4216  0.      0.      0.      0.    ]
 [ 1.1637  0.6195  1.6317 -0.759  -0.4261 -3.2933  1.9672 -0.2561  1.341 ]]

Daha gerçekçi bir örnek için preprocessing.image.ImageDataGeneratortf.data.Dataset olaraktf.data.Dataset deneyin.

Önce verileri indirin:

flowers = tf.keras.utils.get_file(
    'flower_photos',
    'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
    untar=True)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
228818944/228813984 [==============================] - 11s 0us/step

image.ImageDataGenerator oluşturun

img_gen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, rotation_range=20)
images, labels = next(img_gen.flow_from_directory(flowers))
Found 3670 images belonging to 5 classes.

print(images.dtype, images.shape)
print(labels.dtype, labels.shape)
float32 (32, 256, 256, 3)
float32 (32, 5)

ds = tf.data.Dataset.from_generator(
    lambda: img_gen.flow_from_directory(flowers), 
    output_types=(tf.float32, tf.float32), 
    output_shapes=([32,256,256,3], [32,5])
)

ds.element_spec
(TensorSpec(shape=(32, 256, 256, 3), dtype=tf.float32, name=None),
 TensorSpec(shape=(32, 5), dtype=tf.float32, name=None))
for images, label in ds.take(1):
  print('images.shape: ', images.shape)
  print('labels.shape: ', labels.shape)
Found 3670 images belonging to 5 classes.
images.shape:  (32, 256, 256, 3)
labels.shape:  (32, 5)

TFRecord verilerini tüketme

Uçtan uca bir örnek için TFRecords Yükleme bölümüne bakın.

tf.data API, belleğe sığmayan büyük veri kümelerini işleyebilmeniz için çeşitli dosya biçimlerini destekler. Örneğin, TFRecord dosya biçimi, birçok TensorFlow uygulamasının eğitim verileri için kullandığı basit bir kayıt odaklı ikili biçimdir. tf.data.TFRecordDataset sınıfı, bir giriş ardışık düzeninin parçası olarak bir veya daha fazla TFRecord dosyasının içeriği üzerinden akış yapmanızı sağlar.

Fransız Sokak Adı İşaretlerinden (FSNS) alınan test dosyasını kullanan bir örnek aşağıda verilmiştir.

# Creates a dataset that reads all of the examples from two files.
fsns_test_file = tf.keras.utils.get_file("fsns.tfrec", "https://storage.googleapis.com/download.tensorflow.org/data/fsns-20160927/testdata/fsns-00000-of-00001")
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/fsns-20160927/testdata/fsns-00000-of-00001
7905280/7904079 [==============================] - 0s 0us/step

TFRecordDataset başlatıcısının filenames bağımsız değişkeni bir dize, dizeler listesi veya dizelerin tf.Tensor . Bu nedenle, eğitim ve doğrulama amacıyla iki dosya kümeniz varsa, veri kümesini üreten bir fabrika yöntemi oluşturabilirsiniz, dosya adlarını girdi bağımsız değişkeni olarak alabilirsiniz:

dataset = tf.data.TFRecordDataset(filenames = [fsns_test_file])
dataset
<TFRecordDatasetV2 shapes: (), types: tf.string>

Birçok TensorFlow projesi, TFRecord dosyalarında serileştirilmiş tf.train.Example kayıtları kullanır. Bunların incelenmeden önce kodunun çözülmesi gerekir:

raw_example = next(iter(dataset))
parsed = tf.train.Example.FromString(raw_example.numpy())

parsed.features.feature['image/text']
bytes_list {
  value: "Rue Perreyon"
}

Metin verilerini tüketmek

Uçtan uca bir örnek için Metin Yükleme konusuna bakın.

Birçok veri kümesi bir veya daha fazla metin dosyası olarak dağıtılır. tf.data.TextLineDataset , bir veya daha fazla metin dosyasından satır ayıklamak için kolay bir yol sağlar. Bir veya daha fazla dosya adı verildiğinde, bir TextLineDataset bu dosyaların her satırı için dize değerli bir öğe üretir.

directory_url = 'https://storage.googleapis.com/download.tensorflow.org/data/illiad/'
file_names = ['cowper.txt', 'derby.txt', 'butler.txt']

file_paths = [
    tf.keras.utils.get_file(file_name, directory_url + file_name)
    for file_name in file_names
]
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/cowper.txt
819200/815980 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/derby.txt
811008/809730 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/butler.txt
811008/807992 [==============================] - 0s 0us/step

dataset = tf.data.TextLineDataset(file_paths)

İşte ilk dosyanın ilk birkaç satırı:

for line in dataset.take(5):
  print(line.numpy())
b"\xef\xbb\xbfAchilles sing, O Goddess! Peleus' son;"
b'His wrath pernicious, who ten thousand woes'
b"Caused to Achaia's host, sent many a soul"
b'Illustrious into Ades premature,'
b'And Heroes gave (so stood the will of Jove)'

Dosyalar arasında satırları değiştirmek için Dataset.interleave kullanın. Bu, dosyaları birlikte karıştırmayı kolaylaştırır. İşte her çevirinin birinci, ikinci ve üçüncü satırları:

files_ds = tf.data.Dataset.from_tensor_slices(file_paths)
lines_ds = files_ds.interleave(tf.data.TextLineDataset, cycle_length=3)

for i, line in enumerate(lines_ds.take(9)):
  if i % 3 == 0:
    print()
  print(line.numpy())

b"\xef\xbb\xbfAchilles sing, O Goddess! Peleus' son;"
b"\xef\xbb\xbfOf Peleus' son, Achilles, sing, O Muse,"
b'\xef\xbb\xbfSing, O goddess, the anger of Achilles son of Peleus, that brought'

b'His wrath pernicious, who ten thousand woes'
b'The vengeance, deep and deadly; whence to Greece'
b'countless ills upon the Achaeans. Many a brave soul did it send'

b"Caused to Achaia's host, sent many a soul"
b'Unnumbered ills arose; which many a soul'
b'hurrying down to Hades, and many a hero did it yield a prey to dogs and'

Varsayılan olarak, bir TextLineDataset her dosyanın her satırını verir; bu istenmeyebilir, örneğin, dosya bir başlık satırıyla başlıyorsa veya yorumlar içeriyorsa. Bu satırlar Dataset.skip() veya Dataset.filter() dönüşümleri kullanılarak kaldırılabilir. Burada, ilk satırı atlar, ardından yalnızca hayatta kalanları bulmak için filtre uygularsınız.

titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv")
titanic_lines = tf.data.TextLineDataset(titanic_file)
Downloading data from https://storage.googleapis.com/tf-datasets/titanic/train.csv
32768/30874 [===============================] - 0s 0us/step

for line in titanic_lines.take(10):
  print(line.numpy())
b'survived,sex,age,n_siblings_spouses,parch,fare,class,deck,embark_town,alone'
b'0,male,22.0,1,0,7.25,Third,unknown,Southampton,n'
b'1,female,38.0,1,0,71.2833,First,C,Cherbourg,n'
b'1,female,26.0,0,0,7.925,Third,unknown,Southampton,y'
b'1,female,35.0,1,0,53.1,First,C,Southampton,n'
b'0,male,28.0,0,0,8.4583,Third,unknown,Queenstown,y'
b'0,male,2.0,3,1,21.075,Third,unknown,Southampton,n'
b'1,female,27.0,0,2,11.1333,Third,unknown,Southampton,n'
b'1,female,14.0,1,0,30.0708,Second,unknown,Cherbourg,n'
b'1,female,4.0,1,1,16.7,Third,G,Southampton,n'

def survived(line):
  return tf.not_equal(tf.strings.substr(line, 0, 1), "0")

survivors = titanic_lines.skip(1).filter(survived)
for line in survivors.take(10):
  print(line.numpy())
b'1,female,38.0,1,0,71.2833,First,C,Cherbourg,n'
b'1,female,26.0,0,0,7.925,Third,unknown,Southampton,y'
b'1,female,35.0,1,0,53.1,First,C,Southampton,n'
b'1,female,27.0,0,2,11.1333,Third,unknown,Southampton,n'
b'1,female,14.0,1,0,30.0708,Second,unknown,Cherbourg,n'
b'1,female,4.0,1,1,16.7,Third,G,Southampton,n'
b'1,male,28.0,0,0,13.0,Second,unknown,Southampton,y'
b'1,female,28.0,0,0,7.225,Third,unknown,Cherbourg,y'
b'1,male,28.0,0,0,35.5,First,A,Southampton,y'
b'1,female,38.0,1,5,31.3875,Third,unknown,Southampton,n'

CSV verilerini tüketme

Daha fazla örnek için bkz. CSV Dosyalarını Yükleme ve Pandas Veri Çerçevelerini Yükleme .

CSV dosya formatı, tablo şeklindeki verileri düz metin olarak depolamak için popüler bir formattır.

Örneğin:

titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv")
df = pd.read_csv(titanic_file)
df.head()

Verileriniz belleğe Dataset.from_tensor_slices , aynı Dataset.from_tensor_slices yöntemi sözlükler üzerinde çalışır ve bu verilerin kolayca içe aktarılmasına izin verir:

titanic_slices = tf.data.Dataset.from_tensor_slices(dict(df))

for feature_batch in titanic_slices.take(1):
  for key, value in feature_batch.items():
    print("  {!r:20s}: {}".format(key, value))
  'survived'          : 0
  'sex'               : b'male'
  'age'               : 22.0
  'n_siblings_spouses': 1
  'parch'             : 0
  'fare'              : 7.25
  'class'             : b'Third'
  'deck'              : b'unknown'
  'embark_town'       : b'Southampton'
  'alone'             : b'n'

Daha ölçeklenebilir bir yaklaşım, gerektiğinde diskten yüklemektir.

tf.data modülü, RFC 4180 ile uyumlu bir veya daha fazla CSV dosyasından kayıtları ayıklamak için yöntemler sağlar.

experimental.make_csv_dataset işlevi, csv dosya kümelerini okumak için yüksek düzeyli bir arabirimdir. Kullanımı basitleştirmek için sütun türü çıkarımını ve yığınlama ve karıştırma gibi diğer birçok özelliği destekler.

titanic_batches = tf.data.experimental.make_csv_dataset(
    titanic_file, batch_size=4,
    label_name="survived")
for feature_batch, label_batch in titanic_batches.take(1):
  print("'survived': {}".format(label_batch))
  print("features:")
  for key, value in feature_batch.items():
    print("  {!r:20s}: {}".format(key, value))
'survived': [0 0 0 1]
features:
  'sex'               : [b'male' b'male' b'male' b'female']
  'age'               : [11. 16. 28. 19.]
  'n_siblings_spouses': [5 4 0 0]
  'parch'             : [2 1 0 2]
  'fare'              : [46.9    39.6875  7.75   26.2833]
  'class'             : [b'Third' b'Third' b'Third' b'First']
  'deck'              : [b'unknown' b'unknown' b'unknown' b'D']
  'embark_town'       : [b'Southampton' b'Southampton' b'Queenstown' b'Southampton']
  'alone'             : [b'n' b'n' b'y' b'n']

Yalnızca bir sütun alt kümesine ihtiyacınız varsa, select_columns bağımsız değişkenini kullanabilirsiniz.

titanic_batches = tf.data.experimental.make_csv_dataset(
    titanic_file, batch_size=4,
    label_name="survived", select_columns=['class', 'fare', 'survived'])
for feature_batch, label_batch in titanic_batches.take(1):
  print("'survived': {}".format(label_batch))
  for key, value in feature_batch.items():
    print("  {!r:20s}: {}".format(key, value))
'survived': [0 1 1 0]
  'fare'              : [ 0.     12.2875 30.      7.75  ]
  'class'             : [b'Second' b'Third' b'First' b'Third']

Daha ince taneli kontrol sağlayan daha düşük seviyeli bir experimental.CsvDataset sınıfı da vardır. Sütun türü çıkarımını desteklemez. Bunun yerine, her bir sütunun türünü belirtmelisiniz.

titanic_types  = [tf.int32, tf.string, tf.float32, tf.int32, tf.int32, tf.float32, tf.string, tf.string, tf.string, tf.string] 
dataset = tf.data.experimental.CsvDataset(titanic_file, titanic_types , header=True)

for line in dataset.take(10):
  print([item.numpy() for item in line])
[0, b'male', 22.0, 1, 0, 7.25, b'Third', b'unknown', b'Southampton', b'n']
[1, b'female', 38.0, 1, 0, 71.2833, b'First', b'C', b'Cherbourg', b'n']
[1, b'female', 26.0, 0, 0, 7.925, b'Third', b'unknown', b'Southampton', b'y']
[1, b'female', 35.0, 1, 0, 53.1, b'First', b'C', b'Southampton', b'n']
[0, b'male', 28.0, 0, 0, 8.4583, b'Third', b'unknown', b'Queenstown', b'y']
[0, b'male', 2.0, 3, 1, 21.075, b'Third', b'unknown', b'Southampton', b'n']
[1, b'female', 27.0, 0, 2, 11.1333, b'Third', b'unknown', b'Southampton', b'n']
[1, b'female', 14.0, 1, 0, 30.0708, b'Second', b'unknown', b'Cherbourg', b'n']
[1, b'female', 4.0, 1, 1, 16.7, b'Third', b'G', b'Southampton', b'n']
[0, b'male', 20.0, 0, 0, 8.05, b'Third', b'unknown', b'Southampton', b'y']

Bazı sütunlar boşsa, bu düşük düzeyli arabirim sütun türleri yerine varsayılan değerler sağlamanıza olanak tanır.

%%writefile missing.csv
1,2,3,4
,2,3,4
1,,3,4
1,2,,4
1,2,3,
,,,
Writing missing.csv

# Creates a dataset that reads all of the records from two CSV files, each with
# four float columns which may have missing values.

record_defaults = [999,999,999,999]
dataset = tf.data.experimental.CsvDataset("missing.csv", record_defaults)
dataset = dataset.map(lambda *items: tf.stack(items))
dataset
<MapDataset shapes: (4,), types: tf.int32>
for line in dataset:
  print(line.numpy())
[1 2 3 4]
[999   2   3   4]
[  1 999   3   4]
[  1   2 999   4]
[  1   2   3 999]
[999 999 999 999]

Varsayılan olarak, bir CsvDataset dosyanın her satırının her sütununu verir ve bu istenmeyebilir, örneğin dosya yok sayılması gereken bir başlık satırıyla başlıyorsa veya girdide bazı sütunlar gerekli değilse. Bu satırlar ve alanlar sırasıyla header ve select_cols argümanları ile kaldırılabilir.

# Creates a dataset that reads all of the records from two CSV files with
# headers, extracting float data from columns 2 and 4.
record_defaults = [999, 999] # Only provide defaults for the selected columns
dataset = tf.data.experimental.CsvDataset("missing.csv", record_defaults, select_cols=[1, 3])
dataset = dataset.map(lambda *items: tf.stack(items))
dataset
<MapDataset shapes: (2,), types: tf.int32>
for line in dataset:
  print(line.numpy())
[2 4]
[2 4]
[999   4]
[2 4]
[  2 999]
[999 999]

Dosya setleri tüketmek

Her dosyanın bir örnek olduğu bir dizi dosya olarak dağıtılmış birçok veri kümesi vardır.

flowers_root = tf.keras.utils.get_file(
    'flower_photos',
    'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
    untar=True)
flowers_root = pathlib.Path(flowers_root)

Kök dizin, her sınıf için bir dizin içerir:

for item in flowers_root.glob("*"):
  print(item.name)
sunflowers
daisy
LICENSE.txt
roses
tulips
dandelion

Her bir sınıf dizinindeki dosyalar örnektir:

list_ds = tf.data.Dataset.list_files(str(flowers_root/'*/*'))

for f in list_ds.take(5):
  print(f.numpy())
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/4868595281_1e58083785.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/5883162120_dc7274af76_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/12883412424_cb5086b43f_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/13264214185_d6aa79b3bd.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/6690926183_afedba9f15_n.jpg'

tf.io.read_file işlevini kullanarak verileri okuyun ve etiketi yoldantf.io.read_file (image, label) çiftleri döndürür:

def process_path(file_path):
  label = tf.strings.split(file_path, os.sep)[-2]
  return tf.io.read_file(file_path), label

labeled_ds = list_ds.map(process_path)
for image_raw, label_text in labeled_ds.take(1):
  print(repr(image_raw.numpy()[:100]))
  print()
  print(label_text.numpy())
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xfe\x00\x0cAppleMark\n\xff\xe2\x05(ICC_PROFILE\x00\x01\x01\x00\x00\x05\x18appl\x02 \x00\x00scnrRGB XYZ \x07\xd3\x00\x07\x00\x01\x00\x00\x00\x00\x00\x00acspAPPL\x00\x00\x00\x00'

b'sunflowers'

Veri kümesi öğelerini gruplama

Basit gruplama

En basit gruplama biçimi, bir veri kümesinin n ardışık öğesini tek bir öğede yığınlar. Dataset.batch() dönüşümü, öğelerin her bileşenine uygulanan tf.stack() operatörü ile aynı kısıtlamalarla tam olarak bunu yapar: yani, her i bileşeni için, tüm öğeler tam olarak aynı şekle sahip bir tensöre sahip olmalıdır.

inc_dataset = tf.data.Dataset.range(100)
dec_dataset = tf.data.Dataset.range(0, -100, -1)
dataset = tf.data.Dataset.zip((inc_dataset, dec_dataset))
batched_dataset = dataset.batch(4)

for batch in batched_dataset.take(4):
  print([arr.numpy() for arr in batch])
[array([0, 1, 2, 3]), array([ 0, -1, -2, -3])]
[array([4, 5, 6, 7]), array([-4, -5, -6, -7])]
[array([ 8,  9, 10, 11]), array([ -8,  -9, -10, -11])]
[array([12, 13, 14, 15]), array([-12, -13, -14, -15])]

tf.data şekil bilgilerini tf.data çalışırken, Dataset.batch varsayılan ayarları, son toplu iş dolu olmayabileceğinden bilinmeyen bir yığın boyutuyla sonuçlanır. Şekildeki None edin:

batched_dataset
<BatchDataset shapes: ((None,), (None,)), types: (tf.int64, tf.int64)>

Son kümeyi yok saymak ve tam şekil yayılımı elde etmek için drop_remainder bağımsız değişkenini kullanın:

batched_dataset = dataset.batch(7, drop_remainder=True)
batched_dataset
<BatchDataset shapes: ((7,), (7,)), types: (tf.int64, tf.int64)>

Dolgulu harmanlama tensörleri

Yukarıdaki tarif, hepsi aynı boyutta olan tensörler için işe yarar. Bununla birlikte, birçok model (örneğin, dizi modelleri) değişen boyutlara sahip olabilen girdi verileriyle çalışır (örneğin, farklı uzunluktaki diziler). Bu durumu ele almak için, Dataset.padded_batch dönüşümü, içinde doldurulabilecekleri bir veya daha fazla boyut belirleyerek farklı şekildeki tensörleri Dataset.padded_batch olanak tanır.

dataset = tf.data.Dataset.range(100)
dataset = dataset.map(lambda x: tf.fill([tf.cast(x, tf.int32)], x))
dataset = dataset.padded_batch(4, padded_shapes=(None,))

for batch in dataset.take(2):
  print(batch.numpy())
  print()
[[0 0 0]
 [1 0 0]
 [2 2 0]
 [3 3 3]]

[[4 4 4 4 0 0 0]
 [5 5 5 5 5 0 0]
 [6 6 6 6 6 6 0]
 [7 7 7 7 7 7 7]]


Dataset.padded_batch dönüşümü, her bileşenin her bir boyutu için farklı dolgu ayarlamanıza olanak tanır ve değişken uzunlukta (yukarıdaki örnekte None ile belirtilir) veya sabit uzunlukta olabilir. Varsayılan olarak 0 olan doldurma değerini geçersiz kılmak da mümkündür.

Eğitim iş akışları

Birden çok dönemi işleme

tf.data API, aynı verilerin birden çok dönemini işlemek için iki ana yol sunar.

Bir veri kümesi üzerinde birden çok çağda yineleme yapmanın en basit yolu, Dataset.repeat() dönüşümünü kullanmaktır. İlk olarak, titanik verilerden bir veri kümesi oluşturun:

titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv")
titanic_lines = tf.data.TextLineDataset(titanic_file)
def plot_batch_sizes(ds):
  batch_sizes = [batch.shape[0] for batch in ds]
  plt.bar(range(len(batch_sizes)), batch_sizes)
  plt.xlabel('Batch number')
  plt.ylabel('Batch size')

Dataset.repeat() dönüşümünün bağımsız değişken olmadan uygulanması, girdiyi süresiz olarak tekrar eder.

Dataset.repeat dönüşümü, bir dönemin sonunu ve sonraki dönemin başlangıcını bildirmeden bağımsız değişkenlerini birleştirir. Bu nedenle bir Dataset.batch sonra uygulanır Dataset.repeat toplu verecektir Üstüne binilir dönem sınırları olun:

titanic_batches = titanic_lines.repeat(3).batch(128)
plot_batch_sizes(titanic_batches)

png

Net bir dönem ayrımına ihtiyacınız varsa, Dataset.batch önce Dataset.batch koyun:

titanic_batches = titanic_lines.batch(128).repeat(3)

plot_batch_sizes(titanic_batches)

png

Her dönemin sonunda özel bir hesaplama (örneğin, istatistik toplamak için) gerçekleştirmek isterseniz, en basit yöntem, her çağda veri kümesi yinelemesini yeniden başlatmaktır:

epochs = 3
dataset = titanic_lines.batch(128)

for epoch in range(epochs):
  for batch in dataset:
    print(batch.shape)
  print("End of epoch: ", epoch)
(128,)
(128,)
(128,)
(128,)
(116,)
End of epoch:  0
(128,)
(128,)
(128,)
(128,)
(116,)
End of epoch:  1
(128,)
(128,)
(128,)
(128,)
(116,)
End of epoch:  2

Girdi verilerini rastgele karıştırmak

Dataset.shuffle() dönüşümü, sabit boyutlu bir arabelleği korur ve sonraki öğeyi bu arabellekten rastgele rastgele olarak seçer.

Etkisini görebilmek için veri kümesine bir dizin ekleyin:

lines = tf.data.TextLineDataset(titanic_file)
counter = tf.data.experimental.Counter()

dataset = tf.data.Dataset.zip((counter, lines))
dataset = dataset.shuffle(buffer_size=100)
dataset = dataset.batch(20)
dataset
<BatchDataset shapes: ((None,), (None,)), types: (tf.int64, tf.string)>

buffer_size 100 olduğundan ve toplu iş boyutu 20 olduğundan, ilk grup 120'den büyük indeksi olan hiçbir öğe içermez.

n,line_batch = next(iter(dataset))
print(n.numpy())
[ 90  75  39  84 102   5  98 101  51  72  54  33 104  59 110  29  92  50
  36 103]

Olduğu gibi Dataset.batch göre sipariş Dataset.repeat konularda.

Dataset.shuffle , karıştırma arabelleği boşalana kadar bir dönemin sonunu Dataset.shuffle . Dolayısıyla, bir tekrardan önce yerleştirilen bir karıştırma, bir dönemin her öğesini bir sonrakine geçmeden önce gösterir:

dataset = tf.data.Dataset.zip((counter, lines))
shuffled = dataset.shuffle(buffer_size=100).batch(10).repeat(2)

print("Here are the item ID's near the epoch boundary:\n")
for n, line_batch in shuffled.skip(60).take(5):
  print(n.numpy())
Here are the item ID's near the epoch boundary:

[550 618 614 435 556 530 578 451 590 604]
[464 453 610 412 282 596 601 612 584 606]
[368 469 575 607 586 537 444 300]
[ 15  98  65  26  40  39 101  54  32  10]
[  8 102  68 108  12  96   2  87  80  37]

shuffle_repeat = [n.numpy().mean() for n, line_batch in shuffled]
plt.plot(shuffle_repeat, label="shuffle().repeat()")
plt.ylabel("Mean item ID")
plt.legend()
<matplotlib.legend.Legend at 0x7f3f083eebe0>

png

Ancak bir karıştırma işleminden önce bir tekrar, çağın sınırlarını birbirine karıştırır:

dataset = tf.data.Dataset.zip((counter, lines))
shuffled = dataset.repeat(2).shuffle(buffer_size=100).batch(10)

print("Here are the item ID's near the epoch boundary:\n")
for n, line_batch in shuffled.skip(55).take(15):
  print(n.numpy())
Here are the item ID's near the epoch boundary:

[576 618 527   9 602 612  21 574 504 622]
[623  26  32 616 626 482 617 598   0 614]
[476   1 473  14  10 267  29  31  43  48]
[588  13 470 467  12 596 619  46  28 528]
[609   2  52 542 607  23  35  38 620 523]
[509 477 571  15  56  74 565 525  58  19]
[359  40  22 627 317  54 526  16 562  33]
[ 67 500 584 531  49  86  51  81  78 583]
[ 24 557 452  47 124 485 610  45  27  17]
[379  66  85  91 599  97 499 112 108  11]
[ 39 164 101  96 543  64 109 564  82  18]
[533 120  30  63 115  88  95  75 133  34]
[ 92  65 102 132  76 119 131 475 572  50]
[ 94 145 144 603 152 505 621 140 448 122]
[ 70 159 146  84  71 160  42  72  41 139]

repeat_shuffle = [n.numpy().mean() for n, line_batch in shuffled]

plt.plot(shuffle_repeat, label="shuffle().repeat()")
plt.plot(repeat_shuffle, label="repeat().shuffle()")
plt.ylabel("Mean item ID")
plt.legend()
<matplotlib.legend.Legend at 0x7f3f0838c860>

png

Ön işleme verileri

Dataset.map(f) dönüşümü, girdi veri kümesinin her bir öğesine belirli bir f işlevini uygulayarak yeni bir veri kümesi üretir. İşlevsel programlama dillerinde listelere (ve diğer yapılara) yaygın olarak uygulanan map() işlevine dayanmaktadır. f işlevi, tf.Tensor tek bir öğeyi temsil eden tf.Tensor nesnelerini alır ve yeni veri kümesindeki tek bir öğeyi temsil edecek tf.Tensor nesnelerini döndürür. Uygulaması, bir öğeyi diğerine dönüştürmek için standart TensorFlow işlemlerini kullanır.

Bu bölüm, Dataset.map() nin nasıl kullanılacağına Dataset.map() yaygın örnekleri kapsar.

Görüntü verilerinin kodunu çözme ve yeniden boyutlandırma

Bir sinir ağını gerçek dünyadaki görüntü verileri üzerinde eğitirken, genellikle farklı boyutlardaki görüntüleri ortak bir boyuta dönüştürmek gerekir, böylece sabit bir boyuta toplu hale getirilebilirler.

Çiçek dosya adları veri kümesini yeniden oluşturun:

list_ds = tf.data.Dataset.list_files(str(flowers_root/'*/*'))

Veri kümesi öğelerini işleyen bir işlev yazın.

# Reads an image from a file, decodes it into a dense tensor, and resizes it
# to a fixed shape.
def parse_image(filename):
  parts = tf.strings.split(filename, os.sep)
  label = parts[-2]

  image = tf.io.read_file(filename)
  image = tf.image.decode_jpeg(image)
  image = tf.image.convert_image_dtype(image, tf.float32)
  image = tf.image.resize(image, [128, 128])
  return image, label

Çalıştığını test edin.

file_path = next(iter(list_ds))
image, label = parse_image(file_path)

def show(image, label):
  plt.figure()
  plt.imshow(image)
  plt.title(label.numpy().decode('utf-8'))
  plt.axis('off')

show(image, label)

png

Veri kümesi üzerinde eşleyin.

images_ds = list_ds.map(parse_image)

for image, label in images_ds.take(2):
  show(image, label)

png

png

Keyfi Python mantığını uygulama

Performans nedenleriyle, verilerinizi mümkün olduğunca önişlemek için TensorFlow işlemlerini kullanın. Ancak, bazen girdi verilerinizi ayrıştırırken harici Python kitaplıklarını çağırmak yararlı olabilir. Dataset.map() dönüşümünde tf.py_function() işlemini kullanabilirsiniz.

Örneğin, rastgele bir döndürme uygulamak istiyorsanız, tf.image modülünde yalnızca tf.image.rot90 ve bu, görüntü büyütme için pek kullanışlı değildir.

Göstermek için tf.py_function , kullanmayı deneyin scipy.ndimage.rotate yerine işlevi:

import scipy.ndimage as ndimage

def random_rotate_image(image):
  image = ndimage.rotate(image, np.random.uniform(-30, 30), reshape=False)
  return image
image, label = next(iter(images_ds))
image = random_rotate_image(image)
show(image, label)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

png

Bu fonksiyonu kullanmak için Dataset.map aynı uyarılar olduğu gibi uygulamak Dataset.from_generator , size işlevini uyguladığınızda dönüş şekil ve türlerini tanımlamak gerekir:

def tf_random_rotate_image(image, label):
  im_shape = image.shape
  [image,] = tf.py_function(random_rotate_image, [image], [tf.float32])
  image.set_shape(im_shape)
  return image, label
rot_ds = images_ds.map(tf_random_rotate_image)

for image, label in rot_ds.take(2):
  show(image, label)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

png

png

tf.Example ayrıştırma. tf.Example protokol tampon mesajları

Birçok girdi ardışık tf.train.Example protokol arabellek mesajlarını bir TFRecord formatından çıkarır. Her tf.train.Example kaydı bir veya daha fazla "özellik" içerir ve giriş ardışık tf.train.Example tipik olarak bu özellikleri tensörlere dönüştürür.

fsns_test_file = tf.keras.utils.get_file("fsns.tfrec", "https://storage.googleapis.com/download.tensorflow.org/data/fsns-20160927/testdata/fsns-00000-of-00001")
dataset = tf.data.TFRecordDataset(filenames = [fsns_test_file])
dataset
<TFRecordDatasetV2 shapes: (), types: tf.string>

Sen çalışabilirsiniz tf.train.Example a protos dışarıdantf.data.Dataset verileri anlamak:

raw_example = next(iter(dataset))
parsed = tf.train.Example.FromString(raw_example.numpy())

feature = parsed.features.feature
raw_img = feature['image/encoded'].bytes_list.value[0]
img = tf.image.decode_png(raw_img)
plt.imshow(img)
plt.axis('off')
_ = plt.title(feature["image/text"].bytes_list.value[0])

png

raw_example = next(iter(dataset))
def tf_parse(eg):
  example = tf.io.parse_example(
      eg[tf.newaxis], {
          'image/encoded': tf.io.FixedLenFeature(shape=(), dtype=tf.string),
          'image/text': tf.io.FixedLenFeature(shape=(), dtype=tf.string)
      })
  return example['image/encoded'][0], example['image/text'][0]
img, txt = tf_parse(raw_example)
print(txt.numpy())
print(repr(img.numpy()[:20]), "...")
b'Rue Perreyon'
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02X' ...

decoded = dataset.map(tf_parse)
decoded
<MapDataset shapes: ((), ()), types: (tf.string, tf.string)>
image_batch, text_batch = next(iter(decoded.batch(10)))
image_batch.shape
TensorShape([10])

Zaman serisi pencereleme

Uçtan uca zaman serisi örneği için bkz: Zaman serisi tahmini .

Zaman serisi verileri genellikle zaman ekseni bozulmadan düzenlenir.

Dataset.range için basit bir Dataset.range kullanın:

range_ds = tf.data.Dataset.range(100000)

Tipik olarak, bu tür verilere dayalı modeller bitişik bir zaman dilimi isteyecektir.

En basit yaklaşım, verileri gruplamak olacaktır:

batch kullanma

batches = range_ds.batch(10, drop_remainder=True)

for batch in batches.take(5):
  print(batch.numpy())
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]

Ya da geleceğe doğru bir adım ileride yoğun tahminlerde bulunmak için, özellikleri ve etiketleri birbirine göre bir adım kaydırabilirsiniz:

def dense_1_step(batch):
  # Shift features and labels one step relative to each other.
  return batch[:-1], batch[1:]

predict_dense_1_step = batches.map(dense_1_step)

for features, label in predict_dense_1_step.take(3):
  print(features.numpy(), " => ", label.numpy())
[0 1 2 3 4 5 6 7 8]  =>  [1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18]  =>  [11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28]  =>  [21 22 23 24 25 26 27 28 29]

Sabit bir ofset yerine tüm bir pencereyi tahmin etmek için grupları iki bölüme ayırabilirsiniz:

batches = range_ds.batch(15, drop_remainder=True)

def label_next_5_steps(batch):
  return (batch[:-5],   # Take the first 5 steps
          batch[-5:])   # take the remainder

predict_5_steps = batches.map(label_next_5_steps)

for features, label in predict_5_steps.take(3):
  print(features.numpy(), " => ", label.numpy())
[0 1 2 3 4 5 6 7 8 9]  =>  [10 11 12 13 14]
[15 16 17 18 19 20 21 22 23 24]  =>  [25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]  =>  [40 41 42 43 44]

Bir grubun özellikleri ile diğerinin etiketleri arasında bir miktar örtüşmeye izin vermek için Dataset.zip kullanın:

feature_length = 10
label_length = 3

features = range_ds.batch(feature_length, drop_remainder=True)
labels = range_ds.batch(feature_length).skip(1).map(lambda labels: labels[:label_length])

predicted_steps = tf.data.Dataset.zip((features, labels))

for features, label in predicted_steps.take(5):
  print(features.numpy(), " => ", label.numpy())
[0 1 2 3 4 5 6 7 8 9]  =>  [10 11 12]
[10 11 12 13 14 15 16 17 18 19]  =>  [20 21 22]
[20 21 22 23 24 25 26 27 28 29]  =>  [30 31 32]
[30 31 32 33 34 35 36 37 38 39]  =>  [40 41 42]
[40 41 42 43 44 45 46 47 48 49]  =>  [50 51 52]

window kullanarak

Dataset.batch kullanılırken daha hassas kontrole ihtiyaç duyabileceğiniz durumlar vardır. Dataset.window yöntemi size tam kontrol sağlar, ancak biraz özen gerektirir: bir Dataset Datasets Dataset döndürür. Ayrıntılar için Veri kümesi yapısına bakın.

window_size = 5

windows = range_ds.window(window_size, shift=1)
for sub_ds in windows.take(5):
  print(sub_ds)
<_VariantDataset shapes: (), types: tf.int64>
<_VariantDataset shapes: (), types: tf.int64>
<_VariantDataset shapes: (), types: tf.int64>
<_VariantDataset shapes: (), types: tf.int64>
<_VariantDataset shapes: (), types: tf.int64>

Dataset.flat_map yöntemi, veri kümelerinden oluşan bir veri kümesini alabilir ve bunu tek bir veri kümesinde düzleştirebilir:

for x in windows.flat_map(lambda x: x).take(30):
   print(x.numpy(), end=' ')
0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 

Neredeyse tüm durumlarda, önce veri kümesini .batch isteyeceksiniz:

def sub_to_batch(sub):
  return sub.batch(window_size, drop_remainder=True)

for example in windows.flat_map(sub_to_batch).take(5):
  print(example.numpy())
[0 1 2 3 4]
[1 2 3 4 5]
[2 3 4 5 6]
[3 4 5 6 7]
[4 5 6 7 8]

Şimdi, shift argümanının her pencerenin ne kadar hareket edeceğini kontrol ettiğini görebilirsiniz.

Bunu bir araya getirerek şu işlevi yazabilirsiniz:

def make_window_dataset(ds, window_size=5, shift=1, stride=1):
  windows = ds.window(window_size, shift=shift, stride=stride)

  def sub_to_batch(sub):
    return sub.batch(window_size, drop_remainder=True)

  windows = windows.flat_map(sub_to_batch)
  return windows
ds = make_window_dataset(range_ds, window_size=10, shift = 5, stride=3)

for example in ds.take(10):
  print(example.numpy())
[ 0  3  6  9 12 15 18 21 24 27]
[ 5  8 11 14 17 20 23 26 29 32]
[10 13 16 19 22 25 28 31 34 37]
[15 18 21 24 27 30 33 36 39 42]
[20 23 26 29 32 35 38 41 44 47]
[25 28 31 34 37 40 43 46 49 52]
[30 33 36 39 42 45 48 51 54 57]
[35 38 41 44 47 50 53 56 59 62]
[40 43 46 49 52 55 58 61 64 67]
[45 48 51 54 57 60 63 66 69 72]

Ardından, daha önce olduğu gibi etiketleri çıkarmak kolaydır:

dense_labels_ds = ds.map(dense_1_step)

for inputs,labels in dense_labels_ds.take(3):
  print(inputs.numpy(), "=>", labels.numpy())
[ 0  3  6  9 12 15 18 21 24] => [ 3  6  9 12 15 18 21 24 27]
[ 5  8 11 14 17 20 23 26 29] => [ 8 11 14 17 20 23 26 29 32]
[10 13 16 19 22 25 28 31 34] => [13 16 19 22 25 28 31 34 37]

Yeniden örnekleme

Sınıf açısından oldukça dengesiz bir veri kümesiyle çalışırken, veri kümesini yeniden örneklemek isteyebilirsiniz. tf.data bunu yapmak için iki yöntem sağlar. Kredi kartı dolandırıcılığı veri kümesi, bu tür bir soruna iyi bir örnektir.

zip_path = tf.keras.utils.get_file(
    origin='https://storage.googleapis.com/download.tensorflow.org/data/creditcard.zip',
    fname='creditcard.zip',
    extract=True)

csv_path = zip_path.replace('.zip', '.csv')
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/creditcard.zip
69156864/69155632 [==============================] - 3s 0us/step

creditcard_ds = tf.data.experimental.make_csv_dataset(
    csv_path, batch_size=1024, label_name="Class",
    # Set the column types: 30 floats and an int.
    column_defaults=[float()]*30+[int()])

Şimdi, sınıfların dağılımını kontrol edin, oldukça çarpık:

def count(counts, batch):
  features, labels = batch
  class_1 = labels == 1
  class_1 = tf.cast(class_1, tf.int32)

  class_0 = labels == 0
  class_0 = tf.cast(class_0, tf.int32)

  counts['class_0'] += tf.reduce_sum(class_0)
  counts['class_1'] += tf.reduce_sum(class_1)

  return counts
counts = creditcard_ds.take(10).reduce(
    initial_state={'class_0': 0, 'class_1': 0},
    reduce_func = count)

counts = np.array([counts['class_0'].numpy(),
                   counts['class_1'].numpy()]).astype(np.float32)

fractions = counts/counts.sum()
print(fractions)
[0.9952 0.0048]

Dengesiz bir veri kümesiyle eğitime yönelik yaygın bir yaklaşım, onu dengelemektir. tf.data , bu iş akışını etkinleştiren birkaç yöntem içerir:

Veri kümeleri örnekleme

Bir veri kümesini yeniden örneklemeye yönelik bir yaklaşım, sample_from_datasets kullanmaktır. Bu, her sınıf için ayrı birdata.Dataset sahip olduğunuzda daha uygulanabilirdir.

Burada, kredi kartı dolandırıcılık verilerinden oluşturmak için filtreyi kullanın:

negative_ds = (
  creditcard_ds
    .unbatch()
    .filter(lambda features, label: label==0)
    .repeat())
positive_ds = (
  creditcard_ds
    .unbatch()
    .filter(lambda features, label: label==1)
    .repeat())
for features, label in positive_ds.batch(10).take(1):
  print(label.numpy())
[1 1 1 1 1 1 1 1 1 1]

tf.data.experimental.sample_from_datasets kullanmak için veri kümelerini ve her birinin ağırlığını tf.data.experimental.sample_from_datasets :

balanced_ds = tf.data.experimental.sample_from_datasets(
    [negative_ds, positive_ds], [0.5, 0.5]).batch(10)

Artık veri kümesi, her bir sınıfın örneklerini 50/50 olasılıkla üretir:

for features, labels in balanced_ds.take(10):
  print(labels.numpy())
[1 0 1 0 1 1 0 0 1 0]
[0 0 1 1 1 1 0 0 1 1]
[1 1 0 1 1 0 1 1 0 0]
[1 0 1 1 0 0 0 0 0 1]
[1 1 0 1 1 0 0 0 1 0]
[1 0 1 1 1 0 0 0 1 1]
[0 1 1 0 0 0 1 0 1 0]
[0 1 1 1 1 0 1 1 1 0]
[0 0 1 1 1 1 0 0 1 1]
[0 0 0 0 1 0 0 1 0 0]

Reddetme yeniden örnekleme

Yukarıdaki experimental.sample_from_datasets yaklaşımıyla ilgili bir sorun, sınıf başına ayrı birtf.data.Dataset gerektirmesidir. Dataset.filter kullanmak çalışır, ancak tüm verilerin iki kez yüklenmesine neden olur.

data.experimental.rejection_resample işlevi, bir veri kümesini yalnızca bir kez yüklerken yeniden dengelemek için uygulanabilir. Dengeyi sağlamak için veri kümesinden öğeler çıkarılacaktır.

data.experimental.rejection_resample bir class_func bağımsız değişkeni alır. Bu class_func , her veri kümesi öğesine uygulanır ve dengeleme amacıyla bir örneğin hangi sınıfa ait olduğunu belirlemek için kullanılır.

creditcard_ds öğeleri zaten (features, label) çiftleridir. Dolayısıyla, class_func yalnızca bu etiketleri döndürmelidir:

def class_func(features, label):
  return label

Yeniden örnekleyicinin ayrıca bir hedef dağıtıma ve isteğe bağlı olarak bir ilk dağıtım tahminine ihtiyacı vardır:

resampler = tf.data.experimental.rejection_resample(
    class_func, target_dist=[0.5, 0.5], initial_dist=fractions)

Yeniden örnekleyici, ayrı örneklerle ilgilenir, bu nedenle yeniden örnekleyiciyi uygulamadan önce veri kümesini unbatch gerekir:

resample_ds = creditcard_ds.unbatch().apply(resampler).batch(10)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/data/experimental/ops/resampling.py:156: Print (from tensorflow.python.ops.logging_ops) is deprecated and will be removed after 2018-08-20.
Instructions for updating:
Use tf.print instead of tf.Print. Note that tf.print returns a no-output operator that directly prints the output. Outside of defuns or eager mode, this operator will not be executed unless it is directly specified in session.run or used as a control dependency for other operators. This is only a concern in graph mode. Below is an example of how to ensure tf.print executes in graph mode:


Yeniden örnekleyici, class_func çıktısından (class, example) çiftler oluşturur. Bu durumda, example bir zaten (feature, label) kullanımı çifti, bu yüzden map etiketlerin fazladan bir kopyasını düşmesi:

balanced_ds = resample_ds.map(lambda extra_label, features_and_label: features_and_label)

Artık veri kümesi, her sınıfın örneklerini 50/50 olasılıkla üretir:

for features, labels in balanced_ds.take(10):
  print(labels.numpy())
[0 1 0 1 1 1 0 1 1 1]
[0 1 1 1 1 0 1 0 0 1]
[1 0 1 1 0 1 0 1 1 1]
[1 0 0 1 1 0 0 0 1 0]
[1 1 1 1 1 0 0 0 1 0]
[0 0 0 0 1 0 1 1 0 1]
[0 1 0 1 1 1 0 1 1 0]
[1 0 0 0 0 1 0 1 0 0]
[0 1 1 1 0 1 1 1 1 0]
[0 1 1 1 1 0 1 1 1 0]

Yineleyici Kontrol İşaretleme

Tensorflow, eğitim süreciniz yeniden başladığında ilerlemesinin çoğunu kurtarmak için en son kontrol noktasını geri yükleyebilmesi için kontrol noktaları almayı destekler. Model değişkenlerini kontrol etmeye ek olarak, veri kümesi yineleyicisinin ilerlemesini de kontrol edebilirsiniz. Büyük bir veri kümeniz varsa ve veri kümesini her yeniden başlatmada baştan başlatmak istemiyorsanız bu yararlı olabilir. Ancak, shuffle ve prefetch gibi dönüşümler yineleyici içinde arabelleğe alma öğeleri gerektirdiğinden yineleyici denetim noktalarının büyük olabileceğini unutmayın.

Yineleyicinizi bir denetim noktasına dahil etmek için yineleyiciyi tf.train.Checkpoint yapıcısına tf.train.Checkpoint .

range_ds = tf.data.Dataset.range(20)

iterator = iter(range_ds)
ckpt = tf.train.Checkpoint(step=tf.Variable(0), iterator=iterator)
manager = tf.train.CheckpointManager(ckpt, '/tmp/my_ckpt', max_to_keep=3)

print([next(iterator).numpy() for _ in range(5)])

save_path = manager.save()

print([next(iterator).numpy() for _ in range(5)])

ckpt.restore(manager.latest_checkpoint)

print([next(iterator).numpy() for _ in range(5)])
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[5, 6, 7, 8, 9]

Tf.data'yı tf.keras ile kullanma

tf.keras API, makine öğrenimi modellerini oluşturmanın ve tf.keras birçok yönünü basitleştirir. .fit() ve .evaluate() ve .predict() API'leri veri kümelerini girdi olarak destekler. İşte hızlı bir veri kümesi ve model kurulumu:

train, test = tf.keras.datasets.fashion_mnist.load_data()

images, labels = train
images = images/255.0
labels = labels.astype(np.int32)
fmnist_train_ds = tf.data.Dataset.from_tensor_slices((images, labels))
fmnist_train_ds = fmnist_train_ds.shuffle(5000).batch(32)

model = tf.keras.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(10)
])

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), 
              metrics=['accuracy'])

Model.fit ve Model.evaluate için gereken tek şey (feature, label) çiftinden oluşan bir veri Model.evaluate :

model.fit(fmnist_train_ds, epochs=2)
Epoch 1/2
1875/1875 [==============================] - 4s 2ms/step - loss: 0.7804 - accuracy: 0.7374
Epoch 2/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4711 - accuracy: 0.8393

<tensorflow.python.keras.callbacks.History at 0x7f3ef05b1390>

Örneğin Dataset.repeat() çağırarak sonsuz bir veri kümesi geçirirseniz, steps_per_epoch bağımsız değişkenini de steps_per_epoch gerekir:

model.fit(fmnist_train_ds.repeat(), epochs=2, steps_per_epoch=20)
Epoch 1/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4312 - accuracy: 0.8562
Epoch 2/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4509 - accuracy: 0.8344

<tensorflow.python.keras.callbacks.History at 0x7f3ef062e198>

Değerlendirme için değerlendirme adımlarının sayısını geçebilirsiniz:

loss, accuracy = model.evaluate(fmnist_train_ds)
print("Loss :", loss)
print("Accuracy :", accuracy)
1875/1875 [==============================] - 4s 2ms/step - loss: 0.4347 - accuracy: 0.8516
Loss : 0.43466493487358093
Accuracy : 0.8515999913215637

Uzun veri kümeleri için değerlendirilecek adımların sayısını ayarlayın:

loss, accuracy = model.evaluate(fmnist_train_ds.repeat(), steps=10)
print("Loss :", loss)
print("Accuracy :", accuracy)
10/10 [==============================] - 0s 2ms/step - loss: 0.4131 - accuracy: 0.8750
Loss : 0.41311272978782654
Accuracy : 0.875

Model.predict etiketlere gerek Model.predict .

predict_ds = tf.data.Dataset.from_tensor_slices(images).batch(32)
result = model.predict(predict_ds, steps = 10)
print(result.shape)
(320, 10)

Ancak, bunları içeren bir veri kümesini geçirirseniz etiketler yok sayılır:

result = model.predict(fmnist_train_ds, steps = 10)
print(result.shape)
(320, 10)