Introduction
Khi huấn luyện các mô hình deep learning, chúng ta thường dành nhiều sự quan tâm đến kiến trúc mô hình, lựa chọn loss function phù hợp, optimizer, tuning hyperparameters,... Nhưng có một thứ cũng khá quan trọng mà ta thường không quan tâm nhiều đó là hiệu suất xử lý dữ liệu đầu vào.
Multi-stage data preprocessing pipelines bao gồm loading, decoding hay augmentations là bước không thể thiếu trong các ứng dụng liên quan đến học sâu, các pipelines này hiện đang được xử lý trên CPU đã trở thành bottleneck cản trở hiệu suất và khả năng scalability của quá trình training và inference khi mà mô hình thì chờ dữ liệu, còn CPU thì trì trệ để xử lý ảnh từng batch một. Bởi vậy mà ta có thể tham khảo một thư viện cho data preprocessing, NVIDIA DALI (Data Loading Library) ra đời để giải quyết vấn đề này.
Overview
NVIDIA Data Loading Library (DALI) là một thư viện GPU-accelerated cho data loading và data preprocessing để tăng tốc các ứng dụng học sâu. Thư viện cung cấp các building blocks được tối ưu hóa cao để tải và xử lý dữ liệu hình ảnh, video và âm thanh. Nó có thể được sử dụng như một sự thay thế cho data loaders và data iterators trong các deep learning frameworks.
Ngoài ra, deep learning frameworks có nhiều triển khai tiền xử lý dữ liệu, dẫn đến những thách thức như tính di động của quy trình training và inference, và khả năng bảo trì code. Data processing pipelines được triển khai bằng DALI có tính di động vì chúng có thể dễ dàng được chuyển hướng sang TensorFlow, PyTorch, ...
Dưới đây là hình ảnh minh họa trong thực tiễn, nhìn phát là hiểu:
Highlights
Dưới đây là một số điểm chính mà documentations của DALI có đề cập:
- API Python theo phong cách chức năng dễ sử dụng.
- Hỗ trợ nhiều định dạng dữ liệu - LMDB, RecordIO, TFRecord, COCO, JPEG, JPEG 2000, WAV, FLAC, OGG, H.264, VP9 và HEVC.
- Hỗ trợ deep learning frameworks: TensorFlow, PyTorch, PaddlePaddle, JAX.
- Hỗ trợ thực thi CPU và GPU, multi-GPU
- Customize pipelines, operators, ...
- Tăng tốc image classification (ResNet-50), object detecttion (SSD) workloads cũng như các mô hình ASR (Jasper, RNN-T).
- Cho phép đường dẫn dữ liệu trực tiếp giữa sotrage và GPU memory với GPUDirect Storage.
- Dễ dàng tích hợp với NVIDIA Triton Inference Server với DALI TRITON Backend.
- Quan trọng và không thể thiếu: Open-source
Ngoài ra, DALI hỗ trợ toàn bộ tất cả Linux distribution và gián tiếp với Windows thông qua WSL, tuy nhiên MacOS thì chưa.
Một số thông tin cơ bản
Data pipeline
Trong DALI, các tác vụ xử lý dữ liệu thông qua Pipeline. Đây là một instance của nvidia.dali.Pipeline
hoặc derived class. Pipeline đóng gói data preprocessing graph và execution engine. Một số cách định nghĩa DALI pipeline:
-
Sử dụng decorator
pipeline_def()
cho một function. -
Khởi tạo trực tiếp đối tượng Pipeline, xây dựng graph và thiết lập đầu ra của pipeline với
Pipeline.set_outputs()
. -
Kế thừa từ
Pipeline class
và overridePipeline.define_graph()
.
Data Processing Graphs
DALI pipeline được biểu diến như đồ thị operatorations, bao gồm 2 loại nodes trong graph:
- Operators
- DataNode: inputs và outputs của operators Datanode có thể được transformed bằng cách gọi các hàm operator. Chúng cũng hỗ trợ Python-style indexing và có thể được kết hợp trong các biểu thức toán học.
Ví dụ:
@pipeline_def # create a pipeline with processing graph
def my_pipeline(): """ Create a pipeline which reads images and masks, decodes the images and returns them. """ img_files, labels = fn.readers.file(file_root="image_dir", device='cpu') mask_files, _ = fn.readers.file(file_root="mask_dir", seed=1) images = fn.decoders.image(img_files, device="mixed") masks = fn.decoders.image(mask_files, device="mixed") return images, masks, labels pipe = my_pipeline(batch_size=4, num_threads=2, device_id=0)
Đồ thị có dạng:
Data pipelines được thực thi trong các stages và sẽ tương ứng với tham số device
được xác định trong operator và thực thi theo thứ tự sau:
cpu
: operators chấp nhận CPU inputs và tạo CPU outputsmixed
: CPU inputs và GPU outputsgpu
: GPU inputs và outputs
Conditional Execution:
Như cái tên, DALI cũng cho phép thực thi operators conditional với if
:
@pipeline_def(enable_conditionals=True)
def random_rotate(): jpegs, _ = fn.readers.file(device="cpu", file_root=images_dir) images = fn.decoders.image(jpegs, device="mixed") do_rotate = fn.random.coin_flip(probability=0.25, dtype=DALIDataType.BOOL) if do_rotate: result = fn.rotate(images, angle=fn.random.uniform(range=(10, 30)), fill_value=0) else: result = images return result
Types and Mathematical Expressions
DALI cũng hỗ trợ rất nhiều kiểu loại dữ liệu và các hàm toán học, phép toán số học bao gồm cách thức cũng như cách nó hoạt động, mọi người có thể tham khảo thêm trong tài liệu của DALI.
Automatic Augmentations
Automatic augmentations là các probabilistic augmentation policies. Khi sử dụng, mỗi mẫu dữ liệu được xử lý bằng các phép tăng cường (các thao tác biến đổi hình ảnh) được chọn ngẫu nhiên theo một số phân phối xác suất được xác định. DALI triển khai các phép tăng cường tự động bằng cách sử dụng thực thi có điều kiện.
Module nvidia.dali.auto_aug
đã hỗ trợ 1 số phép tăng cường bao gồm: AutoAugment, RandAugment và TrivialAugment để dùng trực tiếp trong pipelines. Ta cũng có thể customize hoặc xác định các cách mới.
Để sử dụng , ta cần xác định pipeline sử dụng decorator @pipeline_def
và đặt enable_conditionals=True
. Tiếp theo, gọi automatic augmentation trong pipeline. Ví dụ nếu ta muốn sử dụng AutoAugment cho bộ dữ liệu Imagenet chẳng hạn:
from nvidia.dali import pipeline_def, fn, types
from nvidia.dali.auto_aug import auto_augment @pipeline_def(enable_conditionals=True)
def training_pipe(data_dir, image_size): jpegs, labels = fn.readers.file(file_root=data_dir, ...) shapes = fn.peek_image_shape(jpegs) images = fn.decoders.image(jpegs, device="mixed", output_type=types.RGB) # Applies the AutoAugment policy for ImageNet augmented_images = auto_augment.auto_augment_image_net(images, shape=shapes) resized_images = fn.resize(augmented_images, size=[image_size, image_size]) return resized_images, labels
Một số khái niệm trong Automatic Augmentations:
-
augmentation: Danh sách các phép tăng cường được sử dụng trong
AutoAugment, RandAugment và TrivialAugment
, cũng như API để tùy chỉnh. Có thể sử dụngdecorator
@augmentation
để triển khai các phép tăng cường mới. -
policy - tập hợp các phép tăng cường và tham số mô tả cách áp dụng cho input cũng như "mức độ" của hoạt động.
-
apply operation - hàm gọi policy đã chỉ định trên một loạt hình ảnh trong DALI pipeline.
Tổng kết
Bài viết này của mình chỉ cho mục đích giới thiệu thông tin cơ bản cũng như mục đích của DALI thôi. Nếu các bạn muốn đọc thêm về DALI advanced thì mọi người nên đọc trực tiếp từ trong tài liệu cho đầy đủ. Chắc bài viết này ngắn gọn vậy thôi, trong bài viết tới mình sẽ thử trải nghiệm hiệu suất của DALi xem như thế nào nhé. Nếu có thời gian mình cũng sẽ thử dùng cả DALI cho inference với Triton Inference Server với DALi Backend.