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

tf.data: TensorFlow giriş boru hatları oluşturma

TensorFlow.org üzerinde görüntüle Google Colab'da yayınla Kaynağı GitHub'da görüntüle Not defterini indir

tf.data API, basit, tekrar kullanılabilir parçalardan karmaşık giriş boru hatları oluşturmanıza olanak tanır. Örneğin, bir görüntü modeli için ardışık düzen, dağıtılmış bir dosya sistemindeki dosyalardan veri toplayabilir, her görüntüye rastgele pertürbasyonlar uygulayabilir ve rastgele seçilen görüntüleri eğitim için toplu olarak birleştirebilir. Bir metin modeli için boru hattı, ham metin verilerinden sembollerin çıkarılmasını, bir arama tablosu ile tanımlayıcıları gömmeye dönüştürülmesini ve farklı uzunluklardaki dizileri toplu olarak birleştirmeyi içerebilir. tf.data API, büyük miktarda veriyi işlemeyi, farklı veri formatlarından okuma ve karmaşık dönüşümler gerçekleştirmeyi mümkün kılar.

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

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

  • Veri kaynağı , bellekte veya bir veya daha fazla dosyada saklanan verilerden bir Dataset oluşturur.

  • Veri dönüşümü bir veya daha fazla tf.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ş kanalı 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ırsa, tf.data.TFRecordDataset() kullanabilirsiniz.

Bir Dataset nesneniz olduğunda, 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çin tf.data.Dataset belgelerine bakın.

Dataset nesnesi bir Python yinelemelidir. 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

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

 it = iter(dataset)

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

Alternatif olarak, veri kümesi elemanları, tek bir sonuç elde etmek için tüm elemanları reduce dönüştürme dönüşümünü kullanarak tüketilebilir. Aşağıdaki örnek, bir tamsayı 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 , veya tf.data.Dataset .

Dataset.element_spec özelliği, her öğe bileşeninin türünü denetlemenizi sağlar. Özellik, tf.TypeSpec nesnelerinin iç içe geçmiş bir yapısını döndürür; tek bir bileşen, bir bileşen tf.TypeSpec veya iç içe geçmiş bir bileşen tf.TypeSpec 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 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 1 2 6 1 7 2 6 1 3]
[6 5 6 5 3 5 2 5 3 6]
[5 8 4 8 3 1 4 6 4 8]
[2 4 5 8 3 5 7 9 4 2]

 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 kullanma

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

Giriş verilerinizin tümü belleğe tf.Tensor , onlardan bir Dataset oluşturmanın en basit yolu bunları 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 [==============================] - 0s 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 kullanma

Bir tf.data.Dataset olarak kolayca alınabilen başka bir yaygın veri kaynağı da python üretecidir.

 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 bir tf.data.Dataset .

Yapıcı bir yineleyici değil, girdi olarak çağrılabilir alır. Bu, jeneratörün sonuna ulaştığında yeniden başlatmasını sağlar. args argüman olarak iletilen isteğe bağlı bir argüman argümanı 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, sıralaması bilinmeyen tensörleri desteklemediğinden şiddetle önerilir. Belirli bir eksenin uzunluğu bilinmiyor veya değişkense, output_shapes bunu None olarak output_shapes .

Bu dikkat etmek de önemlidir output_shapes ve output_types diğer veri kümesi yöntemleriyle aynı yuvalama kurallara tabidir.

İşte her iki yönü de gösteren bir örnek oluşturucu, dizilerin tuples'lerini döndürür, burada ikinci dizi bilinmeyen uzunlukta bir vektördü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.978  -1.0531  0.1959 -2.1618]
1 : [ 1.9185 -0.1874  0.5084]
2 : [0.1441 0.3987 0.7737 0.9266 1.5057 0.9151]
3 : [ 0.681  -0.6155 -0.1231 -0.2429  0.6892  1.2571 -1.7588 -1.6575 -0.5375]
4 : [-0.5567  1.5298  0.7242  0.2213]
5 : [ 1.5572 -0.6856]
6 : [-1.0965 -0.336   1.2405  0.6006]

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

İlk öğe skaler, şekil () ve ikincisi bilinmeyen uzunluk, şekil (None,) Vektö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)>

