Google I/O एक लपेट है! TensorFlow सत्रों पर पकड़ बनाएं सत्र देखें

सीएसवी डेटा लोड करें

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

यह ट्यूटोरियल TensorFlow के साथ CSV डेटा का उपयोग करने के उदाहरण प्रदान करता है।

इसके दो मुख्य भाग हैं:

  1. डिस्क से डेटा लोड हो रहा है
  2. प्रशिक्षण के लिए उपयुक्त रूप में इसे पूर्व-संसाधित करना।

यह ट्यूटोरियल लोडिंग पर केंद्रित है, और प्रीप्रोसेसिंग के कुछ त्वरित उदाहरण देता है। प्रीप्रोसेसिंग पहलू पर ध्यान केंद्रित करने वाले ट्यूटोरियल के लिए प्रीप्रोसेसिंग लेयर्स गाइड और ट्यूटोरियल देखें।

सेट अप

import pandas as pd
import numpy as np

# Make numpy values easier to read.
np.set_printoptions(precision=3, suppress=True)

import tensorflow as tf
from tensorflow.keras import layers

मेमोरी डेटा में

किसी भी छोटे CSV डेटासेट के लिए उस पर TensorFlow मॉडल को प्रशिक्षित करने का सबसे सरल तरीका है कि इसे मेमोरी में पांडा डेटाफ़्रेम या NumPy सरणी के रूप में लोड किया जाए।

एक अपेक्षाकृत सरल उदाहरण अबालोन डेटासेट है।

  • डेटासेट छोटा है।
  • सभी इनपुट सुविधाएँ सभी सीमित-श्रेणी के फ़्लोटिंग पॉइंट मान हैं।

DataFrame में डेटा डाउनलोड करने का तरीका यहां दिया गया है:

abalone_train = pd.read_csv(
    "https://storage.googleapis.com/download.tensorflow.org/data/abalone_train.csv",
    names=["Length", "Diameter", "Height", "Whole weight", "Shucked weight",
           "Viscera weight", "Shell weight", "Age"])

abalone_train.head()

डेटासेट में अबालोन के माप का एक सेट होता है, जो एक प्रकार का समुद्री घोंघा होता है।

एक अबालोन खोल

"अबालोन शेल" ( निकी दुगन पोग द्वारा, CC BY-SA 2.0)

इस डेटासेट के लिए नाममात्र का कार्य अन्य मापों से आयु की भविष्यवाणी करना है, इसलिए प्रशिक्षण के लिए सुविधाओं और लेबल को अलग करें:

abalone_features = abalone_train.copy()
abalone_labels = abalone_features.pop('Age')

इस डेटासेट के लिए आप सभी सुविधाओं को एक समान मानेंगे। सुविधाओं को एक एकल NumPy सरणी में पैक करें।

abalone_features = np.array(abalone_features)
abalone_features
array([[0.435, 0.335, 0.11 , ..., 0.136, 0.077, 0.097],
       [0.585, 0.45 , 0.125, ..., 0.354, 0.207, 0.225],
       [0.655, 0.51 , 0.16 , ..., 0.396, 0.282, 0.37 ],
       ...,
       [0.53 , 0.42 , 0.13 , ..., 0.374, 0.167, 0.249],
       [0.395, 0.315, 0.105, ..., 0.118, 0.091, 0.119],
       [0.45 , 0.355, 0.12 , ..., 0.115, 0.067, 0.16 ]])

अगला एक प्रतिगमन मॉडल बनाएं जो उम्र की भविष्यवाणी करता है। चूंकि केवल एक इनपुट टेंसर है, एक keras.Sequential । अनुक्रमिक मॉडल यहां पर्याप्त है।

abalone_model = tf.keras.Sequential([
  layers.Dense(64),
  layers.Dense(1)
])

abalone_model.compile(loss = tf.losses.MeanSquaredError(),
                      optimizer = tf.optimizers.Adam())

उस मॉडल को प्रशिक्षित करने के लिए, सुविधाओं और लेबल को Model.fit पर पास करें:

abalone_model.fit(abalone_features, abalone_labels, epochs=10)
Epoch 1/10
104/104 [==============================] - 1s 2ms/step - loss: 63.0446
Epoch 2/10
104/104 [==============================] - 0s 2ms/step - loss: 11.9429
Epoch 3/10
104/104 [==============================] - 0s 2ms/step - loss: 8.4836
Epoch 4/10
104/104 [==============================] - 0s 2ms/step - loss: 8.0052
Epoch 5/10
104/104 [==============================] - 0s 2ms/step - loss: 7.6073
Epoch 6/10
104/104 [==============================] - 0s 2ms/step - loss: 7.2485
Epoch 7/10
104/104 [==============================] - 0s 2ms/step - loss: 6.9883
Epoch 8/10
104/104 [==============================] - 0s 2ms/step - loss: 6.7977
Epoch 9/10
104/104 [==============================] - 0s 2ms/step - loss: 6.6477
Epoch 10/10
104/104 [==============================] - 0s 2ms/step - loss: 6.5359
<keras.callbacks.History at 0x7f70543c7350>

आपने अभी-अभी CSV डेटा का उपयोग करके किसी मॉडल को प्रशिक्षित करने का सबसे बुनियादी तरीका देखा है। इसके बाद, आप सीखेंगे कि संख्यात्मक कॉलम को सामान्य करने के लिए प्रीप्रोसेसिंग कैसे लागू करें।

बेसिक प्रीप्रोसेसिंग

