tensorflow_datasets(tfds)을 사용하여 custom dataset 생성하고자 한다. 구글에서 공개한 tensorflow 모델을 custom dataset으로 학습하는 세팅이다.(개발환경 세팅은 여기와 여기 참고)
작업환경
- ubuntu18.04 + Docker Container
*tensorflow_datasets와 tf.data
1) tensorflow_datasets(공식문서)
목적:
- 공개되어 있는 많은 데이터셋들의 원본을 tfds 모듈로 불러들일 수 있음
주요 특징:
- 연구에서 사용되고 있는 많은 데이터셋 원본 파일들(전처리 X)을 공개해둠(데이터셋 목록)
- tfds.features으로 데이터셋 정의(Audio, ClassLabel, Image, Sequence, Tensor, Text, Video, BBox)
- 연구에 활용하기 위해서는 목적에 맞게 전처리를 해야함!
2) tf.data(공식문서)
목적:
- 모델의 input pipeline build를 위한 API collection
주요 특징:
- 데이터셋 전처리 및 학습을 위한 batch 구성을 쉽게 구축할 수 있음
- tf.train.BytesList, tf.train.FloatList, tf.train.Int64List로 데이터를 serialize하여 저장하고 불러옴
tfds를 통해 받은 파일을 열어보면 언뜻 보기에는 tf.record 파일들을 생성하는 것 같지만 record 파일로는 str 데이터를 저장하고 불러올 때 utf-8 encode, decode 과정이 필요하다. 공개된 모델들의 경우 tfds기반으로 데이터를 record화 시키고 학습할 때 불러오며, 이때 유의할 점은 tf.train.Example에 사용되는 tf.train.BytesList, tf.train.FloatList, tf.train.Int64List가 아닌 tfds.features.Text, tfds.features.Image, tfds.features.Audio로 저장이 된다는 것이다.
0. TFDS 데이터셋 생성을 위한 데이터셋 준비
- train, test 폴더를 각각 생성한 후 학습, 평가에 사용할 데이터셋 저장(txt, pandas 상관없음)
- train, test를 하나의 파일로 압축(data.zip)
data
└ train
└ train.csv
└ test
└ test.csv
zip -r data.zip train test
data.zip 파일을 어디로 옮겨야 하는지는 포스팅에 설명하겠다.
1. Custom Datset 생성하기
0) 전체 개요
- tensorflow_datasets 모듈 설치 및 프로젝트 생성
- custom dataset 생성 파일 작성
- Custom Dataset 빌드
1) tfds 모듈 설치 및 프로젝트 생성
pip install tensorflow_datasets
cd [dataset 작업 폴더]
tfds new custom_dataset # 생성 및 테스트를 위한 템플릿 파일 생성
>> 2021-03-09 05:10:26.215601: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
>> Dataset generated at ..dataset/path/custom_dataset
>> You can start searching `TODO(custom_dataset)` to complete the implementation.
>> Please check https://www.tensorflow.org/datasets/add_dataset for additional details.
프로젝트를 생성하면 다음과 같은 파일들이 생성된다. 이 중 custom_dataset.py만 수정하면 된다.
2) custom dataset 생성 파일 작성
공식 문서에서는 웹에서 데이터를 받는 형태로 설명이 되어 있으나, custom data의 경우 이미 저장되어 있는 데이터를 활용하는 경우가 많을 것이다. 때문에 데이터가 로컬에 저장되어 있으며, manual_dir에서 데이터를 불러오는 세팅으로 설명하고자 한다. manual_dir은 tfds가 데이터를 읽어들이는 폴더이며 /root/tensorflow_datasets/downloads/manual이 초기값이다.
custom_dataset.py을 열어보면 만들고자 하는 class가 정의되어 있으며 3개의 abstract method만 정의하면 된다.
- _info: 데이터셋 feature 및 설명 정의
- _split_generators: 위에서 압축한 파일(data.zip)을 읽어들이고 train, test에 사용할 데이터 나눔
- _generate_examples: 각 example을 생성하는 generator 정의
초기 CustomDataset Class
class CustomDataset(tfds.core.GeneratorBasedBuilder):
"""DatasetBuilder for custom_dataset dataset."""
VERSION = tfds.core.Version('1.0.0')
RELEASE_NOTES = {
'1.0.0': 'Initial release.',
}
def _info(self) -> tfds.core.DatasetInfo:
"""Returns the dataset metadata."""
# TODO(custom_dataset): Specifies the tfds.core.DatasetInfo object
return tfds.core.DatasetInfo(
builder=self,
description=_DESCRIPTION,
features=tfds.features.FeaturesDict({
# These are the features of your dataset like images, labels ...
'image': tfds.features.Image(shape=(None, None, 3)),
'label': tfds.features.ClassLabel(names=['no', 'yes']),
}),
# 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'), # Set to `None` to disable
homepage='https://dataset-homepage/',
citation=_CITATION,
)
def _split_generators(self, dl_manager: tfds.download.DownloadManager):
"""Returns SplitGenerators."""
# TODO(custom_dataset): Downloads the data and defines the splits
path = dl_manager.download_and_extract('https://todo-data-url')
# TODO(custom_dataset): Returns the Dict[split names, Iterator[Key, Example]]
return {
'train': self._generate_examples(path / 'train_imgs'),
}
def _generate_examples(self, path):
"""Yields examples."""
# TODO(custom_dataset): Yields (key, example) tuples from the dataset
for f in path.glob('*.jpeg'):
yield 'key', {
'image': f,
'label': 'yes',
}
i. _info
먼저 MANUAL_DOWNLOAD_INSTRUCTIONS을 CustomClass에 정의해준다.
MANUAL_DOWNLOAD_INSTRUCTIONS = """
data.zip files should be located at /root/tensorflow_dataset/downloads/manual
"""
이후 tfds.features.FeaturesDict로 input, label 등을 정의한다. (feature 항목 참고)
def _info(self) -> tfds.core.DatasetInfo:
"""Returns the dataset metadata."""
# TODO(custom_dataset): Specifies the tfds.core.DatasetInfo object
return tfds.core.DatasetInfo(
builder=self,
description=_DESCRIPTION,
features=tfds.features.FeaturesDict({
# These are the features of your dataset like images, labels ...
'image': tfds.features.Image(shape=(None, None, 3)),
'label': tfds.features.ClassLabel(names=['no', 'yes']),
'custom_text': tfds.features.Text()
}),
# 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'), # Set to `None` to disable
homepage='https://dataset-homepage/',
citation=_CITATION,
)
ii. _split_generators
여기가 중요하다. archive_path, extracted_path를 정의한다. archive_path = dl_manager.manual로 지정이 되어있는데 attribute를 바꾸려고 해도 바꿀 수 없다고 한다. 해당 디렉토리가 어디인지는 아래에서 설명하겠으며 일단 data.zip를 manual_dir으로 지정해준다.
def _split_generators(self, dl_manager: tfds.download.DownloadManager):
"""Returns SplitGenerators."""
# TODO(custom_dataset): Downloads the data and defines the splits
# path = dl_manager.download_and_extract('https://todo-data-url')
archive_path = dl_manager.manual_dir / 'data.zip'
extracted_path = dl_manager.extract(archive_path)
# TODO(custom_dataset): Returns the Dict[split names, Iterator[Key, Example]]
return {
'train': self._generate_examples(path = extracted_path/'train'),
'test': self._generate_examples(path = extracted_path/'test'),
}
iii. _generate_examples
학습에 사용할 example generator를 정의한다. example의 id, input feature, label등을 정의한다.
예시들)
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'],
}
def _generate_examples(self, path):
"""Yields examples."""
# TODO(custom_dataset): Yields (key, example) tuples from the dataset
for f in path.glob('*.jpeg'):
yield 'key', {
'image': f,
'label': 'yes',
}
3) Custom Dataset Build
custom_dataset.py이 있는 폴더에서 tfds로 빌드한다.
cd /path/to/custom_dataset.py
tfds build # tfds 데이터셋 빌드
이때 'AssertionError: Manual directory /root/tensorflow_datasets/downloads/manual does not exist or is empty. Create it and download/extract dataset artifacts in there using instructions:'라는 에러가 뜬다. 위에서 만든 data.zip 파일을 해당 디렉토리로 이동시켜준다.
cd /root/tensorflow_datasets/downloads
mkdir manual # manual directory 생성
mv (..)/data.zip /root/tensorflow_datasets/downloads/manual/data.zip # data.zip 파일 이동
cd /path/to/custom_dataset.py
tfds build # tfds 데이터셋 빌드
작업 시간 데이터 양에 따라 다르지만 10분 이내로 생성되며 /root/tensorflow_datasets/cumstom_dataset/1.0.0에 train, test record 파일들이 생성이 된다.
이 데이터들을 tfds 모듈로 import 하게 된다.
2. tfds로 custom_dataset 불러오기
tfds를 import하고 load할 데이터 경로를 tfds build한 경로로 지정하고 train, test 중 어느 것을 불러올지 설정해서 불러온다.
import tensorflow_datasets as tfds
data_dir = '/root/tensorflow_datasets/custom_dataset/1.0.0/'
input_files = tf.io.gfile.glob(
os.path.join(data_dir, "*{}.tfrecord*".format(split))) # 'tfrecord'이 포함된 파일 리스트 불러옴
d = tf.data.Dataset.from_tensor_slices(tf.constant(input_files))
d = d.shuffle(buffer_size=len(input_files))
# Non deterministic mode means that the interleaving is not exact.
# This adds even more randomness to the training pipeline.
d = d.interleave(tf.data.TFRecordDataset,
deterministic=False,
num_parallel_calls=tf.data.experimental.AUTOTUNE)
[references]
'개발' 카테고리의 다른 글
[ubuntu] 프로세스 백그라운드에서 실행 (0) | 2021.03.10 |
---|---|
[ubuntu] 파일, 폴더 용량 확인 (0) | 2021.03.10 |
[ubuntu] zip, unzip 명령어 (0) | 2021.03.09 |
PyCharm 디버깅 세션 실행 방법 (0) | 2021.02.10 |
Docker Container 중지 없이 빠져나오기 (0) | 2021.02.09 |