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

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

Thực hiện 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ó chưa.

TL; DR

Cách dễ nhất để viế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

Bộ dữ liệu được phân phối ở tất cả các loại định dạng và ở tất cả các loại địa điểm và không phải lúc nào chúng cũng được lưu trữ ở định dạng sẵn sàng cung cấp cho hệ thống máy học. Nhập TFDS.

TFDS xử lý các bộ 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ể tải định dạng này dưới dạng quy trình máy học (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. Lầ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 bộ dữ liệu triển khai một lớp con của tfds.core.DatasetBuilder , chỉ định:

  • Dữ liệu đến từ đâu (tức là các 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ó);
  • Cách phân chia dữ liệu (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 một 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ụ tập dữ liệu

Tất cả các bộ dữ liệu được triển khai các lớp con của tfds.core.DatasetBuilder , đảm nhiệm 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 các 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.

Hãy xem chi tiết 3 phương pháp trừu tượng để ghi đè.

_info : siêu dữ liệu tập dữ liệu

_info trả về tfds.core.DatasetInfo chứa siêu dữ liệu của 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 được tự giải thích. Một số độ chính xác:

Viết BibText CITATIONS.bib :

  • Tìm kiếm trang web tập dữ liệu để biết hướng dẫn trích dẫn (sử dụng ở định dạng BibTex).
  • Đối với bài báo arXiv : tìm bài báo và nhấp vào liên kết BibText ở phía bên tay phải.
  • Tìm bài báo 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 liên quan (ví dụ: chỉ có một trang web), bạn có thể sử dụng Trình chỉnh sửa trực tuyến BibTeX để 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 trong tệp đã 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 được lưu trữ để phân bổ các lớp đồng đều hơn trên tập dữ liệu, vì thường các bản ghi thuộc cùng một lớp 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 vô hiệu hóa xáo trộn có tác động đến hiệu suất vì các phân đoạn không thể được đọc song song nữa.

_split_generators : tải xuống và chia nhỏ 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 xuống dữ liệu từ web. Điều 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 .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 đó trả về tfds.core.Path (bí danh cho epath.Path ), là các đối tượng giống như pathlib.Path .

Các 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ể 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 dữ liệu đó vào manual_dir/ (mặc định là ~/tensorflow_datasets/downloads/manual/ ).

Các tệp sau đó 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 một 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 tách 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ó phần tách traintest ), hãy giữ lại các phần tách đó. Mặt khác, chỉ chỉ định một phần tách tfds.Split.TRAIN duy nhất. 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%:]' ).

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à các bộ dữ liệu năng suất (key, feature_dict) :

  • key : Mã định danh ví dụ. Được sử dụng để xáo trộn một cách xác định các ví dụ bằng cách sử dụng hash(key) hoặc để sắp xếp theo khóa khi tính năng xáo trộn bị tắt (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.
    • tất định : Không nên phụ thuộc vào thứ tự download_dir , os.path.listdir ,... Việc 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ị ví dụ.
    • 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ụ: 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] ,...)
    • Xem hướng dẫn trình 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ữ Đám mây, hãy tránh sử dụng các thao tác I/O tích hợp Python.

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

phụ thuộc thêm

Một số bộ dữ liệu chỉ yêu cầu 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ữ cho tensorflow-datasets nhỏ. Người dùng sẽ chỉ cài đặt các 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 cho quá trình nhập của bạn vào LazyImporterLazyImportsTest .
  • 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ố bộ dữ liệu không hoàn toàn sạch 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à tệp JPEG không hợp lệ). Những ví dụ này nên được bỏ qua, nhưng hãy để lại ghi chú trong phần mô tả tập dữ liệu có bao nhiêu ví dụ bị loại bỏ và lý do.

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

Một số bộ dữ liệu có thể có nhiều biến thể hoặc tùy chọn về cách dữ liệu được 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 ,...).

Điều 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ê 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 là 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 "bên 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 một tập dữ liệu:

  • Đối với 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 vào 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 xuống phiên bản mới nhất. Bất kỳ 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 khi lập phiên bản ngữ nghĩa .

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

Đừng quên nhập mô-đun bộ dữ liệu vào dự án của bạn __init__ để đượ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 thư mục con của nó __init__.py (ví dụ: image/__init__.py .

Kiểm tra các vấn đề triển khai phổ biến

Vui lòng kiểm tra các vấn đề thực hiện phổ biến .

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

Tải xuống 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ệ.
  • --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 X ví dụ đầu tiên (mặc định là 1), thay vì toàn bộ tập dữ liệu.
  • --register_checksums : Ghi lại tổng kiểm tra của các url đã tải xuống. Chỉ nên được sử dụng trong khi đang 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ủa 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,... Điều 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 bộ dữ liệu của mình thông qua PyPI, đừng quên xuất các tệp checksums.tsv (ví dụ: trong package_data của setup.py của bạn).

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

tfds.testing.DatasetBuilderTestCase là một TestCase cơ sở để 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 my_dataset/dummy_data/ và phải bắt chước các thành phần tạo tác 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 các dữ liệu khác nhau trong các 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 các phần tách tập dữ liệu của bạn trùng lặp.
  • 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 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 đang 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 các vấn đề. Bạn đã gặp sự cố hoặc lỗi nào khi tạo tập dữ liệu? Có phần nào gây nhầm lẫn hoặc không hoạt động ngay lần đầu tiên không?

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