तिथि को रक्षित करें! Google I / O 18-20 मई को पंजीकृत करता है
इस पेज का अनुवाद 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 परिवर्तन का उपयोग कैसे करें।

048e3d420
22

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

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

अजगर निर्माणों कि तत्वों की (नेस्टेड) संरचना व्यक्त करने के लिए इस्तेमाल किया जा सकता शामिल हैं tuple , dict , NamedTuple , और OrderedDict । विशेष रूप से, डेटासेट तत्वों की संरचना को व्यक्त करने के लिए list एक वैध निर्माण नहीं है। इसका कारण यह है जल्दी tf.data उपयोगकर्ताओं दृढ़ता के बारे में महसूस किया है list (उदाहरण के लिए पारित किया आदानों tf.data.Dataset.from_tensors ) स्वचालित रूप से tensors और के रूप में पैक किया जा रहा list outputs (उपयोगकर्ता परिभाषित कार्यों का उदाहरण वापसी मान) एक मजबूर किया जा रहा tuple । एक परिणाम के रूप में, यदि आप एक संरचना के रूप में माना जाने वाला एक list इनपुट चाहते हैं, तो आपको इसे tuple में बदलने की आवश्यकता है और यदि आप एक एकल घटक होने के लिए एक list आउटपुट चाहते हैं, तो आपको स्पष्ट रूप से tf.stack का उपयोग करके इसे पैक करना tf.stack

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
02c054f9090
# 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
0

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())
[1 7 5 6 1 3 1 2 2 6]
[1 9 6 4 8 4 2 4 1 8]
[7 2 8 5 4 6 2 8 7 6]
[2 5 8 7 9 4 6 6 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))>
05bd47820
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 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step
images, labels = train
images = images/255

dataset = tf.data.Dataset.from_tensor_slices((images, labels))
dataset
<TensorSliceDataset shapes: ((28, 28), ()), types: (tf.float64, tf.uint8)>

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

एक अन्य सामान्य डेटा स्रोत जिसे आसानी से एक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 अन्य डेटासेट विधियों के समान ही नियमों का पालन करते हैं।

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

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.0406 -1.1395  0.1461  1.1128  0.2999  0.407  -0.4695]
1 : [ 0.2245 -0.2066 -1.8607]
2 : []
3 : [ 1.4813 -1.5021]
4 : [-0.523   2.0254 -1.3379 -0.7026  1.1167 -0.8914]
5 : [ 0.1134  0.6948 -0.9116  0.726 ]
6 : [ 2.0992 -0.6726  1.3971]

पहला आउटपुट एक 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())
[ 1 10  2 14  9  8 21 17 16 19]

[[ 0.      0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-1.1061 -0.7509 -1.8781 -0.2469  0.1069 -1.159   0.7171  0.0187 -0.638 ]
 [-0.1725  0.7828 -1.6536  0.8356 -0.4334  0.      0.      0.      0.    ]
 [ 0.7425  0.0505 -0.8275 -0.093   0.      0.      0.      0.      0.    ]
 [-0.6104 -1.7805  1.9596 -0.7051  0.1891  0.      0.      0.      0.    ]
 [ 0.6521  0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-1.1652 -0.1417 -0.3912  0.      0.      0.      0.      0.      0.    ]
 [-0.5748 -0.4071  0.7315  0.4816  0.8288  1.4523  0.6656  0.      0.    ]
 [-0.5187 -1.1124 -0.3008 -1.0433  0.3527  2.4732  0.9108  0.      0.    ]
 [ 0.6676 -0.8961 -0.4914 -1.1748  0.4043  0.2664  1.987  -0.722   0.7257]]

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

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

061a0b100
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
228818944/228813984 [==============================] - 1s 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(
    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))
044195957070
Found 3670 images belonging to 5 classes.
images.shape:  (32, 256, 256, 3)
labels.shape:  (32, 5)

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)
df.head()

यदि आपका डेटा मेमोरी में एक ही Dataset.from_tensor_slices विधि में फिट बैठता है, तो यह डेटा आसानी से आयात करने की अनुमति देता है:

0770b2db0
'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': [1 1 1 0]
features:
  'sex'               : [b'female' b'female' b'female' b'male']
  'age'               : [28. 42. 31. 65.]
  'n_siblings_spouses': [0 0 1 0]
  'parch'             : [0 0 1 0]
  'fare'              : [  7.8792 227.525   20.525   26.55  ]
  'class'             : [b'Third' b'First' b'Third' b'First']
  'deck'              : [b'unknown' b'unknown' b'unknown' b'E']
  'embark_town'       : [b'Queenstown' b'Cherbourg' b'Southampton' b'Southampton']
  'alone'             : [b'y' b'y' b'n' b'y']