Şimdi normal bir tf.data.Dataset gibi kullanılabilir. Değişken şekilli bir veri kümesini 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())
 
[ 2 10 18  3  6 15 25 23  0  4]

[[ 1.2665 -0.6274  0.4076  1.0146  0.      0.      0.      0.    ]
 [ 0.8091 -0.0683 -0.1464  0.2734  0.7461 -0.1009  0.      0.    ]
 [-0.9381  1.5075  0.      0.      0.      0.      0.      0.    ]
 [ 1.5705  0.4438  0.      0.      0.      0.      0.      0.    ]
 [-0.4692 -1.8328 -2.2838  0.7418  0.0172 -0.3547 -1.4502 -1.2786]
 [-1.574   0.      0.      0.      0.      0.      0.      0.    ]
 [-0.9274  1.4758  0.      0.      0.      0.      0.      0.    ]
 [-0.5043  0.7066  0.9599 -1.2986  0.      0.      0.      0.    ]
 [ 0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-0.4893 -0.6937  0.      0.      0.      0.      0.      0.    ]]

Daha gerçekçi bir örnek için preprocessing.image.ImageDataGenerator bir tf.data.Dataset olarak kaydırmayı deneyin.

İlk ö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 [==============================] - 2s 0us/step

image.ImageDataGenerator oluşturun. image.ImageDataGenerator

 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(
    img_gen.flow_from_directory, args=[flowers], 
    output_types=(tf.float32, tf.float32), 
    output_shapes=([32,256,256,3], [32,5])
)

ds
 
<FlatMapDataset shapes: ((32, 256, 256, 3), (32, 5)), types: (tf.float32, tf.float32)>

TFRecord verilerini kullanma

Uçtan uca bir örnek için TFRecords Yükleme konusuna 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, kayıt odaklı bir ikili biçimdir. tf.data.TFRecordDataset sınıfı, bir giriş kanalının parçası olarak bir veya daha fazla TFRecord dosyasının içeriği üzerinden akış gerçekleştirmenizi sağlar.

Fransız Sokak Adı İşaretleri'nden (FSNS) test dosyasını kullanan bir örnek.

 # 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, bir dize listesi veya bir tf.Tensor dizesi tf.Tensor . Bu nedenle, eğitim ve doğrulama amacıyla iki dosya kümeniz varsa, dosya adlarını girdi bağımsız değişkeni olarak alarak veri kümesini üreten bir fabrika yöntemi oluşturabilirsiniz:

 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 deşifre edilmesi 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 kullanma

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ırları ayıklamak için kolay bir yol sağlar. Bir veya daha fazla dosya adı verildiğinde, TextLineDataset bu dosyaların her satırı için bir dize değerine sahip öğe oluşturur.

 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)
 

İlk 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ındaki satırları değiştirmek için Dataset.interleave kullanın. Bu, dosyaları birlikte karıştırmayı kolaylaştırır. Her çeviriden 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, örneğin dosya bir başlık satırı ile başlıyorsa veya yorum içeriyorsa, istenmeyebilir. Bu çizgiler, Dataset.skip() veya Dataset.filter() dönüşümleri kullanılarak kaldırılabilir. Burada, ilk satırı atlayın, sonra sadece hayatta kalanları bulmak için filtreleyin.

 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 CSV Dosyalarını Yükleme ve Pandalar Veri Çerçevelerini Yükleme konusuna bakın.

CSV dosya biçimi, sekmeli verileri düz metin olarak saklamak için popüler bir biçimdir.

Ö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, index_col=None)
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ükleme yapmaktır.

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

experimental.make_csv_dataset işlevi, csv dosyalarının setlerini okumak için yüksek seviye arayüzdür. 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 1 0 0]
features:
  'sex'               : [b'male' b'female' b'male' b'male']
  'age'               : [28. 42. 43. 21.]
  'n_siblings_spouses': [0 0 0 0]
  'parch'             : [0 0 0 0]
  'fare'              : [47.1    13.      8.05    8.6625]
  'class'             : [b'First' b'Second' b'Third' b'Third']
  'deck'              : [b'unknown' b'unknown' b'unknown' b'unknown']
  'embark_town'       : [b'Southampton' b'Southampton' b'Southampton' b'Southampton']
  'alone'             : [b'y' b'y' 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 1 1]
  'fare'              : [24.15    0.     13.8583 53.1   ]
  'class'             : [b'Third' b'Second' b'Second' b'First']

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ü belirtmeniz gerekir.

 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 alt düzey 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 göz ardı edilmesi gereken bir başlık satırı ile başlıyorsa veya girişte bazı sütunlar gerekli değilse, dosyanın her satırının her sütununu verir. Bu satırlar ve alanlar, sırasıyla header ve select_cols bağımsız değişkenleriyle 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 kümelerini kullanma

