Google I / O, 18-20 Mayıs'ta geri dönüyor! Yer ayırın ve programınızı oluşturun Şimdi kaydolun

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'si, 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, giriş verileriniz önerilen TFRecord biçiminde 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 bir eleman bileşenlerinin aynı (iç içe) bir yapıdır elemanları, bir dizi üretir. Yapının ayrı ayrı bileşenleri tf.TypeSpec tarafından temsil edilebilen herhangi bir türde olabilir; tf.Tensor , tf.sparse.SparseTensor ,tf.RaggedTensor , tf.TensorArray veyatf.data.Dataset .

Elemanların (iç içe geçmiş) yapısını ifade etmek için kullanılabilen Python yapıları arasında tuple , dict , NamedTuple ve OrderedDict . Özellikle list , veri kümesi öğelerinin yapısını ifade etmek için geçerli bir yapı değildir. Bunun nedeni, erken tf.data kullanıcılarının list girdilerinin (ör. tf.data.Dataset.from_tensors ) otomatik olarak tensörler olarak paketlendiğini ve list çıktılarının (ör. Kullanıcı tanımlı işlevlerin dönüş değerleri) bir tuple halinde zorlandığını tuple . Sonuç olarak, bir istiyorsanız, list bir yapı olarak tedavi edilecek girişi, sen dönüştürmek için gereken tuple ve bir isterseniz list tek bir bileşen olarak çıktı, o zaman açıkça kullanarak paketi gerekir tf.stack .

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 ve öğenin yapısıyla eşleşen, tek bir bileşen, bileşenlerin demeti veya iç içe geçmiş bileşen demeti olabilir. Ö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())
[8 6 2 1 5 3 8 8 3 6]
[6 8 8 8 5 4 5 1 3 3]
[2 9 9 1 9 2 8 9 4 6]
[1 1 4 1 5 7 1 9 6 7]
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 bilinmiyor 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 : [-0.7193  0.1489  0.3015]
1 : [ 0.9257 -0.8073  1.1848 -0.4203 -0.5188 -1.7014 -1.0934  2.6323]
2 : [-0.2845 -0.3942  0.8429 -0.2441  0.8038]
3 : [ 0.0553 -0.2246]
4 : [ 0.5449 -0.0552 -0.4308 -0.5846  0.2252  0.475  -0.6507  1.3336 -0.6148]
5 : []
6 : [-0.0788 -0.2671 -0.5868 -1.038  -0.145 ]

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

İlk öğe bir skaler, şekil () ve ikincisi, bilinmeyen uzunlukta bir vektör, şekil (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 şekle sahip 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())
[14  2 16 18  5 13  3  4  0 25]

[[ 2.2655e-03 -1.1356e+00 -6.3269e-01  0.0000e+00  0.0000e+00  0.0000e+00
   0.0000e+00  0.0000e+00  0.0000e+00]
 [ 5.9163e-01  1.1532e-01 -9.4578e-01 -5.7305e-01  5.8756e-01 -8.3086e-01
   1.0705e+00  4.6149e-01 -7.8259e-01]
 [ 8.7261e-01 -1.4031e+00  2.1707e-01  0.0000e+00  0.0000e+00  0.0000e+00
   0.0000e+00  0.0000e+00  0.0000e+00]
 [ 0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00
   0.0000e+00  0.0000e+00  0.0000e+00]
 [ 2.2473e-01 -4.9448e-02 -5.0318e-01 -7.6812e-01 -5.9628e-01  0.0000e+00
   0.0000e+00  0.0000e+00  0.0000e+00]
 [-5.1477e-01  0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00  0.0000e+00
   0.0000e+00  0.0000e+00  0.0000e+00]
 [-1.3577e+00  7.6869e-02  1.3755e+00  1.1951e-01  0.0000e+00  0.0000e+00
   0.0000e+00  0.0000e+00  0.0000e+00]
 [ 1.4727e+00  5.2939e-01  1.1665e-01  6.6326e-01  0.0000e+00  0.0000e+00
   0.0000e+00  0.0000e+00  0.0000e+00]
 [-1.5769e+00  7.4631e-01  8.4916e-01  5.3781e-01 -2.3621e+00  1.0438e-01
   9.3234e-01  0.0000e+00  0.0000e+00]
 [-1.7867e+00 -1.5707e+00  1.7925e-02  0.0000e+00  0.0000e+00  0.0000e+00
   0.0000e+00  0.0000e+00  0.0000e+00]]

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 [==============================] - 6s 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ıklamanın kolay bir yolunu 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 ve 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 kullanma

