Deep Learning cơ bản | Deep Learning cơ bản
 

Category: Deep Learning cơ bản

Hướng dẫn cuộc thi Data-Centric AI Competition 2021

| Comments Off on Hướng dẫn cuộc thi Data-Centric AI Competition 2021

Mục tiêu của cuộc thi

Xử lý dữ liệu là một phần rất quan trọng trong việc xây dựng và phát triển các ứng dụng AI. Tuy nhiên, hầu hết các cuộc thi về AI trước đây đều tập trung vào việc xây dựng mô hình, các kĩ thuật về xử lý dữ liệu chưa được quan tâm đúng mức. Do đó, FPT Software đã tổ chức cuộc thi “Data-Centric AI Competition” theo xu hướng tập trung phát triển dữ liệu. Trong cuộc thi này, mô hình (yolov5s) sẽ được giữ cố định cho các đội chơi, thí sinh cần sử dụng các kỹ thuật xử lý dữ liệu như tiền xử lý và tăng cường dữ liệu để cải thiện hiệu suất của mô hình.

Dựa trên nhu cầu thực tế trong giai đoạn dịch bệnh, bài toán của cuộc thi là nhận diện vật thể (object detection) với 3 lớp là đeo khẩu trang, không đeo khẩu trang và đeo khẩu trang không đúng cách. Ban tổ chức cung cấp một bộ dữ liệu gồm 1,064 ảnh với 1,692 khuôn mặt được chụp lại trong các điều kiện ánh sáng, bối cảnh và góc máy khác nhau.

Ví dụ về dữ liệu của cuộc thi

Theo dõi các thử nghiệm

Thay vì sử dụng các công nghệ theo dõi phức tạp như MLFlow, W&B, chúng tôi đã quyết định lựa chọn ứng dụng Microsoft Excel để quản lý các lần thử nghiệm vì nó khá phù hợp cho các tác vụ đơn giản. Mục đích của việc này nhằm ghi lại mức độ tác động của dữ liệu đối với mô hình sau mỗi lần làm mới. Qua đó chúng ta có các chiến lược phù hợp để điều chỉnh dữ liệu cho các lần thử nghiệm khác trong tương lai. Dưới đây là ảnh chụp mẫu bảng tính mà chúng tôi sử dụng cho cuộc thi.

Bảng 1: Kết quả các lần thử nghiệm

Các kỹ thuật nên sử dụng

Làm sạch dữ liệu

Các dữ liệu trong tập train/validation mà BTC cung cấp bị label sai hoặc thiếu khá nhiều, các bạn thí sinh nên label lại cho chuẩn. Để xem cách label dữ liệu chuẩn thì các bạn nên tham khảo tập public test, vì BTC có nói là đây là tập chuẩn và đại diện cho tập private test. Các bạn có thể sử dụng công cụ labelImg để label lại dữ liệu cho chuẩn.

Công cụ hỗ trợ label dữ liệu

Để ý đến dữ liệu trong tập public test

Vì tập public test được label chuẩn và gần giống với tập private test nhất nên các bạn nên quan sát tập public test để có cái nhìn sơ bộ về dữ liệu trong private test. Và khi thực hiện các kĩ thuật augment cũng nên tập trung vào các ảnh trong public test hơn là các ảnh trong tập train/validation mà BTC cung cấp.

Bên cạnh đó trộn tập public test vào tập train/val sau đó chia lại và nộp kết quả cũng có thể tăng được hiệu suất của mô hình.

Các kỹ thuật tăng cường dữ liệu

Để tăng cường dữ liệu, có rất nhiều sự lựa chọn với các công cụ có sẵn mà mọi người có thể tham khảo. Dưới đây là danh sách các kỹ thuật tăng cường dữ liệu phổ biến mà các bạn có thể áp dụng:

Ví dụ về các kĩ thuật tăng cường dữ liệu

Để kiểm tra tính hiệu quả của các phương pháp trên chúng tôi đã thay thế khoảng 10% – 50% dữ liệu gốc bằng các phiên bản tăng cường và huấn luyện mô hình trên tập dữ liệu mới. 

Các phương pháp tăng cường dữ liệu như Gaussian blur, xoay, thay đổi độ tương phản hoặc độ sáng, mixup và cutout giúp cải thiện đáng kể hiệu suất của mô hình. Việc thêm dữ liệu edge case vào tập huấn luyện cũng tạo ra một sự thay đổi lớn về hiệu suất mô hình.

Kết quả dự đoán của các mô hình với các kĩ thuật xử lý, tăng cường dữ liệu khác nhau