Dosya kümesi olarak dağıtılan birçok veri kümesi vardır; burada her dosya bir örnektir.

 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 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/dandelion/7243478942_30bf542a2d_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/4525067924_177ea3bfb4.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/7002703410_3e97b29da5_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/6299910262_336309ffa5_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/6140661443_bb48344226.jpg'

tf.io.read_file işlevini kullanarak verileri okuyun ve etiketi (image, label) çiftleri döndürerek yoldan çıkarın:

 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\x01\x00H\x00H\x00\x00\xff\xe2\x0cXICC_PROFILE\x00\x01\x01\x00\x00\x0cHLino\x02\x10\x00\x00mntrRGB XYZ \x07\xce\x00\x02\x00\t\x00\x06\x001\x00\x00acspMSFT\x00\x00\x00\x00IEC sRGB\x00\x00\x00\x00\x00\x00'

b'tulips'

Toplu veri kümesi öğeleri

Basit dozajlama

Yığınları dozajları en basit bir şekilde n , tek bir eleman bir veri kümesinin ardışık elemanları. Dataset.batch() dönüşümü, öğelerin her bileşenine uygulanan tf.stack() işleciyle aynı kısıtlamalarla tam olarak bunu yapar: yani her bileşen i için , tüm öğelerin tam olarak aynı şekle sahip bir tensörü 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ı bilinmeyen bir toplu iş boyutuyla sonuçlanır, çünkü son toplu iş tam olmayabilir. None şeklindedir:

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

Son toplu işi yoksaymak 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)>

Dolgu ile dozaj tensörleri

Yukarıdaki tarif, hepsi aynı boyuta sahip tansörler için geçerlidir. Bununla birlikte, birçok model (örneğin dizi modelleri), değişen boyutlara sahip olabilen giriş verileriyle çalışır (örneğin, farklı uzunluklardaki diziler). Bu durumu ele almak için, Dataset.padded_batch dönüşümü, içinde yer Dataset.padded_batch bir veya daha fazla boyut belirterek farklı şekildeki tansörleri toplu hale Dataset.padded_batch sağlar.

 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 bir bileşenin her 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'si, aynı verilerin birden fazla tf.data için iki ana yol sunar.

Birden çok çağda veri kümesi üzerinde yineleme yapmanın en basit yolu Dataset.repeat() dönüşümünü kullanmaktır. İlk olarak, bir titanik veri 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ü bağımsız değişken olmadan uygulamak, girdiyi süresiz olarak tekrarlar.

Dataset.repeat dönüşümü, bir çağın sonunu ve bir sonraki çağın başlangıcını bildirmeden argümanlarını 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 ayırmaya ihtiyacınız varsa, Dataset.batch önce 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) yapmak istiyorsanız, her çağda veri kümesi yinelemesini yeniden başlatmak en basit yöntemdir:

 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

Giriş verilerini rastgele karıştırma

Dataset.shuffle() dönüşümü, sabit boyutlu bir arabelleği korur ve bir sonraki öğeyi, bu arabelleğe göre rasgele bir şekilde seçer.

Efekti 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 ve parti boyutu 20 olduğundan, ilk parti 120'den fazla indeksi olan eleman içermez.

 n,line_batch = next(iter(dataset))
print(n.numpy())
 
[ 63  48 101  12 103  52   6  39   4   9  93  91   5  86  79  64  95  33
 102  50]

Dataset.batch ile olduğu gibi. Dataset.batch göre siparişi Dataset.repeat olarak Dataset.repeat .

Dataset.shuffle , karıştırma arabelleği boşalana kadar bir dönemin sonunu işaret etmez. Bu nedenle, 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:

