tf.data: TensorFlow giriş işlem hatları oluşturun

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyinNot defterini indir

tf.data API'si basit, yeniden kullanılabilir parçalara karmaşık girdi boru hatlarını inşa etmek mümkün kılar. Örneğin, bir görüntü modeli için ardışık düzen, dağıtılmış bir dosya sistemindeki dosyalardan verileri toplayabilir, her görüntüye rastgele bozulmalar uygulayabilir ve rastgele seçilen görüntüleri eğitim için bir toplu iş halinde birleştirebilir. Bir metin modelinin boru hattı, ham metin verilerinden sembollerin çıkarılmasını, bunları bir arama tablosuyla gömme tanımlayıcılara dönüştürmeyi ve farklı uzunluklardaki dizileri bir araya toplamayı içerebilir. tf.data API mümkün, büyük miktarda veri işlemek farklı formatlar arasında okuyabilir ve karmaşık dönüşümleri gerçekleştirmek için yapar.

tf.data API getiren bir tf.data.Dataset soyutlama her bir eleman, bir ya da daha fazla bileşenden oluştuğu elemanların bir sekans, temsil eder. Ö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şeniyle tek bir eğitim örneği olabilir.

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

  • Bir veri kaynağı oluşturur Dataset verileri bellekte depolanan bir ya da daha fazla dosya in.

  • Bir veri dönüşümü, bir ya da daha fazla bir veri kümesi oluşturur tf.data.Dataset nesneleri.

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ş hattını oluşturmak için, bir veri kaynağı ile başlamalıdır. Örneğin, bir yapı için Dataset bellekte verilerden, kullanabilirsiniz tf.data.Dataset.from_tensors() ya da tf.data.Dataset.from_tensor_slices() . Senin girdi veri tavsiye TFRecord formatında bir dosyada saklanır, alternatif olarak kullanabileceğiniz tf.data.TFRecordDataset() .

Eğer bir edindikten sonra Dataset nesnesi, yeni bir dönüşmesi olabilir Dataset üzerinde yöntem çağrıları zincirleme tarafından tf.data.Dataset nesne. Örneğin, aşağıdaki gibi başına elemanı dönüşümleri uygulayabilirsiniz Dataset.map() , ve bu şekilde çoklu element dönüşümleri Dataset.batch() . Belgelerine bakın tf.data.Dataset dönüşümlerin tam listesi için.

Dataset nesnesi bir Python iterable olduğunu. 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 açıkça Python oluşturarak yineleyici kullanarak iter ve kullanarak elemanları tüketen next :

it = iter(dataset)

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

Alternatif olarak, veri kümesi elemanlar kullanılarak tüketilebilir reduce tek bir sonuç elde etmek için tüm elemanları azaltır dönüşümü. Aşağıdaki örnek, nasıl kullanılacağını gösterir reduce bir tamsayı veri kümesi toplamını hesaplamak dönüşümü.

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ısı bireysel bileşenlerin herhangi bir tip gösterilebilen olabilir tf.TypeSpec de dahil olmak üzere, tf.Tensor , tf.sparse.SparseTensor , tf.RaggedTensor , tf.TensorArray veya tf.data.Dataset .

