- vừa được xem lúc

Paper reading | ACTION-Net: Multipath Excitation for Action Recognition

0 0 10

Người đăng: Viblo AI

Theo Viblo Asia

Đóng góp của bài báo

Trong các bài toán liên quan tới video, thông tin cần nắm bắt không chỉ là thông tin về mặt không gian (spatial information) giống như hình ảnh mà còn là thông tin về thời gian (temporal information) và sự phụ thuộc của chúng. Ví dụ, cho 2 video thực hiện hành động như sau, video 1 là video mà một người xoay nắm đấm cửa theo chiều kim đồng hồ, video 2 là video mà một người xoay nắm đấm cửa ngược chiều kim đồng hồ. Về mặt không gian, 2 video mang đặc trưng tương tự nhau, nhưng về mặt thời gian thì hoàn toàn ngược lại. Do đó, để thiết kế một mô hình hiệu quả cho việc training video thì bắt buộc cần phải mô hình phải biểu diễn được mối quan hệ của 2 loại thông tin này.

image.png

Các mô hình 3D CNN hiện tại mặc dù mô hình hóa được thông tin spatio-temporal nhưng vẫn mang một số nhược điểm sau:

  • Thông tin spatio-temporal được capture không đầy đủ.
  • Bổ sung thêm luồng optical flow làm tăng đáng kể hiệu suất nhưng tài nguyên tính toán sử dụng là lớn, tốc độ inference chậm nên sẽ ảnh hưởng khi sử dụng vào các ứng dụng thực tế.

Bài báo đề xuất một module giúp training video hiệu quả có tên là ACTION (spAtio-temporal, Channel and moTion excitatION) xử lý nhiều loại thông tin trong một mạng duy nhất. ACTION thực hiện mô hình hóa chuyển động dựa trên feature level thay vì tạo một loại input khác (ví dụ như optical flow) cho model. ACTION thực hiện trích xuất hiệu quả các thông tin: spatio-temporal pattern, channel-wise feature và thông tin chuyển động (motion information) dùng cho việc nhận dạng hành động (action recognition).

Phương pháp

Mô hình ACTION gồm có 3 module:

  • Spatio-Temporal Excitation (STE)
  • Channel Excitation (CE)
  • Motion Excitation (ME)

Spatio-Temporal Excitation (STE)

Module STE được thiết kế để capture thông tin spatio-temporal sử dụng 3D convolution. Sơ đồ của module được thể hiện trong hình dưới đây.

image.png

Cụ thể, cho đầu vào là XRN×T×C×H×W\mathbf{X} \in \mathbb{R}^{N \times T \times C \times H \times W}, trong đó:

  • NN là batch size
  • TT là số frame trong một segment
  • CC là channel
  • HH là height
  • WW là width

Đầu tiên, ta sẽ thực hiện tính trung bình input tensor theo chiều channel (đi qua channel pooling) để nhận một global spatio-temporal tensor FRN×T×1×H×W\mathbf{F} \in \mathbb{R}^{N \times T \times 1 \times H \times W}. Sau đó ta sẽ reshape F\mathbf{F} thành FRN×1×T×H×W\mathbf{F^*} \in \mathbb{R}^{N \times 1 \times T \times H \times W} để đưa vào layer 3D convolutional K\mathbf{K} với kernel size là 3×3×33 × 3 × 3, được công thức hóa như sau:

image.png

Sau đó, ta sẽ reshape Fo\mathbf{F^*_o} quay trở lại thành shape cũ FoRN×T×1×H×W\mathbf{F_o} \in \mathbb{R}^{N \times T \times 1 \times H \times W} và đưa vào 1 hàm sigmoid để thu được mask MRN×T×1×H×W\mathbf{M} \in \mathbb{R}^{N \times T \times 1 \times H \times W} được biểu diễn như sau:

image.png

Output cuối cùng thu được như sau:

image.png

So với 3D convolution thông thường, STE thể hiện sự hiệu quả tính toán hơn do feature F\mathbf{F^*} được tính trung bình theo chiều channel.

Channel Excitation (CE)

Module CE được thiết kế như hình dưới.

image.png

Cụ thể, cho input XRN×T×C×H×W\mathbf{X} \in \mathbb{R}^{N \times T \times C \times H \times W} ta sẽ cho qua layer spatial average pooling như sau:

image.png

