इस पेज का अनुवाद Cloud Translation API से किया गया है.
Switch to English

tf.data: TensorFlow इनपुट पाइपलाइनों का निर्माण करें

TensorFlow.org पर देखें Google Colab में चलाएं GitHub पर स्रोत देखें नोटबुक डाउनलोड करें

tf.data API आपको सरल, पुन: प्रयोज्य टुकड़ों से जटिल इनपुट पाइपलाइन बनाने में सक्षम बनाता है। उदाहरण के लिए, छवि मॉडल के लिए पाइपलाइन वितरित फ़ाइल सिस्टम में फ़ाइलों से डेटा एकत्र कर सकती है, प्रत्येक छवि पर यादृच्छिक गड़बड़ी लागू कर सकती है, और प्रशिक्षण के लिए बैच में यादृच्छिक रूप से चयनित छवियों को मर्ज कर सकती है। एक टेक्स्ट मॉडल के लिए पाइपलाइन में कच्चे टेक्स्ट डेटा से प्रतीकों को निकालना शामिल हो सकता है, जिससे वे लुकिंग टेबल के साथ पहचानकर्ता को परिवर्तित कर सकते हैं, और विभिन्न लंबाई के अनुक्रमों को एक साथ बैच सकते हैं। tf.data API बड़ी मात्रा में डेटा को संभालना, विभिन्न डेटा स्वरूपों से पढ़ना और जटिल परिवर्तनों को करना संभव बनाता है।

tf.data एपीआई एक tf.data.Dataset अमूर्त का परिचय देता है जो तत्वों के एक अनुक्रम का प्रतिनिधित्व करता है, जिसमें प्रत्येक तत्व में एक या अधिक घटक होते हैं। उदाहरण के लिए, एक छवि पाइपलाइन में, एक तत्व एक एकल प्रशिक्षण उदाहरण हो सकता है, जिसमें छवि और उसके लेबल का प्रतिनिधित्व करने वाले दसियों घटकों की एक जोड़ी होती है।

डेटासेट बनाने के दो अलग-अलग तरीके हैं:

  • डेटा स्रोत मेमोरी में या एक या अधिक फ़ाइलों में संग्रहीत डेटा से Dataset निर्माण करता है।

  • डेटा परिवर्तन एक या अधिक tf.data.Dataset ऑब्जेक्ट से डेटासेट tf.data.Dataset है।

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)

बुनियादी यांत्रिकी

एक इनपुट पाइपलाइन बनाने के लिए, आपको एक डेटा स्रोत से शुरू करना होगा। उदाहरण के लिए, मेमोरी में डेटा से Dataset बनाने के लिए, आप tf.data.Dataset.from_tensors() या tf.data.Dataset.from_tensor_slices() उपयोग कर सकते हैं। वैकल्पिक रूप से, यदि आपका इनपुट डेटा अनुशंसित TFRecord प्रारूप में एक फ़ाइल में संग्रहीत है, तो आप tf.data.TFRecordDataset() उपयोग कर सकते हैं।

एक बार आपके पास Dataset ऑब्जेक्ट होने के बाद, आप इसे tf.data.Dataset ऑब्जेक्ट पर मेथड कॉल कॉलिंग द्वारा एक नए Dataset में बदल सकते हैं। उदाहरण के लिए, आप प्रति-तत्व परिवर्तन जैसे Dataset.map() और Dataset.map() बहु-तत्व परिवर्तन जैसे Dataset.batch() लागू कर सकते हैं। परिवर्तनों की पूरी सूची के लिए tf.data.Dataset लिए दस्तावेज़ देखें।

Dataset ऑब्जेक्ट एक पायथन पुनरावृत्ति है। यह लूप के लिए अपने तत्वों का उपभोग करना संभव बनाता है:

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

या स्पष्ट रूप से एक पायथन पुनरावृति का उपयोग करके iter का उपयोग करके और इसके तत्वों का उपयोग करके next :

it = iter(dataset)

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

वैकल्पिक रूप से, डेटासेट तत्वों को reduce परिवर्तन का उपयोग करके खाया जा सकता है, जो एकल परिणाम उत्पन्न करने के लिए सभी तत्वों को कम करता है। निम्न उदाहरण दिखाता है कि पूर्णांक के डेटासेट की राशि की गणना reduce लिए reduce परिवर्तन का उपयोग कैसे करें।

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

डेटासेट संरचना

डेटासेट में ऐसे तत्व होते हैं, जिनमें से प्रत्येक में समान (नेस्टेड) ​​संरचना होती है और संरचना के अलग-अलग घटक tf.TypeSpec द्वारा किसी भी प्रकार का प्रतिनिधित्व कर tf.TypeSpec , जिसमें tf.Tensor , tf.sparse.SparseTensor , tf.RaggedTensor , tf.TensorArray । या tf.data.Dataset