Elemanların (iç içe) bir yapıya ifade etmek için kullanılabilir Python yapılar içerir tuple , dict , NamedTuple ve OrderedDict . Özellikle, list kümesi elemanlarının yapısını ifade etmek için, geçerli bir yapı değildir. Erken tf.data kullanıcıların şiddetle ilgili keçe olmasıdır list (örneğin geçirilen girişler tf.data.Dataset.from_tensors ) otomatik tensörlerle gibi paketlenmiş olan list bir zorlandığını edilen çıktıların (kullanıcı tanımlı fonksiyonların örneğin dönüş değerlerine) 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 eleman bileşen türünü incelemek için izin verir. Özelliği iç içe geçmiş bir yapı döndüren tf.TypeSpec tek bir bileşen, bileşenleri bir demet ya da bileşenlerin bir iç içe demet de olabilir eleman, yapısını eşleşen, nesne. Ö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())
[5 4 1 7 2 7 2 7 5 5]
[9 5 9 2 4 5 8 9 7 7]
[5 4 3 9 8 4 8 2 8 2]
[2 4 1 6 1 1 5 5 8 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 tüketme

Bkz NumPy diziler yükleme Daha fazla örnek için.

Bellekte sizin giriş veri uyan tüm bir oluşturmanın en basit yolu ise Dataset onlardan bunları dönüştürmek olduğunu tf.Tensor nesneleri ve kullanım Dataset.from_tensor_slices() .

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
40960/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
26435584/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
16384/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
4431872/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üketme

Kolayca olarak yutulur edilebilir Başka bir ortak veri kaynağı tf.data.Dataset piton jeneratör.

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ı bir tam fonksiyonel için piton jeneratör dönüştürür tf.data.Dataset .

Yapıcı, bir yineleyici değil, bir çağrılabilir girdi olarak alır. Bu, sona ulaştığında jeneratörü yeniden başlatmasını sağlar. Bu isteğe bağlı bir sürer args çağrılabilir argümanlarının olarak aktarılacağını.

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 ama çok bilinmeyen rütbesiyle tensörleri desteklemeyen birçok tensorflow operasyonları olarak tavsiye edilir. Belirli bir eksen uzunluğu bilinmeyen veya değişken ise, olarak ayarlamak None içinde 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 örnek bir üreteç, ikinci dizinin bilinmeyen uzunlukta bir vektör olduğu dizilerin demetlerini döndürür.

def gen_series():
  i = 0
  while True:
    size = np.random.randint(0, 10)
    yield i, np.random.normal(size=(size,))
    i += 1
for i, series in gen_series():
  print(i, ":", str(series))
  if i > 5:
    break
0 : []
1 : [0.018]
2 : [-0.1799 -0.4538 -1.7808  1.2569 -0.77  ]
3 : [ 0.1728  1.0476 -1.3632  1.2148  1.0274  0.7899]
4 : [-1.5616  0.8348 -0.7334]
5 : [ 0.0777  1.5326 -2.0872]
6 : [-0.0785 -0.3282  0.2665]

İlk çıkış, bir olduğu int32 ikinci a, float32 .

İlk öğe bir sayıl, şekli () ve ikinci bilinmeyen uzunluğu, şekli bir vektörüdü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 düzenli gibi kullanılabilir tf.data.Dataset . Değişken şekli ile bir veri kümesi toplu işlerken, kullanmak gerektiğini Not 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())
[13  7  5 17 19 14 12 26 16  6]

[[ 0.976   0.2999  1.1758 -0.7253  0.5655  0.    ]
 [-0.5697 -0.3878 -0.8197  0.8563  1.1502 -0.3431]
 [ 0.      0.      0.      0.      0.      0.    ]
 [ 0.      0.      0.      0.      0.      0.    ]
 [-0.415   1.5524  0.0372  0.8279  0.      0.    ]
 [-2.1594  0.3963  0.5639 -0.1209  0.6403  0.7756]
 [-2.0557  0.3314  0.      0.      0.      0.    ]
 [-0.3955  0.0811 -0.4472  0.      0.      0.    ]
 [-0.7648 -0.8468  0.      0.      0.      0.    ]
 [ 0.3892  0.      0.      0.      0.      0.    ]]

Daha gerçekçi Örneğin, sarma deneyin preprocessing.image.ImageDataGenerator bir şekilde tf.data.Dataset .

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