trong đó FRN×T×C×1×1\mathbf{F} \in \mathbb{R}^{N \times T \times C \times 1 \times 1}. Ta thực hiện giảm số channel của F\mathbf{F} với một tỉ lệ rr như sau:

image.png

trong đó K1\mathbf{K_1} là layer 1×11 \times 1 2D convolution và FrRN×T×Cr×1×1\mathbf{F}_r \in \mathbb{R}^{N \times T \times \frac{C}{r} \times 1 \times 1}. Sau đó ta sẽ reshape Fr\mathbf{F}_r thành FrRN×Cr×T×1×1\mathbf{F}_r^* \in \mathbb{R}^{N \times \frac{C}{r} \times T \times 1 \times 1}. Sau đó ta thực hiện:

image.png

trong đó FtempRN×Cr×T×1×1\mathbf{F}_{t e m p}^* \in \mathbb{R}^{N \times \frac{C}{r} \times T \times 1 \times 1}. K2\mathbf{K}_2 là layer convolution với kernel size là 3.

Sau đó Ftemp\mathbf{F}_{t e m p}^* được reshape thành FtempRN×T×Cr×1×1\mathbf{F}_{t e m p} \in \mathbb{R}^{N \times T \times \frac{C}{r} \times 1 \times 1} và được đi qua 1×11 \times 1 2D convolutional layer K3\mathbf{K}_3. Cuối cùng output sẽ được đưa vào một hàm sigmoid. Công thức được mô tả như sau:

image.png

trong đó FoRN×T×C×1×1\mathbf{F}_{o} \in \mathbb{R}^{N \times T \times C \times 1 \times 1}MRN×T×C×1×1\mathbf{M} \in \mathbb{R}^{N \times T \times C \times 1 \times 1}.

Output cuối cùng được tính giống như output cuối cùng của module CE nhưng sử dụng mask M\mathbf{M} khác 😄

Motion Excitation (ME)

Module ME được mô tả trong hình dưới:

image.png

Thông tin chuyển động (motion information) được mô hình bởi các frame kề nhau (như trong hình trên). Ta thực hiện các chiến lược squeeze và unsqueeze như module CE. Cho feature FrRN×T×Cr×H×W\mathbf{F}_r \in \mathbb{R}^{N \times T \times \frac{C}{r} \times H \times W} được tạo sau khi thực hiện squeeze, motion feature được biểu diễn như sau

image.png

trong đó K\mathbf{K}3×33 \times 3 2D convolutional layer và FmRN×1×Cr×H×W\mathbf{F}_m \in \mathbb{R}^{N \times 1 \times \frac{C}{r} \times H \times W}.

Motion feature sau đó được concat với nhau theo chiều temporal và được pad 0 với phần tử cuối như sau: FM=[Fm(1),,Fm(t1),0],FMRN×T×Cr×H×W\mathbf{F}_M=[\mathbf{F}_m(1), \ldots, \mathbf{F}_m(t- 1),0], \mathbf{F}_M \in \mathbb{R}^{N \times T \times \frac{C}{r} \times H \times W}. FM\mathbf{F}_M được đưa qua spatial average pooling. Feature output FoRN×T×C×1×1\mathbf{F}_{o} \in \mathbb{R}^{N \times T \times C \times 1 \times 1} và mask MRN×T×C×1×1\mathbf{M} \in \mathbb{R}^{N \times T \times C \times 1 \times 1} sẽ được tính giống như trong module CE.

ACTION-Net

Tổng quan của ACTION module được thể hiện trong hình dưới:

image.png

Nhận thấy rằng ACTION module nhận đầu vào là các output feature của 3 module ta đã tìm hiểu ở trên và thực hiện phép cộng element-wise. Bằng cách này, output của ACTION module sẽ có thông tin spatio-temporal, sự phụ thuộc giữa các channel và motion. Module ACTION trong hình trên được tích hợp vào kiến trúc ResNet-50.

Coding

Ta sẽ cài đặt module ACTION như sau:

import torch
import torch.nn as nn
import torch.nn.functional as F
import math
import pdb class Action(nn.Module): def __init__(self, net, n_segment=3, shift_div=8): super(Action, self).__init__() self.net = net self.n_segment = n_segment self.in_channels = self.net.in_channels self.out_channels = self.net.out_channels self.kernel_size = self.net.kernel_size self.stride = self.net.stride self.padding = self.net.padding self.reduced_channels = self.in_channels//16 self.avg_pool = nn.AdaptiveAvgPool2d(1) self.relu = nn.ReLU(inplace=True) self.sigmoid = nn.Sigmoid() self.fold = self.in_channels // shift_div # shifting self.action_shift = nn.Conv1d( self.in_channels, self.in_channels, kernel_size=3, padding=1, groups=self.in_channels, bias=False) self.action_shift.weight.requires_grad = True self.action_shift.weight.data.zero_() self.action_shift.weight.data[:self.fold, 0, 2] = 1 # shift left self.action_shift.weight.data[self.fold: 2 * self.fold, 0, 0] = 1 # shift right  if 2*self.fold < self.in_channels: self.action_shift.weight.data[2 * self.fold:, 0, 1] = 1 # fixed # # spatial temporal excitation self.action_p1_conv1 = nn.Conv3d(1, 1, kernel_size=(3, 3, 3), stride=(1, 1 ,1), bias=False, padding=(1, 1, 1)) # # channel excitation self.action_p2_squeeze = nn.Conv2d(self.in_channels, self.reduced_channels, kernel_size=(1, 1), stride=(1 ,1), bias=False, padding=(0, 0)) self.action_p2_conv1 = nn.Conv1d(self.reduced_channels, self.reduced_channels, kernel_size=3, stride=1, bias=False, padding=1, groups=1) self.action_p2_expand = nn.Conv2d(self.reduced_channels, self.in_channels, kernel_size=(1, 1), stride=(1 ,1), bias=False, padding=(0, 0)) # motion excitation self.pad = (0,0,0,0,0,0,0,1) self.action_p3_squeeze = nn.Conv2d(self.in_channels, self.reduced_channels, kernel_size=(1, 1), stride=(1 ,1), bias=False, padding=(0, 0)) self.action_p3_bn1 = nn.BatchNorm2d(self.reduced_channels) self.action_p3_conv1 = nn.Conv2d(self.reduced_channels, self.reduced_channels, kernel_size=(3, 3), stride=(1 ,1), bias=False, padding=(1, 1), groups=self.reduced_channels) self.action_p3_expand = nn.Conv2d(self.reduced_channels, self.in_channels, kernel_size=(1, 1), stride=(1 ,1), bias=False, padding=(0, 0)) print('=> Using ACTION') def forward(self, x): nt, c, h, w = x.size() n_batch = nt // self.n_segment x_shift = x.view(n_batch, self.n_segment, c, h, w) x_shift = x_shift.permute([0, 3, 4, 2, 1]) # (n_batch, h, w, c, n_segment) x_shift = x_shift.contiguous().view(n_batch*h*w, c, self.n_segment) x_shift = self.action_shift(x_shift) # (n_batch*h*w, c, n_segment) x_shift = x_shift.view(n_batch, h, w, c, self.n_segment) x_shift = x_shift.permute([0, 4, 3, 1, 2]) # (n_batch, n_segment, c, h, w) x_shift = x_shift.contiguous().view(nt, c, h, w) # 3D convolution: c*T*h*w, spatial temporal excitation nt, c, h, w = x_shift.size() x_p1 = x_shift.view(n_batch, self.n_segment, c, h, w).transpose(2,1).contiguous() x_p1 = x_p1.mean(1, keepdim=True) x_p1 = self.action_p1_conv1(x_p1) x_p1 = x_p1.transpose(2,1).contiguous().view(nt, 1, h, w) x_p1 = self.sigmoid(x_p1) x_p1 = x_shift * x_p1 + x_shift # 2D convolution: c*T*1*1, channel excitation x_p2 = self.avg_pool(x_shift) x_p2 = self.action_p2_squeeze(x_p2) nt, c, h, w = x_p2.size() x_p2 = x_p2.view(n_batch, self.n_segment, c, 1, 1).squeeze(-1).squeeze(-1).transpose(2,1).contiguous() x_p2 = self.action_p2_conv1(x_p2) x_p2 = self.relu(x_p2) x_p2 = x_p2.transpose(2,1).contiguous().view(-1, c, 1, 1) x_p2 = self.action_p2_expand(x_p2) x_p2 = self.sigmoid(x_p2) x_p2 = x_shift * x_p2 + x_shift # # 2D convolution: motion excitation x3 = self.action_p3_squeeze(x_shift) x3 = self.action_p3_bn1(x3) nt, c, h, w = x3.size() x3_plus0, _ = x3.view(n_batch, self.n_segment, c, h, w).split([self.n_segment-1, 1], dim=1) x3_plus1 = self.action_p3_conv1(x3) _ , x3_plus1 = x3_plus1.view(n_batch, self.n_segment, c, h, w).split([1, self.n_segment-1], dim=1) x_p3 = x3_plus1 - x3_plus0 x_p3 = F.pad(x_p3, self.pad, mode="constant", value=0) x_p3 = self.avg_pool(x_p3.view(nt, c, h, w)) x_p3 = self.action_p3_expand(x_p3) x_p3 = self.sigmoid(x_p3) x_p3 = x_shift * x_p3 + x_shift out = self.net(x_p1 + x_p2 + x_p3) return out

