Yardım Kaggle üzerinde TensorFlow ile Büyük Bariyer Resifi korumak Meydan Üyelik

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())
[3 1 4 9 2 5 1 3 1 1]
[4 8 6 1 5 2 4 6 2 4]
[6 4 7 7 6 7 8 9 2 5]
[3 6 3 8 2 2 3 8 1 6]
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.2659 -0.0164  0.8822  0.9887 -0.5352 -1.1873  0.6209]
1 : [-0.492  -2.3205 -0.5924 -0.2635  0.6136  1.9545  1.7315  0.4508]
2 : [0.2972]
3 : [ 0.2433  0.0502 -1.0612 -0.1499 -0.0939  0.5694  0.2207]
4 : [-1.8696 -0.4797]
5 : [ 0.3438 -0.4853 -0.36  ]
6 : [-0.9741]

İ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())
[ 5  7 10  4  2 13 25 18 17 27]

[[ 0.8387  0.2497  1.7194  0.      0.      0.      0.      0.      0.    ]
 [-2.3122 -1.1238 -1.3219 -0.0437 -0.0156 -1.5395  1.0858  0.      0.    ]
 [-0.8438  0.6191 -0.9143 -0.0623  0.1734 -0.5583  0.8883  0.      0.    ]
 [-0.955   0.3145  0.4488  0.6816  0.      0.      0.      0.      0.    ]
 [ 0.3774  0.      0.      0.      0.      0.      0.      0.      0.    ]
 [ 0.0288  0.5001 -1.4579  0.576  -0.8185  0.1437  0.8146 -0.9032  0.    ]
 [ 0.      0.      0.      0.      0.      0.      0.      0.      0.    ]
 [ 0.      0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-0.7994 -0.8724 -0.4017  0.      0.      0.      0.      0.      0.    ]
 [-0.0224  0.9805  0.0618 -0.0507 -0.3333 -0.4813  0.7181  0.351   0.097 ]]

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 [==============================] - 5s 0us/step
228827136/228813984 [==============================] - 5s 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 verilerini 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': [1 1 0 0]
features:
  'sex'               : [b'male' b'female' b'male' b'male']
  'age'               : [45.  2. 22. 37.]
  'n_siblings_spouses': [0 0 0 1]
  'parch'             : [0 1 0 0]
  'fare'              : [ 8.05   12.2875  7.7958 26.    ]
  'class'             : [b'Third' b'Third' b'Third' b'Second']
  'deck'              : [b'unknown' b'unknown' b'unknown' b'unknown']
  'embark_town'       : [b'Southampton' b'Southampton' b'Southampton' b'Southampton']
  'alone'             : [b'y' b'n' b'y' b'n']

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 0 0 0]
  'fare'              : [30.      7.0542  8.05   79.2   ]
  'class'             : [b'First' b'Third' b'Third' b'First']

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/daisy/2045022175_ad087f5f60_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/19425920580_cdc8f49aed_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/160456948_38c3817c6a_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/17012955700_7141d29eee.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/4933823300_39fd4420b6.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\x00\x00\x01\x00\x01\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'dandelion'

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
<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())
[ 83  24   4  14   6  53  37   2  18  71  27  40  77  76 110  11  30  47
  46  28]

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:

[612 458 485 439 305 506 624 570 625 523]
[529 544 597 620 610 615 592 487 566 454]
[611 572 585   0 520 601 398 594]
[ 65  22  75  78  73  55 105  86   8  94]
[ 14  52   4  36  85  66  69 100  38  33]
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 0x7fcea41e1a50>

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:

[593 580 524 619 506 555 617 526  24 520]
[586 445 356  26 600  20  16 528 504  39]
[583 594 576  37 560  13 626 314  41 501]
[571  46 574 542  32  52   4  10  40  35]
[590 541  34 625  56 609 529 446 618  50]
[ 64 611 582 538 443  72 604  23 613  79]
[ 36  14  17 557   2  59 622  25 395 565]
[400 483 588  89  51 599  67 591  12 458]
[ 69  33 373 101  29  98 102 468 104  94]
[548  21  68  30  61  49 581 513  44 360]
[ 75 121  97 603  58  62 577  15 452  80]
[426  48  65  90 105 616 124 100  66 134]
[ 99  74 620 136  82 587  88  96  31 127]
[138  87 151 131 143 471  86 140 146 117]
[  0 514 119 130  45   8   9 110 107  55]
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 0x7fcdd84fd5d0>

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.io.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.9973 0.0027]

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 /tmp/ipykernel_11206/929671245.py:2: sample_from_datasets_v2 (from tensorflow.python.data.experimental.ops.interleave_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.sample_from_datasets(...)`.

Ş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())
[1 1 0 1 0 1 0 0 1 1]
[0 0 0 0 0 0 1 1 1 0]
[0 1 1 0 1 0 0 0 0 1]
[1 1 1 0 0 0 0 0 0 1]
[0 1 1 1 1 1 1 1 1 0]
[0 0 1 0 0 1 1 1 1 1]
[1 1 1 1 1 0 1 1 1 0]
[0 0 0 0 0 0 0 1 1 0]
[0 1 1 1 0 1 1 1 1 0]
[0 1 0 1 0 1 0 1 0 1]

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)
WARNING:tensorflow:From /tmp/ipykernel_11206/2462412449.py:2: rejection_resample (from tensorflow.python.data.experimental.ops.resampling) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.rejection_resample(...)`.

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/ops/dataset_ops.py:6097: 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 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())
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
Proportion of examples rejected by sampler is high: [0.997265637][0.997265637 0.00273437495][0 1]
[1 1 1 0 1 1 1 0 1 1]
[0 1 1 0 1 1 0 0 1 0]
[1 0 1 1 0 1 0 0 0 1]
[0 1 0 1 0 1 1 0 0 0]
[0 0 0 1 0 1 1 0 0 0]
[1 0 1 0 0 1 1 1 1 0]
[0 1 1 1 1 1 0 1 0 0]
[1 1 1 0 0 1 1 1 0 0]
[0 1 1 0 1 0 1 0 0 0]
[0 0 1 0 1 1 1 1 0 1]

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.5979 - accuracy: 0.7986
Epoch 2/2
1875/1875 [==============================] - 4s 2ms/step - loss: 0.4610 - accuracy: 0.8429
<keras.callbacks.History at 0x7fce40120590>

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.4489 - accuracy: 0.8484
Epoch 2/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4426 - accuracy: 0.8625
<keras.callbacks.History at 0x7fce4029cfd0>

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.8513
Loss : 0.4351990818977356
Accuracy : 0.8513000011444092

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

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

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)