Chúng ta có thể thấy rõ được sự cải thiện về hiệu suất sau khi mô hình được huấn luyện với các bộ dữ liệu tăng cường khác nhau. Ở đây, các ô viền đỏ đại diện cho lớp “không đeo khẩu trang”, các ô viền xanh lá được sử dụng cho lớp “đeo khẩu trang” và các ô viền vàng được sử dụng cho lớp “đeo khẩu trang không đúng cách”.

Hình a cho thấy mô hình được huấn luyện trên tập dữ liệu gốc có hiệu suất không cao. Mô hình này có xu hướng gắn nhãn sai khuôn mặt trong điều kiện ánh sáng kém và không thể phát hiện nhãn một số khuôn mặt. Vấn đề này được giải quyết bằng cách áp dụng kỹ thuật như Gaussian blur và điều chỉnh độ tương phản cũng như độ sáng của dữ liệu. Minh chứng ở hình b cho thấy các khuôn mặt trong vùng tối đã được phát hiện và gán nhãn bởi mô hình. Lần thử nghiệm tăng cường dữ liệu này giúp hiệu suất mô hình đạt 0.48 trên đánh giá mAP@.5. 

Chúng tôi tiếp tục sử dụng thêm các kỹ thuật như add random zoom, shift và crop để tạo ra hình ảnh với các mức độ thu phóng khác nhau với mục đích phát hiện các khẩu trang nhỏ trên khuôn mặt. Điều này giúp cải thiện hiệu suất thêm 4% (Hình c).

Mức tăng hiệu suất mô hình lớn nhất (28% so với baseline) được ghi nhận khi chúng tôi thêm edge case và sử dụng các kỹ thuật như mixup, cutout. Mô hình này có thể gán nhãn các ví dụ thử nghiệm khó như minh họa trong hình 6d.

Kết quả các lần thử được tổng hợp trong bảng 1.

Các kỹ thuật khác nên thử

  • Tối đa hóa kích thước tập dữ liệu.
  • Tập trung tăng cường dữ liệu cho lớp đeo khẩu trang sai và không đeo khẩu trang.
  • Bổ sung các dữ liệu bên ngoài cuộc thi.
  • Sử dụng kĩ thuật sinh dữ liệu như Generative Adversarial Network (GAN).
  • Sử dụng kỹ thuật mosaic.

Bài trước mình đã học về cách xây dựng model (NN, CNN) bằng Pytorch, bài này mình sẽ học cách load dữ liệu, sau đó train model bằng Pytorch.

Dataset

torch.utils.data.Dataset trong Pytorch mô tả dữ liệu giống như dữ liệu thực tế mọi người có, trong đó có hai hàm quan trọng:

  • __len__: trả về số sample trong dataset, tương ứng len(dataset).
  • __getitem__ : lấy ra sample thứ i trong dataset, tương ứng dataset[i].
Dataset trong Pytorch, hỗ trợ hàm len và lấy phần tử theo index.

Ví dụ như khi load dataset cifar10 từ torchvision.dataset

from torchvision import datasets

# Đường dẫn lưu để sau load lại không cần download.
data_path = '/content/drive/MyDrive/Pytorch/Pytorch Tutorial/'

# load dataset cifar10
cifar10 = datasets.CIFAR10(data_path, train=True, download=True)

Khi đó cifar10 là một Dataset.

print(isinstance(cifar10, torch.utils.data.Dataset)) # True
print(len(cifar10)) # 50000
print(cifar10[0]) # (<PIL.Image.Image image mode=RGB size=32x32 at 0x7F729582BF50>, 6)

Dataset cifar10 có 50.000 dữ liệu, trong đó khi lấy index theo từng phần tử sẽ trả lại 1 tuple gồm 2 phần tử (PIL image, label).

Mình có thể visualize ảnh lên, tuy nhiên ảnh kích thước nhỏ (32*32) nên mở lên sẽ hơi vỡ.

img, label = cifar10[0]
plt.imshow(img)
frog

Transformer

Dữ liệu mình lấy được ở trên thì ảnh ở dạng PIL image, mình cần convert về dạng Torch tensor để cho Pytorch xử lý và tính toán. Module torchvision.transforms hỗ trợ các phép chuyển đổi trên ảnh như: chuyển sang tensor, normalization, augmentation,…

ToTensor

to_tensor = transforms.ToTensor()
# Hàm chuyển PIL image sang tensor
img_t = to_tensor(img)
print(img_t.shape) # torch.Size([3, 32, 32])

Mình có thể transform trong lớp dataset khi load dữ liệu cifar10

tensor_cifar10 = datasets.CIFAR10(data_path, train=True, download=False,
 transform=transforms.ToTensor())
img_t, _ = tensor_cifar10[99]
print(type(img_t)) # torch.Tensor