अपने मॉडल के इनपुट को सामान्य करना एक अच्छा अभ्यास है। केरस प्रीप्रोसेसिंग परतें इस सामान्यीकरण को आपके मॉडल में बनाने का एक सुविधाजनक तरीका प्रदान करती हैं।

परत प्रत्येक कॉलम के माध्य और विचरण को पूर्व-गणना करेगी, और इनका उपयोग डेटा को सामान्य करने के लिए करेगी।

सबसे पहले आप परत बनाएं:

normalize = layers.Normalization()

फिर आप अपने डेटा के लिए सामान्यीकरण परत को अनुकूलित करने के लिए Normalization.adapt() विधि का उपयोग करते हैं।

normalize.adapt(abalone_features)

फिर अपने मॉडल में सामान्यीकरण परत का उपयोग करें:

norm_abalone_model = tf.keras.Sequential([
  normalize,
  layers.Dense(64),
  layers.Dense(1)
])

norm_abalone_model.compile(loss = tf.losses.MeanSquaredError(),
                           optimizer = tf.optimizers.Adam())

norm_abalone_model.fit(abalone_features, abalone_labels, epochs=10)
Epoch 1/10
104/104 [==============================] - 0s 2ms/step - loss: 92.5851
Epoch 2/10
104/104 [==============================] - 0s 2ms/step - loss: 55.1199
Epoch 3/10
104/104 [==============================] - 0s 2ms/step - loss: 18.2937
Epoch 4/10
104/104 [==============================] - 0s 2ms/step - loss: 6.2633
Epoch 5/10
104/104 [==============================] - 0s 2ms/step - loss: 5.1257
Epoch 6/10
104/104 [==============================] - 0s 2ms/step - loss: 5.0217
Epoch 7/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9775
Epoch 8/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9730
Epoch 9/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9348
Epoch 10/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9416
<keras.callbacks.History at 0x7f70541b2a50>

मिश्रित डेटा प्रकार

"टाइटैनिक" डेटासेट में टाइटैनिक के यात्रियों के बारे में जानकारी होती है। इस डेटासेट पर नाममात्र का कार्य यह भविष्यवाणी करना है कि कौन बच गया।

भीमकाय

विकिमीडिया से छवि

कच्चे डेटा को आसानी से पंडों के DataFrame के रूप में लोड किया जा सकता है, लेकिन TensorFlow मॉडल के इनपुट के रूप में तुरंत उपयोग करने योग्य नहीं है।

titanic = pd.read_csv("https://storage.googleapis.com/tf-datasets/titanic/train.csv")
titanic.head()
titanic_features = titanic.copy()
titanic_labels = titanic_features.pop('survived')

विभिन्न डेटा प्रकारों और श्रेणियों के कारण आप केवल सुविधाओं को NumPy सरणी में स्टैक नहीं कर सकते हैं और इसे keras.Sequential मॉडल में पास कर सकते हैं। प्रत्येक कॉलम को व्यक्तिगत रूप से संभाला जाना चाहिए।

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

इस उदाहरण में, आप एक ऐसा मॉडल बनाएंगे जो केरस फंक्शनल एपीआई का उपयोग करके प्रीप्रोसेसिंग लॉजिक को लागू करता है। आप इसे सबक्लासिंग करके भी कर सकते हैं।

कार्यात्मक एपीआई "प्रतीकात्मक" टेंसर पर काम करता है। सामान्य "उत्सुक" टेंसर का एक मूल्य होता है। इसके विपरीत ये "प्रतीकात्मक" टेंसर नहीं करते हैं। इसके बजाय वे ट्रैक करते हैं कि उन पर कौन से ऑपरेशन चल रहे हैं, और गणना का प्रतिनिधित्व करते हैं, जिसे आप बाद में चला सकते हैं। यहाँ एक त्वरित उदाहरण है:

# Create a symbolic input
input = tf.keras.Input(shape=(), dtype=tf.float32)

# Perform a calculation using the input
result = 2*input + 1

# the result doesn't have a value
result
<KerasTensor: shape=(None,) dtype=float32 (created by layer 'tf.__operators__.add')>
calc = tf.keras.Model(inputs=input, outputs=result)
print(calc(1).numpy())
print(calc(2).numpy())
3.0
5.0

प्रीप्रोसेसिंग मॉडल बनाने के लिए, प्रतीकात्मक keras.Input का एक सेट बनाकर शुरू करें। इनपुट ऑब्जेक्ट्स, सीएसवी कॉलम के नाम और डेटा-प्रकार से मेल खाते हैं।

inputs = {}

for name, column in titanic_features.items():
  dtype = column.dtype
  if dtype == object:
    dtype = tf.string
  else:
    dtype = tf.float32

  inputs[name] = tf.keras.Input(shape=(1,), name=name, dtype=dtype)

inputs
{'sex': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'sex')>,
 'age': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'age')>,
 'n_siblings_spouses': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'n_siblings_spouses')>,
 'parch': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'parch')>,
 'fare': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'fare')>,
 'class': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'class')>,
 'deck': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'deck')>,
 'embark_town': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'embark_town')>,
 'alone': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'alone')>}

आपके प्रीप्रोसेसिंग तर्क में पहला कदम संख्यात्मक इनपुट को एक साथ जोड़ना है, और उन्हें सामान्यीकरण परत के माध्यम से चलाना है:

numeric_inputs = {name:input for name,input in inputs.items()
                  if input.dtype==tf.float32}