Dataset.element_spec संपत्ति आपको प्रत्येक तत्व घटक के प्रकार का निरीक्षण करने की अनुमति देती है। संपत्ति tf.TypeSpec ऑब्जेक्ट्स की नेस्टेड संरचना tf.TypeSpec है, तत्व की संरचना से मेल खाती है, जो एक एकल घटक, घटकों का एक ट्यूपल या घटकों का नेस्टेड टपल हो सकता है। उदाहरण के लिए:

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)
6145e8bee
tensorflow.python.framework.sparse_tensor.SparseTensor

Dataset रूपांतरण किसी भी संरचना के डेटासेट का समर्थन करते हैं। Dataset.map() , और Dataset.filter() परिवर्तनों का उपयोग करते Dataset.map() , जो प्रत्येक तत्व के लिए एक फ़ंक्शन लागू करते हैं, तत्व संरचना फ़ंक्शन के तर्कों को निर्धारित करती है:

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())
[6 4 2 6 4 7 8 5 2 3]
[3 6 2 3 8 6 1 2 3 4]
[8 4 4 2 7 3 1 7 7 8]
[9 9 3 7 9 1 9 1 1 7]

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

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

dataset3
<ZipDataset shapes: ((10,), ((), (100,))), types: (tf.int32, (tf.float32, tf.int32))>
93931982121
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)

इनपुट डेटा पढ़ना

खपत NumPy सरणियों

अधिक उदाहरणों के लिए लोडिंग NumPy सरणियाँ देखें।

यदि आपके सभी इनपुट डेटा मेमोरी में फिट होते हैं, तो उनसे Dataset बनाने का सबसे सरल तरीका उन्हें tf.Tensor ऑब्जेक्ट में कनवर्ट करना और Dataset.from_tensor_slices() उपयोग 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
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 1s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step

images, labels = train
images = images/255

dataset = tf.data.Dataset.from_tensor_slices((images, labels))
dataset
a6d4a78c9

पायथन जनरेटर का उपभोग करना

एक अन्य सामान्य डेटा स्रोत जिसे आसानी से एक tf.data.Dataset रूप में tf.data.Dataset जा सकता है अजगर जनरेटर है।

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 कंस्ट्रक्टर अजगर जनरेटर को पूरी तरह कार्यात्मक tf.data.Dataset

कंस्ट्रक्टर इनपुट के रूप में एक कॉल करने योग्य लेता है, न कि एक पुनरावृत्ति करने वाला। यह जनरेटर को पुनरारंभ करने की अनुमति देता है जब यह अंत तक पहुंचता है। यह एक वैकल्पिक args तर्क लेता है, जिसे args तर्कों के रूप में पारित किया जाता है।

output_types तर्क की आवश्यकता है क्योंकि tf.Graph आंतरिक रूप से tf.data बनाता है, और ग्राफ़ किनारों को 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 तर्क की आवश्यकता नहीं है, लेकिन अत्यधिक पुनर्संयोजित किया जाता है क्योंकि कई टेंसरफ़्लो ऑपरेशन अज्ञात रैंक के साथ टेंसरों का समर्थन नहीं करते हैं। यदि किसी विशेष अक्ष की लंबाई अज्ञात या परिवर्तनशील है, तो इसे output_shapes में None सेट output_shapes

यह भी ध्यान रखना महत्वपूर्ण है कि output_shapes और output_types समान output_types नियमों को अन्य डेटासेट विधियों के रूप में अनुसरण करते हैं।

यहां एक उदाहरण जनरेटर है जो दोनों पहलुओं को प्रदर्शित करता है, यह सरणियों के ट्यूपल लौटाता है, जहां दूसरा सरणी अज्ञात लंबाई वाला एक वेक्टर है।

def gen_series():
  i = 0
  while True:
    size = np.random.randint(0, 10)
    yield i, np.random.normal(size=(size,))
    i += 1
for i, series in gen_series():
  print(i, ":", str(series))
  if i > 5:
    break
0 : [-0.119  -0.1705  0.6298  1.6472]
1 : [0.4102 0.858 ]
2 : [ 1.1845 -0.4004 -0.5682  0.7648 -2.0806  1.2242 -2.0966  0.8446]
3 : [-2.2548  1.4521  0.8092]
4 : [ 0.8081  0.7604 -0.6913  0.5043  1.0684]
5 : [-0.1358  0.3046  0.0346]
6 : []

पहला आउटपुट एक int32 और दूसरा एक float32

पहला आइटम एक अदिश, आकार () , और दूसरा अज्ञात लंबाई, आकार (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)>

अब इसे रेगुलर tf.data.Dataset तरह इस्तेमाल किया जा सकता है। ध्यान दें कि किसी डेटासेट को वैरिएबल शेप में Dataset.padded_batch , आपको Dataset.padded_batch का उपयोग 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())
[16 19 15  2  0 23 12  6 27 20]