Ảnh ở dạng PIL image thì các pixel có giá trị từ 0-255, tuy nhiên khi chuyển về dạng tensor (ToTensor) thì dữ liệu pixel được scale về khoảng 0.0-1.0

print(img_t.min(), img_t.max()) # tensor(0.) tensor(1.)

Normalization

Việc normalization dữ liệu giúp các pixel có cùng scale cũng như distribution, do đó mình có thể dùng thuật toán gradient descent cho các tham số với cùng một learning rate. Thông thường mình sẽ normalize để mỗi channel về standard normal distribution (N(0, 1), normal distribution với 0 mean và 1 standard deviation)

\displaystyle v[c] = \frac{v[c] - mean[c]}{std[c]}

Mình có thể tính mean và std theo từng channel của dữ liệu.

imgs.view(3, -1).mean(dim=1) # tensor([0.4915, 0.4823, 0.4468])
imgs.view(3, -1).std(dim=1) # tensor([0.2470, 0.2435, 0.2616])

Sau đó mình sẽ dùng transforms.Normalize để normalize dữ liệu.

# Tham số đầu là mean, tham số sau là std
transforms.Normalize((0.4915, 0.4823, 0.4468), (0.2470, 0.2435, 0.2616))

Compose

Ngoài ra Pytorch transforms còn hỗ trợ rất nhiều phép biển đổi khác như: RandomCrop, RandomRotation, RandomAffine (để shear), RandomHorizontalFlip,… Chi tiết mọi người xem ở đây.

Để thực hiện nhiều phép biến đổi trên dữ liệu đầu vào, transforms hỗ trợ hàm compose để gộp các transforms lại.

transform=transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.4915, 0.4823, 0.4468),
 (0.2470, 0.2435, 0.2616))
])

Khi load Dataset mình sẽ dùng transform cho tất cả các ảnh

tensor_cifar10 = datasets.CIFAR10(data_path, train=True, download=False,
 transform=transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.4915, 0.4823, 0.4468),
 (0.2470, 0.2435, 0.2616))
]))

Như vậy là mình đã có Dataset và thực hiện transform các ảnh đưa về dạng tensor cũng như normalize các ảnh. Giờ mình cần lấy các ảnh cho quá trình traning.

DataLoader

Khi cho dữ liệu vào model để học thì thông thường sẽ cho dữ liệu theo từng batch một, DataLoader sẽ giúp chúng ta lấy dữ liệu theo từng batch, shuffle dữ liệu cũng như load dữ liệu song song với nhiều multiprocessing workers.

train_loader = torch.utils.data.DataLoader(cifar10, batch_size=64,
                                           shuffle=True)

Tham số mình sẽ truyền vào Dataset (cifar10), batch_size bằng 64 và để shuffle bằng True (shuffle data sau mỗi epoch).

Train CIFAR10 classifier

Model

Mình sẽ xây dựng một mạng CNN đơn giản.

# model
class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(16, 8, kernel_size=3, padding=1)
        self.fc1 = nn.Linear(8 * 8 * 8, 32)
        # bài toán phân loại 10 lớp nên output ra 10 nodes
        self.fc2 = nn.Linear(32, 10)
        
    def forward(self, x):
        out = F.max_pool2d(torch.tanh(self.conv1(x)), 2)
        out = F.max_pool2d(torch.tanh(self.conv2(out)), 2)
        # flatten về dạng vector để cho vào neural network
        out = out.view(-1, 8 * 8 * 8)
        out = torch.tanh(self.fc1(out))
        out = self.fc2(out)
        return out

Loss

Loss mình sẽ dùng categorical crossentropy loss

loss_fn = nn.CrossEntropyLoss()

Lưu ý: Hàm CrossEntropyLoss của Pytorch đã bao gồm cả activation softmax ở lớp output và categorial crossentropy loss thế nên khi dựng model không cần dùng activation softmax ở output layer.

Train

def training_loop(n_epochs, optimizer, model, loss_fn, train_loader, val_loader):
    for epoch in range(1, n_epochs + 1):
        loss_train = 0.0
        for imgs, labels in train_loader:

            outputs = model(imgs)
            loss = loss_fn(outputs, labels)
            optimizer.zero_grad()     
            loss.backward() 
            optimizer.step()
            loss_train += loss.item()
        correct = 0
        # tính độ chính xác trên tập validation
        with torch.no_grad():
            for data in val_loader:
                images, labels = data
                outputs = model(images)
                _, predicted = torch.max(outputs, 1)
                c = (predicted == labels).squeeze()
                correct += c.sum()
        if epoch == 1 or epoch % 1 == 0:
            print('Epoch {}, Training loss {}, Val accuracy {}'.format(
                epoch,
                loss_train / len(train_loader),
                correct / len(cifar10_val)))