x = layers.Concatenate()(list(numeric_inputs.values()))
norm = layers.Normalization()
norm.adapt(np.array(titanic[numeric_inputs.keys()]))
all_numeric_inputs = norm(x)

all_numeric_inputs
<KerasTensor: shape=(None, 4) dtype=float32 (created by layer 'normalization_1')>

सभी प्रतीकात्मक प्रीप्रोसेसिंग परिणामों को बाद में संयोजित करने के लिए एकत्र करें।

preprocessed_inputs = [all_numeric_inputs]

स्ट्रिंग इनपुट के लिए tf.keras.layers.StringLookup फ़ंक्शन का उपयोग किसी शब्दावली में स्ट्रिंग्स से पूर्णांक इंडेक्स तक मैप करने के लिए करें। इसके बाद, tf.keras.layers.CategoryEncoding का उपयोग करके इंडेक्स को मॉडल के लिए उपयुक्त फ्लोट32 डेटा में float32

tf.keras.layers.CategoryEncoding परत के लिए डिफ़ॉल्ट सेटिंग्स प्रत्येक इनपुट के लिए एक-हॉट वेक्टर बनाती हैं। एक परत। layers.Embedding भी काम करेगी। इस विषय पर अधिक जानकारी के लिए प्रीप्रोसेसिंग लेयर गाइड और ट्यूटोरियल देखें।

for name, input in inputs.items():
  if input.dtype == tf.float32:
    continue

  lookup = layers.StringLookup(vocabulary=np.unique(titanic_features[name]))
  one_hot = layers.CategoryEncoding(max_tokens=lookup.vocab_size())

  x = lookup(input)
  x = one_hot(x)
  preprocessed_inputs.append(x)
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
प्लेसहोल्डर26

inputs और processed_inputs के संग्रह के साथ, आप सभी प्रीप्रोसेस्ड इनपुट्स को एक साथ जोड़ सकते हैं, और एक मॉडल बना सकते हैं जो प्रीप्रोसेसिंग को हैंडल करता है:

preprocessed_inputs_cat = layers.Concatenate()(preprocessed_inputs)

titanic_preprocessing = tf.keras.Model(inputs, preprocessed_inputs_cat)

tf.keras.utils.plot_model(model = titanic_preprocessing , rankdir="LR", dpi=72, show_shapes=True)

पीएनजी

इस model में सिर्फ इनपुट प्रीप्रोसेसिंग शामिल है। आप इसे यह देखने के लिए चला सकते हैं कि यह आपके डेटा के साथ क्या करता है। केरस मॉडल स्वचालित रूप से पंडों के DataFrames को परिवर्तित नहीं करते हैं क्योंकि यह स्पष्ट नहीं है कि इसे एक टेंसर में या टेंसर के शब्दकोश में परिवर्तित किया जाना चाहिए। तो इसे टेंसर के शब्दकोश में परिवर्तित करें:

titanic_features_dict = {name: np.array(value) 
                         for name, value in titanic_features.items()}

पहले प्रशिक्षण उदाहरण को स्लाइस करें और इसे इस प्रीप्रोसेसिंग मॉडल में पास करें, आप संख्यात्मक विशेषताओं और स्ट्रिंग वन-हॉट्स को एक साथ जोड़कर देखते हैं:

features_dict = {name:values[:1] for name, values in titanic_features_dict.items()}
titanic_preprocessing(features_dict)
<tf.Tensor: shape=(1, 28), dtype=float32, numpy=
array([[-0.61 ,  0.395, -0.479, -0.497,  0.   ,  0.   ,  1.   ,  0.   ,

         0.   ,  0.   ,  1.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,
         0.   ,  0.   ,  0.   ,  1.   ,  0.   ,  0.   ,  0.   ,  1.   ,
         0.   ,  0.   ,  1.   ,  0.   ]], dtype=float32)>

अब इसके ऊपर मॉडल बनाएं:

def titanic_model(preprocessing_head, inputs):
  body = tf.keras.Sequential([
    layers.Dense(64),
    layers.Dense(1)
  ])

  preprocessed_inputs = preprocessing_head(inputs)
  result = body(preprocessed_inputs)
  model = tf.keras.Model(inputs, result)

  model.compile(loss=tf.losses.BinaryCrossentropy(from_logits=True),
                optimizer=tf.optimizers.Adam())
  return model

titanic_model = titanic_model(titanic_preprocessing, inputs)

जब आप मॉडल को प्रशिक्षित करते हैं, तो सुविधाओं के शब्दकोश को x और लेबल को y के रूप में पास करें।

titanic_model.fit(x=titanic_features_dict, y=titanic_labels, epochs=10)
Epoch 1/10
20/20 [==============================] - 1s 4ms/step - loss: 0.8017
Epoch 2/10
20/20 [==============================] - 0s 4ms/step - loss: 0.5913
Epoch 3/10
20/20 [==============================] - 0s 5ms/step - loss: 0.5212
Epoch 4/10
20/20 [==============================] - 0s 5ms/step - loss: 0.4841
Epoch 5/10
20/20 [==============================] - 0s 5ms/step - loss: 0.4615
Epoch 6/10
20/20 [==============================] - 0s 5ms/step - loss: 0.4470
Epoch 7/10
20/20 [==============================] - 0s 5ms/step - loss: 0.4367
Epoch 8/10
20/20 [==============================] - 0s 5ms/step - loss: 0.4304
Epoch 9/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4265
Epoch 10/10
20/20 [==============================] - 0s 5ms/step - loss: 0.4239
<keras.callbacks.History at 0x7f70b1f82a50>
प्लेसहोल्डर33