oluştur 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(
    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

Bkz yükleniyor TFRecords uçtan-uca örneğin.

tf.data API'si bellekte sığmayan büyük veri kümelerini işleyebilmesi dosya biçimlerinin çeşitli destekler. Örneğin, TFRecord dosya formatı, birçok TensorFlow uygulamasının eğitim verileri için kullandığı, kayıt odaklı basit bir ikili formattır. tf.data.TFRecordDataset sınıf bir giriş boru hattının bir parçası olarak bir veya daha fazla TFRecord dosyaların içeriğini üzerinde yayını yapmasını sağlar.

İşte Fransız Sokak Adı İşaretlerinden (FSNS) alınan 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
7913472/7904079 [==============================] - 0s 0us/step

filenames için argüman TFRecordDataset ya bir dize, bir dize listesidir veya olabilir başlatıcısı tf.Tensor dizeleri. Bu nedenle, eğitim ve doğrulama amacıyla iki dosya grubunuz 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 projeleri tefrika kullanmak tf.train.Example kendi TFRecord dosyalarında kayıtları. Bunların denetlenebilmeleri için kodlarının çö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üketme

Bkz Yükleme Metin uç örnek bir son verilmesi için.

Birçok veri seti, bir veya daha fazla metin dosyası olarak dağıtılır. tf.data.TextLineDataset Bir veya daha fazla metin dosyalarından satırları ayıklamak için kolay bir yol sağlar. Bir veya daha fazla dosya adları göz önüne alındığında, bir TextLineDataset bu dosyaların satır başına bir dizge değerli elemanı üretecek.

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
827392/815980 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/derby.txt
811008/809730 [==============================] - 0s 0us/step
819200/809730 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/butler.txt
811008/807992 [==============================] - 0s 0us/step
819200/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 alternatif hatlar için kullanmak Dataset.interleave . Bu, dosyaları birlikte karıştırmayı kolaylaştırır. İşte 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 dosyası bir pompa çıkışı hattı ile başlar veya yorum içeriyorsa, örneğin, arzu edilir olmayabilir her dosya, her bir çizgi elde edilir. Bu hatlar kullanılarak temizlenebilir Dataset.skip() ya da Dataset.filter() dönüşümleri. Burada, ilk satırı atlarsınız, ardından yalnızca hayatta kalanları bulmak için filtrelersiniz.

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
40960/30874 [=======================================] - 0s 0us/step
for line in titanic_lines.take(10):
  print(line.numpy())
b'survived,sex,age,n_siblings_spouses,parch,fare,class,deck,embark_town,alone'
b'0,male,22.0,1,0,7.25,Third,unknown,Southampton,n'
b'1,female,38.0,1,0,71.2833,First,C,Cherbourg,n'
b'1,female,26.0,0,0,7.925,Third,unknown,Southampton,y'
b'1,female,35.0,1,0,53.1,First,C,Southampton,n'
b'0,male,28.0,0,0,8.4583,Third,unknown,Queenstown,y'
b'0,male,2.0,3,1,21.075,Third,unknown,Southampton,n'
b'1,female,27.0,0,2,11.1333,Third,unknown,Southampton,n'
b'1,female,14.0,1,0,30.0708,Second,unknown,Cherbourg,n'
b'1,female,4.0,1,1,16.7,Third,G,Southampton,n'
def survived(line):
  return tf.not_equal(tf.strings.substr(line, 0, 1), "0")

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

CSV verilerini tüketme

Bkz CSV dosyaları yükleme ve Yükleme Pandalar DataFrames fazla örnek için.

CSV dosya formatı, tablo halindeki 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()

Eğer bellekte veri nöbetleri aynı Dataset.from_tensor_slices bu verileri sağlayan sözlüklere yöntem işleri kolayca ithal edilecek:

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ü karşılayan bir ya da daha fazla CSV dosyalarından ayıklamak kayıtlarına yöntemler sağlar RFC 4180 .

experimental.make_csv_dataset işlevi CSV dosyaları setleri okumak için üst düzey arayüzüdür. Kullanımı basitleştirmek için sütun türü çıkarımını ve toplu işleme 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'               : [30. 26. 31. 20.]
  'n_siblings_spouses': [1 0 0 0]
  'parch'             : [0 0 0 0]
  'fare'              : [24.      7.925  10.5     7.8542]
  'class'             : [b'Second' b'Third' b'Second' b'Third']
  'deck'              : [b'unknown' b'unknown' b'unknown' b'unknown']
  'embark_town'       : [b'Cherbourg' b'Southampton' b'Southampton' b'Southampton']
  'alone'             : [b'n' b'y' b'y' b'y']

Sen kullanabilirsiniz select_columns yalnızca sütunların bir alt kümesini gerekirse argüman.

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 1 0 0]
  'fare'              : [110.8833  41.5792   8.05    10.5   ]
  'class'             : [b'First' b'Second' b'Third' b'Second']

Daha düşük bir düzey vardır experimental.CsvDataset ince taneli bir kontrol sağlar sınıfı. Sütun türü çıkarımını desteklemez. Bunun yerine her 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 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 dosya yok edilmesi gereken bir pompa çıkışı hattı ile başlarsa bu, ya da sütun girişinde gerekli değilse, örneğin, arzu edilir olmayabilir dosyasının her satır, her sütun verir. Bu hatlar, ve alanlar temizlenebilir header ve select_cols sırasıyla bağımsız değişkenler.

# 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 tüketme

Her dosyanın bir örnek olduğu bir dizi dosya olarak dağıtılan 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 sınıf dizinindeki dosyalar örneklerdir:

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/4560613196_91a04f8dcf_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/8223949_2928d3f6f6_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/15951588433_c0713cbfc6_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/2960610406_b61930727f_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/4809566219_88f9a1aea3.jpg'