[613 609 624 553 608 583 493 617 611 610]
[217 508 579 601 319 616 606 549 618 623]
[416 567 404 622 283 458 503 602]
[ 87  68  56  16   6  62   1  89  58 106]
[98 80 43 10 67 44 19 34 13 57]

 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 0x7fe0a00a1d68>

png

Ancak, bir karıştırmadan önce tekrar, çağın sınırlarını 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:

[440  15   8 599 567  18 550   5  19  17]
[ 12 501 571 473 466  21 531 596 580 555]
[  3 573  38 563  25 416 595  29  46 602]
[485 566 561  16 331 615 386  28 609  41]
[611 622 575  10 589  61 598 527  52  35]
[ 55 597  42  23  13  47  11 505  68 582]
[612 613  75  43   7 392  74 452  82 509]
[  9  44  62 491  71 343  51 590  60  98]
[  6  95 619  86 625 537 617  85 465   0]
[ 88  27  92 101 109 111 104  24  36 113]
[103 118  79  53  70  40 121 100  65  33]
[562 588 124 125  64  84  83  67 610 130]
[  4 142 131  90 518 129 143 112   2 551]
[377  91 140  76  50  48 526 553 156 591]
[105 128  69 114  93 520 154  56 145 115]

 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 0x7fe0582fbb70>

png

Önişleme verileri

Dataset.map(f) dönüşümü, giriş veri kümesinin her öğesine belirli bir işlev f uygulanarak yeni bir veri kümesi oluşturur. İşlevsel programlama dillerindeki 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ümesinde tek bir öğeyi temsil edecek tf.Tensor nesnelerini döndürür. Uygulaması, bir elemanı diğerine dönüştürmek için standart TensorFlow işlemlerini kullanır.

Bu bölüm Dataset.map() nasıl kullanılacağına Dataset.map() yaygın örnekleri içerir.

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 yığınlanabilirler.

Ç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

Performansla ilgili nedenlerle, verilerinizi mümkün olduğunca önceden işlemek için TensorFlow işlemlerini kullanın. Ancak, giriş verilerinizi ayrıştırırken bazen harici Python kitaplıklarını çağırmak yararlı olabilir. Bir Dataset.map() dönüştürmesinde tf.py_function() işlemini kullanabilirsiniz.

Örneğin, rasgele bir döndürme uygulamak istiyorsanız, tf.image modülünde yalnızca görüntü büyütme için çok yararlı olmayan tf.image.rot90 .

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 protokol tampon mesajlarını ayrıştırma

Birçok giriş hattı tf.train.Example protokol tampon mesajlarını TFRecord formatından çıkarır. Her tf.train.Example kaydı bir veya daha fazla "özellik" içerir ve giriş kanalı genellikle 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>

Verileri anlamak için bir tf.data.Dataset dışındaki tf.train.Example protos ile tf.train.Example :

 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 olduğu gibi 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 dayanan modeller bitişik bir zaman dilimi isteyecektir.

En basit yaklaşım, verileri toplu olarak kullanmak 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 yoğun tahminler yapmak 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, partileri iki parçaya bölebilirsiniz:

 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 başka bir grubun etiketleri arasında bir miktar çakışmaya izin vermek için Dataset.zip kullanın:

 feature_length = 10
label_length = 5

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

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

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]
[10 11 12 13 14 15 16 17 18 19]  =>  [20 21 22 23 24]
[20 21 22 23 24 25 26 27 28 29]  =>  [30 31 32 33 34]

window kullanma

Dataset.batch çalışmalarını kullanırken daha hassas kontrole ihtiyaç duyabileceğiniz durumlar vardır. Dataset.window yöntemi size tam denetim sağlar, ancak biraz dikkat 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ümelerinin bir veri kümesini alıp tek bir veri kümesine düzleştirebilir:

  for x in windows.flat_map(lambda x: x).take(30):
   print(x.numpy(), end=' ')
 
WARNING:tensorflow:AutoGraph could not transform <function <lambda> at 0x7fe0582dbbf8> and will run it as-is.
Cause: could not parse the source code:

for x in windows.flat_map(lambda x: x).take(30):

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function <lambda> at 0x7fe0582dbbf8> and will run it as-is.
Cause: could not parse the source code:

for x in windows.flat_map(lambda x: x).take(30):

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
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 etmek istersiniz:

 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ı dengesiz olan 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ı sahtekarlığı veri kümesi bu tür sorunlara 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 [==============================] - 10s 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, çok eğri:

 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.996 0.004]