Thực nghiệm

ACTION-Net luôn vượt trội so với các model 2D trên ba bộ dữ liệu đại diện. Tất cả các phương pháp đều sử dụng ResNet-50 là backbone và 8 frame input để so sánh được công bằng hơn.

image.png

So sánh các model SOTA trên tập dữ liệu Something-Something V2.

image.png

Độ chính xác và độ phức tạp của mô hình trên bộ dữ liệu EgoGesture. Ba module STE, CE, ME được so sánh với TSM và TSN. Tất cả các phương pháp đều sử dụng ResNet-50 làm backbone và input gồm 8 frame để đảm bảo sự so sánh công bằng. So sánh FLOPs/ΔFLOPs/Param được thể hiện trong bảng sau:

image.png

Nghiên cứu về việc sử dụng ACTION trong các block của Resnet-50. image.png

ACTION thể hiện khả năng tổng quát hóa tốt với các backbone và dataset khác nhau.

image.png

Tài liệu tham khảo

[1] ACTION-Net: Multipath Excitation for Action Recognition

[2] https://github.com/V-Sense/ACTION-Net

[3] Temporal Segment Networks: Towards Good Practices for Deep Action Recognition

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tấn công và phòng thủ bậc nhất cực mạnh cho các mô hình học máy

tấn công bậc nhất cực mạnh = universal first-order adversary. Update: Bleeding edge của CleverHans đã lên từ 3.1.0 đến 4.

0 0 42

- vừa được xem lúc

[Deep Learning] Key Information Extraction from document using Graph Convolution Network - Bài toán trích rút thông tin từ hóa đơn với Graph Convolution Network

Các nội dung sẽ được đề cập trong bài blog lần này. . Tổng quan về GNN, GCN. Bài toán Key Information Extraction, trích rút thông tin trong văn bản từ ảnh.

0 0 219

- vừa được xem lúc

Trích xuất thông tin bảng biểu cực đơn giản với OpenCV

Trong thời điểm nhà nước đang thúc đẩy mạnh mẽ quá trình chuyển đổi số như hiện nay, Document Understanding nói chung cũng như Table Extraction nói riêng đang trở thành một trong những lĩnh vực được quan tâm phát triển và chú trọng hàng đầu. Vậy Table Extraction là gì? Document Understanding là cái

0 0 230

- vừa được xem lúc

Con đường AI của tôi

Gần đây, khá nhiều bạn nhắn tin hỏi mình những câu hỏi đại loại như: có nên học AI, bắt đầu học AI như nào, làm sao tự học cho đúng, cho nhanh, học không bị nản, lộ trình học AI như nào... Sau nhiều lần trả lời, mình nghĩ rằng nên viết hẳn một bài để trả lời chi tiết hơn, cũng như để các bạn sau này

0 0 157

- vừa được xem lúc

[B5'] Smooth Adversarial Training

Đây là một bài trong series Báo khoa học trong vòng 5 phút. Được viết bởi Xie et. al, John Hopkins University, trong khi đang intern tại Google. Hiện vẫn là preprint do bị reject tại ICLR 2021.

0 0 45

- vừa được xem lúc

Deep Learning với Java - Tại sao không?

Muốn tìm hiểu về Machine Learning / Deep Learning nhưng với background là Java thì sẽ như thế nào và bắt đầu từ đâu? Để tìm được câu trả lời, hãy đọc bài viết này - có thể kỹ năng Java vốn có sẽ giúp bạn có những chuyến phiêu lưu thú vị. DJL là tên viết tắt của Deep Java Library - một thư viện mã ng

0 0 139