[[ 1.7982  0.6075  0.8935  1.5496 -0.9427  0.9026 -1.0912  0.      0.    ]
 [ 0.      0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-0.3835 -0.7199  0.6697 -0.5535 -1.2751  1.0727 -1.6975 -1.8727  0.6132]
 [-0.7542  2.4467  1.6744  0.6795  0.3545  0.4416  0.      0.      0.    ]
 [-1.1485  0.2186 -0.5212 -0.6324 -1.1361 -2.0172  0.      0.      0.    ]
 [ 0.3903  0.0763  0.1203 -1.5849  0.      0.      0.      0.      0.    ]
 [-0.361   0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-0.3172 -0.3045 -0.4404  1.0413 -2.2203 -0.9137  0.      0.      0.    ]
 [ 0.1888  1.432   1.4547  0.5166 -0.2852  2.3501 -0.3476 -0.1323 -0.0585]
 [ 0.0677  0.5017  1.5934  0.5202  0.      0.      0.      0.      0.    ]]

अधिक यथार्थवादी उदाहरण के लिए, एक tf.data.Dataset रूप में preprocessing.image.ImageDataGenerator रैपिंग का प्रयास करें।

सबसे पहले डेटा डाउनलोड करें:

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 [==============================] - 3s 0us/step

चित्र बनाएँ। image.ImageDataGenerator

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

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

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

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

TFRecord डेटा का उपभोग करना

एंड-टू-एंड उदाहरण के लिए लोड हो रहे TFRecords देखें।

tf.data API विभिन्न प्रकार के फ़ाइल स्वरूपों का समर्थन करता है ताकि आप बड़े डेटासेट को संसाधित कर सकें जो स्मृति में फिट नहीं होते हैं। उदाहरण के लिए, TFRecord फ़ाइल स्वरूप एक सरल रिकॉर्ड-ओरिएंटेड बाइनरी प्रारूप है, जो कई TensorFlow एप्लिकेशन प्रशिक्षण डेटा के लिए उपयोग करते हैं। tf.data.TFRecordDataset वर्ग आपको इनपुट पाइपलाइन के भाग के रूप में एक या अधिक TFRecord फ़ाइलों की सामग्री को स्ट्रीम करने में सक्षम बनाता है।

यहाँ फ्रेंच स्ट्रीट नेम साइन्स (FSNS) से परीक्षण फ़ाइल का उपयोग करके एक उदाहरण दिया गया है।

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

TFRecordDataset initializer के लिए filenames तर्क या तो एक स्ट्रिंग, स्ट्रिंग्स की एक सूची या स्ट्रिंग्स का tf.Tensor है। इसलिए, यदि आपके पास प्रशिक्षण और सत्यापन उद्देश्यों के लिए दो सेट फाइलें हैं, तो आप एक फैक्ट्री विधि बना सकते हैं, जो डेटासेट का उत्पादन करती है, फ़ाइल नाम इनपुट तर्क के रूप में लेती है:

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

कई TensorFlow प्रोजेक्ट्स अपनी TFRecord फ़ाइलों में क्रमबद्ध tf.train.Example रिकॉर्ड्स का उपयोग करते हैं। निरीक्षण किए जाने से पहले इन्हें डिकोड किया जाना चाहिए:

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

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

पाठ डेटा का उपभोग करना

उदाहरण के लिए अंत तक लोड हो रहा पाठ देखें।

कई डेटासेट एक या अधिक पाठ फ़ाइलों के रूप में वितरित किए जाते हैं। tf.data.TextLineDataset एक या अधिक पाठ फ़ाइलों से लाइनें निकालने का एक आसान तरीका प्रदान करता है। एक या एक से अधिक फ़ाइलनामों को देखते हुए, एक TextLineDataset उन फ़ाइलों के प्रति एक स्ट्रिंग-मूल्यवान तत्व का उत्पादन करेगा।

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

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

dataset = tf.data.TextLineDataset(file_paths)

यहाँ पहली फ़ाइल की पहली कुछ पंक्तियाँ हैं:

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

फ़ाइलों के बीच वैकल्पिक लाइनों के लिए Dataset.interleave उपयोग Dataset.interleave । इससे फाइलों को एक साथ फेरबदल करना आसान हो जाता है। यहाँ प्रत्येक अनुवाद से पहली, दूसरी और तीसरी पंक्तियाँ हैं:

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'

डिफ़ॉल्ट रूप से, एक TextLineDataset प्रत्येक फ़ाइल की प्रत्येक पंक्ति की पैदावार करता है , जो वांछनीय नहीं हो सकता है, उदाहरण के लिए, यदि फ़ाइल हेडर लाइन से शुरू होती है, या जिसमें टिप्पणियां होती हैं। इन पंक्तियों को Dataset.skip() या Dataset.filter() परिवर्तनों का उपयोग करके हटाया जा सकता है। यहां, आप पहली पंक्ति को छोड़ देते हैं, फिर केवल बचे को खोजने के लिए फ़िल्टर करें।

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

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

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

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