Kullanarak verilerini okuma tf.io.read_file fonksiyonunu ve geri dönen, yolundan etiket ayıklamak (image, label) çiftleri:

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'daisy'

Veri kümesi öğelerini toplu işleme

Basit gruplama

Yığınları dozajları en basit bir şekilde n , tek bir eleman bir veri kümesinin ardışık elemanları. Dataset.batch() dönüşümü ile aynı kısıtlamalar, tam olarak yapar tf.stack() elemanlarının her bileşenine uygulanan operatörü: yani her bir bileşeni için, tüm elemanlar aynı şekle sahip bir tensörünün 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])]

İken tf.data çalışır şekil bilgisini yaymak için, varsayılan ayarları Dataset.batch bilinmeyen bir seri boyutunda sonucu son parti tam olmayabilir çünkü. Not None şeklinde s:

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

Kullanım drop_remainder bu son toplu görmezden ve tam şekil yayılmasını almak için argüman:

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

Dolgulu tensörleri harmanlama

Yukarıdaki tarif, tümü aynı boyuta sahip tensörler için çalışır. Bununla birlikte, birçok model (örneğin dizi modelleri), değişen boyutlara sahip olabilen girdi verileriyle çalışır (örneğin, farklı uzunluklardaki diziler). Bu durumda işlemek için Dataset.padded_batch dönüşüm bunlar petlenebilir içinde bir ya da daha fazla boyut belirterek farklı şekilde toplu tansörlerine 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 bileşenin, her boyut için farklı dolgu ayarlamak için olanak tanır ve (ile gösterilen değişken uzunlukta olabilir None veya sabit uzunlukta, örneğin yukarıda). Varsayılan olarak 0 olan dolgu değerini geçersiz kılmak da mümkündür.

Eğitim iş akışları

Birden çok çağın işlenmesi

tf.data API teklifler iki ana yöntem aynı veriyi birden dönemini işlemek için.

Birden evreler bir veri kümesi üzerinde yineleme için en kolay yolu kullanmaktır Dataset.repeat() dönüşümü. İ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')

Başvuru Dataset.repeat() bir bağımsız değişken ile transformasyon süresiz girişi tekrar edecektir.

Dataset.repeat dönüşümü bir çağın sonunu ve sonraki dönemin başlangıcını işaret vermeden argümanları 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

Eğer açık çağ ayrımı gerekiyorsa, koyun Dataset.batch tekrarı önce:

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, en basit yöntem her bir dönemde 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

Giriş verilerini rastgele karıştırma

Dataset.shuffle() dönüşümü, sabit boyutlu tampon muhafaza eder ve bu tampondan rastgele homojen bir sonraki öğeyi seçer.

