सामान्य कार्यान्वयन गोचर

यह पृष्ठ नए डेटासेट को लागू करते समय सामान्य कार्यान्वयन गेटचा का वर्णन करता है।

लिगेसी SplitGenerator बचना चाहिए

पुराना tfds.core.SplitGenerator API अप्रचलित है।

def _split_generator(...):
  return [
      tfds.core.SplitGenerator(name='train', gen_kwargs={'path': train_path}),
      tfds.core.SplitGenerator(name='test', gen_kwargs={'path': test_path}),
  ]

द्वारा प्रतिस्थापित किया जाना चाहिए:

def _split_generator(...):
  return {
      'train': self._generate_examples(path=train_path),
      'test': self._generate_examples(path=test_path),
  }

तर्क : नया एपीआई कम क्रियात्मक और अधिक स्पष्ट है। पुराने एपीआई को भविष्य के संस्करण में हटा दिया जाएगा।

नए डेटासेट एक फ़ोल्डर में स्व-निहित होने चाहिए

tensorflow_datasets/ रिपॉजिटरी के अंदर डेटासेट जोड़ते समय, कृपया डेटासेट-एज़-फ़ोल्डर संरचना (सभी चेकसम, डमी डेटा, कार्यान्वयन कोड एक फ़ोल्डर में स्व-निहित) का पालन करना सुनिश्चित करें।

  • पुराने डेटासेट (ख़राब): <category>/<ds_name>.py
  • नए डेटासेट (अच्छे): <category>/<ds_name>/<ds_name>.py

टेम्प्लेट बनाने के लिए TFDS CLI ( tfds new , या gtfds new for googlers) का उपयोग करें।

तर्क : पुरानी संरचना को चेकसम, नकली डेटा के लिए पूर्ण पथ की आवश्यकता थी और कई स्थानों पर डेटासेट फ़ाइलों को वितरित कर रहा था। इससे टीएफडीएस रिपॉजिटरी के बाहर डेटासेट लागू करना कठिन हो रहा था। एकरूपता के लिए नई संरचना का प्रयोग अब हर जगह होना चाहिए।

विवरण सूचियों को मार्कडाउन के रूप में स्वरूपित किया जाना चाहिए

DatasetInfo.description str मार्कडाउन के रूप में स्वरूपित किया गया है। मार्कडाउन सूचियों के लिए पहले आइटम से पहले एक खाली पंक्ति की आवश्यकता होती है:

_DESCRIPTION = """
Some text.
                      # << Empty line here !!!
1. Item 1
2. Item 1
3. Item 1
                      # << Empty line here !!!
Some other text.
"""

तर्क : ख़राब स्वरूपित विवरण हमारे कैटलॉग दस्तावेज़ में दृश्य कलाकृतियाँ बनाते हैं। खाली पंक्तियों के बिना, उपरोक्त पाठ को इस प्रकार प्रस्तुत किया जाएगा:

कुछ पाठ. 1. आइटम 1 2. आइटम 1 3. आइटम 1 कोई अन्य पाठ

क्लासलेबल नाम भूल गए

tfds.features.ClassLabel उपयोग करते समय, मानव-पठनीय लेबल str names= या names_file= ( num_classes=10 के बजाय) के साथ प्रदान करने का प्रयास करें।

features = {
    'label': tfds.features.ClassLabel(names=['dog', 'cat', ...]),
}

तर्क : मानव पठनीय लेबल का उपयोग कई स्थानों पर किया जाता है:

छवि का आकार भूल गए

tfds.features.Image , tfds.features.Video का उपयोग करते समय, यदि छवियों का आकार स्थिर है, तो उन्हें स्पष्ट रूप से निर्दिष्ट किया जाना चाहिए:

features = {
    'image': tfds.features.Image(shape=(256, 256, 3)),
}

तर्क : यह स्थैतिक आकार अनुमान (उदाहरण के लिए ds.element_spec['image'].shape ) की अनुमति देता है, जो बैचिंग के लिए आवश्यक है (अज्ञात आकार की छवियों को बैच करने के लिए पहले उन्हें आकार देने की आवश्यकता होगी)।

tfds.features.Tensor के बजाय अधिक विशिष्ट प्रकार को प्राथमिकता दें

जब संभव हो, तो सामान्य tfds.features.Tensor के बजाय अधिक विशिष्ट प्रकार tfds.features.ClassLabel , tfds.features.BBoxFeatures ,... को प्राथमिकता दें।

तर्क : शब्दार्थ की दृष्टि से अधिक सही होने के अलावा, विशिष्ट सुविधाएँ उपयोगकर्ताओं को अतिरिक्त मेटाडेटा प्रदान करती हैं और टूल द्वारा पता लगाई जाती हैं।