Code mọi người xem ở đây.

Bài toán nhận diện biển số xe Việt Nam là một bài toán không còn mới, đã được phát triển dựa trên các phương pháp xử lý ảnh truyền thống và cả những kỹ thuật mới sử dụng Deep Learning. Trong bài toán này mình chỉ phát triển bài toán phát hiện biển số (một phần trong bài toán nhận diện biển số) dựa trên thuật toán YOLO-Tinyv4 với mục đích:

  • Hướng dẫn chuẩn bị dữ liệu cho bài toán Object Detection.
  • Hướng dẫn huấn luyện YOLO-TinyV4 dùng darknet trên Google Colab.


Thi Toeic là vấn đề chung và nhức nhối của sinh viên. Thậm chí nhiều bạn học xong hết rồi nhưng vì vướng tiếng anh nên vẫn ra trường. Mục đích của bài này là ứng dụng Natural Language Processing (NLP) để giải quyết câu hỏi trong phần 5 của bài thi Toeic. Trong bài thi Toeic thì phần 5 chiếm đến 40/100 câu của bài đọc.

Ví dụ câu hỏi phần 5 của bài thi Toeic


Ở những bài trước mình đã giới thiệu về mô hình Recurrent Neural Network (RNN) cho bài toán dữ liệu dạng chuỗi. Tuy nhiên RNN chỉ có short term memory và bị vanishing gradient. Tiếp đó mình đã giới thiệu về Long short term memory (LSTM) có cả short term memory và long term memory, hơn thế nữa tránh được vaninishing gradient. Bài này mình sẽ viết về ứng dụng của LSTM cho ứng dụng image captioning.


RNN có thể mang thông tin từ các layer trước đến các layer sau, nhưng thực tế là thông tin chỉ mang được qua một số lượng state nhất định, sau đó thì sẽ bị vanishing gradient, hay nói cách khác là model chỉ học được từ các state gần nó => short term memory.
Cùng thử lấy ví dụ về short-term memory nhé. Bài toán là dự đoán từ tiếp theo trong đoạn văn. Đoạn đầu tiên “Mặt trời mọc ở hướng …”, ta có thể chỉ sử dụng các từ trước trong câu để đoán là đông. Tuy nhiên, với đoạn, “Tôi là người Việt Nam. Tôi đang sống ở nước ngoài. Tôi có thể nói trôi chảy tiếng …” thì rõ ràng là chỉ sử dụng từ trong câu đấy hoặc câu trước là không thể dự đoán được từ cần điền là Việt. Ta cần các thông tin từ state ở trước đó rất xa => cần long term memory điều mà RNN không làm được => Cần một mô hình mới để giải quyết vấn đề này => Long short term memory (LSTM) ra đời.


Deep learning có 2 mô hình lớn là Convolutional Neural Network (CNN) cho bài toán có input là ảnh và Recurrent neural network (RNN) cho bài toán dữ liệu dạng chuỗi (sequence). Mình đã giới thiệu về Convolutional Neural Network (CNN) và các ứng dụng của deep learning trong computer vision bao gồm: classification, object detection, segmentation. Có thể nói là tương đối đầy đủ các dạng bài toán liên quan đến CNN. Bài này mình sẽ giới thiệu về RNN.


Bài trước mình đã giới thiệu về object detection, đi tìm các bounding box quanh các đối tượng trong ảnh và sau đó phân loại các bounding box. Tuy nhiên là các bounding box thì không biểu thị được đúng hình dạng của đối tượng và có nhiều nhiễu ở trong bounding box đấy ví dụ như trong bounding box màu đỏ có cả một phần của cây thông cũng như cái gối. => Image segmentation ra đời để chia ảnh thành nhiều vùng khác nhau hay tìm được đúng hình dạng của các đối tượng.


Bài này mình tổng hợp một số kĩ thuật để train model tốt hơn, cũng như một số khái niệm bạn sẽ gặp khi làm việc với deep learning. Đầu tiên mình nói về tầm quan trọng của vectorization, tiếp mình sẽ nói về kĩ thuật mini-batch gradient descent với lượng dữ liệu lớn. Sau đó mình nói về bias, variance, cách đánh giá bias-variance trong model và một số biện pháp để giải quyết vấn đề high bias, high variance. Mình có giải thích về kĩ thuật dropout để tránh overfitting. Phần cuối mình nói về vanishing và exploding gradient, cũng như giới thiệu một số hàm activation function phổ biến và cách chọn hàm activation.


Deep Learning cơ bản ©2024. All Rights Reserved.
Powered by WordPress. Theme by Phoenix Web Solutions