चूंकि प्रीप्रोसेसिंग मॉडल का हिस्सा है, आप मॉडल को सहेज सकते हैं और इसे कहीं और पुनः लोड कर सकते हैं और समान परिणाम प्राप्त कर सकते हैं:

titanic_model.save('test')
reloaded = tf.keras.models.load_model('test')
2022-01-26 06:36:18.822459: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: test/assets
features_dict = {name:values[:1] for name, values in titanic_features_dict.items()}

before = titanic_model(features_dict)
after = reloaded(features_dict)
assert (before-after)<1e-3
print(before)
print(after)
tf.Tensor([[-1.791]], shape=(1, 1), dtype=float32)
tf.Tensor([[-1.791]], shape=(1, 1), dtype=float32)

tf.डेटा का उपयोग करना

पिछले अनुभाग में आपने मॉडल को प्रशिक्षित करते समय मॉडल के अंतर्निहित डेटा फेरबदल और बैचिंग पर भरोसा किया था।

यदि आपको इनपुट डेटा पाइपलाइन पर अधिक नियंत्रण की आवश्यकता है या डेटा का उपयोग करने की आवश्यकता है जो आसानी से मेमोरी में फिट नहीं होता है: tf.data का उपयोग करें।

अधिक उदाहरणों के लिए tf.data गाइड देखें।

मेमोरी डेटा में चालू है

CSV डेटा में tf.data लागू करने के पहले उदाहरण के रूप में, पिछले अनुभाग से सुविधाओं के शब्दकोश को मैन्युअल रूप से अलग करने के लिए निम्नलिखित कोड पर विचार करें। प्रत्येक सूचकांक के लिए, यह प्रत्येक सुविधा के लिए उस सूचकांक को लेता है:

import itertools

def slices(features):
  for i in itertools.count():
    # For each feature take index `i`
    example = {name:values[i] for name, values in features.items()}
    yield example

इसे चलाएँ और पहला उदाहरण प्रिंट करें:

for example in slices(titanic_features_dict):
  for name, value in example.items():
    print(f"{name:19s}: {value}")
  break
sex                : male
age                : 22.0
n_siblings_spouses : 1
parch              : 0
fare               : 7.25
class              : Third
deck               : unknown
embark_town        : Southampton
alone              : n

मेमोरी डेटा लोडर में सबसे बुनियादी tf.data.Dataset Dataset.from_tensor_slices कंस्ट्रक्टर है। यह एक tf.data.Dataset देता है जो TensorFlow में उपरोक्त slices फ़ंक्शन के सामान्यीकृत संस्करण को लागू करता है।

features_ds = tf.data.Dataset.from_tensor_slices(titanic_features_dict)

आप एक tf.data.Dataset पर पुनरावृति कर सकते हैं जैसे कि कोई अन्य अजगर चलने योग्य:

for example in features_ds:
  for name, value in example.items():
    print(f"{name:19s}: {value}")
  break
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'

from_tensor_slices फ़ंक्शन नेस्टेड शब्दकोशों या टुपल्स की किसी भी संरचना को संभाल सकता है। निम्नलिखित कोड (features_dict, labels) जोड़े का एक डेटासेट बनाता है:

titanic_ds = tf.data.Dataset.from_tensor_slices((titanic_features_dict, titanic_labels))

इस Dataset का उपयोग करके किसी मॉडल को प्रशिक्षित करने के लिए, आपको कम से कम डेटा को shuffle और batch करना होगा।

titanic_batches = titanic_ds.shuffle(len(titanic_labels)).batch(32)

Model.fit में features और labels को पास करने के बजाय, आप डेटासेट पास करते हैं:

titanic_model.fit(titanic_batches, epochs=5)
Epoch 1/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4230
Epoch 2/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4216
Epoch 3/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4203
Epoch 4/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4198
Epoch 5/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4194
<keras.callbacks.History at 0x7f70b12485d0>

एक ही फाइल से

अब तक इस ट्यूटोरियल ने इन-मेमोरी डेटा के साथ काम किया है। tf.data डेटा पाइपलाइन बनाने के लिए एक उच्च स्केलेबल टूलकिट है, और CSV फ़ाइलों को लोड करने से निपटने के लिए कुछ कार्य प्रदान करता है।

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

अब फ़ाइल से CSV डेटा पढ़ें और एक tf.data.Dataset

(पूर्ण दस्तावेज़ीकरण के लिए, tf.data.experimental.make_csv_dataset देखें)

titanic_csv_ds = tf.data.experimental.make_csv_dataset(
    titanic_file_path,
    batch_size=5, # Artificially small to make examples easier to show.
    label_name='survived',
    num_epochs=1,
    ignore_errors=True,)

इस फ़ंक्शन में कई सुविधाजनक सुविधाएं शामिल हैं ताकि डेटा के साथ काम करना आसान हो। यह भी शामिल है:

  • कॉलम हेडर का उपयोग डिक्शनरी कीज़ के रूप में करना।
  • प्रत्येक कॉलम के प्रकार को स्वचालित रूप से निर्धारित करना।
for batch, label in titanic_csv_ds.take(1):
  for key, value in batch.items():
    print(f"{key:20s}: {value}")
  print()
  print(f"{'label':20s}: {label}")