वैश्विक क्षेत्र में आलसी आयात

वैश्विक स्तर से आलस्यपूर्ण आयात नहीं बुलाया जाना चाहिए। उदाहरण के लिए निम्नलिखित गलत है:

tfds.lazy_imports.apache_beam # << Error: Import beam in the global scope

def f() -> beam.Map:
  ...

तर्क : वैश्विक दायरे में आलसी आयात का उपयोग करने से सभी tfds उपयोगकर्ताओं के लिए मॉड्यूल आयात हो जाएगा, जिससे आलसी आयात का उद्देश्य विफल हो जाएगा।

गतिशील रूप से ट्रेन/परीक्षण विभाजन की गणना

यदि डेटासेट आधिकारिक विभाजन प्रदान नहीं करता है, तो टीएफडीएस भी नहीं करना चाहिए। निम्नलिखित से बचना चाहिए:

_TRAIN_TEST_RATIO = 0.7

def _split_generator():
  ids = list(range(num_examples))
  np.random.RandomState(seed).shuffle(ids)

  # Split train/test
  train_ids = ids[_TRAIN_TEST_RATIO * num_examples:]
  test_ids = ids[:_TRAIN_TEST_RATIO * num_examples]
  return {
      'train': self._generate_examples(train_ids),
      'test': self._generate_examples(test_ids),
  }

तर्क : टीएफडीएस मूल डेटा के समान ही डेटासेट प्रदान करने का प्रयास करता है। इसके बजाय उप-विभाजन एपीआई का उपयोग किया जाना चाहिए ताकि उपयोगकर्ता गतिशील रूप से अपने इच्छित उप-विभाजन बना सकें:

ds_train, ds_test = tfds.load(..., split=['train[:80%]', 'train[80%:]'])

पायथन स्टाइल गाइड

पाथलिब एपीआई का उपयोग करना पसंद करें

tf.io.gfile API के बजाय, pathlib API का उपयोग करना बेहतर है। सभी dl_manager विधियाँ GCS, S3, के साथ संगत पाथलिब-जैसी ऑब्जेक्ट लौटाती हैं...

path = dl_manager.download_and_extract('http://some-website/my_data.zip')

json_path = path / 'data/file.json'

json.loads(json_path.read_text())

तर्क : पाथलिब एपीआई एक आधुनिक ऑब्जेक्ट ओरिएंटेड फ़ाइल एपीआई है जो बॉयलरप्लेट को हटा देती है। .read_text() / .read_bytes() का उपयोग यह भी गारंटी देता है कि फ़ाइलें सही ढंग से बंद हैं।

यदि विधि self उपयोग नहीं कर रही है, तो यह एक फ़ंक्शन होना चाहिए

यदि कोई क्लास विधि self का उपयोग नहीं कर रही है, तो यह एक सरल फ़ंक्शन होना चाहिए (क्लास के बाहर परिभाषित)।

तर्क : यह पाठक को स्पष्ट कर देता है कि फ़ंक्शन का कोई साइड इफेक्ट नहीं है, न ही छिपा हुआ इनपुट/आउटपुट है:

x = f(y)  # Clear inputs/outputs

x = self.f(y)  # Does f depend on additional hidden variables ? Is it stateful ?

पायथन में आलसी आयात

हम आलस्यपूर्वक TensorFlow जैसे बड़े मॉड्यूल आयात करते हैं। आलसी आयात मॉड्यूल के वास्तविक आयात को मॉड्यूल के पहले उपयोग तक टाल देता है। इसलिए जिन उपयोगकर्ताओं को इस बड़े मॉड्यूल की आवश्यकता नहीं है वे इसे कभी आयात नहीं करेंगे। हम etils.epy.lazy_imports उपयोग करते हैं।

from tensorflow_datasets.core.utils.lazy_imports_utils import tensorflow as tf
# After this statement, TensorFlow is not imported yet

...

features = tfds.features.Image(dtype=tf.uint8)
# After using it (`tf.uint8`), TensorFlow is now imported

हुड के तहत, LazyModule वर्ग एक फ़ैक्टरी के रूप में कार्य करता है, जो वास्तव में केवल तभी मॉड्यूल आयात करेगा जब कोई विशेषता एक्सेस की जाती है ( __getattr__ )।

आप इसे संदर्भ प्रबंधक के साथ भी आसानी से उपयोग कर सकते हैं:

from etils import epy

with epy.lazy_imports(error_callback=..., success_callback=...):
  import some_big_module