CSV डेटा का उपभोग करना

अधिक उदाहरणों के लिए लोड हो रहे CSV फ़ाइलें और लोड हो रहे पंडों के डेटाफ़्रेम देखें।

CSV फ़ाइल स्वरूप सादे पाठ में सारणीबद्ध डेटा संग्रहीत करने के लिए एक लोकप्रिय प्रारूप है।

उदाहरण के लिए:

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

यदि आपका डेटा मेमोरी में समान Dataset.from_tensor_slices में फिट बैठता है। शब्दकोशों पर काम करता है। इस डेटा को आसानी से आयात किया जा सकता है:

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'

एक अधिक स्केलेबल दृष्टिकोण आवश्यक रूप से डिस्क से लोड करना है।

tf.data मॉड्यूल RFC 4180 का अनुपालन करने वाली एक या अधिक CSV फ़ाइलों से रिकॉर्ड निकालने के तरीके प्रदान करता है।

experimental.make_csv_dataset . experimental.make_csv_dataset फ़ंक्शन csv फ़ाइलों के सेट पढ़ने के लिए उच्च स्तरीय इंटरफ़ेस है। यह उपयोग को सरल बनाने के लिए कॉलम टाइप इंफरेंस और बैचिंग और शफलिंग जैसी कई अन्य विशेषताओं का समर्थन करता है।

titanic_batches = tf.data.experimental.make_csv_dataset(
    titanic_file, batch_size=4,
    label_name="survived")
for feature_batch, label_batch in titanic_batches.take(1):
  print("'survived': {}".format(label_batch))
  print("features:")
  for key, value in feature_batch.items():
    print("  {!r:20s}: {}".format(key, value))
'survived': [0 0 0 1]
features:
  'sex'               : [b'male' b'male' b'female' b'male']
  'age'               : [30. 28. 28. 36.]
  'n_siblings_spouses': [0 0 0 0]
  'parch'             : [0 0 2 1]
  'fare'              : [ 13.       7.8958   7.75   512.3292]
  'class'             : [b'Second' b'Third' b'Third' b'First']
  'deck'              : [b'unknown' b'unknown' b'unknown' b'B']
  'embark_town'       : [b'Southampton' b'Southampton' b'Queenstown' b'Cherbourg']
  'alone'             : [b'y' b'y' b'n' b'n']

यदि आप केवल स्तंभों के सबसेट की आवश्यकता है, तो आप select_columns तर्क का उपयोग कर सकते हैं।

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'              : [ 7.925 32.5   13.     8.05 ]
  'class'             : [b'Third' b'Second' b'Second' b'Third']

एक निम्न-स्तरीय experimental.CsvDataset । CvDataset वर्ग जो महीन दानेदार नियंत्रण प्रदान करता है। यह स्तंभ प्रकार के निष्कासन का समर्थन नहीं करता है। इसके बजाय आपको प्रत्येक कॉलम का प्रकार निर्दिष्ट करना होगा।

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

यदि कुछ कॉलम खाली हैं, तो यह निम्न-स्तरीय इंटरफ़ेस आपको कॉलम प्रकारों के बजाय डिफ़ॉल्ट मान प्रदान करने की अनुमति देता है।

%%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]

डिफ़ॉल्ट रूप से, एक CsvDataset फ़ाइल की प्रत्येक पंक्ति के प्रत्येक कॉलम की पैदावार करता है , जो वांछनीय नहीं हो सकता है, उदाहरण के लिए यदि फ़ाइल हेडर लाइन से शुरू होती है जिसे अनदेखा किया जाना चाहिए, या यदि इनपुट में कुछ कॉलम की आवश्यकता नहीं है। इन पंक्तियों और फ़ील्ड को क्रमशः header और select_cols तर्कों के साथ हटाया जा सकता है।

# 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]

फाइलों का उपभोग करना

फ़ाइलों के एक सेट के रूप में कई डेटासेट वितरित किए जाते हैं, जहां प्रत्येक फ़ाइल एक उदाहरण है।

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)

रूट निर्देशिका में प्रत्येक वर्ग के लिए एक निर्देशिका होती है:

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

प्रत्येक कक्षा निर्देशिका में फाइलें उदाहरण हैं:

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

for f in list_ds.take(5):
  print(f.numpy())
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/4746648726_e37a2de16d_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/2862944799_45bc8e7302.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/13513644515_a51470b899.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/506018088_4f7a15a7c5_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/15381511376_fd743b7330_n.jpg'

tf.io.read_file फ़ंक्शन का उपयोग करके डेटा पढ़ें और लेबल को पथ से tf.io.read_file , वापस tf.io.read_file (image, label) जोड़े:

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