Etkiyi görebilmeniz 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
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/data/experimental/ops/counter.py:66: scan (from tensorflow.python.data.experimental.ops.scan_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.scan(...) instead
<BatchDataset shapes: ((None,), (None,)), types: (tf.int64, tf.string)>

Yana buffer_size 100, parti boyutu 20, ilk parti 120 üzerine oluşturulmuş bir indeks göre uygun elementler içerir.

n,line_batch = next(iter(dataset))
print(n.numpy())
[75  3 49 55 24 30  8 10 91 94 88 40 52 67 89 41 33 63 79 26]

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

Dataset.shuffle karışık tampon boşalana kadar bir dönemin sonunu işaret etmez. Bu nedenle, bir tekrardan önce yerleştirilen bir karıştırma, bir sonrakine geçmeden önce bir dönemin her öğesini 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:

[502 531 625 473 532 600 585 607 381 598]
[544 341 583 586 577 603 377 468 492 512]
[588 562 584 602 596 592 550 286]
[ 40  94   2  58  53  95  77 105  79  20]
[ 16  19  46  72   9 114 108  30  50 103]
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 0x7fd46416f590>

png

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

[579 613 483 542 370   9 622 201  26  30]
[595 431 584  20 419 406  18 606 626 562]
[603  39  10 464  25  12 601  43 620  40]
[598  13 581 540  44  15  54 568 478 591]
[ 36  52  53  34   8  62 597 550 599 614]
[593  68 565 617 520 619 604 611  28 572]
[546  71 233  45  29  38  83  80 605 434]
[556  77 575 526  51 552  55  33  56  58]
[559 502  91  61 618  23  66 103 498 609]
[ 76  81   4  83 446 113   1 100 107 474]
[ 21 596 578 104 602  69 126 588  78 102]
[112  19  64  93 131 531 580  60 409   0]
[  7  97  14 138 115  42 141  17 623  95]
[117   2  70  16 114  31 157 151 133 499]
[111 140 144  30 544 105 135 148 506 167]
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 0x7fd42079ab10>

png

Ön işleme verileri

Dataset.map(f) dönüşümü, belirli bir fonksiyon uygulanarak yeni bir veri kümesi üretir f giriş veri kümesi her bir elemanına. Bu dayanmaktadır map() yaygın fonksiyonel programlama dillerinde listeleri (ve diğer yapıların) uygulanır fonksiyonu. Fonksiyon f alır tf.Tensor giriş tek bir öğeyi temsil eden nesneleri ve döner tf.Tensor yeni veri kümesi tek bir öğeyi temsil edecek nesneleri. Uygulaması, bir öğeyi diğerine dönüştürmek için standart TensorFlow işlemlerini kullanır.

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

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

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

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

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

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

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

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

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

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

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

show(image, label)

png

Veri kümesi üzerinde eşleyin.

images_ds = list_ds.map(parse_image)

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

png

png

Keyfi Python mantığını uygulama

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

Eğer rastgele bir rotasyon uygulamak istiyorsanız Örneğin, tf.image modülü yalnızca sahiptir tf.image.rot90 görüntü büyütme için çok faydalı olmadığı,.

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

Ayrıştırma tf.Example protokolü tampon mesajları

Bir çok giriş boru özü tf.train.Example bir TFRecord biçiminden protokol tampon mesajları. Her tf.train.Example rekor bir veya daha fazla "özellikleri" içerir ve giriş boru hattı, tipik tensörlerle bu yüz çevirir.

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ıdan tf.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

Bitiş zamanı serisi örnek bir son için bkz: Zaman serisi tahmin .

Zaman serisi verileri genellikle zaman ekseni bozulmadan düzenlenir.

Basit kullanın Dataset.range göstermek için:

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 hale getirmek olacaktır:

kullanılması batch

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]

Veya geleceğe yönelik bir adım 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 bütün 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],   # Inputs: All except the last 5 steps
          batch[-5:])   # Labels: The last 5 steps

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]

Tek parti özellikleri ve diğerinin etiketler arasında örtüşme izin vermek için kullanın Dataset.zip :

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]

kullanılması window

Kullanırken Dataset.batch eserler, sen daha iyi bir kontrol gerekebilir durumlar vardır. Dataset.window yöntem size tam kontrol sağlar, ancak bazı dikkat gerektirir: Bir döndüren Dataset arasında Datasets . Bkz Veri kümesi yapısını detayları için.

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ümesi almak ve tek bir veri kümesi içine dümdüz:

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, isteyeceklerdir .batch ilk veri kümesi:

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, bunu görebilirsiniz shift argüman kontrolleri ne kadar her pencere hamle bitti.

Bunu bir araya getirerek bu işlevi yazabilirsiniz:

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

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

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

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

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

dense_labels_ds = ds.map(dense_1_step)

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

yeniden örnekleme

Sınıf açısından ç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 seti, 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 [==============================] - 1s 0us/step
69165056/69155632 [==============================] - 1s 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.9958 0.0042]

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

Veri kümeleri örneklemesi

Bir veri kümesini yeniden örnekleme için bir yaklaşım kullanmaktır sample_from_datasets . Eğer ayrı olduğunda bu daha uygulanabilir data.Dataset her sınıf için.

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

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

Kullanım için tf.data.experimental.sample_from_datasets veri setleri ve her biri için ağırlık geçmesi:

balanced_ds = tf.data.experimental.sample_from_datasets(
    [negative_ds, positive_ds], [0.5, 0.5]).batch(10)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/data/experimental/ops/interleave_ops.py:260: RandomDataset.__init__ (from tensorflow.python.data.ops.dataset_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.random(...)`.

Şimdi veri seti, her bir sınıfın 50/50 olasılıkla örneklerini üretiyor:

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

Reddetme yeniden örnekleme

Yukarıdaki ile ilgili bir problem experimental.sample_from_datasets yaklaşımı ayrı bir gereksinim duymasıdır tf.data.Dataset Sınıf başına. Kullanılması Dataset.filter çalışır, ancak tüm verilerin sonuçları iki kez yüklenen.

data.experimental.rejection_resample fonksiyonu sadece bir kez yüklenirken, bunu dengelemek için bir veri kümesi için uygulanabilir. Dengeyi sağlamak için öğeler veri kümesinden çıkarılacaktır.

data.experimental.rejection_resample bir sürer class_func argüman. Bu class_func Her veri kümesi elemanına uygulanan ve bir örnek dengelenmesi amacıyla ait olan sınıf belirlemek için kullanılır.

Elemanları creditcard_ds zaten (features, label) çiftleri. Yani class_func sadece bu etiketleri dönmek gerekiyor:

def class_func(features, label):
  return label

Yeniden örnekleyici ayrıca bir hedef dağıtı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)

Bireysel örneklerle örnekleyicinin fırsatlar, böylece gerekir unbatch Resampler uygulamadan önce veri kümesi:

resample_ds = creditcard_ds.unbatch().apply(resampler).batch(10)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/data/experimental/ops/resampling.py:159: 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 döner oluşturur (class, example) çıkışından çiftleri class_func . 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)

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

for features, labels in balanced_ds.take(10):
  print(labels.numpy())
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
Proportion of examples rejected by sampler is high: [0.995800793][0.995800793 0.00419921894][0 1]
[1 0 0 1 0 1 0 0 1 1]
[0 1 0 1 0 0 0 1 0 1]
[0 0 0 0 0 0 1 1 0 0]
[1 0 0 1 0 1 0 1 0 1]
[1 0 1 1 1 0 1 1 0 0]
[0 1 0 0 0 0 1 1 0 1]
[1 1 1 1 1 0 0 1 0 0]
[0 0 1 1 0 1 1 1 0 0]
[0 0 1 1 1 0 1 0 0 0]
[0 0 1 1 0 1 0 0 0 0]

Yineleyici Kontrol Noktası

Tensorflow destekleri kontrol noktalarını alarak böylece eğitim süreci yeniden başlar onun ilerleme en kurtarmak için son kontrol noktasından geri yükleyebilirsiniz zaman o. Model değişkenlerini denetlemeye ek olarak, veri kümesi yineleyicisinin ilerlemesini de kontrol edebilirsiniz. Bu, büyük bir veri kümeniz varsa ve her yeniden başlatmada veri kümesini baştan başlatmak istemiyorsanız yararlı olabilir. Yineleyici kontrol noktaları gibi dönüşümler, çünkü büyük olabilir, ancak not shuffle ve prefetch yineleyici içinde tamponlama elemanları gerektirmektedir.

Bir kontrol noktasında da liste koleksiyonunun için, şu yineleyici geçmesi tf.train.Checkpoint yapıcısı.

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.keras ile tf.data kullanma

tf.keras oluşturma ve makine öğrenme modellerini yürütme API basitleştirir birçok yönleri. Bu .fit() ve .evaluate() ve .predict() API girdi olarak veri kümelerini destekler. İşte hızlı bir veri seti 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'])

Bir veri kümesi Geçme (feature, label) çiftleri için gerekli olduğunu hepsi bu Model.fit ve Model.evaluate :

model.fit(fmnist_train_ds, epochs=2)
Epoch 1/2
1875/1875 [==============================] - 4s 2ms/step - loss: 0.5909 - accuracy: 0.8016
Epoch 2/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4605 - accuracy: 0.8416
<keras.callbacks.History at 0x7fd4203a1790>

Eğer arayarak örneğin sonsuz veri kümesi, geçerseniz Dataset.repeat() , sadece aynı zamanda geçmeleri gerekiyor steps_per_epoch argüman:

model.fit(fmnist_train_ds.repeat(), epochs=2, steps_per_epoch=20)
Epoch 1/2
20/20 [==============================] - 0s 2ms/step - loss: 0.5205 - accuracy: 0.8109
Epoch 2/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4074 - accuracy: 0.8641
<keras.callbacks.History at 0x7fd420221350>

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.4352 - accuracy: 0.8516
Loss : 0.4352473020553589
Accuracy : 0.8516333103179932

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.3755 - accuracy: 0.8875
Loss : 0.3755129277706146
Accuracy : 0.887499988079071

Etiketler çağrılırken gerekli değildir 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ümesi iletirseniz etiketler yok sayılır:

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