עקוב אחר המדריך הזה כדי ליצור מערך נתונים חדש (ב-TFDS או במאגר משלך).
בדוק את רשימת מערכי הנתונים שלנו כדי לראות אם מערך הנתונים שאתה רוצה כבר קיים.
TL;DR
הדרך הקלה ביותר לכתוב מערך נתונים חדש היא להשתמש ב- 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
, המציין:
- מהיכן מגיעים הנתונים (כלומר כתובות האתרים שלו);
- איך נראה מערך הנתונים (כלומר התכונות שלו);
- כיצד יש לפצל את הנתונים (למשל
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
, אשר דואג לרוב ה-boilerplate. זה תומך:
- מערכי נתונים קטנים/בינוניים שניתן להפיק במכונה בודדת (מדריך זה).
- מערכי נתונים גדולים מאוד הדורשים יצירה מבוזרת (באמצעות 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
בצד ימין. - מצא את המאמר ב- Google Scholar ולחץ על המירכאות הכפולות מתחת לכותרת ובחלון הקופץ, לחץ על
BibTeX
. - אם אין נייר משויך (לדוגמה, יש רק אתר אינטרנט), אתה יכול להשתמש בעורך BibTeX Online כדי ליצור ערך 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)
tuples:
-
key
: מזהה לדוגמה. משמש כדי לערבב באופן דטרמיניסטי את הדוגמאות באמצעותhash(key)
או כדי למיין לפי מפתח כאשר ערבוב מושבת (ראה סעיף שמירה על סדר הנתונים ). צריך להיות:- ייחודי : אם שתי דוגמאות משתמשות באותו מפתח, יועלה חריג.
- דטרמיניסטית : לא אמור להיות תלוי ב-
download_dir
,os.path.listdir
סדר,... יצירת הנתונים פעמיים אמורה להניב את אותו מפתח. - דומה : אם ערבוב מושבת, המפתח ישמש למיון מערך הנתונים.
-
feature_dict
:dict
המכיל את הערכים לדוגמה.- המבנה צריך להתאים
features=
שהוגדר ב-tfds.core.DatasetInfo
. - סוגי נתונים מורכבים (תמונה, וידאו, אודיו,...) יקודדו אוטומטית.
- כל תכונה מקבלת לעתים קרובות סוגי קלט מרובים (למשל video accept
/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
על מנת לתמוך במערכות אחסון בענן, הימנע משימוש ב-Python ה-I/O ops המובנה.
במקום זאת, ה- 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 במקום מובנה עבור פעולות קבצים:
-
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
s:
הגדר את אובייקט התצורה שלך כתת-מחלקה של
tfds.core.BuilderConfig
. לדוגמה,MyDatasetConfig
.@dataclasses.dataclass class MyDatasetConfig(tfds.core.BuilderConfig): img_size: Tuple[int, int] = (0, 0)
הגדר את חבר הכיתה
BUILDER_CONFIGS = []
ב-MyDataset
שמפרטMyDatasetConfig
s שמערך הנתונים חושף.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
s.
גִרְסָה
הגרסה יכולה להתייחס לשתי משמעויות שונות:
- גרסת הנתונים המקורית "חיצונית": למשל 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
, הוסף את ייבוא המודול לספריית המשנה שלו __init__.py
(למשל image/__init__.py
.
בדוק אם יש שיטות יישום נפוצות
אנא בדוק את שיטות היישום הנפוצות .
בדוק את מערך הנתונים שלך
הורד והכנה: 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
: רשום את סכומי הבדיקה של כתובות אתרים שהורדו. יש להשתמש רק בזמן הפיתוח.
עיין בתיעוד 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 .