sex                 : [b'male' b'male' b'female' b'male' b'male']
age                 : [27. 18. 15. 46. 50.]
n_siblings_spouses  : [0 0 0 1 0]
parch               : [0 0 0 0 0]
fare                : [ 7.896  7.796  7.225 61.175 13.   ]
class               : [b'Third' b'Third' b'Third' b'First' b'Second']
deck                : [b'unknown' b'unknown' b'unknown' b'E' b'unknown']
embark_town         : [b'Southampton' b'Southampton' b'Cherbourg' b'Southampton' b'Southampton']
alone               : [b'y' b'y' b'y' b'n' b'y']

label               : [0 0 1 0 0]

यह मक्खी पर डेटा को डीकंप्रेस भी कर सकता है। मेट्रो अंतरराज्यीय ट्रैफ़िक डेटासेट वाली gzipped CSV फ़ाइल यहां दी गई है

ट्रैफ़िक जाम।

विकिमीडिया से छवि

traffic_volume_csv_gz = tf.keras.utils.get_file(
    'Metro_Interstate_Traffic_Volume.csv.gz', 
    "https://archive.ics.uci.edu/ml/machine-learning-databases/00492/Metro_Interstate_Traffic_Volume.csv.gz",
    cache_dir='.', cache_subdir='traffic')
Downloading data from https://archive.ics.uci.edu/ml/machine-learning-databases/00492/Metro_Interstate_Traffic_Volume.csv.gz
409600/405373 [==============================] - 1s 1us/step
417792/405373 [==============================] - 1s 1us/step

संपीड़ित फ़ाइल से सीधे पढ़ने के लिए compression_type तर्क सेट करें:

traffic_volume_csv_gz_ds = tf.data.experimental.make_csv_dataset(
    traffic_volume_csv_gz,
    batch_size=256,
    label_name='traffic_volume',
    num_epochs=1,
    compression_type="GZIP")

for batch, label in traffic_volume_csv_gz_ds.take(1):
  for key, value in batch.items():
    print(f"{key:20s}: {value[:5]}")
  print()
  print(f"{'label':20s}: {label[:5]}")
holiday             : [b'None' b'None' b'None' b'None' b'None']
temp                : [280.56 266.79 281.64 292.71 270.48]
rain_1h             : [0. 0. 0. 0. 0.]
snow_1h             : [0. 0. 0. 0. 0.]
clouds_all          : [46 90 90  0 64]
weather_main        : [b'Clear' b'Clouds' b'Mist' b'Clear' b'Clouds']
weather_description : [b'sky is clear' b'overcast clouds' b'mist' b'Sky is Clear'
 b'broken clouds']
date_time           : [b'2012-11-05 20:00:00' b'2012-12-17 23:00:00' b'2013-10-06 19:00:00'
 b'2013-08-23 22:00:00' b'2013-11-11 05:00:00']

label               : [2415  966 3459 2633 2576]

कैशिंग

सीएसवी डेटा को पार्स करने के लिए कुछ ओवरहेड है। छोटे मॉडलों के लिए यह प्रशिक्षण में अड़चन हो सकती है।

आपके उपयोग के मामले के आधार पर Dataset.cache या data.experimental.snapshot का उपयोग करना एक अच्छा विचार हो सकता है ताकि csv डेटा केवल पहले युग में ही पार्स किया जा सके।

cache और snapshot विधियों के बीच मुख्य अंतर यह है कि cache फ़ाइलों का उपयोग केवल TensorFlow प्रक्रिया द्वारा किया जा सकता है जिसने उन्हें बनाया है, लेकिन snapshot फ़ाइलों को अन्य प्रक्रियाओं द्वारा पढ़ा जा सकता है।

उदाहरण के लिए, traffic_volume_csv_gz_ds पर 20 बार पुनरावृति करने पर, कैशिंग के बिना ~15 सेकंड या कैशिंग के साथ ~2 सेकंड लगते हैं।

%%time
for i, (batch, label) in enumerate(traffic_volume_csv_gz_ds.repeat(20)):
  if i % 40 == 0:
    print('.', end='')
print()
...............................................................................................
CPU times: user 14.9 s, sys: 3.7 s, total: 18.6 s
Wall time: 11.2 s
%%time
caching = traffic_volume_csv_gz_ds.cache().shuffle(1000)

for i, (batch, label) in enumerate(caching.shuffle(1000).repeat(20)):
  if i % 40 == 0:
    print('.', end='')
print()
...............................................................................................
CPU times: user 1.43 s, sys: 173 ms, total: 1.6 s
Wall time: 1.28 s
%%time
snapshot = tf.data.experimental.snapshot('titanic.tfsnap')
snapshotting = traffic_volume_csv_gz_ds.apply(snapshot).shuffle(1000)

for i, (batch, label) in enumerate(snapshotting.shuffle(1000).repeat(20)):
  if i % 40 == 0:
    print('.', end='')