Dengesiz bir veri seti ile eğitim için ortak bir yaklaşım, onu dengelemektir. tf.data , bu iş akışını etkinleştiren birkaç yöntem içerir:

Veri kümesi örnekleme

Bir veri kümesini yeniden örneklemeye yönelik bir yaklaşım, sample_from_datasets kullanmaktır. Bu, ayrı bir data.Dataset olduğunda daha geçerlidir. Her sınıf için veri data.Dataset .

Burada, bunları kredi kartı sahtekarlığı verilerinden oluşturmak için filtreyi kullanmanız yeterlidir:

 negative_ds = (
  creditcard_ds
    .unbatch()
    .filter(lambda features, label: label==0)
    .repeat())
positive_ds = (
  creditcard_ds
    .unbatch()
    .filter(lambda features, label: label==1)
    .repeat())
 
WARNING:tensorflow:AutoGraph could not transform <function <lambda> at 0x7fe0a01fd1e0> and will run it as-is.
Cause: could not parse the source code:

    .filter(lambda features, label: label==0)

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function <lambda> at 0x7fe0a01fd1e0> and will run it as-is.
Cause: could not parse the source code:

    .filter(lambda features, label: label==0)

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:AutoGraph could not transform <function <lambda> at 0x7fe058159620> and will run it as-is.
Cause: could not parse the source code:

    .filter(lambda features, label: label==1)

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function <lambda> at 0x7fe058159620> and will run it as-is.
Cause: could not parse the source code:

    .filter(lambda features, label: label==1)

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert

 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)
 

Şimdi veri seti, her sınıftan 50/50 olasılıkla örnekler üretir:

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

Reddetme yeniden örnekleme

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

data.experimental.rejection_resample işlevi, yeniden dengelemek için veri kümesine yalnızca bir kez yüklenirken uygulanabilir. Dengeyi sağlamak için öğeler veri kümesinden düşecektir.

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. Yani class_func sadece bu etiketleri döndürmek gerekir:

 def class_func(features, label):
  return label
 

Yeniden örnekleyici ayrıca bir hedef dağılıma ve isteğe bağlı olarak bir ilk dağıtım tahminine ihtiyaç duyar:

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

Yeniden örnekleyici tek tek örneklerle ilgilenir, bu nedenle yeniden örnekleyiciyi uygulamadan önce veri kümesinin 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 oluşturur (class, example) çiftleri class_func . Bu durumda, example zaten bir (feature, label) çiftiydi, bu nedenle etiketlerin fazladan kopyasını bırakmak için map kullanın:

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

Şimdi veri seti, her bir sınıftan 50/50 olasılıkla örnekler üretir:

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

Yineleyici Kontrol Noktası

Tensorflow kontrol noktalarının alınmasını destekleyerek eğitim süreciniz yeniden başladığında ilerlemesinin çoğunu kurtarmak için en son kontrol noktasını geri yükleyebilir. 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 her yeniden başlatma işleminde veri kümesini baştan başlatmak istemiyorsanız bu yararlı olabilir. Ancak, shuffle ve prefetch gibi dönüşümler yineleyici içinde tamponlama öğeleri gerektirdiğinden yineleyici kontrol noktalarının büyük olabileceğine dikkat edin.

Yineleyicinizi bir kontrol 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]

Yüksek seviye API'ları kullanma

tf.keras

tf.keras API, makine öğrenimi modelleri oluşturma 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 Model.fit gereken (feature, label) çiftlerinin veri kümesini Model.fit Model.evaluate :

 model.fit(fmnist_train_ds, epochs=2)
 
Epoch 1/2
WARNING:tensorflow:Layer flatten is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2.  The layer has dtype float32 because it's dtype defaults to floatx.

If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2.

To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor.

1875/1875 [==============================] - 4s 2ms/step - loss: 0.6031 - accuracy: 0.7937
Epoch 2/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4620 - accuracy: 0.8416

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

Örneğin Dataset.repeat() çağırarak sonsuz bir veri kümesi Dataset.repeat() , sadece steps_per_epoch argümanını da 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.4050 - accuracy: 0.8672
Epoch 2/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4077 - accuracy: 0.8703

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

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 [==============================] - 3s 2ms/step - loss: 0.4474 - accuracy: 0.8439
Loss : 0.4474281072616577
Accuracy : 0.843916654586792