डेटासेट तत्वों को बैचना

साधारण बैचिंग

ढेर batching का सबसे सरल रूप n एक भी तत्व में किसी डेटासेट के लगातार तत्वों। Dataset.batch() परिवर्तन ठीक यही करता है, तत्वों की प्रत्येक घटक पर लागू tf.stack() ऑपरेटर के समान बाधाओं के साथ: अर्थात प्रत्येक घटक i के लिए , सभी तत्वों में सटीक समान आकृति का tf.stack() होना चाहिए।

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

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

हालांकि tf.data आकार की जानकारी का प्रचार करने की कोशिश करता है, लेकिन Dataset.batch की डिफ़ॉल्ट सेटिंग्स एक अज्ञात बैच आकार में होती हैं क्योंकि अंतिम बैच पूर्ण नहीं हो सकता है। आकार में None ध्यान दें:

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

उस अंतिम बैच को अनदेखा करने और पूर्ण आकार का प्रचार प्राप्त करने के लिए drop_remainder तर्क का उपयोग करें:

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

पैडिंग के साथ टेनिंग बैच

उपरोक्त नुस्खा दसियों के लिए काम करता है कि सभी का आकार समान है। हालाँकि, कई मॉडल (उदाहरण अनुक्रम मॉडल) इनपुट डेटा के साथ काम करते हैं जिनके आकार अलग-अलग हो सकते हैं (जैसे विभिन्न लंबाई के अनुक्रम)। इस मामले को संभालने के लिए, Dataset.padded_batch रूपांतरण आपको एक या अधिक आयामों को निर्दिष्ट करके विभिन्न आकार के Dataset.padded_batch को Dataset.padded_batch सक्षम करता है जिसमें वे गद्देदार हो सकते हैं।

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 परिवर्तन आपको प्रत्येक घटक के प्रत्येक आयाम के लिए अलग-अलग पैडिंग सेट करने की अनुमति देता है, और यह परिवर्तनशील-लंबाई (ऊपर दिए गए उदाहरण में None ) या स्थिर-लंबाई हो सकती है। पैडिंग मान को ओवरराइड करना भी संभव है, जो कि 0 से चूक जाता है।

प्रशिक्षण वर्कफ़्लोज़

कई युगों का प्रसंस्करण

tf.data एपीआई एक ही डेटा के कई युगों को संसाधित करने के लिए दो मुख्य तरीके प्रदान करता है।

कई युगों में किसी डेटासेट पर पुनरावृति करने का सबसे सरल तरीका है डेटासेट Dataset.repeat()Dataset.repeat() रूपांतरण का उपयोग करना। सबसे पहले, टाइटैनिक डेटा का डेटासेट बनाएं:

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

Dataset.repeat() परिवर्तन को बिना किसी तर्क के लागू करने से इनपुट अनिश्चित काल तक दोहराया जाएगा।

Dataset.repeat परिवर्तन एक युग के अंत और अगले युग की शुरुआत के संकेत के बिना अपने तर्कों को Dataset.repeat । इस वजह से Dataset.batch बाद एक Dataset.batch लागू किया गया है, जो उस युग की सीमाओं को Dataset.repeat :

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

png

यदि आपको स्पष्ट युग- Dataset.batch आवश्यकता है, तो दोहराने से पहले Dataset.batch :

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

plot_batch_sizes(titanic_batches)

png

यदि आप प्रत्येक काल के अंत में एक कस्टम संगणना (उदाहरण के लिए आँकड़े एकत्र करना) करना चाहते हैं, तो प्रत्येक कालखंड पर डेटासेट पुनरावृत्ति को पुनः आरंभ करना सबसे सरल है:

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

बेतरतीब ढंग से इनपुट डेटा फेरबदल

Dataset.shuffle() परिवर्तन एक निश्चित आकार के बफर को बनाए रखता है और उस बफर से यादृच्छिक रूप से अगले तत्व को समान रूप से चुनता है।

डेटासेट में कोई अनुक्रमणिका जोड़ें ताकि आप प्रभाव देख सकें:

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

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

चूंकि buffer_size 100 है, और बैच का आकार 20 है, पहले बैच में 120 से अधिक के इंडेक्स वाले तत्व नहीं हैं।

n,line_batch = next(iter(dataset))
print(n.numpy())
[  6  41  35  53  36  50  52  80   1  26  22  29  38  55  84  18  47  68
 100 105]

Dataset.batch के सापेक्ष Dataset.repeat मामलों के अनुसार ऑर्डर करें।

Dataset.shuffle फेरबदल बफर खाली होने तक एक युग के अंत का संकेत नहीं देता है। इसलिए एक दोहराव से पहले रखा जाने वाला एक फेरबदल अगले में जाने से पहले एक युग के प्रत्येक तत्व को दिखाएगा:

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:

[594 456 585 615 536 627 514 297 617 620]
[495 530 356 622 395 602 505 593 611 492]
[573 597 575 528 561 616 609 494]
[51 85 41  4 37  9 91 74 89  8]
[ 13 107 104  65  52  83  71  16 101  92]

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

png

लेकिन एक फेरबदल से पहले एक दोहराव युगीन सीमाओं को एक साथ मिलाता है:

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:

[570 263 533  22  17  14 485 348 517 606]
[501 488 620 611 624 599 534 398 542 521]
[446 596 359 587   6 475 436 610   2 605]
[ 35 583  49  16 547  46  39 576  47   8]
[ 30  26  63  55 496  51   9 575  66 571]
[ 41  57  33 589  43 550 540 404 591 595]
[ 12 512  48 581 600  25  67  19  85  56]
[ 83  65 563 597  52  61  90 585  91  78]
[ 11  37 445 621 618 482  92 103  82  32]
[ 42  79  62  88 543  80  95 598 539 113]
[ 38  86 107 124  50 114  76 535   3  27]
[111  64  71 130  29 129 470 120  94 101]
[425 122 131  18  40  84  87  73 519  21]
[272  58 143 145 331  77  60 612 127  13]
[495  96  99 523 138 627 115 167 135 152]

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

png

प्रीप्रोसेसिंग डेटा

Dataset.map(f) इनपुट डेटासेट के प्रत्येक तत्व में दिए गए फंक्शन f को लागू करके एक नया डेटासेट बनाता है। यह map() फ़ंक्शन पर आधारित है जो आमतौर पर कार्यात्मक प्रोग्रामिंग भाषाओं में सूचियों (और अन्य संरचनाओं) पर लागू होता है। फ़ंक्शन f tf.Tensor ऑब्जेक्ट्स को इनपुट में एक एकल तत्व का प्रतिनिधित्व करता है, और tf.Tensor ऑब्जेक्ट्स को tf.Tensor है जो नए डेटासेट में एक एकल तत्व का प्रतिनिधित्व करेगा। इसका कार्यान्वयन एक तत्व को दूसरे में बदलने के लिए मानक TensorFlow संचालन का उपयोग करता है।

इस खंड में Dataset.map() का उपयोग करने के सामान्य उदाहरण शामिल हैं।

इमेज डेटा को डिकोड करना और उसका आकार बदलना

वास्तविक-विश्व छवि डेटा पर एक तंत्रिका नेटवर्क को प्रशिक्षित करते समय, अक्सर विभिन्न आकारों की छवियों को एक सामान्य आकार में परिवर्तित करना आवश्यक होता है, ताकि उन्हें एक निश्चित आकार में बांधा जा सके।

फूल फाइलनाम डेटासेट का पुनर्निर्माण करें:

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

एक फ़ंक्शन लिखें जो डेटासेट तत्वों में हेरफेर करता है।

# 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

परीक्षण करें कि यह काम करता है।

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

डेटासेट पर इसे मैप करें।

images_ds = list_ds.map(parse_image)

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

png

png

मनमानी पायथन तर्क को लागू करना

प्रदर्शन कारणों के लिए, जब भी संभव हो अपने डेटा को प्रीप्रोसेस करने के लिए TensorFlow संचालन का उपयोग करें। हालांकि, आपके इनपुट डेटा को पार्स करते समय बाहरी पायथन लाइब्रेरी को कॉल करना कभी-कभी उपयोगी होता है। आप Dataset.map() परिवर्तन में tf.py_function() ऑपरेशन का उपयोग कर सकते हैं।

उदाहरण के लिए, यदि आप एक यादृच्छिक घुमाव लागू करना चाहते हैं, तो tf.image मॉड्यूल में केवल tf.image.rot90 , जो छवि वृद्धि के लिए बहुत उपयोगी नहीं है।

tf.py_function प्रदर्शित करने के लिए, इसके बजाय scipy.ndimage.rotate फ़ंक्शन का उपयोग करने का प्रयास करें:

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)

png

के साथ इस समारोह का उपयोग करने के Dataset.map ही कैविएट्स के साथ के रूप में लागू Dataset.from_generator , तो आपको समारोह लागू वापसी आकृति और प्रकारों का वर्णन करने की जरूरत है:

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

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

png

png

पार्सिंग tf.Example प्रोटोकॉल बफर संदेश

कई इनपुट पाइपलाइन tf.train.Example प्रोटोकॉल बफर संदेशों को TFRecord प्रारूप से निकालते हैं। प्रत्येक tf.train.Example रिकॉर्ड में एक या अधिक "सुविधाएँ" होती हैं, और इनपुट पाइपलाइन आम तौर पर इन विशेषताओं को tf.train.Example में बदल देती है।

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>

