Object detection : YOLO

yolo
object-detection

#1

Bài này lâu rồi nhưng YOLO(v1,v2,v3) là mô hình object detection khá phổ biến, mình copy lại trong này có thể có người cần.

1. Giới thiệu

Object detection là một bài toán quan trọng trong Computer Vision. Trong post này tôi sẽ giới thiệu YOLO, một trong những phương pháp tốt nhất và nhanh nhất (real-time) hiện nay. Tôi viết 2 bài về YOLO, bài thứ nhất (bài này) sẽ giúp các bạn hiểu về nguyên lý hoạt động của YOLO, bài thứ 2 sẽ giới thiệu cách huấn luyện mô hình YOLO cho dữ liệu riêng.

Bài báo gốc về YOLO có thể tìm ở đây version 1, version 2, version 3.

Code source, hướng dẫn chạy test và huấn luyện với dữ liệu ảnh Pascal Voc ở đây here.

2. Dependencies

Để đọc bài này, cần kiến thức cơ bản về neural network

3. Nhận dạng

YOLO là một deep net kết hợp giữa convolutional layers và connected layers :

YOLO phân chia hình ảnh thành một mạng lưới 7x7 ô (grid_size=7x7):

yolo_01

YOLO sẽ dự đoán xem trong mỗi ô xem liệu có object mà điểm trung tâm rơi vào ô đó. Và dự đoán điểm trung tâm, kích thước của object đó và xác xuất object đó là object nào trong các objects cần xác định.

Mỗi ô này có trách nhiệm dự đoán 2 hộp (boxes_number=2) bao quanh. Mỗi 1 hộp mô tả hình chữ nhật bao quanh một object.

Giả sử ta đang huấn luyên YOLO nhận dạng 20_objects khác nhau. Sau khi qua các layers, image input sẽ được biến đổi thành 1 tensor kích thước 7x7x30.

Ta có thể hiểu là mỗi ô sẽ có 30 tham số , tham số thứ nhất là xác xuất ô có chứa 1 object, tham số 2,3,4,5 lấn lượt là x_center, y_center, width, height của box 1. Tương tự tham số 6,7,8,9,10 là của box 2. Tham số thứ 11 là xác xuất object trong ô là object1 (trong 20_objects cần nhận dạng). Tương tự tham số 12 là xác xuất object trong ô là object2 … cho đên tham số 30 là xác xuất object trong ô là object20.

Ta có thể hiểu đơn giản như sau:

  1. Image input được resize thành 1 image 448x448x3 (image_dimension = 448x448 với số channels = 3, YOLO sử dụng hệ màu HSV)
  2. Qua các layers, biến đổi image 448x448x3 thành 1 grid có kích thước 7x7 với số tham số cho mỗi ô trong grid là 30 (30 = 5xboxes_number + number_of_objects)
  3. Neural net có nhiệm vụ huấn luyện các trọng số của các layers để có được mô hình tốt cuối cùng.
  4. Để nhận dạng một image mới, các bước 1,2 sẽ được thực hiện. Sau đó dựa vào các tham số trong grid 7x7x30 ta sẽ xác định được các box chứa object với xác xuất cao. (các box đè lên nhau sẽ được loại bằng phương pháp NMS, chỉ giữ lại box có xác xuất cao nhất)

Có thể xem video sau của các bạn gấu Nga để hiểu rõ hơn (chỉ có phần nhận dạng, ko có phần huấn luyện) https://youtu.be/L0tzmv--CGY&usg=ALkJrhgvWHttKiRTLXiQDrI_a3f0tpJ0oA

4. Huấn luyện

Để hiểu cách neural net huấn luyện các trọng số thì điều quan trọng nhất là phải hiểu hàm mất mát (loss function)

