개인 생각
Dense한 feature라는 것이 두가지 의미를 가지고 있다고 이해했다.
1. Feature들이 오밀조밀 모여있다는 것을 의미
2. Sparse voxel feature에 공간적인 특성을 부여했다는 의미
저자는 2번째 의미에서의 dense한 feature를 피했다는 것을 강조한다.
- 이를 확신하는 이유는 backbone adaptation 부분에서 설명할 예정이다.
Sparse voxel feature를 input부터 output까지 유지했다는 점이 VoxelNeXt의 특징이며, 진짜 sparse함을 극한까지 활용했다는 것을 알 수 있다.
추가로 언급되는 query voxel은 어떻게 찾아야하는지, 코드 상에서 어떻게 구현됐는지 저자가 밝히지 않았다.
그래서 issue를 남겨놨으니, 혹시나 query voxel에 대해 궁금한 사람들은 들어가보자.
이 논문에 대한 정리를 찾는 사람들이 내 포스팅을 찾을때쯤에는 답글이 달려있길 바란다.
Dense voxel feature
먼저 내가 해석한 dense voxel feature에 대해 설명하고 넘어가려한다.
Sparse voxel feature는 값의 나열일뿐, 공간적인 특성을 가지지 않는다.
물론, 공간적인 정보는 가지고 있지만 이것이 tensor의 형태로 반영되어있지 않다.
Sparse voxel feature와 dense voxel feature간의 구성요소를 통해 차이점을 소개해보자면 다음과 같다.
Sparse voxel feature
- Feature list
shape : (90000, 5)
- Feature indices
shape : (90000, 4)
Dense voxel feature
- Feature
shape : (40, 1440, 1440)
Dense voxel feature는 sparse voxel feature의 feature들을 해당하는 위치(indices)에 넣어놓은 것이다.
즉, 공간적인 특성을 부여한것과 다르지 않다는 것을 알 수 있다.
다만 공간적인 특성을 부여하면서, 차지하는 메모리가 미친듯이 불어나기때문에 무턱대로 dense하게 변환했다가는 메모리가 터진다.
이런 특징을 이해하면서 앞으로의 내용을 이해해보도록 하자.
Abstract
기존 3D object detector들은 직접 만드는(hand-crafted) proxy들에 의존했다.
- Anchors
- Centers
- 잘 알려진 2D frameworks 구조를 3D로 옮겨오는 것 등등..
저런 proxy가 처리할 수 있는 형태로 만들기 위해서는 필수적으로 dense해야했다.
그러나 dense한 feature는 메모리나 계산량 이슈를 피할수가 없다.
VoxelNeXt는 dense하게 변환하지 않은 상태(fully sparse)에서 prediction까지 한번에 해버린다.
이름하야 voxel-to-object scheme.
- Sparse해지면서 위에서 설명한 proxy들을 안 쓰게 됐다.
- NMS 같은 post-processing도 안 한다.
Backbone부터 head network까지 어떻게 바꿨는지 알아보도록 하자.
Introduction
최근의 3d object detector들은 성능 향상을 위해 다음 두가지를 사용.
1. 효율적인 feature extraction을 위한 sparse convolution 사용
2. Hand-crafted된 Anchor`나 Center들을 사용
Anchor나 center들은 규칙적이고 grid-structured된 image 데이터를 위해 만들어짐
- 3D data의 sparsity(희소성)와 irregularity(불규칙성)는 고려하지 않음
3차원의 sparse한 데이터를 2차원의 dense한 feature로 변환하는 방식을 사용하지만, 이는 비효율적이고 복잡하다.
- Heatmap을 확인해보면, 대부분 값이 0이다.
- Dense prediction head는 feature map의 모든 부분을 확인해야하고, 이 과정에서 dense convolution이 사용된다.
- Non-maximum suppression과 같은 post-processing도 사용해야한다.
--> Dense한 경우, 비슷한 위치에 여러개의 prediction이 생길 수 있기 때문
그래서 VoxelNeXt는 간단 + 효율 + post-processing free한 3D object detector를 만들어냈다.
- Voxel-to-object scheme을 사용
--> Fully sparse convolution nextwork를 통해 voxel feature로부터 직접적으로 3차원 객체를 예측
--> 이는 sparse하고 필요한 위치로부터만 예측을 하게 된다.
--> Dense feature를 피하기 때문에 3차원 tracking으로 확장이 쉽다.
- 다음과 같은 것들이 없다.
--> Anchor proxies
--> Sparse-to-dense conversion
--> Region proposal networks
--> 그외 복잡했던 요소들
VoxelNeXt는 query voxel이라는 것을 tracking에 활용한다.
Query voxel들은 box prediction에 사용되는 voxel들이다.
- 나는 이게 뭔말인지 모르겠다.
- Box prediction에 사용되는 voxel이 한두개가 아닌데, 논문에서는 object당 하나인 것처럼 말한다.
- Query voxel이 input data voxel중 하나라는데, 어떻게 구해지는지 알 수가 없다.
FSD, VoteNet같은 경우에는 성능 향상을 위해 객체의 위치를 반복적으로 voting하는 과정이 있었다.
- 3차원의 sparse한 데이터는 일반적으로 객체의 표면에 흩뿌려져있기 때문에 이런 voting 과정은 오히려 bias나 error를 일으킨다.
우리는 그런거 없다라는 전개 시작
Fully Sparse Voxel-based Network
저자는 기존 방식에서 "아주 조금" 수정했더니 sparse voxel만 가지고도 SOTA를 찍었다고 말한다.
3가지 섹션으로 구분된다.
- Backbone Adaptation
- Sparse Head Design
- 3D Object Tracking
[Backbone Adaptation] Additional Down-sampling
Sparse한 voxel feature로부터 직접적이고 정확한 예측을 가능하게 하려면 다음 두가지가 필요하다.
- 강력한 feature representation
- 충분한 receptive fields
따라서 이를 위해 다음과 같은 것들을 사용한 연구가 진행됐었다.
- Well-design된 convolution
- Large kernels
- transformers
저자들은 sparse한 김에 더 deep하게 network를 구성해서 Effective Receptive Field를 키우고자 했다.
이걸 보면 알 수 있겠지만, 단순히 feature들끼리 가까이 위치하게 만드는 것이 요점이었다면 이런 접근이 나왔을리없다.
이전 접근들이 4개의 stage만 사용하여 backbone을 구성하는 이유는 dense하게 변환하여 사용해야하기 때문이라고 이해했다.
Dense하게 변환한 뒤에 더 deep하게 network를 구성하기엔 cost가 너무 커지기 때문이다.
따라서 저자는 dense한 변환이 없다면
1. Sparse한 상태의 feature를 그대로 가져가면서 더 deep하게 구성하는 것이 가능하고
2. 이를 통해 effective receptive field를 키울 수 있다고 이해했다.
기존에는 4개의 stage로 구성됐지만, 추가적으로 2번의 downsampling을 한 뒤, 4번째 stage의 feature와 합친다.(concatenation)
합칠때는 4번째 stage feature과 resolution을 맞춘다.
- 5번째 stage feature의 index에 2배
- 6번째 stage feature의 index에 4배
이때 sparse voxel feature들은 단순히 feature list, feature indices로 구성돼있으므로 concatenation은 list 이어붙이기랑 같이 동작한다.
[Backbone Adaptation] Sparse Height Compression
기본 방식은 sparse한 feature를 dense하게 변환한 뒤, height와 channel 차원을 flatten했다.
- (Batch, Channel, Depth, Height, Width) --> (Batch, Channel x Depth, Height, Width)
VoxelNeXt는 sparse한 상태를 유지 + (x, y)가 같은 feature들은 모두 더하는 것으로 compression한다.
- (Batch, Channel, Depth, Height, Width) --> (Batch, Channel, Height, Width)
[Backbone Adaptation] Spatially Voxel Pruning
중요도를 기준으로 voxel을 정렬하고, 이 중 상위 ((1-pruning ratio) * 100)% 만큼만 선택한다.
이렇게 선택된 voxel에 대해서만 dilation(Submanifold Sparse Convoluiton)을 적용해서 차지하는 공간을 늘려준다.
이후 stride 2인 sparse convolution을 적용하면, 중요한 부분이 좀 더 오래 남아있게 된다.
Table 3, 4를 보면 왜 pruing ratio를 0.5로 설정했고, 1~3 stage에 대해서만 pruning을 적용했는지 알 수 있다.
FLOPS는 50% 가까이 아끼긴 했는데, 실제 속도 향상이 10% 미만이라 코드에서 pruning 버전의 config파일은 제공하지 않는다고 한다.
[Sparse Prediction Head] Voxel Selection
Heatmap의 peak을 object의 center가 아니라 center 근처의 voxel로 regression하게 만들었다.
참고로 이 문단에서 갑자기 query voxel이 언급된다.
Inference 할때, query voxel이 bounding box의 중심이 아니라 bounding box의 경계에 더 많이 분포한다는 말이 나온다.
그래서 나는 query voxel이 heatmap의 peak중 threshold를 넘긴 위치를 의미한다고 생각했다.
시각화를 해봐도 bounding box center는 아니었다.
그러나 input data voxel과 대응되지는 않았다.
NMS를 피하기 위해 submanifold sparse max pooling 을 사용한다.
1. Kenel내에서 feature의 강도가 제일 큰 것들만 남기면서
2. 남겨진 feature주변에 있는 feature들을 제거하는 효과를 가진다.
[Sparse Prediction Head] Box Regression
Tracking은 CenterPoint (CVPR 2021)의 알고리즘을 사용하기 때문에 velocity를 같이 예측한다.
Waymo Open dataset 한정 성능향상을 위해 IoU를 같이 예측한다.
최종적으로 3 x 3 submanifold sparse convolution을 사용한다.
[3D Tracking] Voxel Association
CenterPoint (CVPR 2021)의 방식을 쓰는데, object의 center를 쓰는게 아니라 query voxel을 사용한다는 것만 다르다.
여기서 query position을 stride-8 position이 아닌 original input voxel에서 고른다고 되어있다.
뭘 어떻게 고른다는건지 모르겠다.