Viết bộ dữ liệu tùy chỉnh

Làm theo hướng dẫn này để tạo tập dữ liệu mới (trong TFDS hoặc trong kho lưu trữ của riêng bạn).

Kiểm tra danh sách tập dữ liệu của chúng tôi để xem tập dữ liệu bạn muốn đã có sẵn chưa.

TL;DR

Cách dễ nhất để viết một tập dữ liệu mới là sử dụng 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/`

Để sử dụng tập dữ liệu mới với tfds.load('my_dataset') :

  • tfds.load sẽ tự động phát hiện và tải tập dữ liệu được tạo trong ~/tensorflow_datasets/my_dataset/ (ví dụ: bởi tfds build ).
  • Ngoài ra, bạn có thể import my.project.datasets.my_dataset để đăng ký tập dữ liệu của mình:
import my.project.datasets.my_dataset  # Register `my_dataset`

ds = tfds.load('my_dataset')  # `my_dataset` registered

Tổng quan

Các bộ dữ liệu được phân phối ở mọi loại định dạng và ở mọi nơi, đồng thời chúng không phải lúc nào cũng được lưu trữ ở định dạng sẵn sàng đưa vào quy trình học máy. Nhập TFDS.

TFDS xử lý các tập dữ liệu đó thành định dạng chuẩn (dữ liệu bên ngoài -> tệp được tuần tự hóa), sau đó có thể được tải dưới dạng quy trình học máy (tệp được tuần tự hóa -> tf.data.Dataset ). Việc tuần tự hóa chỉ được thực hiện một lần. Quyền truy cập tiếp theo sẽ đọc trực tiếp từ các tệp được xử lý trước đó.

Hầu hết quá trình tiền xử lý được thực hiện tự động. Mỗi tập dữ liệu triển khai một lớp con của tfds.core.DatasetBuilder , trong đó chỉ định:

  • Dữ liệu đến từ đâu (tức là URL của nó);
  • Tập dữ liệu trông như thế nào (tức là các tính năng của nó);
  • Dữ liệu nên được phân chia như thế nào (ví dụ TRAINTEST );
  • và các ví dụ riêng lẻ trong tập dữ liệu.

Viết tập dữ liệu của bạn

Mẫu mặc định: tfds new

Sử dụng TFDS CLI để tạo các tệp python mẫu được yêu cầu.

cd path/to/project/datasets/  # Or use `--dir=path/to/project/datasets/` below
tfds new my_dataset

Lệnh này sẽ tạo thư mục my_dataset/ mới với cấu trúc sau:

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).

Tìm kiếm TODO(my_dataset) tại đây và sửa đổi cho phù hợp.

Ví dụ về tập dữ liệu

Tất cả các tập dữ liệu đều là các lớp con được triển khai của tfds.core.DatasetBuilder , lớp này xử lý hầu hết các bản soạn sẵn. Nó hỗ trợ:

Đây là một ví dụ tối thiểu về trình tạo tập dữ liệu dựa trên 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',
      }

Lưu ý rằng, đối với một số định dạng dữ liệu cụ thể, chúng tôi cung cấp trình tạo tập dữ liệu sẵn sàng sử dụng để xử lý hầu hết quá trình xử lý dữ liệu.

Chúng ta hãy xem chi tiết 3 phương thức trừu tượng để ghi đè.

_info : siêu dữ liệu dữ liệu

_info trả về tfds.core.DatasetInfo chứa siêu dữ liệu tập dữ liệu .

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,
  )

Hầu hết các lĩnh vực nên tự giải thích. Một số độ chính xác:

Viết tệp BibText CITATIONS.bib :

  • Tìm kiếm hướng dẫn trích dẫn trên trang web tập dữ liệu (sử dụng hướng dẫn đó ở định dạng BibTex).
  • Đối với các bài viết arXiv : tìm bài viết và nhấp vào liên kết BibText ở phía bên phải.
  • Tìm bài viết trên Google Scholar và nhấp vào dấu ngoặc kép bên dưới tiêu đề và trên cửa sổ bật lên, nhấp vào BibTeX .
  • Nếu không có giấy tờ liên quan (ví dụ: chỉ có một trang web), bạn có thể sử dụng BibTeX Online Editor để tạo mục nhập BibTeX tùy chỉnh (menu thả xuống có loại mục nhập Online ).

Cập nhật tệp TAGS.txt :

  • Tất cả các thẻ được phép đều được điền sẵn vào tệp được tạo.
  • Xóa tất cả các thẻ không áp dụng cho tập dữ liệu.
  • Các thẻ hợp lệ được liệt kê trong tensorflow_datasets/core/valid_tags.txt .
  • Để thêm thẻ vào danh sách đó, vui lòng gửi PR.

Duy trì thứ tự tập dữ liệu

Theo mặc định, các bản ghi của tập dữ liệu được xáo trộn khi lưu trữ để làm cho việc phân bổ các lớp đồng đều hơn trên tập dữ liệu, vì các bản ghi thuộc cùng một lớp thường liền kề nhau. Để chỉ định rằng tập dữ liệu phải được sắp xếp theo khóa được tạo bởi _generate_examples , trường disable_shuffling phải được đặt thành True . Theo mặc định, nó được đặt thành False .

def _info(self):
  return self.dataset_info_from_configs(
    # [...]
    disable_shuffling=True,
    # [...]
  )

Hãy nhớ rằng việc tắt chức năng xáo trộn có ảnh hưởng đến hiệu suất vì các phân đoạn không thể đọc song song được nữa.

_split_generators : tải xuống và chia tách dữ liệu

Tải xuống và trích xuất dữ liệu nguồn

Hầu hết các bộ dữ liệu cần tải dữ liệu từ web. Việc này được thực hiện bằng cách sử dụng đối số đầu vào tfds.download.DownloadManager của _split_generators . dl_manager có các phương thức sau:

  • download : hỗ trợ http(s):// , ftp(s)://
  • extract : hiện hỗ trợ các tệp .zip , .gz.tar .
  • download_and_extract : Tương tự như dl_manager.extract(dl_manager.download(urls))

Tất cả các phương thức đó đều trả về tfds.core.Path (bí danh cho epath.Path ), là các đối tượng giống pathlib.Path .

Những phương thức đó hỗ trợ cấu trúc lồng nhau tùy ý ( list , dict ), như:

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/'),
}

Tải xuống và trích xuất thủ công

Một số dữ liệu không thể được tự động tải xuống (ví dụ: yêu cầu đăng nhập), trong trường hợp này, người dùng sẽ tải xuống dữ liệu nguồn theo cách thủ công và đặt nó vào manual_dir/ (mặc định là ~/tensorflow_datasets/downloads/manual/ ).

Sau đó, các tệp có thể được truy cập thông qua 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)
    ...

Vị trí manual_dir có thể được tùy chỉnh bằng tfds build --manual_dir= hoặc sử dụng tfds.download.DownloadConfig .

Đọc lưu trữ trực tiếp

dl_manager.iter_archive đọc kho lưu trữ một cách tuần tự mà không cần giải nén chúng. Điều này có thể tiết kiệm dung lượng lưu trữ và cải thiện hiệu suất trên một số hệ thống tệp.

for filename, fobj in dl_manager.iter_archive('path/to/archive.zip'):
  ...

fobj có các phương thức tương tự như with open('rb') as fobj: (ví dụ fobj.read() )

Chỉ định phân chia tập dữ liệu

Nếu tập dữ liệu đi kèm với các phần tách được xác định trước (ví dụ: MNIST có các phần tách traintest ), hãy giữ lại các phần tách đó. Nếu không, chỉ chỉ định một phần tách all . Người dùng có thể tự động tạo các phần chia nhỏ của riêng mình bằng API chia nhỏ (ví dụ: split='train[80%:]' ). Lưu ý rằng bất kỳ chuỗi chữ cái nào cũng có thể được sử dụng làm tên phân tách, ngoại trừ all các chuỗi .

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 : Trình tạo ví dụ

_generate_examples tạo các ví dụ cho mỗi phần tách từ dữ liệu nguồn.

Phương pháp này thường sẽ đọc các tạo phẩm của tập dữ liệu nguồn (ví dụ: tệp CSV) và mang lại các bộ dữ liệu (key, feature_dict) :

  • key : Mã định danh ví dụ. Được sử dụng để xáo trộn các ví dụ một cách xác định bằng cách sử dụng hash(key) hoặc để sắp xếp theo khóa khi chức năng xáo trộn bị vô hiệu hóa (xem phần Duy trì thứ tự tập dữ liệu ). Nên là:
    • duy nhất : Nếu hai ví dụ sử dụng cùng một khóa, một ngoại lệ sẽ được đưa ra.
    • xác định : Không nên phụ thuộc vào thứ tự download_dir , os.path.listdir ,... Tạo dữ liệu hai lần sẽ mang lại cùng một khóa.
    • có thể so sánh : Nếu tính năng xáo trộn bị tắt, khóa sẽ được sử dụng để sắp xếp tập dữ liệu.
  • feature_dict : Một dict chứa các giá trị mẫu.
    • Cấu trúc phải khớp với cấu trúc features= được xác định trong tfds.core.DatasetInfo .
    • Các loại dữ liệu phức tạp (hình ảnh, video, âm thanh,...) sẽ được mã hóa tự động.
    • Mỗi tính năng thường chấp nhận nhiều loại đầu vào (ví dụ: chấp nhận video /path/to/vid.mp4 , np.array(shape=(l, h, w, c)) , List[paths] , List[np.array(shape=(h, w, c)] , List[img_bytes] ,...)
    • Xem hướng dẫn kết nối tính năng để biết thêm thông tin.
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'],
      }

Truy cập tệp và tf.io.gfile

Để hỗ trợ các hệ thống lưu trữ trên Đám mây, hãy tránh sử dụng các hoạt động I/O tích hợp sẵn của Python.

Thay vào đó, dl_manager trả về các đối tượng giống pathlib tương thích trực tiếp với bộ lưu trữ 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())

Ngoài ra, hãy sử dụng API tf.io.gfile thay vì tích hợp sẵn cho các thao tác với tệp:

Pathlib nên được ưu tiên hơn tf.io.gfile ( xem .

Phụ thuộc bổ sung

Một số bộ dữ liệu chỉ yêu cầu các phần phụ thuộc Python bổ sung trong quá trình tạo. Ví dụ: tập dữ liệu SVHN sử dụng scipy để tải một số dữ liệu.

Nếu bạn đang thêm tập dữ liệu vào kho lưu trữ TFDS, vui lòng sử dụng tfds.core.lazy_imports để giữ gói tensorflow-datasets ở kích thước nhỏ. Người dùng sẽ chỉ cài đặt các phần phụ thuộc bổ sung khi cần thiết.

Để sử dụng lazy_imports :

  • Thêm mục nhập cho tập dữ liệu của bạn vào DATASET_EXTRAS trong setup.py . Điều này giúp người dùng có thể thực hiện, chẳng hạn như pip install 'tensorflow-datasets[svhn]' để cài đặt các phần phụ thuộc bổ sung.
  • Thêm mục nhập để bạn nhập vào LazyImporter và vào LazyImportsTest .
  • Sử dụng tfds.core.lazy_imports để truy cập phần phụ thuộc (ví dụ: tfds.core.lazy_imports.scipy ) trong DatasetBuilder của bạn.

Dữ liệu bị hỏng

Một số tập dữ liệu không hoàn toàn sạch sẽ và chứa một số dữ liệu bị hỏng (ví dụ: hình ảnh ở dạng tệp JPEG nhưng một số là JPEG không hợp lệ). Nên bỏ qua những ví dụ này nhưng hãy để lại ghi chú trong phần mô tả tập dữ liệu về số lượng ví dụ bị loại bỏ và lý do.

Cấu hình/biến thể tập dữ liệu (tfds.core.BuilderConfig)

Một số bộ dữ liệu có thể có nhiều biến thể hoặc các tùy chọn về cách xử lý trước và ghi vào đĩa. Ví dụ: Cycle_gan có một cấu hình cho mỗi cặp đối tượng ( cycle_gan/horse2zebra , cycle_gan/monet2photo ,...).

Việc này được thực hiện thông qua tfds.core.BuilderConfig s:

  1. Xác định đối tượng cấu hình của bạn dưới dạng lớp con của tfds.core.BuilderConfig . Ví dụ: MyDatasetConfig .

    @dataclasses.dataclass
    class MyDatasetConfig(tfds.core.BuilderConfig):
      img_size: Tuple[int, int] = (0, 0)
    
  2. Xác định thành viên lớp BUILDER_CONFIGS = [] trong MyDataset liệt kê các MyDatasetConfig mà tập dữ liệu hiển thị.

    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
    
  3. Sử dụng self.builder_config trong MyDataset để định cấu hình tạo dữ liệu (ví dụ: shape=self.builder_config.img_size ). Điều này có thể bao gồm việc đặt các giá trị khác nhau trong _info() hoặc thay đổi quyền truy cập dữ liệu tải xuống.

Ghi chú:

  • Mỗi cấu hình có một tên duy nhất. Tên đủ điều kiện của cấu hình dataset_name/config_name (ví dụ coco/2017 ).
  • Nếu không được chỉ định, cấu hình đầu tiên trong BUILDER_CONFIGS sẽ được sử dụng (ví dụ: tfds.load('c4') mặc định là c4/en )

Xem anli để biết ví dụ về tập dữ liệu sử dụng BuilderConfig s.

Phiên bản

Phiên bản có thể đề cập đến hai ý nghĩa khác nhau:

  • Phiên bản dữ liệu gốc “ngoài”: vd COCO v2019, v2017,...
  • Phiên bản mã TFDS "nội bộ": ví dụ đổi tên một tính năng trong tfds.features.FeaturesDict , sửa lỗi trong _generate_examples

Để cập nhật tập dữ liệu:

  • Để cập nhật dữ liệu "bên ngoài": Nhiều người dùng có thể muốn truy cập đồng thời một năm/phiên bản cụ thể. Điều này được thực hiện bằng cách sử dụng một tfds.core.BuilderConfig cho mỗi phiên bản (ví dụ coco/2017 , coco/2019 ) hoặc một lớp cho mỗi phiên bản (ví dụ Voc2007 , Voc2012 ).
  • Đối với cập nhật mã “nội bộ”: Người dùng chỉ tải phiên bản mới nhất. Bất kỳ bản cập nhật mã nào cũng phải tăng thuộc tính lớp VERSION (ví dụ: từ 1.0.0 lên VERSION = tfds.core.Version('2.0.0') sau phiên bản ngữ nghĩa .

Thêm một lần nhập để đăng ký

Đừng quên nhập mô-đun tập dữ liệu vào dự án __init__ của bạn để được đăng ký tự động trong tfds.load , tfds.builder .

import my_project.datasets.my_dataset  # Register MyDataset

ds = tfds.load('my_dataset')  # MyDataset available

Ví dụ: nếu bạn đang đóng góp cho tensorflow/datasets , hãy thêm mô-đun nhập vào __init__.py của thư mục con của nó (ví dụ: image/__init__.py .

Kiểm tra các vấn đề triển khai chung

Vui lòng kiểm tra các lỗi triển khai phổ biến .

Kiểm tra tập dữ liệu của bạn

Tải về và chuẩn bị: tfds build

Để tạo tập dữ liệu, hãy chạy tfds build từ thư mục my_dataset/ :

cd path/to/datasets/my_dataset/
tfds build --register_checksums

Một số cờ hữu ích để phát triển:

  • --pdb : Vào chế độ gỡ lỗi nếu có ngoại lệ xuất hiện.
  • --overwrite : Xóa các tệp hiện có nếu tập dữ liệu đã được tạo.
  • --max_examples_per_split : Chỉ tạo các ví dụ X đầu tiên (mặc định là 1), thay vì tạo tập dữ liệu đầy đủ.
  • --register_checksums : Ghi lại tổng kiểm tra các url đã tải xuống. Chỉ nên sử dụng khi đang trong quá trình phát triển.

Xem tài liệu CLI để biết danh sách đầy đủ các cờ.

Tổng kiểm tra

Bạn nên ghi lại tổng kiểm tra các tập dữ liệu của mình để đảm bảo tính xác định, trợ giúp về tài liệu,... Việc này được thực hiện bằng cách tạo tập dữ liệu với --register_checksums (xem phần trước).

Nếu bạn đang phát hành tập dữ liệu của mình thông qua PyPI, đừng quên xuất tệp checksums.tsv (ví dụ: trong package_data của setup.py ).

Kiểm tra đơn vị tập dữ liệu của bạn

tfds.testing.DatasetBuilderTestCase là một TestCase cơ bản để thực hiện đầy đủ một tập dữ liệu. Nó sử dụng "dữ liệu giả" làm dữ liệu thử nghiệm bắt chước cấu trúc của tập dữ liệu nguồn.

  • Dữ liệu thử nghiệm phải được đặt trong thư mục my_dataset/dummy_data/ và phải bắt chước các tạo phẩm của tập dữ liệu nguồn khi được tải xuống và trích xuất. Nó có thể được tạo thủ công hoặc tự động bằng một tập lệnh ( tập lệnh ví dụ ).
  • Đảm bảo sử dụng dữ liệu khác nhau trong phần tách dữ liệu thử nghiệm của bạn, vì thử nghiệm sẽ thất bại nếu phần tách tập dữ liệu của bạn chồng chéo lên nhau.
  • Dữ liệu thử nghiệm không được chứa bất kỳ tài liệu có bản quyền nào . Nếu nghi ngờ, đừng tạo dữ liệu bằng cách sử dụng tài liệu từ tập dữ liệu gốc.
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()

Chạy lệnh sau để kiểm tra tập dữ liệu.

python my_dataset_test.py

Gửi phản hồi cho chúng tôi

Chúng tôi liên tục cố gắng cải thiện quy trình tạo tập dữ liệu nhưng chỉ có thể làm như vậy nếu chúng tôi nhận thức được vấn đề. Bạn gặp phải vấn đề hoặc lỗi nào khi tạo tập dữ liệu? Có phần nào khó hiểu hoặc không hoạt động trong lần đầu tiên không?

Vui lòng chia sẻ phản hồi của bạn trên GitHub .