4.1 Các khái niệm

  • 1^{obj}_{i\ j} = 1 nếu box thứ j của ô thứ i có chứa object. Vì huấn luyện cần các image với ground-truth (vị trí của các objects) nên YOLO biết điểm trung tâm của từng object rơi vào ô nào trong grid 7x7.

  • 1^{noobj}_{i\ j} = 1 nếu box thứ j của ô thứ i không chứa object.

  • 1^{obj}_{i} = 1 nếu ô thứ i có chứa object

  • S^2=7\times7, B = boxes_number = số box mỗi ô sẽ dự đoán, được cố định = 2

  • \lambda_{coord} = 5.0, \lambda_{noobj} = 0.5

  • classes : các lớp đối tượng cần được nhận dạng, ví dụ chó, mèo, oto…

4.2 Hàm mất mát

  • (1) Tính toán loss (tổn thất) của điểm trung tâm (x, y) cho hộp j của ô i nơi object tồn tại. Chú ý là \hat{x}_i là tham số của tensor output của neural net còn x_i là của ground-truth. Tương tự cho tất cả các biến khác.

  • (2) Tính toán tổn thất width và height của hộp j của ô i nơi object tồn tại.

  • (3) Đối với các hộp j của ô i nơi object tồn tại, tính tổn thất của xác xuất object tồn tại. Chú ý C_i luôn = 1.

  • (4) Đối với hộp j của ô i và nơi không có object, tính tổn thất của xác xuất này. Chú ý C_i luôn = 0.

  • (5) Tính tổn thất của xác suất có điều kiện cho ô i nơi object tồn tại. Chú ý p_i(c) luôn = 1 nếu đúng lớp c với ground-truth, ngược lại thì p_i(c) luôn = 0.

  • \lambda_{coord} = 5.0 thông số cân bằng để cân bằng tổn thất tọa độ (x, y, w, h) với các tổn thất khác.

  • \lambda_{noobj} = 0.5 thông số cân bằng để cân bằng giữa hộp có và không có object. (Nói chung, đa số các ô trong image không có object, rất ít ô có object)

4.3 Huấn luyện

Đây là kiến thức cơ bản của neural net. Neural net sẽ tính toán từng ảnh (có thể lặp lại 1 ảnh) để tối ưu hàm mất mát. Việc tối ưu này sẽ giúp neural net tìm ra 1 bộ trọng số tốt nhất để biểu diễn dữ liệu của bạn và giúp nhận dạng các ảnh mới.

Hiểu hàm mất mát giúp bạn hiểu cơ chế hoạt động của từng neural net và cách huấn luyện chúng và giúp bạn dễ dàng hiểu code source, và trải nghiệm với nó.

5. YOLO version 2 (YOLOv2)

5.1 Thay đổi quan trọng : sử dụng Anchor boxes

Anchor boxes là các box được định nghĩa trước về hình dạng (width, height). Kĩ thuật này được giới thiệu trong Faster RCNN (paper)
YOLO dự đoán trực tiếp các thông số của hộp chứa object (hình chữ nhật, bounding box) dựa vào connected layers. YOLOv2 loại bỏ connected layers và các convolutional layers sẽ dự đoán các tham số của hộp chứa object dựa vao anchor boxes rồi tinh chỉnh x,y,width,height cũng như các xác xuất \hat{C}_i\hat{p}_i(c))
Để có anchor boxes, YOLOv2 sử dụng k-means clustering trên các ground-truth boxes (thông số các objects trong các ảnh dùng để huấn luyện).

5.2. Các thay đổi khác cần lưu ý

  • Sử dụng Batch normalization
  • grid_size=13x13
  • box_number=5
  • image_dimension = 416x416

6. YOLO version 3 (YOLOv3)

Version 3 thêm 1 số ý tưởng từ các papers khác nhưng phần loss và mô hình chung ko thay đổi nhiều. Chi tiết xem ở đây : version 3.

7. Code

Các bạn có thể vọc code để hiểu hơn hoặc thay đổi phục vụ cho bài toán của mình. Ví dụ mình đã thực hiện 1 phương pháp semi-supervised learning dựa vào YOLO. Có thể bắt đầu với 2 files quan trọng sau:

  • examples/detector.c: code cho detection gồm train, test, valid
  • src/region_layer.c : loss function ở trong đây

