בצעו מדריך זה כדי ליצור מערך נתונים חדש (ב-TFDS או במאגר משלכם).
בדוק את רשימת מערכי הנתונים שלנו כדי לראות אם מערך הנתונים הרצוי כבר קיים.
למען הסר ספק
הדרך הקלה ביותר לכתוב מערך נתונים חדש היא להשתמש ב- TFDS CLI :
cd path/to/my/project/datasets/
tfds new my_dataset # Create `my_dataset/my_dataset.py` template files
# [...] Manually modify `my_dataset/my_dataset_dataset_builder.py` to implement your dataset.
cd my_dataset/
tfds build # Download and prepare the dataset to `~/tensorflow_datasets/`
כדי להשתמש במערך הנתונים החדש עם tfds.load('my_dataset') :
-
tfds.loadיזהה ויטען אוטומטית את מערך הנתונים שנוצר ב-~/tensorflow_datasets/my_dataset/(למשל, על ידיtfds build). - לחלופין, ניתן
import my.project.datasets.my_datasetכדי לרשום את מערך הנתונים שלך:
import my.project.datasets.my_dataset # Register `my_dataset`
ds = tfds.load('my_dataset') # `my_dataset` registered
סקירה כללית
מערכי נתונים מופצים בכל מיני פורמטים ובכל מיני מקומות, והם לא תמיד מאוחסנים בפורמט שמוכן להזנה לתוך צינור למידת מכונה. היכנסו ל-TFDS.
TFDS מעבד את מערכי הנתונים הללו לפורמט סטנדרטי (נתונים חיצוניים -> קבצים שעברו סידור), אשר לאחר מכן ניתן לטעון אותם כצינור למידת מכונה (קבצים שעברו סידור -> tf.data.Dataset ). הסידור מתבצע פעם אחת בלבד. גישה לאחר מכן תיקרא ישירות מהקבצים שעברו עיבוד מראש.
רוב העיבוד המקדים מתבצע באופן אוטומטי. כל מערך נתונים מממש תת-מחלקה של tfds.core.DatasetBuilder , אשר מציינת:
- מאיפה מגיעים הנתונים (כלומר, כתובות ה-URL שלהם);
- כיצד נראה מערך הנתונים (כלומר, התכונות שלו);
- כיצד יש לפצל את הנתונים (למשל
TRAINו-TEST); - והדוגמאות הבודדות במערך הנתונים.
כתוב את מערך הנתונים שלך
תבנית ברירת מחדל: tfds new
השתמש ב- TFDS CLI כדי ליצור את קבצי התבנית הנדרשים של פייתון.
cd path/to/project/datasets/ # Or use `--dir=path/to/project/datasets/` below
tfds new my_dataset
פקודה זו תיצור תיקייה חדשה בשם my_dataset/ עם המבנה הבא:
my_dataset/
__init__.py
README.md # Markdown description of the dataset.
CITATIONS.bib # Bibtex citation for the dataset.
TAGS.txt # List of tags describing the dataset.
my_dataset_dataset_builder.py # Dataset definition
my_dataset_dataset_builder_test.py # Test
dummy_data/ # (optional) Fake data (used for testing)
checksum.tsv # (optional) URL checksums (see `checksums` section).
חפש כאן את TODO(my_dataset) ושנה בהתאם.
דוגמה למערך נתונים
כל מערכי הנתונים הם תת-מחלקות של tfds.core.DatasetBuilder , אשר מטפל ברוב הפונקציות הבסיסיות. הוא תומך ב:
- מערכי נתונים קטנים/בינוניים שניתן ליצור על מכונה אחת (מדריך זה).
- מערכי נתונים גדולים מאוד הדורשים יצירה מבוזרת (באמצעות Apache Beam , עיינו במדריך מערכי הנתונים העצום שלנו)
הנה דוגמה מינימלית של בונה נתונים המבוסס על tfds.core.GeneratorBasedBuilder :
class Builder(tfds.core.GeneratorBasedBuilder):
"""DatasetBuilder for my_dataset dataset."""
VERSION = tfds.core.Version('1.0.0')
RELEASE_NOTES = {
'1.0.0': 'Initial release.',
}
def _info(self) -> tfds.core.DatasetInfo:
"""Dataset metadata (homepage, citation,...)."""
return self.dataset_info_from_configs(
features=tfds.features.FeaturesDict({
'image': tfds.features.Image(shape=(256, 256, 3)),
'label': tfds.features.ClassLabel(
names=['no', 'yes'],
doc='Whether this is a picture of a cat'),
}),
)
def _split_generators(self, dl_manager: tfds.download.DownloadManager):
"""Download the data and define splits."""
extracted_path = dl_manager.download_and_extract('http://data.org/data.zip')
# dl_manager returns pathlib-like objects with `path.read_text()`,
# `path.iterdir()`,...
return {
'train': self._generate_examples(path=extracted_path / 'train_images'),
'test': self._generate_examples(path=extracted_path / 'test_images'),
}
def _generate_examples(self, path) -> Iterator[Tuple[Key, Example]]:
"""Generator of examples for each split."""
for img_path in path.glob('*.jpeg'):
# Yields (key, example)
yield img_path.name, {
'image': img_path,
'label': 'yes' if img_path.name.startswith('yes_') else 'no',
}
שימו לב שעבור פורמטים ספציפיים של נתונים, אנו מספקים בוני נתונים מוכנים לשימוש כדי לטפל ברוב עיבוד הנתונים.
בואו נראה בפירוט את 3 השיטות המופשטות להחלפה.
_info : מטא-נתונים של מערך הנתונים
_info מחזירה את הפונקציה tfds.core.DatasetInfo המכילה את המטא-דאטה של קבוצת הנתונים .
def _info(self):
# The `dataset_info_from_configs` base method will construct the
# `tfds.core.DatasetInfo` object using the passed-in parameters and
# adding: builder (self), description/citations/tags from the config
# files located in the same package.
return self.dataset_info_from_configs(
homepage='https://dataset-homepage.org',
features=tfds.features.FeaturesDict({
'image_description': tfds.features.Text(),
'image': tfds.features.Image(),
# Here, 'label' can be 0-4.
'label': tfds.features.ClassLabel(num_classes=5),
}),
# If there's a common `(input, target)` tuple from the features,
# specify them here. They'll be used if as_supervised=True in
# builder.as_dataset.
supervised_keys=('image', 'label'),
# Specify whether to disable shuffling on the examples. Set to False by default.
disable_shuffling=False,
)
רוב השדות אמורים להיות מובנים מאליהם. כמה פרטים נוספים:
-
features: מאפיינים אלה מציינים את מבנה, הצורה וכו' של מערך הנתונים. תמיכה בסוגי נתונים מורכבים (אודיו, וידאו, רצפים מקוננים וכו'). עיין בתכונות הזמינות או במדריך מחבר התכונות לקבלת מידע נוסף. -
disable_shuffling: ראה סעיף שמירה על סדר מערך הנתונים .
כתיבת קובץ BibText CITATIONS.bib :
- חפש באתר הנתונים הוראות ציטוט (השתמש בפורמט BibTex).
- עבור מאמרים ב-arXiv : מצא את המאמר ולחץ על הקישור
BibTextבצד ימין. - מצא את המאמר בגוגל סקולר ולחץ על סימן המירכאות הכפול מתחת לכותרת. בחלון הקופץ לחץ על
BibTeX. - אם אין מאמר משויך (לדוגמה, יש רק אתר אינטרנט), ניתן להשתמש בעורך BibTeX המקוון כדי ליצור ערך BibTeX מותאם אישית (התפריט הנפתח מכיל ערך
Online).
עדכון קובץ TAGS.txt :
- כל התגים המותרים מולאו מראש בקובץ שנוצר.
- הסר את כל התגים שאינם רלוונטיים לקבוצת הנתונים.
- תגיות תקפות רשומות בקובץ tensorflow_datasets/core/valid_tags.txt .
- כדי להוסיף תגית לרשימה זו, אנא שלחו פרטי התקשרות.
שמירה על סדר מערך הנתונים
כברירת מחדל, רשומות מערכי הנתונים עוברות ערבוב בעת האחסון על מנת להפוך את פיזור המחלקות לאחיד יותר על פני מערך הנתונים, מכיוון שלעתים קרובות רשומות השייכות לאותה מחלקה הן רציפות. על מנת לציין שיש למיין את מערך הנתונים לפי המפתח שנוצר על ידי _generate_examples , השדה disable_shuffling צריך להיות מוגדר כ- True . כברירת מחדל הוא מוגדר כ- False .
def _info(self):
return self.dataset_info_from_configs(
# [...]
disable_shuffling=True,
# [...]
)
קחו בחשבון שהשבתת ערבוב הנתונים משפיעה על הביצועים מכיוון שלא ניתן עוד לקרוא שרדים במקביל.
_split_generators : הורדה ופיצול של נתונים
הורדה וחילוץ של נתוני מקור
רוב מערכי הנתונים צריכים להוריד נתונים מהאינטרנט. זה נעשה באמצעות ארגומנט הקלט tfds.download.DownloadManager של _split_generators . dl_manager יש את השיטות הבאות:
-
download: תומך ב-http(s)://,ftp(s):// -
extract: תומך כעת בקבצי.zip,.gzו-.tar. -
download_and_extract: זהה ל-dl_manager.extract(dl_manager.download(urls))
כל המתודות הללו מחזירות tfds.core.Path (כינויים עבור epath.Path ), שהם אובייקטים דמויי pathlib.Path .
שיטות אלו תומכות במבנה מקונן שרירותי ( list , dict ), כמו:
extracted_paths = dl_manager.download_and_extract({
'foo': 'https://example.com/foo.zip',
'bar': 'https://example.com/bar.zip',
})
# This returns:
assert extracted_paths == {
'foo': Path('/path/to/extracted_foo/'),
'bar': Path('/path/extracted_bar/'),
}
הורדה וחילוץ ידניים
חלק מהנתונים לא ניתנים להורדה אוטומטית (למשל, נדרשת התחברות). במקרה זה, המשתמש יוריד ידנית את נתוני המקור וימקם אותם ב- manual_dir/ (ברירת המחדל היא ~/tensorflow_datasets/downloads/manual/ ).
לאחר מכן ניתן לגשת לקבצים דרך dl_manager.manual_dir :
class MyDataset(tfds.core.GeneratorBasedBuilder):
MANUAL_DOWNLOAD_INSTRUCTIONS = """
Register into https://example.org/login to get the data. Place the `data.zip`
file in the `manual_dir/`.
"""
def _split_generators(self, dl_manager):
# data_path is a pathlib-like `Path('<manual_dir>/data.zip')`
archive_path = dl_manager.manual_dir / 'data.zip'
# Extract the manually downloaded `data.zip`
extracted_path = dl_manager.extract(archive_path)
...
ניתן להתאים אישית את מיקום manual_dir באמצעות tfds build --manual_dir= או באמצעות tfds.download.DownloadConfig .
קרא את הארכיון ישירות
dl_manager.iter_archive קוראת ארכיונים באופן סדרתי מבלי לחלץ אותם. פעולה זו יכולה לחסוך מקום אחסון ולשפר את הביצועים במערכות קבצים מסוימות.
for filename, fobj in dl_manager.iter_archive('path/to/archive.zip'):
...
fobj יש את אותן המתודות כמו with open('rb') as fobj: (לדוגמה, fobj.read() )
ציון פיצולי מערך נתונים
אם קבוצת הנתונים מגיעה עם פיצולים מוגדרים מראש (לדוגמה, MNIST יש פיצולי train ו- test ), יש לשמור אותם. אחרת, יש לציין רק פיצול all יחיד. משתמשים יכולים ליצור באופן דינמי פיצולי משנה משלהם באמצעות API ה-subsplit (לדוגמה split='train[80%:]' ). שים לב שכל מחרוזת אלפביתית יכולה לשמש כשם פיצול, מלבד all שהוזכר לעיל.
def _split_generators(self, dl_manager):
# Download source data
extracted_path = dl_manager.download_and_extract(...)
# Specify the splits
return {
'train': self._generate_examples(
images_path=extracted_path / 'train_imgs',
label_path=extracted_path / 'train_labels.csv',
),
'test': self._generate_examples(
images_path=extracted_path / 'test_imgs',
label_path=extracted_path / 'test_labels.csv',
),
}
_generate_examples : מחולל דוגמאות
_generate_examples מייצרת את הדוגמאות עבור כל פיצול מנתוני המקור.
שיטה זו בדרך כלל תקרא ארטיפקטים של מערך נתונים של מקור (למשל קובץ CSV) ותניב צמדים (key, feature_dict) :
-
key: מזהה דוגמה. משמש לערבוב דטרמיניסטי של הדוגמאות באמצעותhash(key)או למיון לפי מפתח כאשר ערבוב מושבת (ראה סעיף שמירה על סדר מערך נתונים ). צריך להיות:- ייחודי : אם שתי דוגמאות משתמשות באותו מפתח, יופעל חריג.
- דטרמיניסטי : לא אמור להיות תלוי בסדר
download_dir,os.path.listdir,... יצירת הנתונים פעמיים אמורה להניב את אותו מפתח. - comparable : אם ערבוב הנתונים מושבת, המפתח ישמש למיון קבוצת הנתונים.
-
feature_dict:dictהמכילה את ערכי הדוגמה.- המבנה צריך להתאים ל-
features=structure שמוגדר ב-tfds.core.DatasetInfo. - סוגי נתונים מורכבים (תמונה, וידאו, אודיו וכו') יקודדו אוטומטית.
- כל תכונה מקבלת לרוב מספר סוגי קלט (למשל, וידאו מקבל
/path/to/vid.mp4,np.array(shape=(l, h, w, c)),List[paths],List[np.array(shape=(h, w, c)],List[img_bytes],...) - עיין במדריך מחבר התכונות לקבלת מידע נוסף.
- המבנה צריך להתאים ל-
def _generate_examples(self, images_path, label_path):
# Read the input data out of the source files
with label_path.open() as f:
for row in csv.DictReader(f):
image_id = row['image_id']
# And yield (key, feature_dict)
yield image_id, {
'image_description': row['description'],
'image': images_path / f'{image_id}.jpeg',
'label': row['label'],
}
גישה לקבצים ו- tf.io.gfile
על מנת לתמוך במערכות אחסון בענן, יש להימנע משימוש בפעולות קלט/פלט מובנות של פייתון.
במקום זאת, ה- dl_manager מחזיר אובייקטים דמויי pathlib התואמים ישירות לאחסון Google Cloud:
path = dl_manager.download_and_extract('http://some-website/my_data.zip')
json_path = path / 'data/file.json'
json.loads(json_path.read_text())
לחלופין, השתמשו tf.io.gfile API במקום ב- API המובנה עבור פעולות קבצים:
-
open->tf.io.gfile.GFile -
os.rename->tf.io.gfile.rename - ...
יש להעדיף את Pathlib על פני tf.io.gfile (ראה רציונל ).
תלויות נוספות
חלק ממערכי הנתונים דורשים תלויות נוספות של Python רק במהלך היצירה. לדוגמה, מערך הנתונים SVHN משתמש scipy כדי לטעון נתונים מסוימים.
אם אתם מוסיפים מערך נתונים למאגר TFDS, אנא השתמשו ב- tfds.core.lazy_imports כדי לשמור על חבילת tensorflow-datasets קטנה. משתמשים יתקינו תלויות נוספות רק לפי הצורך.
כדי להשתמש ב- lazy_imports :
- הוסף ערך עבור מערך הנתונים שלך לתוך
DATASET_EXTRASבקובץsetup.py. זה מאפשר למשתמשים לבצע, לדוגמה,pip install 'tensorflow-datasets[svhn]'כדי להתקין את התלויות הנוספות. - הוסף ערך עבור הייבוא שלך ל-
LazyImporterול-LazyImportsTest. - השתמש ב-
tfds.core.lazy_importsכדי לגשת לתלות (לדוגמה,tfds.core.lazy_imports.scipy) ב-DatasetBuilderשלך.
נתונים פגומים
חלק ממערכי הנתונים אינם נקיים לחלוטין ומכילים נתונים פגומים (לדוגמה, התמונות נמצאות בקבצי JPEG אך חלקן הן קבצי JPEG לא חוקיים). יש לדלג על דוגמאות אלו, אך יש להשאיר הערה בתיאור מערך הנתונים כמה דוגמאות הושמטו ומדוע.
תצורת/וריאנטים של מערך נתונים (tfds.core.BuilderConfig)
לחלק ממערכי הנתונים עשויות להיות מספר וריאציות, או אפשרויות לאופן שבו הנתונים מעובדים מראש וכתובם לדיסק. לדוגמה, ל-cycle_gan יש תצורה אחת לכל זוג אובייקטים ( cycle_gan/horse2zebra , cycle_gan/monet2photo ,...).
זה נעשה באמצעות tfds.core.BuilderConfig :
הגדר את אובייקט התצורה שלך כתת-מחלקה של
tfds.core.BuilderConfig. לדוגמה,MyDatasetConfig.@dataclasses.dataclass class MyDatasetConfig(tfds.core.BuilderConfig): img_size: Tuple[int, int] = (0, 0)הגדר את חבר המחלקה
BUILDER_CONFIGS = []ב-MyDatasetשמפרט את ה-MyDatasetConfigשקבוצת הנתונים חושפת.class MyDataset(tfds.core.GeneratorBasedBuilder): VERSION = tfds.core.Version('1.0.0') # pytype: disable=wrong-keyword-args BUILDER_CONFIGS = [ # `name` (and optionally `description`) are required for each config MyDatasetConfig(name='small', description='Small ...', img_size=(8, 8)), MyDatasetConfig(name='big', description='Big ...', img_size=(32, 32)), ] # pytype: enable=wrong-keyword-argsהשתמשו ב-
self.builder_configב-MyDatasetכדי להגדיר את יצירת הנתונים (לדוגמה,shape=self.builder_config.img_size). זה עשוי לכלול הגדרת ערכים שונים ב_info()או שינוי גישה לנתוני הורדה.
הערות:
- לכל תצורה יש שם ייחודי. השם המלא של תצורה הוא
dataset_name/config_name(לדוגמה,coco/2017). - אם לא צוין, ייעשה שימוש בתצורה הראשונה ב-
BUILDER_CONFIGS(לדוגמה, ברירת המחדלtfds.load('c4')היאc4/en)
ראה anli לדוגמה של מערך נתונים המשתמש ב- BuilderConfig .
גִרְסָה
גרסה יכולה להתייחס לשתי משמעויות שונות:
- גרסת הנתונים המקורית "החיצונית": לדוגמה COCO v2019, v2017,...
- גרסת הקוד "הפנימית" של TFDS: לדוגמה שינוי שם של פיצ'ר ב-
tfds.features.FeaturesDict, תיקון באג ב-_generate_examples
כדי לעדכן מערך נתונים:
- עבור עדכון נתונים "חיצוני": ייתכן שמספר משתמשים ירצו לגשת לשנה/גרסה ספציפית בו זמנית. ניתן לעשות זאת באמצעות קובץ
tfds.core.BuilderConfigאחד לכל גרסה (למשלcoco/2017,coco/2019) או מחלקה אחת לכל גרסה (למשלVoc2007,Voc2012). - עבור עדכון קוד "פנימי": משתמשים מורידים רק את הגרסה העדכנית ביותר. כל עדכון קוד צריך להגדיל את תכונת המחלקה
VERSION(למשל מ1.0.0ל-VERSION = tfds.core.Version('2.0.0')) בעקבות ניהול גרסאות סמנטיות .
הוסף ייבוא לצורך רישום
אל תשכחו לייבא את מודול הנתונים לפרויקט שלכם בשם __init__ כדי שיירשם אוטומטית ב- tfds.load ו- tfds.builder .
import my_project.datasets.my_dataset # Register MyDataset
ds = tfds.load('my_dataset') # MyDataset available
לדוגמה, אם אתם תורמים ל- tensorflow/datasets , הוסיפו את המודול import ל __init__.py של תת-הספרייה שלו (למשל, image/__init__.py .
בדוק אם ישנן תקלות יישום נפוצות
אנא בדוק את gotchas המימוש הנפוץ .
בדוק את מערך הנתונים שלך
הורדה והכנה: tfds build
כדי ליצור את מערך הנתונים, הפעל tfds build מהספרייה my_dataset/ :
cd path/to/datasets/my_dataset/
tfds build --register_checksums
כמה דגלים שימושיים לפיתוח:
-
--pdb: היכנס למצב ניפוי שגיאות אם נוצר חריג. -
--overwrite: מחיקת קבצים קיימים אם מערך הנתונים כבר נוצר. -
--max_examples_per_split: יוצר רק את X הדוגמאות הראשונות (ברירת מחדל היא 1), ולא את מערך הנתונים המלא. -
--register_checksums: רשום את סכומי הבדיקה של כתובות URL שהורדו. יש להשתמש בו רק במהלך הפיתוח.
עיין בתיעוד של ממשק שורת הפקודה (CLI) לקבלת רשימה מלאה של דגלים.
סכומי בדיקה
מומלץ לתעד את סכומי הבדיקה של מערכי הנתונים שלך כדי להבטיח דטרמיניזם, לסייע בתיעוד,... ניתן לעשות זאת על ידי יצירת מערך הנתונים באמצעות --register_checksums (ראה סעיף קודם).
אם אתם משחררים את מערכי הנתונים שלכם דרך PyPI, אל תשכחו לייצא את קבצי checksums.tsv (למשל, ב- package_data של setup.py שלכם).
בדיקת יחידה של מערך הנתונים שלך
tfds.testing.DatasetBuilderTestCase הוא TestCase בסיסי להפעלה מלאה של מערך נתונים. הוא משתמש ב"נתוני דמה" כנתוני בדיקה המחקים את המבנה של מערך הנתונים המקורי.
- יש להכניס את נתוני הבדיקה לספרייה
my_dataset/dummy_data/וצריכים לחקות את אובייקטי הנתונים של קבוצת הנתונים המקורית כפי שהורדו וחולצו. ניתן ליצור אותם באופן ידני או אוטומטי באמצעות סקריפט ( סקריפט לדוגמה ). - ודאו שאתם משתמשים בנתונים שונים בפיצולי נתוני הבדיקה שלכם, מכיוון שהבדיקה תיכשל אם פיצולי מערך הנתונים שלכם חופפים.
- נתוני הבדיקה לא צריכים להכיל חומר המוגן בזכויות יוצרים . במקרה של ספק, אין ליצור את הנתונים באמצעות חומר ממערך הנתונים המקורי.
import tensorflow_datasets as tfds
from . import my_dataset_dataset_builder
class MyDatasetTest(tfds.testing.DatasetBuilderTestCase):
"""Tests for my_dataset dataset."""
DATASET_CLASS = my_dataset_dataset_builder.Builder
SPLITS = {
'train': 3, # Number of fake train example
'test': 1, # Number of fake test example
}
# If you are calling `download/download_and_extract` with a dict, like:
# dl_manager.download({'some_key': 'http://a.org/out.txt', ...})
# then the tests needs to provide the fake output paths relative to the
# fake data directory
DL_EXTRACT_RESULT = {
'name1': 'path/to/file1', # Relative to my_dataset/dummy_data dir.
'name2': 'file2',
}
if __name__ == '__main__':
tfds.testing.test_main()
הפעל את הפקודה הבאה כדי לבדוק את מערך הנתונים.
python my_dataset_test.py
שלחו לנו משוב
אנו מנסים כל הזמן לשפר את תהליך העבודה של יצירת מערך הנתונים, אך נוכל לעשות זאת רק אם נהיה מודעים לבעיות. אילו בעיות או שגיאות נתקלתם בהן בעת יצירת מערך הנתונים? האם היה חלק שהיה מבלבל, או שלא עבד בפעם הראשונה?
אנא שתפו את המשוב שלכם ב- GitHub .