आप के साथ काम कर सकते हैं tf.train.Example एक की protos बाहर tf.data.Dataset डेटा को समझने के लिए:

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])

समय श्रृंखला विंडोिंग

एंड टू एंड टाइम सीरीज़ उदाहरण देखें: टाइम सीरीज़ फोरकास्टिंग

समय श्रृंखला डेटा अक्सर समय अक्ष अक्ष के साथ आयोजित किया जाता है।

सरल Dataset.range का उपयोग करें। प्रदर्शित करने के लिए Dataset.range करें:

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

आमतौर पर, डेटा के इस प्रकार के आधार पर मॉडल एक आकस्मिक समय टुकड़ा चाहते हैं।

डेटा को बैचने के लिए सबसे सरल तरीका होगा:

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]

या भविष्य में घनी भविष्यवाणियों को एक कदम बनाने के लिए, आप एक दूसरे के सापेक्ष एक कदम से सुविधाओं और लेबल को स्थानांतरित कर सकते हैं:

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]

एक निश्चित ऑफसेट के बजाय पूरी विंडो की भविष्यवाणी करने के लिए आप बैचों को दो भागों में विभाजित कर सकते हैं:

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

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

predict_5_steps = batches.map(label_next_5_steps)

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

एक बैच और दूसरे के लेबल के बीच कुछ ओवरलैप की अनुमति देने के लिए, Dataset.zip उपयोग Dataset.zip :

feature_length = 10
label_length = 5

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

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

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

window का उपयोग करना

Dataset.batch कार्यों का उपयोग करते समय, ऐसी परिस्थितियाँ होती हैं जहाँ आपको बेहतर नियंत्रण की आवश्यकता हो सकती है। Dataset.window विधि आप पूरा नियंत्रण देता है, लेकिन कुछ देखभाल की आवश्यकता होती है: यह एक रिटर्न Dataset के Datasets । विवरण के लिए डेटासेट संरचना देखें।

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 विधि डेटासेट का एक डेटासेट ले सकती है और इसे एकल डेटासेट में समतल कर सकती है:

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

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

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

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

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

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

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 

लगभग सभी मामलों में, आप पहले डेटासेट को .batch :

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]

अब, आप देख सकते हैं कि shift तर्क नियंत्रित करता है कि प्रत्येक विंडो कितनी चलती है।

इसे एक साथ रखकर आप इस फ़ंक्शन को लिख सकते हैं:

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]

फिर पहले की तरह लेबल निकालना आसान है:

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]

रीसेंपलिंग

जब वह बहुत वर्ग-असंतुलित हो एक डेटासेट के साथ काम कर रहा है, तो आप डेटासेट को फिर से शुरू कर सकते हैं। tf.data ऐसा करने के लिए दो तरीके प्रदान करता है। क्रेडिट कार्ड फ्रॉड डेटासेट इस तरह की समस्या का एक अच्छा उदाहरण है।

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

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

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

अब, कक्षाओं के वितरण की जाँच करें, यह अत्यधिक तिरछा है:

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.9964 0.0036]

असंतुलित डेटासेट के साथ प्रशिक्षण के लिए एक सामान्य दृष्टिकोण इसे संतुलित करना है। tf.data में कुछ तरीके शामिल हैं जो इस वर्कफ़्लो को सक्षम करते हैं:

डेटासैट का नमूना

डेटासेट को sample_from_datasets उपयोग करने के लिए एक तरीका sample_from_datasets का उपयोग sample_from_datasets । यह तब लागू होता है जब आपके पास एक अलग data.Dataset । प्रत्येक वर्ग के लिए data.Dataset

यहां, क्रेडिट कार्ड धोखाधड़ी डेटा से उन्हें उत्पन्न करने के लिए बस फ़िल्टर का उपयोग करें:

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

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

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

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

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

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

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

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

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

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

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

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

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

for features, label in positive_ds.batch(10).take(1):
  print(label.numpy())
[1 1 1 1 1 1 1 1 1 1]

tf.data.experimental.sample_from_datasets उपयोग करने के लिए डेटासेट पास करें, और इसके लिए वजन:

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

अब डाटासेट 50/50 संभावना वाले प्रत्येक वर्ग के उदाहरण प्रस्तुत करता है:

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

अस्वीकृति पुनः जारी करना

उपरोक्त experimental.sample_from_datasets . tf.data.Dataset दृष्टिकोण के साथ एक समस्या यह है कि इसे प्रति वर्ग एक अलग tf.data.Dataset आवश्यकता है। Dataset.filter का उपयोग करना, लेकिन सभी डेटा को दो बार लोड किए जाने के परिणामस्वरूप।

data.experimental.rejection_resample फ़ंक्शन को इसे फिर से लोड करने के लिए एक डेटासेट में लागू किया जा सकता है, जबकि केवल एक बार लोड हो रहा है। संतुलन हासिल करने के लिए डेटासेट से तत्वों को छोड़ दिया जाएगा।