Có thể so sánh sự thay đổi các version dựa vào file config:
cfg YOLO vs. cfg YOLOv2 vs. cfg YOLOv3


#2

bài anh viết hay quá , anh có thể tiếp một bài chuyên sâu hơn về YOLO được không ạ ? Cảm ơn anh !


#3

Em cũng từng dùng YOLOV3. Khá hay, pre-train model sử dụng với độ chính xác cao. Nhưng mã nguồn này chỉ cung cấp object detection. Nêu muốn tracking thì phải áp dụng thêm giải thuật. Em sử dụng IUO để tracking đối tượng qua từng khung hình của video. Anh/Chị nào có giải pháp nào hay hơn không ạ, em đang khá tắc với vấn đề này :< Ngoài ra thì Python wrapper của YOLOV3 trên windown sẽ bị nghẽn cổ chai À bản YOLOv3 trên win là bản port từ linux sang thui


#4

Anh đang bận nên chưa viết nốt mấy bài định viết cho forum… Về tracking thì thuật toán này khá hay, có code . https://arxiv.org/abs/1602.00763

Mà bây giờ anh khuyến khích mọi người dùng segmentation, nếu đủ data thì kết quả đẹp hơn detection :slight_smile:


#5

bài viết rất hay :hugs: !


#8

anh ơi viết bài huấn luyện YOLOv3 đi anh :smiley:


#9

Cảm ơn bạn vì bài viết có tâm. Cho mình hỏi xíu về “box_number”, ở v1 nó là 2, ở v2 nó là 5. Tức là ở v1, mỗi grid cell có khả năng dectect tối đa 2 objects, còn v2 là 5 objects đúng không bạn? Và nếu như mình muốn dectect mỗi grid cell tối đa 10 object thì mình thể tự động modify “box_number” để làm theo ý mình phải không bạn? Cám ơn bạn.


#10

@Phan_Huu_Tho 2 box_number nghĩa là đưa ra 1 dự đoán cho mỗi anchor. Ở yolo v2 nó là 5. Nó là các pirror box tương ứng ở SSD.


#11


Tương úng khi dự đoán được tâm object sẽ có 2 hộp bao quanh đối tượng với kích thước cho trước như thế này.


#12

Cám ơn bạn đã trả lời. Tức là ở dự đoán được tâm object sẽ có 2 hộp bao quanh với YOLOv1 và 5 hộp bao quanh với YOLOv2 đúng hong bạn?


#13

Tức là tại mỗi grid cell sẽ đưa ra dự đoán về tâm, chiều cao, độ dài, … Cho mỗi hộp hộp( 2 vs yolov1)


#14

Anh ơi theo origin paper của YOLO9000 thì cái dimension không phải 416x416 mà là trong quá trình train every 10 batches nó sẽ lấy random dimension trong khoảng {320; 352;…; 608}


#15

cho e hỏi ý nghĩa của số 1260/1261 và 1.74s/it là gì thế khi chạy MOVIEPY tạo ra 1 video


#16

Anh có thể giải thích cho em là ở lớp cuối làm thế nào để connect tensor 114096 với tensor 7730 không ạ


#17

Theo như clip giải thích của các anh Nga ngố mà anh Van đã post ở trên

tensor 4096x1 được kết nối với 1 tensor 1470x1 sau đó reshape tensor 1470x1 thành tensor 7x7x30


#18

có bạn nào còn video của anh Nga ngố không ạ cho mình xin với. Link trên bị die rồi


#19

Bạn có thể nói rõ làm sao để biết được box thứ j của ô thứ i là có chứa object hay không ? Giả sử mạng cho ra ở ô thứ i 2 box có object với confidence là 0.9 và 0.8. Nhưng thực tế là chỉ có 1 object ở ô thứ i. Vậy confidence loss là (0.9-1)^2 + (0.8-0)^2 hay (0.9-0)^2 + (0.8-1)^2?