print()
WARNING:tensorflow:From <timed exec>:1: snapshot (from tensorflow.python.data.experimental.ops.snapshot) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.data.Dataset.snapshot(...)`.
...............................................................................................
CPU times: user 2.17 s, sys: 460 ms, total: 2.63 s
Wall time: 1.6 s

यदि csv फ़ाइलों को लोड करने से आपका डेटा लोड धीमा हो जाता है, और cache और snapshot आपके उपयोग के मामले के लिए अपर्याप्त हैं, तो अपने डेटा को अधिक सुव्यवस्थित प्रारूप में फिर से एन्कोड करने पर विचार करें।

एकाधिक फ़ाइलें

इस खंड में अब तक के सभी उदाहरण tf.data के बिना आसानी से किए जा सकते हैं। फाइलों के संग्रह से निपटने के दौरान एक जगह जहां tf.data वास्तव में चीजों को सरल बना सकता है।

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

फोंट्स

पिक्साबे से विली हीडलबैक द्वारा छवि

डेटासेट डाउनलोड करें, और अंदर की फाइलों पर एक नजर डालें:

fonts_zip = tf.keras.utils.get_file(
    'fonts.zip',  "https://archive.ics.uci.edu/ml/machine-learning-databases/00417/fonts.zip",
    cache_dir='.', cache_subdir='fonts',
    extract=True)
Downloading data from https://archive.ics.uci.edu/ml/machine-learning-databases/00417/fonts.zip
160317440/160313983 [==============================] - 8s 0us/step
160325632/160313983 [==============================] - 8s 0us/step
import pathlib
font_csvs =  sorted(str(p) for p in pathlib.Path('fonts').glob("*.csv"))

font_csvs[:10]
['fonts/AGENCY.csv',
 'fonts/ARIAL.csv',
 'fonts/BAITI.csv',
 'fonts/BANKGOTHIC.csv',
 'fonts/BASKERVILLE.csv',
 'fonts/BAUHAUS.csv',
 'fonts/BELL.csv',
 'fonts/BERLIN.csv',
 'fonts/BERNARD.csv',
 'fonts/BITSTREAMVERA.csv']
len(font_csvs)
153

फ़ाइलों के एक समूह के साथ काम करते समय आप एक ग्लोब-शैली file_pattern को experimental.make_csv_dataset .make_csv_dataset फ़ंक्शन में पास कर सकते हैं। फ़ाइलों का क्रम प्रत्येक पुनरावृत्ति में फेरबदल किया जाता है।

समानांतर में कितनी फाइलें पढ़ी जाती हैं और एक साथ इंटरलीव की जाती हैं, यह निर्धारित करने के लिए num_parallel_reads तर्क का उपयोग करें।

fonts_ds = tf.data.experimental.make_csv_dataset(
    file_pattern = "fonts/*.csv",
    batch_size=10, num_epochs=1,
    num_parallel_reads=20,
    shuffle_buffer_size=10000)

इन सीएसवी फाइलों में छवियों को एक ही पंक्ति में समतल कर दिया गया है। कॉलम नाम प्रारूपित हैं r{row}c{column} । यहाँ पहला बैच है:

for features in fonts_ds.take(1):
  for i, (name, value) in enumerate(features.items()):
    if i>15:
      break
    print(f"{name:20s}: {value}")
print('...')
print(f"[total: {len(features)} features]")
font                : [b'HANDPRINT' b'NIAGARA' b'EUROROMAN' b'NIAGARA' b'CENTAUR' b'NINA'
 b'GOUDY' b'SITKA' b'BELL' b'SITKA']
fontVariant         : [b'scanned' b'NIAGARA SOLID' b'EUROROMAN' b'NIAGARA SOLID' b'CENTAUR'
 b'NINA' b'GOUDY STOUT' b'SITKA TEXT' b'BELL MT' b'SITKA TEXT']
m_label             : [  49 8482  245   88  174 9643   77  974  117  339]
strength            : [0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4]
italic              : [0 0 0 1 0 0 1 0 1 0]
orientation         : [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
m_top               : [ 0 32 24 32 28 57 38 48 51 64]
m_left              : [ 0 20 24 20 22 24 27 23 25 23]
originalH           : [20 27 55 47 50 15 51 50 27 34]
originalW           : [  4  33  25  33  50  15 116  43  28  53]
h                   : [20 20 20 20 20 20 20 20 20 20]
w                   : [20 20 20 20 20 20 20 20 20 20]
r0c0                : [  1 255 255   1   1 255   1   1   1   1]
r0c1                : [  1 255 255   1   1 255   1   1   1   1]
r0c2                : [  1 217 255   1   1 255  54   1   1   1]
r0c3                : [  1 213 255   1   1 255 255   1   1  64]
...
[total: 412 features]

वैकल्पिक: पैकिंग फ़ील्ड

आप शायद इस तरह के अलग-अलग कॉलम में प्रत्येक पिक्सेल के साथ काम नहीं करना चाहते हैं। इस डेटासेट का उपयोग करने का प्रयास करने से पहले पिक्सेल को इमेज-टेंसर में पैक करना सुनिश्चित करें।

यहां कोड है जो प्रत्येक उदाहरण के लिए छवियों को बनाने के लिए कॉलम नामों को पार करता है:

import re

def make_images(features):
  image = [None]*400
  new_feats = {}

  for name, value in features.items():
    match = re.match('r(\d+)c(\d+)', name)
    if match:
      image[int(match.group(1))*20+int(match.group(2))] = value
    else:
      new_feats[name] = value

  image = tf.stack(image, axis=0)
  image = tf.reshape(image, [20, 20, -1])
  new_feats['image'] = image

  return new_feats

डेटासेट में प्रत्येक बैच में उस फ़ंक्शन को लागू करें:

fonts_image_ds = fonts_ds.map(make_images)

for features in fonts_image_ds.take(1):
  break

परिणामी छवियों को प्लॉट करें:

from matplotlib import pyplot as plt

plt.figure(figsize=(6,6), dpi=120)

for n in range(9):
  plt.subplot(3,3,n+1)
  plt.imshow(features['image'][..., n])
  plt.title(chr(features['m_label'][n]))
  plt.axis('off')

पीएनजी

निचले स्तर के कार्य

अब तक इस ट्यूटोरियल ने csv डेटा पढ़ने के लिए उच्चतम स्तर की उपयोगिताओं पर ध्यान केंद्रित किया है। अन्य दो एपीआई हैं जो उन्नत उपयोगकर्ताओं के लिए सहायक हो सकती हैं यदि आपका उपयोग-मामला बुनियादी पैटर्न में फिट नहीं होता है।

  • tf.io.decode_csv - CSV कॉलम टेंसर की सूची में टेक्स्ट की पंक्तियों को पार्स करने के लिए एक फ़ंक्शन।
  • tf.data.experimental.CsvDataset - एक निचला स्तर csv डेटासेट कंस्ट्रक्टर।

यह खंड make_csv_dataset द्वारा प्रदान की गई कार्यक्षमता को फिर से प्रदर्शित करता है, यह प्रदर्शित करने के लिए कि इस निचले स्तर की कार्यक्षमता का उपयोग कैसे किया जा सकता है।

tf.io.decode_csv

यह फ़ंक्शन एक स्ट्रिंग, या स्ट्रिंग्स की सूची को कॉलम की सूची में डिकोड करता है।

make_csv_dataset के विपरीत यह फ़ंक्शन कॉलम डेटा-प्रकारों का अनुमान लगाने का प्रयास नहीं करता है। आप प्रत्येक कॉलम के लिए सही प्रकार के मान वाले record_defaults की सूची प्रदान करके कॉलम प्रकार निर्दिष्ट करते हैं।

टाइटैनिक डेटा को decode_csv का उपयोग करके स्ट्रिंग्स के रूप में पढ़ने के लिए आप कहेंगे:

text = pathlib.Path(titanic_file_path).read_text()
lines = text.split('\n')[1:-1]

all_strings = [str()]*10
all_strings
['', '', '', '', '', '', '', '', '', '']
features = tf.io.decode_csv(lines, record_defaults=all_strings) 

for f in features:
  print(f"type: {f.dtype.name}, shape: {f.shape}")
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)

उन्हें उनके वास्तविक प्रकारों के साथ पार्स करने के लिए, संबंधित प्रकार के record_defaults की एक सूची बनाएं:

print(lines[0])
0,male,22.0,1,0,7.25,Third,unknown,Southampton,n
titanic_types = [int(), str(), float(), int(), int(), float(), str(), str(), str(), str()]
titanic_types
[0, '', 0.0, 0, 0, 0.0, '', '', '', '']
features = tf.io.decode_csv(lines, record_defaults=titanic_types) 

for f in features:
  print(f"type: {f.dtype.name}, shape: {f.shape}")
type: int32, shape: (627,)
type: string, shape: (627,)
type: float32, shape: (627,)
type: int32, shape: (627,)
type: int32, shape: (627,)
type: float32, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)

tf.data.experimental.CsvDataset

tf.data.experimental.CsvDataset वर्ग make_csv_dataset फ़ंक्शन की सुविधा सुविधाओं के बिना एक न्यूनतम CSV Dataset इंटरफ़ेस प्रदान करता है: कॉलम हेडर पार्सिंग, कॉलम प्रकार-अनुमान, स्वचालित फेरबदल, फ़ाइल इंटरलीविंग।

यह कंस्ट्रक्टर io.parse_csv की तरह ही record_defaults का उपयोग करता है:

simple_titanic = tf.data.experimental.CsvDataset(titanic_file_path, record_defaults=titanic_types, header=True)

for example in simple_titanic.take(1):
  print([e.numpy() for e in example])
[0, b'male', 22.0, 1, 0, 7.25, b'Third', b'unknown', b'Southampton', b'n']

उपरोक्त कोड मूल रूप से इसके बराबर है:

def decode_titanic_line(line):
  return tf.io.decode_csv(line, titanic_types)

manual_titanic = (
    # Load the lines of text
    tf.data.TextLineDataset(titanic_file_path)
    # Skip the header row.
    .skip(1)
    # Decode the line.
    .map(decode_titanic_line)
)

for example in manual_titanic.take(1):
  print([e.numpy() for e in example])
[0, b'male', 22.0, 1, 0, 7.25, b'Third', b'unknown', b'Southampton', b'n']

एकाधिक फ़ाइलें

experimental.CsvDataset .CsvDataset का उपयोग करके फ़ॉन्ट डेटासेट को पार्स करने के लिए, आपको पहले record_defaults के लिए कॉलम प्रकार निर्धारित करने की आवश्यकता है। एक फ़ाइल की पहली पंक्ति का निरीक्षण करके प्रारंभ करें:

font_line = pathlib.Path(font_csvs[0]).read_text().splitlines()[1]
print(font_line)
AGENCY,AGENCY FB,64258,0.400000,0,0.000000,35,21,51,22,20,20,1,1,1,21,101,210,255,255,255,255,255,255,255,255,255,255,255,255,255,255,1,1,1,93,255,255,255,176,146,146,146,146,146,146,146,146,216,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,141,141,141,182,255,255,255,172,141,141,141,115,1,1,1,1,163,255,255,255,255,255,255,255,255,255,255,255,255,255,255,209,1,1,1,1,163,255,255,255,6,6,6,96,255,255,255,74,6,6,6,5,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255

केवल पहले दो फ़ील्ड स्ट्रिंग हैं, बाकी इंट्स या फ़्लोट हैं, और आप कॉमा की गणना करके सुविधाओं की कुल संख्या प्राप्त कर सकते हैं:

num_font_features = font_line.count(',')+1
font_column_types = [str(), str()] + [float()]*(num_font_features-2)

CsvDatasaet कंस्ट्रक्टर इनपुट फ़ाइलों की एक सूची ले सकता है, लेकिन उन्हें क्रमिक रूप से पढ़ता है। CSV की सूची में पहली फ़ाइल AGENCY.csv है:

font_csvs[0]
'fonts/AGENCY.csv'

इसलिए जब आप फाइलों की सूची CsvDataset को पास करते हैं तो CsvDataaset के रिकॉर्ड पहले AGENCY.csv जाते हैं:

simple_font_ds = tf.data.experimental.CsvDataset(
    font_csvs, 
    record_defaults=font_column_types, 
    header=True)
for row in simple_font_ds.take(10):
  print(row[0].numpy())
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'

एकाधिक फ़ाइलों को इंटरलीव करने के लिए, Dataset.interleave का उपयोग करें।

यहां एक प्रारंभिक डेटासेट है जिसमें csv फ़ाइल नाम शामिल हैं:

font_files = tf.data.Dataset.list_files("fonts/*.csv")

यह फ़ाइल नामों को प्रत्येक युग में फेरबदल करता है:

print('Epoch 1:')
for f in list(font_files)[:5]:
  print("    ", f.numpy())
print('    ...')
print()

print('Epoch 2:')
for f in list(font_files)[:5]:
  print("    ", f.numpy())
print('    ...')
Epoch 1:
     b'fonts/CORBEL.csv'
     b'fonts/GLOUCESTER.csv'
     b'fonts/GABRIOLA.csv'
     b'fonts/FORTE.csv'
     b'fonts/GILL.csv'
    ...

Epoch 2:
     b'fonts/MONEY.csv'
     b'fonts/ISOC.csv'
     b'fonts/DUTCH801.csv'
     b'fonts/CALIBRI.csv'
     b'fonts/ROMANTIC.csv'
    ...

interleave विधि एक map_func लेती है जो माता-पिता के प्रत्येक तत्व के लिए एक बच्चा- Dataset बनाता है- Dataset

यहां, आप फ़ाइलों के डेटासेट के प्रत्येक तत्व से एक CsvDataset बनाना चाहते हैं:

def make_font_csv_ds(path):
  return tf.data.experimental.CsvDataset(
    path, 
    record_defaults=font_column_types, 
    header=True)

इंटरलीव द्वारा लौटाया गया Dataset कई बच्चे- Dataset s पर साइकिल चलाकर तत्वों को लौटाता है। ध्यान दें, नीचे, कैसे डेटासेट cycle_length=3 तीन फ़ॉन्ट फ़ाइलों पर चक्रित होता है:

font_rows = font_files.interleave(make_font_csv_ds,
                                  cycle_length=3)
fonts_dict = {'font_name':[], 'character':[]}

for row in font_rows.take(10):
  fonts_dict['font_name'].append(row[0].numpy().decode())
  fonts_dict['character'].append(chr(row[2].numpy()))

pd.DataFrame(fonts_dict)

प्रदर्शन

इससे पहले, यह नोट किया गया था कि स्ट्रिंग्स के बैच पर चलने पर io.decode_csv अधिक कुशल होता है।

सीएसवी लोडिंग प्रदर्शन में सुधार करने के लिए, बड़े बैच आकारों का उपयोग करते समय इस तथ्य का लाभ उठाना संभव है (लेकिन पहले कैशिंग का प्रयास करें)।

बिल्ट-इन लोडर 20 के साथ, 2048-उदाहरण बैचों में लगभग 17 सेकंड लगते हैं।

BATCH_SIZE=2048
fonts_ds = tf.data.experimental.make_csv_dataset(
    file_pattern = "fonts/*.csv",
    batch_size=BATCH_SIZE, num_epochs=1,
    num_parallel_reads=100)
%%time
for i,batch in enumerate(fonts_ds.take(20)):
  print('.',end='')

print()
....................
CPU times: user 24.3 s, sys: 1.46 s, total: 25.7 s
Wall time: 10.9 s

टेक्स्ट लाइनों के बैच को decode_csv में पास करना लगभग 5 सेकंड में तेजी से चलता है:

fonts_files = tf.data.Dataset.list_files("fonts/*.csv")
fonts_lines = fonts_files.interleave(
    lambda fname:tf.data.TextLineDataset(fname).skip(1), 
    cycle_length=100).batch(BATCH_SIZE)

fonts_fast = fonts_lines.map(lambda x: tf.io.decode_csv(x, record_defaults=font_column_types))
%%time
for i,batch in enumerate(fonts_fast.take(20)):
  print('.',end='')

print()
....................
CPU times: user 8.77 s, sys: 0 ns, total: 8.77 s
Wall time: 1.57 s

बड़े बैचों का उपयोग करके सीएसवी प्रदर्शन बढ़ाने के एक अन्य उदाहरण के लिए ओवरफिट और अंडरफिट ट्यूटोरियल देखें।

इस प्रकार का दृष्टिकोण काम कर सकता है, लेकिन cache और snapshot जैसे अन्य विकल्पों पर विचार करें, या अपने डेटा को अधिक सुव्यवस्थित प्रारूप में फिर से एन्कोड करें।