Daha fazla örnek için bkz. CSV Dosyalarını Yükleme ve Pandas DataFrame'leri 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': [1 1 0 1]
features:
  'sex'               : [b'female' b'male' b'male' b'female']
  'age'               : [27. 48. 28. 50.]
  'n_siblings_spouses': [0 1 0 0]
  'parch'             : [2 0 0 0]
  'fare'              : [11.1333 76.7292  7.8958 10.5   ]
  'class'             : [b'Third' b'First' b'Third' b'Second']
  'deck'              : [b'unknown' b'D' b'unknown' b'unknown']
  'embark_town'       : [b'Southampton' b'Cherbourg' b'Southampton' b'Southampton']
  'alone'             : [b'n' b'n' b'y' b'y']

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': [1 0 0 0]
  'fare'              : [29.7     7.8958 15.0458  7.75  ]
  'class'             : [b'First' b'Third' b'Second' 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 bağımsız değişkenleri 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/7652532108_01ef94c476.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/3276552939_8c31b22d3e.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/4363734507_5cc4ed6e01.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/20754920332_53b995fc63_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/15219268336_f2460fca88_m.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\xed\x00\x1cPhotoshop 3.0\x008BIM\x04\x04\x00\x00\x00\x00\x00\x00\xff\xdb\x00C\x00\x03\x02\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\n\x07\x07\x06\x08\x0c\n\x0c\x0c\x0b\n\x0b\x0b\r\x0e\x12\x10\r\x0e\x11\x0e\x0b\x0b\x10'

b'daisy'

Veri kümesi öğelerini gruplama

Basit gruplama

En basit gruplama biçimi, bir veri kümesinin n ardışık elemanını tek bir eleman halinde 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ı şekilde 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 toplu iş boyutuyla sonuçlanır. Şekildeki None edin:

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

Son partiyi 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 dolgu 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.

Birden çok çağda bir veri kümesi üzerinde 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 tekrarlayacaktır.

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 verilerinin rastgele karıştırılması

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())
[ 36  72  81  39  19  32  70  11  64  18  56  86  30  40 111  80  87  13
 110 116]

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

Dataset.shuffle , karıştırma arabelleği boşalıncaya 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österecektir:

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:

[622 295 617 552 465 394 592 593 442 488]
[469 543 329 600 359 471 554 627 620 456]
[565 550 563 464 556 618 587 449]
[20  0 71  8 25 86 10 57 72  2]
[ 78  99  85  36  62  13 108  46  56  97]
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 0x7fcccbcea860>

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:

[607 519 555 627  23 469   9 501   2 500]
[546 470  14  21 583 552  15 539 340  30]
[620  29 586 570 250   6 599 498 618 610]
[ 16  25 518 505 465 418  12  22  59  51]
[ 10 558  47 553  52   7 616 454 561 597]
[363  68 441 530  75 603  57 339  64  37]
[ 46 388 626  39 600 577 609 467 451  44]
[601  78 537  69 514  54  11 613 502  32]
[ 62  76  85 391  34  65  36 105 541  96]
[548 576 107  61 543  19 527  72 111  38]
[ 98  26  43  70 463 581 115 559 590  86]
[ 50 594  77 490  55 108 370  63  87  94]
[122  27 136  73 617 535  40 144 112  24]
[ 67  99 151 128   5 154 120   4 343 102]
[625 132  83  35 356  80 130  60 156 100]
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 0x7fccb44c5f28>

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 dayanı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. Uygulanması, 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ünya 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şleştirin.

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 önceden iş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ırılıyor. tf.Example protokol arabellek 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 daha 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]

Daha sonra, 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 çok 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 bunları oluşturmak için filtre 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 sınıfın örneklerini 50/50 olasılıkla üretir:

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

Reddetme yeniden örnekleme

Yukarıdaki experimental.sample_from_datasets yaklaşımıyla ilgili bir sorun, sınıf başına ayrı birtf.data.Dataset ihtiyaçtf.data.Dataset . 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())
[1 0 0 0 1 1 1 0 0 1]
[0 1 1 0 1 1 1 0 0 0]
[0 0 0 0 1 0 0 1 1 0]
[0 0 1 1 0 1 1 1 0 0]
[0 1 0 1 0 0 0 0 0 0]
[0 0 0 1 0 1 1 0 1 0]
[1 0 0 1 0 1 1 1 0 1]
[0 0 0 0 0 1 0 1 1 1]
[1 0 1 0 1 0 0 0 1 1]
[0 1 0 0 0 1 0 0 0 0]

Yineleyici Denetim Noktası Oluşturma

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.7767 - accuracy: 0.7407
Epoch 2/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4709 - accuracy: 0.8387
<tensorflow.python.keras.callbacks.History at 0x7fcca40a2080>

Ö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.4301 - accuracy: 0.8609
Epoch 2/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4454 - accuracy: 0.8281
<tensorflow.python.keras.callbacks.History at 0x7fccb416bd30>

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.4484 - accuracy: 0.8435
Loss : 0.4483910799026489
Accuracy : 0.843500018119812

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.4643 - accuracy: 0.8531
Loss : 0.4643370509147644
Accuracy : 0.8531249761581421

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)