Bu sayfada yeni bir veri kümesi uygulanırken ortak uygulama kazanımları açıklanmaktadır.
Eski SplitGenerator
kaçınılmalıdır
Eski tfds.core.SplitGenerator
API'si kullanımdan kaldırıldı.
def _split_generator(...):
return [
tfds.core.SplitGenerator(name='train', gen_kwargs={'path': train_path}),
tfds.core.SplitGenerator(name='test', gen_kwargs={'path': test_path}),
]
Şununla değiştirilmelidir:
def _split_generator(...):
return {
'train': self._generate_examples(path=train_path),
'test': self._generate_examples(path=test_path),
}
Gerekçe : Yeni API daha az ayrıntılı ve daha açıktır. Eski API gelecek sürümde kaldırılacaktır.
Yeni veri kümeleri bir klasörde bağımsız olarak bulunmalıdır
tensorflow_datasets/
depo içine bir veri kümesi eklerken, lütfen klasör olarak veri kümesi yapısını izlediğinizden emin olun (tüm sağlama toplamları, yapay veriler, bir klasörde bulunan uygulama kodu).
- Eski veri kümeleri (kötü):
<category>/<ds_name>.py
- Yeni veri kümeleri (iyi):
<category>/<ds_name>/<ds_name>.py
Şablonu oluşturmak için TFDS CLI'yi ( tfds new
veya Google çalışanları için gtfds new
) kullanın.
Gerekçe : Eski yapı, sağlama toplamları için mutlak yollar gerektiriyordu, sahte verilerdi ve veri kümesi dosyalarını birçok yere dağıtıyordu. Veri kümelerinin TFDS deposu dışında uygulanmasını zorlaştırıyordu. Tutarlılık açısından yeni yapının artık her yerde kullanılması gerekiyor.
Açıklama listeleri işaretleme olarak biçimlendirilmelidir
DatasetInfo.description
str
markdown olarak biçimlendirilmiştir. İşaretleme listeleri, ilk öğeden önce boş bir satır gerektirir:
_DESCRIPTION = """
Some text.
# << Empty line here !!!
1. Item 1
2. Item 1
3. Item 1
# << Empty line here !!!
Some other text.
"""
Gerekçe : Kötü biçimlendirilmiş açıklama, katalog belgelerimizde görsel kusurlar yaratır. Boş satırlar olmasaydı yukarıdaki metin şu şekilde oluşturulur:
Biraz metin. 1. Madde 1 2. Madde 1 3. Madde 1 Başka bir metin
ClassLabel adlarını unuttum
tfds.features.ClassLabel
kullanırken, insanlar tarafından okunabilen str
etiketlerini names=
veya names_file=
( num_classes=10
yerine) sağlamaya çalışın.
features = {
'label': tfds.features.ClassLabel(names=['dog', 'cat', ...]),
}
Gerekçe : İnsan tarafından okunabilen etiketler birçok yerde kullanılmaktadır:
-
_generate_examples
doğrudanstr
elde edilmesine izin ver:yield {'label': 'dog'}
-
info.features['label'].names
gibi kullanıcılarda gösterilir (dönüştürme yöntemi.str2int('dog')
,... ayrıca mevcuttur) - Görselleştirmede kullanılır
tfds.show_examples
,tfds.as_dataframe
Resim şeklini unuttum
tfds.features.Image
, tfds.features.Video
kullanılırken, görsellerin statik şekli varsa açıkça belirtilmelidir:
features = {
'image': tfds.features.Image(shape=(256, 256, 3)),
}
Gerekçe : Toplu işlem için gerekli olan statik şekil çıkarımına (örn. ds.element_spec['image'].shape
) izin verir (bilinmeyen şekle sahip görüntülerin toplu olarak işlenmesi, önce bunların yeniden boyutlandırılmasını gerektirir).
tfds.features.Tensor
yerine daha spesifik türü tercih edin
Mümkün olduğunda, genel tfds.features.Tensor
yerine daha spesifik tfds.features.ClassLabel
, tfds.features.BBoxFeatures
,... türlerini tercih edin.
Gerekçe : Anlamsal olarak daha doğru olmasının yanı sıra, belirli özellikler kullanıcılara ek meta veriler sağlar ve araçlar tarafından tespit edilir.
Küresel alanda tembel ithalat
Tembel ithalat küresel alandan çağrılmamalıdır. Örneğin aşağıdakiler yanlıştır:
tfds.lazy_imports.apache_beam # << Error: Import beam in the global scope
def f() -> beam.Map:
...
Gerekçe : Tembel içe aktarmanın küresel kapsamda kullanılması, modülün tüm tfds kullanıcıları için içe aktarılmasına neden olur ve tembel içe aktarmanın amacını boşa çıkarır.
Tren/test ayrımlarını dinamik olarak hesaplama
Veri kümesi resmi bölünmeler sağlamıyorsa TFDS de sağlamamalıdır. Aşağıdakilerden kaçınılmalıdır:
_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),
}
Gerekçe : TFDS, orijinal veriye en yakın veri setlerini sağlamaya çalışır. Kullanıcıların istedikleri alt bölümleri dinamik olarak oluşturmalarına olanak sağlamak için bunun yerine alt bölüm API'si kullanılmalıdır:
ds_train, ds_test = tfds.load(..., split=['train[:80%]', 'train[80%:]'])
Python stili kılavuzu
Pathlib API'yi kullanmayı tercih edin
tf.io.gfile
API'si yerine pathlib API'sinin kullanılması tercih edilir. Tüm dl_manager
yöntemleri, GCS, S3,... ile uyumlu pathlib benzeri nesneleri döndürür.
path = dl_manager.download_and_extract('http://some-website/my_data.zip')
json_path = path / 'data/file.json'
json.loads(json_path.read_text())
Gerekçe : pathlib API, ortak metni kaldıran modern bir nesne yönelimli dosya API'sidir. .read_text()
/ .read_bytes()
işlevini kullanmak aynı zamanda dosyaların doğru şekilde kapatıldığını da garanti eder.
Yöntem self
kullanmıyorsa bir işlev olmalıdır
Bir sınıf yöntemi self
kullanmıyorsa, basit bir işlev olmalıdır (sınıfın dışında tanımlanmış).
Gerekçe : Okuyucuya, işlevin yan etkilerinin ya da gizli girdi/çıktısının olmadığını açıkça belirtir:
x = f(y) # Clear inputs/outputs
x = self.f(y) # Does f depend on additional hidden variables ? Is it stateful ?
Python'da tembel içe aktarma
TensorFlow gibi büyük modülleri tembelce içe aktarıyoruz. Tembel içe aktarmalar, modülün fiili içe aktarımını modülün ilk kullanımına erteler. Yani bu büyük modüle ihtiyaç duymayan kullanıcılar onu asla içe aktarmayacak. etils.epy.lazy_imports
kullanıyoruz.
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
Temelde, LazyModule
sınıfı bir fabrika gibi davranır ve modülü yalnızca bir özniteliğe erişildiğinde ( __getattr__
) içe aktarır.
Ayrıca bir bağlam yöneticisiyle de rahatlıkla kullanabilirsiniz:
from etils import epy
with epy.lazy_imports(error_callback=..., success_callback=...):
import some_big_module