data.experimental.rejection_resample एक class_func तर्क लेता है। यह class_func प्रत्येक डेटासेट तत्व पर लागू होता है, और यह निर्धारित करने के लिए उपयोग किया जाता है कि संतुलन के प्रयोजनों के लिए कौन सा वर्ग उदाहरण है।

creditcard_ds तत्व पहले से ही (features, label) जोड़े हैं। तो class_func केवल उन लेबलों को वापस करना होगा:

def class_func(features, label):
  return label

पुनर्विक्रेता को भी लक्ष्य वितरण की आवश्यकता होती है, और वैकल्पिक रूप से प्रारंभिक वितरण अनुमान:

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

unbatch व्यक्तिगत उदाहरणों के साथ unbatch करता है, इसलिए आपको unbatch को लागू करने से पहले डेटासेट को unbatch करना होगा:

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


Resampler रिटर्न class_func के आउटपुट से जोड़े (class, example) बनाता है। इस मामले में, example पहले से ही एक (feature, label) जोड़ी थी, इसलिए (feature, label) की अतिरिक्त प्रतिलिपि को छोड़ने के लिए map का उपयोग map :

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

अब डाटासेट 50/50 संभावना वाले प्रत्येक वर्ग के उदाहरण प्रस्तुत करता है:

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

इटरेटर चेकपॉइंटिंग

Tensorflow, चौकियों को लेने का समर्थन करती है ताकि जब आपकी प्रशिक्षण प्रक्रिया फिर से शुरू हो जाए तो यह अपनी अधिकांश प्रगति को पुनर्प्राप्त करने के लिए नवीनतम चेकपॉइंट को पुनर्स्थापित कर सके। मॉडल चर की जांच करने के अलावा, आप डेटासेट इट्रेटर की प्रगति की जांच भी कर सकते हैं। यदि आपके पास एक बड़ा डेटासेट है तो यह उपयोगी हो सकता है और प्रत्येक पुनरारंभ पर शुरू से डेटासेट शुरू नहीं करना चाहता। हालाँकि, ध्यान दें कि इटरेटर चौकियाँ बड़ी हो सकती हैं, क्योंकि shuffle और prefetch जैसे परिवर्तनों के लिए इटरेटर के भीतर बफरिंग तत्वों की आवश्यकता होती है।

एक चेकपॉइंट में अपने tf.train.Checkpoint को शामिल करने के लिए, tf.train.Checkpoint को tf.train.Checkpoint कंस्ट्रक्टर में पास करें।

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

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

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

save_path = manager.save()

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

ckpt.restore(manager.latest_checkpoint)

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

Tf.keras के साथ tf.data का उपयोग करना

tf.keras एपीआई मशीन लर्निंग मॉडल बनाने और निष्पादित करने के कई पहलुओं को सरल करता है। इसके .fit() और .evaluate() और .predict() एपीआई इनपुट के रूप में डेटासेट समर्थन करते हैं। यहां एक त्वरित डेटासेट और मॉडल सेटअप है:

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'])

डेटासेट (feature, label) युग्मों को पास करना सभी के लिए आवश्यक है। Model.fit और Model.evaluate :

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

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

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

1875/1875 [==============================] - 3s 2ms/step - loss: 0.6033 - accuracy: 0.7961
Epoch 2/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4633 - accuracy: 0.8411

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

यदि आप एक अनंत डेटासेट पास करते हैं, उदाहरण के लिए Dataset.repeat() कॉल Dataset.repeat() , आपको बस steps_per_epoch तर्क भी पास करना steps_per_epoch :

model.fit(fmnist_train_ds.repeat(), epochs=2, steps_per_epoch=20)
Epoch 1/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4781 - accuracy: 0.8313
Epoch 2/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4285 - accuracy: 0.8516

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

मूल्यांकन के लिए आप मूल्यांकन चरणों की संख्या पास कर सकते हैं:

loss, accuracy = model.evaluate(fmnist_train_ds)
print("Loss :", loss)
print("Accuracy :", accuracy)
1875/1875 [==============================] - 3s 1ms/step - loss: 0.4449 - accuracy: 0.8468
Loss : 0.4448782205581665
Accuracy : 0.846750020980835

लंबे डेटासेट के लिए, मूल्यांकन करने के लिए चरणों की संख्या निर्धारित करें:

loss, accuracy = model.evaluate(fmnist_train_ds.repeat(), steps=10)
print("Loss :", loss)
print("Accuracy :", accuracy)
10/10 [==============================] - 0s 2ms/step - loss: 0.4509 - accuracy: 0.8438
Loss : 0.45086926221847534
Accuracy : 0.84375

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)

यदि आप एक डेटासेट पास करते हैं तो लेबल को अनदेखा कर दिया जाता है:

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