Uzun veri kümeleri için değerlendirilecek adım 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.5262 - accuracy: 0.8156
Loss : 0.5262183547019958
Accuracy : 0.815625011920929

Model.predict etiket gerekli değildir.

 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 iletirseniz etiketler yoksayılır:

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

tf.estimator

Bir kullanmak için Dataset içinde input_fn a tf.estimator.Estimator , basitçe dönmek Dataset gelen input_fn ve çerçeve sizin için kendi elemanlarını tüketen ilgilenir. Örneğin:

 import tensorflow_datasets as tfds

def train_input_fn():
  titanic = tf.data.experimental.make_csv_dataset(
      titanic_file, batch_size=32,
      label_name="survived")
  titanic_batches = (
      titanic.cache().repeat().shuffle(500)
      .prefetch(tf.data.experimental.AUTOTUNE))
  return titanic_batches
 
 embark = tf.feature_column.categorical_column_with_hash_bucket('embark_town', 32)
cls = tf.feature_column.categorical_column_with_vocabulary_list('class', ['First', 'Second', 'Third']) 
age = tf.feature_column.numeric_column('age')
 
 import tempfile
model_dir = tempfile.mkdtemp()
model = tf.estimator.LinearClassifier(
    model_dir=model_dir,
    feature_columns=[embark, cls, age],
    n_classes=2
)
 
INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpefmfuc4o', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

 model = model.train(input_fn=train_input_fn, steps=100)
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/resource_variable_ops.py:1666: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/feature_column/feature_column_v2.py:540: Layer.add_variable (from tensorflow.python.keras.engine.base_layer_v1) is deprecated and will be removed in a future version.
Instructions for updating:
Please use `layer.add_weight` method instead.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/ftrl.py:144: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Call initializer instance with the dtype argument instead of passing it to the constructor
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...
INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpefmfuc4o/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...
INFO:tensorflow:loss = 0.6931472, step = 0
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 100...
INFO:tensorflow:Saving checkpoints for 100 into /tmp/tmpefmfuc4o/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 100...
INFO:tensorflow:Loss for final step: 0.58668363.

 result = model.evaluate(train_input_fn, steps=10)

for key, value in result.items():
  print(key, ":", value)
 
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2020-07-23T01:23:29Z
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpefmfuc4o/model.ckpt-100
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [1/10]
INFO:tensorflow:Evaluation [2/10]
INFO:tensorflow:Evaluation [3/10]
INFO:tensorflow:Evaluation [4/10]
INFO:tensorflow:Evaluation [5/10]
INFO:tensorflow:Evaluation [6/10]
INFO:tensorflow:Evaluation [7/10]
INFO:tensorflow:Evaluation [8/10]
INFO:tensorflow:Evaluation [9/10]
INFO:tensorflow:Evaluation [10/10]
INFO:tensorflow:Inference Time : 0.83507s
INFO:tensorflow:Finished evaluation at 2020-07-23-01:23:30
INFO:tensorflow:Saving dict for global step 100: accuracy = 0.675, accuracy_baseline = 0.58125, auc = 0.71750116, auc_precision_recall = 0.6480325, average_loss = 0.64111984, global_step = 100, label/mean = 0.41875, loss = 0.64111984, precision = 0.85714287, prediction/mean = 0.30204886, recall = 0.26865673
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 100: /tmp/tmpefmfuc4o/model.ckpt-100
accuracy : 0.675
accuracy_baseline : 0.58125
auc : 0.71750116
auc_precision_recall : 0.6480325
average_loss : 0.64111984
label/mean : 0.41875
loss : 0.64111984
precision : 0.85714287
prediction/mean : 0.30204886
recall : 0.26865673
global_step : 100

 for pred in model.predict(train_input_fn):
  for key, value in pred.items():
    print(key, ":", value)
  break
 
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpefmfuc4o/model.ckpt-100
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
logits : [-0.5965]
logistic : [0.3551]
probabilities : [0.6449 0.3551]
class_ids : [0]
classes : [b'0']
all_class_ids : [0 1]
all_classes : [b'0' b'1']