यदि आप केवल स्तंभों के सबसेट की आवश्यकता है, तो आप 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 0 0 0]
  'fare'              : [ 7.925  8.05  24.15   7.75 ]
  'class'             : [b'Third' b'Third' b'Third' b'Third']

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

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/roses/7316409504_7cf3707f8a_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/1273326361_b90ea56d0d_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/1008566138_6927679c8a.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/8690791226_b1f015259f_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/17781940352_a45e4289a5.jpg'

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

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

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

ढेर 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 द्वारा Dataset.padded_batch ) या निरंतर-लंबाई हो सकती है। पैडिंग मान को ओवरराइड करना भी संभव है, जो कि 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)

पींग

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

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

plot_batch_sizes(titanic_batches)

पींग

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

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())
[ 25  41  71  50  12  98  83   3  22  62  10  66  30  81 100  44   6  65
 113   1]

Dataset.batch के रूप में। Dataset.batch के 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:

[362 613 575 338 606 504 517 386 592 505]
[627 347 622 496 500 625 509 579 489 555]
[619 617 482 550 387 581 477 431]
[ 98  25  87  73  78  19  40  64  34 100]
[ 29 107  70   2   8  49  13  63  89  77]
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 0x7f2f6c1fcf28>

पींग

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

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:

[581 620 370  16   8 585 611 567  29 595]
[452  13 602 436 592 234 530 528   7  31]
[564 377 357  37 623  24 554 418 522   6]
[536  20  11 566 464  32 605 540 449  49]
[ 54 482  42  21  47 579  65 627 598  91]
[546 501  48  52 516  66 519 573   4  59]
[608  68  62 324  69   9 531 447 577  90]
[507   5  60  45 410  71  78  55  44 428]
[ 58 426 601 596  70  97  99 624  89  79]
[545 497  85 108 111 105  57  12  83  33]
[106 613  14 523  30  81  41  18 500 129]
[459  17   2 618 128 621  84  25 332  40]
[ 50  46 134 524  63 119 126 617 121  61]
[513 131 305  91  93 130 122  15 117 118]
[133 593 147 140 158  35 146  88 110  43]
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 0x7f2f6c286a58>

पींग

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

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

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

0 बीडीए 5 ई 5 ए 0

पींग

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

images_ds = list_ds.map(parse_image)

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

पींग

पींग

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

प्रदर्शन कारणों के लिए, जब भी संभव हो अपने डेटा को प्रीप्रोसेस करने के लिए 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)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

पींग

के साथ इस समारोह का उपयोग करने के 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).

पींग

पींग

पार्सिंग 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])

पींग

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 = 3

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

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

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

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

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=' ')
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 [==============================] - 2s 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.9951 0.0049]

असंतुलित डेटासेट के साथ प्रशिक्षण के लिए एक सामान्य दृष्टिकोण इसे संतुलित करना है। 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())
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())
[0 1 0 0 1 1 1 1 1 0]
[0 0 0 0 1 1 0 0 0 1]
[1 0 1 1 1 1 0 0 1 1]
[1 1 1 0 0 0 1 0 1 0]
[1 1 1 0 0 0 0 1 1 0]
[1 0 1 0 1 0 0 1 0 1]
[1 1 0 0 1 1 1 1 1 0]
[1 1 0 1 1 0 1 1 1 0]
[0 0 0 1 0 1 1 1 0 1]
[0 1 1 1 0 1 1 0 1 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())
[1 1 1 1 1 1 0 0 0 1]
[0 0 1 0 1 0 0 1 0 1]
[0 1 1 0 0 0 0 0 1 0]
[1 1 0 0 0 0 1 0 0 0]
[1 1 0 0 0 0 1 0 0 1]
[1 1 0 1 0 1 1 1 0 1]
[1 1 0 1 0 0 1 1 1 1]
[0 0 1 0 0 1 1 1 0 0]
[1 1 0 0 0 0 0 0 0 1]
[1 0 1 0 0 0 1 1 0 0]

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

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
1875/1875 [==============================] - 4s 2ms/step - loss: 0.7832 - accuracy: 0.7360
Epoch 2/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4691 - accuracy: 0.8378
<tensorflow.python.keras.callbacks.History at 0x7f2f2c60a4e0>

यदि आप एक अनंत डेटासेट पास करते हैं, उदाहरण के लिए 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.3968 - accuracy: 0.8625
Epoch 2/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4828 - accuracy: 0.8516
<tensorflow.python.keras.callbacks.History at 0x7f2f6c044b38>

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

loss, accuracy = model.evaluate(fmnist_train_ds)
print("Loss :", loss)
print("Accuracy :", accuracy)
1875/1875 [==============================] - 4s 2ms/step - loss: 0.4316 - accuracy: 0.8538
Loss : 0.4315564036369324
Accuracy : 0.853766679763794

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

loss, accuracy = model.evaluate(fmnist_train_ds.repeat(), steps=10)
print("Loss :", loss)
print("Accuracy :", accuracy)
10/10 [==============================] - 0s 2ms/step - loss: 0.5001 - accuracy: 0.8469
Loss : 0.500092625617981
Accuracy : 0.846875011920929

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)