Long-form · Technical Essay

CNN에서 출발해 Point Transformer V3까지

합성곱 신경망만 알고 있는 사람을 위한, 점군(point cloud) 위에서 동작하는 가장 강력한 트랜스포머 — PTv3 — 의 처음부터 끝까지. 도식과 수식, 그리고 그 사이를 잇는 직관을 모두.

§ 01 — Prologue

들어가며 — 왜 이 글인가

2024년 CVPR에서 발표된 Point Transformer V3 (이하 PTv3) 는, 점군(point cloud) 위에서 동작하는 모델이 도달할 수 있는 “좋은 기본값(default)”의 새로운 기준선이 되었다. 단일 모델로 옥내 분할(ScanNet, S3DIS), 옥외 자율주행 분할(nuScenes, SemanticKITTI), 객체 분류(ModelNet), 부품 분할(ShapeNetPart) 등 20여 개의 벤치마크를 동시에 갈아치웠고, PTv2보다 3배 이상 빠르며 10배 이상 메모리를 적게 쓴다. 그러면서도 정확도는 더 높다. 이 “더 빠르고, 더 가볍고, 더 정확한” 보기 드문 조합은 어디서 왔는가?

대답은 PTv3 논문의 부제에서 이미 드러난다 — “Simpler, Faster, Stronger.” 정확하게 자르고 정밀하게 이웃을 묶는 대신, 점들을 1차원 시퀀스로 정렬하고, 그 시퀀스를 단순한 패치로 자른 뒤, 패치 안에서만 어텐션을 돌린다. CNN과 Transformer의 사고방식을 모두 한참 배운 사람이 보면 “고작 그게?” 싶지만, 바로 그 “고작”이 점군 위 트랜스포머의 운명을 바꿨다.

이 글이 약속하는 것

이 글은 CNN 한 가지만 아는 사람이 PTv3를 완전히 이해하도록 만드는 것을 목표로 한다. 그래서 우리는 다소 멀리서부터 출발한다. CNN의 어떤 성질이 점군에서 무너지는지 보고, 그 빈자리를 채우러 들어온 Attention을 만나고, 어텐션을 쌓아 Transformer를 짓고, 트랜스포머가 점군을 만나며 거쳐온 PointNet → PointNet++ → PT v1 → PT v2 → PT v3 의 다섯 정거장을 차례로 통과한다.

각 정거장에서 우리는 (1) 왜 이 모델이 등장했는가, (2) 핵심 아이디어와 수식은 무엇인가, (3) 다음 모델은 무엇을 고치려 했는가 를 묻는다. 모든 수식은 풀이 과정을 함께 적었고, 모든 다이어그램은 SVG로 인라인 삽입되어 인쇄해도 깨지지 않는다.

“Scaling principle is the most important factor for advancing deep learning. Simplicity allows us to scale; precision tries to stop us.”
— PTv3, CVPR 2024 (의역)

읽는 방법

좌측 사이드바의 목차에서 어디로든 점프할 수 있다. 모바일에서는 우측 상단의 햄버거 버튼으로 같은 목차를 펼친다. 다크/라이트 모드 토글은 그 옆에 있다. 수식은 KaTeX로, 도식은 인라인 SVG로 그려져 있어 별도의 네트워크 없이도 글의 본문은 모두 읽힌다(폰트와 KaTeX는 CDN을 사용한다).

§ 02 — Foundations

CNN 복습 — 우리가 떠나는 출발점

이미 잘 아는 내용을 짧게 짚자. 모든 다음 이야기가 이 “CNN의 어떤 성질을 잃었는가”에서 시작된다.

2.1합성곱이라는 약속

2D 영상에 대한 합성곱(convolution)은 다음과 같이 정의된다. 입력 특징 맵 $X \in \mathbb{R}^{H\times W\times C_\text{in}}$ 와 커널 $W \in \mathbb{R}^{k\times k\times C_\text{in}\times C_\text{out}}$가 있을 때, 출력의 $(i,j,c)$ 위치는

(2.1) $$ Y_{i,j,c} = \sum_{u=-r}^{r}\sum_{v=-r}^{r}\sum_{c'=1}^{C_\text{in}} W_{u,v,c',c}\, X_{i+u,\,j+v,\,c'} \quad \text{단, } k = 2r+1. $$

이 한 줄짜리 식 안에 CNN이 의존하는 네 가지 강력한 가정이 들어 있다.

입력 특징 맵 X (H×W×C_in) k×k 윈도우 ⊛ W 슬라이딩 출력 Y (H′×W′×C_out) Y_ij CNN의 4가지 약속 ① 격자 (Regular grid) ② 지역성 (Locality) ③ 가중치 공유 (Shared) ④ 평행이동 등변성 (Translation eq.)
Figure 2.1 합성곱은 “격자 위에서, 좁은 이웃을, 같은 가중치로, 모든 곳에서” 보는 연산이다.
① Regular Grid
픽셀이 균일 간격으로 정렬
② Locality
k×k 안만 본다
③ Weight Sharing
W를 모든 (i,j)에서 공유
④ Translation Eq.
입력이 평행이동하면 출력도 평행이동

2.2왜 이 4개가 함께 등장하는가

이미지에서는 픽셀이 격자에 “놓여” 있다. $X[i+1, j]$는 “왼쪽에서 한 칸 오른쪽”이라는 명확한 의미를 갖는다. 그래서 “3×3 이웃”이 잘 정의된다(지역성). 그리고 “같은 패턴(가령 가로 엣지)이 어디에 있든 똑같이 검출되어야 한다”는 직관이 자연스럽기 때문에 가중치를 공유한다(공유). 그 결과 입력의 평행이동에 대해 출력이 평행이동하는 등변성이 따라온다.

여기서 우리가 기억할 핵심은 — CNN은 입력이 격자라는 사실에 모든 것을 의존한다는 점이다.

§ 03 — Motivation

CNN의 한계 — Attention이 필요한 이유

CNN은 “격자 + 좁은 이웃”에 의존한다고 했다. 두 가지가 모두 무너지는 두 상황을 보자.

3.1먼 거리 의존성 (long-range dependency)

이미지 안에서도 멀리 떨어진 두 영역이 의미적으로 강하게 연결될 수 있다 — 한쪽 끝의 “신호등 색”과 반대쪽 끝의 “보행자 자세” 같은 것. CNN은 한 층에서 k×k만 보기 때문에, 거리를 좁히려면 층을 깊게 쌓거나 stride·풀링으로 해상도를 줄여야 한다. 멀리 있는 한 쌍의 픽셀이 서로 영향을 주려면 “충분히 깊은 층”이 필요하고, 정보가 그 사이를 지나며 흐려진다.

3.2입력이 격자가 아닐 때 (point cloud!)

점군은 $\{x_1, x_2, \dots, x_N\}$ 인 좌표(과 특징)의 집합(set) 이다. 다음 세 성질이 CNN과 충돌한다.

이미지 (격자, 정렬됨) (0,0) (H-1,W-1) 개수: H·W (고정) · 순서: 명확 점군 (집합, 비정렬) 개수: 가변 (N개) · 순서: 정의 안 됨
Figure 3.1 CNN의 모든 가정은 격자에 의존한다. 점군은 그 어떤 것도 만족하지 않는다.
A. 비정렬 (Unordered)
$\{x_1,..,x_N\}$ = 어떤 순열로 적든 동일
B. 비균일 (Non-uniform)
밀도가 지역마다 크게 다름
C. 희소·가변
N이 매번 달라짐

이 세 가지 때문에 — 점들 위에 “3×3 윈도우”를 정의하는 일이 처음부터 막힌다. 위·아래·왼쪽·오른쪽이라는 개념 자체가 점군에는 없다.

3.3두 한계를 한 번에 해소하는 한 가지 발상

“좁은 이웃”의 가정을 버리고, 모든 원소가 모든 원소를 본다. 그 대신, 모든 쌍을 동등하게 보지 않고 중요한 쌍에 가중치를 더 준다. 그 가중치를 데이터로부터 학습한다. 이 발상이 곧 Attention이다.

통찰

CNN의 강점이었던 “격자 + 좁은 이웃 + 공유 가중치”의 자리에, 어텐션은 “집합 + 모든 쌍 + 데이터-적응적 가중치”를 둔다. 이는 점군처럼 격자가 없는 데이터에 자연스럽게 어울린다.

§ 04 — Attention

Attention 메커니즘의 핵심

어텐션을 처음 만나는 사람을 위해, 도서관 비유로 한 번만 짚고 들어간다. 그러고 나서 곧바로 수식으로 들어간다.

4.1도서관 비유 — Query, Key, Value

당신이 도서관에 가서 “1980년대 한국 SF”에 관한 책을 찾는다고 하자. 머릿속에 떠올린 검색어가 Query(질의) 다. 책장에는 책마다 라벨이 붙어 있는데, 그 라벨이 Key(열쇠)다. 그리고 책의 실제 내용물이 Value(값)다.

당신이 하는 일은 (1) 내 Query와 각 책의 Key가 얼마나 비슷한지를 점수로 매기고 (2) 그 점수를 정규화해 “주의의 비중”으로 바꾼 뒤 (3) 모든 책의 Value를 그 비중으로 가중평균하는 것이다. 잘 맞는 책의 내용은 많이, 안 맞는 책의 내용은 적게 가져온다.

Query (Q) "내가 찾는 것" 차원 d_k 책장 안의 N개의 자료 Key₁ d_k Value₁ d_v Key₂ Value₂ …Key_N …Value_N 유사도 Output Σ αᵢ · Vᵢ 차원 d_v α: 점수의 정규화 (softmax)
Figure 4.1 Query는 “내가 찾는 것”, Key는 “네가 어떤 것인지”의 라벨, Value는 실제 내용. 어텐션은 Q와 K의 매칭 점수로 V를 가중합하는 연산이다.

4.2가장 단순한 형태 — Dot-Product Attention

유사도 함수로 가장 단순한 것은 내적(dot product) 이다. 두 벡터가 같은 방향으로 클수록 내적이 커진다. 한 개의 Query $q \in \mathbb{R}^{d_k}$와 N개의 Key $k_i \in \mathbb{R}^{d_k}$, Value $v_i \in \mathbb{R}^{d_v}$가 주어졌을 때, 어텐션 출력은

(4.1) $$ \text{score}_i \;=\; q^\top k_i, \qquad \alpha_i \;=\; \text{softmax}(\text{score})_i \;=\; \frac{\exp(q^\top k_i)}{\sum_{j=1}^{N}\exp(q^\top k_j)}. $$
(4.2) $$ \text{out} \;=\; \sum_{i=1}^{N} \alpha_i\, v_i \;\in\; \mathbb{R}^{d_v}. $$

여기서 softmax는 (a) 모든 출력을 양수로 만들고 (b) 모두 더하면 1이 되도록 한다. 그래서 $\alpha_i$를 “주의의 비중”으로 해석할 수 있다.

4.3√d_k로 나눠야 하는가 — Scaled Dot-Product

이 부분은 보통 천천히 설명되지 않고 지나가는데, PTv3까지 가는 길에 어텐션의 “크기”와 “스케일”이 반복 등장하므로 한 번 제대로 짚고 가자.

$q$$k$의 각 성분이 평균 0, 분산 1인 독립 확률변수라고 가정하자. 그러면

(4.3) $$ q^\top k \;=\; \sum_{i=1}^{d_k} q_i k_i, \qquad \mathbb{E}[q^\top k] = 0, \qquad \mathrm{Var}(q^\top k) = d_k. $$
풀이 — 분산이 d_k가 되는 이유
  1. 독립이고 평균 0이므로 $\mathbb{E}[q_i k_i] = \mathbb{E}[q_i]\mathbb{E}[k_i] = 0$. 따라서 $\mathbb{E}[q^\top k] = 0$.
  2. 같은 가정에서 $\mathrm{Var}(q_i k_i) = \mathbb{E}[q_i^2 k_i^2] - 0 = \mathbb{E}[q_i^2]\mathbb{E}[k_i^2] = 1\cdot 1 = 1$.
  3. 독립인 항들의 합의 분산은 각 항 분산의 합. 항이 $d_k$개이므로 $\mathrm{Var}(q^\top k) = d_k$.

차원 $d_k$가 커질수록 내적의 분산이 함께 커진다. softmax는 입력값이 커지면 — 곧 가장 큰 항이 다른 항을 압도하기 시작하면 — 출력 분포가 거의 one-hot에 가까워진다. 그 영역에서는 softmax의 그래디언트가 거의 0에 수렴해 학습이 멈춰버린다(vanishing gradient). 따라서 분산을 1로 정규화해 주려고 $\sqrt{d_k}$로 나눈다.

(4.4) $$ \boxed{\;\text{Attention}(q, K, V) \;=\; \text{softmax}\!\left(\frac{q^\top K^\top}{\sqrt{d_k}}\right) V\;} $$

여러 개의 Query를 동시에 처리하면 행렬로 정리된다. $Q \in \mathbb{R}^{N\times d_k}$, $K \in \mathbb{R}^{N\times d_k}$, $V \in \mathbb{R}^{N\times d_v}$ 일 때:

(4.5) $$ \text{Attention}(Q, K, V) \;=\; \text{softmax}\!\left(\frac{Q K^\top}{\sqrt{d_k}}\right) V. $$

이때 softmax는 각 행에 대해 독립적으로 적용된다(행마다 한 개의 Query).

§ 05 — Self-Attention

Self-Attention 완전 해부

지금까지의 어텐션에서는 Q, K, V가 서로 다른 곳에서 “이미 주어졌다”고 가정했다. Self-Attention은 — 이름 그대로 — Q, K, V를 같은 입력으로부터 만든다. 입력 시퀀스의 각 원소가 다른 모든 원소를 어떻게 “돌아볼지” 학습한다.

5.1입력에서 Q, K, V 만들기

입력을 $X \in \mathbb{R}^{N \times d_\text{model}}$ 이라 하자(N개의 토큰, 각 토큰의 차원이 $d_\text{model}$). 학습 가능한 세 개의 가중치 행렬

(5.1) $$ W_Q,\, W_K \in \mathbb{R}^{d_\text{model} \times d_k}, \qquad W_V \in \mathbb{R}^{d_\text{model} \times d_v} $$

로 입력을 세 가지 다른 “관점”으로 투영한다.

(5.2) $$ Q = X W_Q, \qquad K = X W_K, \qquad V = X W_V. $$

핵심 — 같은 토큰 $x_i$가 “질문하는 입장(Q)”, “답이 될 후보로 묻혀 있는 입장(K)”, “실제로 다른 토큰에 전달할 내용(V)”의 세 가지 모드로 동시에 변환된다.

X N × d_model ×W_Q ×W_K ×W_V Q N × d_k K N × d_k V N × d_v QKᵀ / √d_k N × N softmax A N × N (행 합 = 1) A · V N × d_v (출력)
Figure 5.1 Self-Attention의 행렬 흐름. 같은 X에서 세 갈래로 갈라져 다시 만난다. 비용은 N×N 행렬에서 비롯된다.

5.2한 줄 요약 — 핵심 수식

(5.3) $$ \boxed{\; \text{SelfAttn}(X) \;=\; \text{softmax}\!\left( \frac{(XW_Q)(XW_K)^\top}{\sqrt{d_k}} \right)(XW_V) \;} $$

5.3한 행의 의미를 풀어 쓰면

출력의 $i$번째 행, 곧 $x_i$가 만든 새 벡터 $y_i$를 풀면:

(5.4) $$ y_i \;=\; \sum_{j=1}^{N} \alpha_{ij}\, v_j, \qquad \alpha_{ij} \;=\; \frac{\exp\!\bigl(\tfrac{q_i^\top k_j}{\sqrt{d_k}}\bigr)}{\sum_{l=1}^{N}\exp\!\bigl(\tfrac{q_i^\top k_l}{\sqrt{d_k}}\bigr)}. $$

이 식이 모든 다음 이야기의 토대다. 한 토큰 $x_i$는 자기 자신을 포함한 N개 모든 토큰의 정보 $v_j$를, 학습된 가중치 $\alpha_{ij}$로 “골라 모은” 결과로 갱신된다.

5.4두 가지 결정적 성질

(a) 순열 불변·등변성

입력 토큰들의 순서를 바꾸면 — 곧 $X$의 행을 임의의 순열 $\pi$로 재배열하면 — Q, K, V도 같은 순열로 재배열되고, 출력 행도 같은 순열로 재배열된다(permutation-equivariant). 만약 출력을 평균 풀링 같은 대칭 함수로 모은다면 그 결과는 순열을 무시한다(permutation-invariant). 이 성질이 점군과 어텐션의 결혼식이다 — 점군은 순서가 없지 않은가.

(b) 임의-거리 의존성

한 층의 어텐션이 모든 쌍을 본다. CNN이 깊이로 쌓아야 했던 “먼 영역 사이 의존성”을 한 층에서 직접 만든다.

5.5대가 — 비용은 N²이다

출력의 모든 N개 행마다 N개의 점수를 계산하므로, 시간·메모리 비용 모두 $O(N^2 d)$ 가 된다. 이미지에서는 N이 많아야 수만, 점군에서는 N이 수십만~수백만이 된다. 우리가 PT v1 → v2 → v3로 가며 마주칠 모든 어려움의 진원지가 바로 이 N² 항이다.

§ 06 — Multi-Head

Multi-Head Attention

한 번의 self-attention은 “하나의 관계 패턴”을 학습한다. 그런데 토큰들 사이에는 동시에 여러 종류의 관계가 있다 — 문법적 관계, 의미적 유사성, 위치적 인접 등. 이를 분담하기 위해, 여러 개의 어텐션을 병렬로 돌리고 결과를 합친다. 이를 multi-head attention이라 부른다.

6.1핵심 아이디어 — 작은 어텐션 여러 개

전체 차원 $d_\text{model}$$h$개의 헤드로 잘라, 헤드마다 차원이 $d_k = d_v = d_\text{model}/h$ 인 self-attention을 따로 돌린다. 그리고 결과를 옆으로 이어 붙인 뒤 마지막으로 한 번 더 선형 변환한다.

(6.1) $$ \text{head}_i \;=\; \text{Attention}(X W_Q^{(i)},\, X W_K^{(i)},\, X W_V^{(i)}). $$
(6.2) $$ \text{MHA}(X) \;=\; \text{Concat}(\text{head}_1, \dots, \text{head}_h)\, W_O, \quad W_O \in \mathbb{R}^{d_\text{model}\times d_\text{model}}. $$

차원이 줄어 헤드 하나가 더 가벼워지고, 동시에 여러 “주의의 종류”를 학습할 수 있다. 모든 헤드를 합쳐도 파라미터 수와 연산량은 단일 헤드와 거의 같은 규모로 유지된다.

X head₁ : Attn(Q₁,K₁,V₁) head₂ : Attn(Q₂,K₂,V₂) head₃ : … head_h : Attn(Q_h,K_h,V_h) Concat N × d_model ×W_O MHA(X)
Figure 6.1 Multi-Head Attention. 각 헤드는 d/h 차원의 더 작은 self-attention이고, 결과는 concat 후 W_O로 한 번 더 섞인다.
관행

원 Transformer 논문(Vaswani 2017)은 d_model = 512, h = 8을 사용한다. 헤드마다 d_k = d_v = 64가 되는 셈이다. PTv3에서도 stage별로 헤드 수가 달라지지만 “부분 차원으로 잘라 병렬”이라는 골격은 같다.

§ 07 — Transformer

Transformer 아키텍처 (Vaswani 2017)

이제 self-attention과 multi-head attention을 ‘부품’으로 갖고 있다. 이를 어떻게 쌓아 “블록”과 “네트워크”로 만드는지가 — 그리고 그 블록의 어떤 부분이 PTv3에까지 살아남는지가 — 이 절의 주제다.

📖
Attention Is All You Need
Vaswani et al. · NeurIPS 2017 · arXiv:1706.03762

RNN과 CNN 없이, 오직 어텐션과 잔차 연결·LayerNorm만으로 시퀀스를 처리할 수 있음을 보였다. 이후 모든 분야의 “Transformer”의 부모.

7.1인코더 블록 — 두 개의 부품, 두 개의 잔차 연결

Transformer 인코더의 한 블록은 다음 두 단계를 차례로 적용한다.

(7.1) $$ X' \;=\; \text{LN}\bigl(X + \text{MHA}(X)\bigr), $$ $$ Y \;=\; \text{LN}\bigl(X' + \text{FFN}(X')\bigr). $$

여기서 LN은 LayerNorm, FFN은 토큰별로 독립적으로 적용되는 2층 MLP다. 즉

(7.2) $$ \text{FFN}(z) \;=\; \sigma(z W_1 + b_1) W_2 + b_2, $$

이때 $\sigma$는 ReLU 또는 GELU. 첫 행렬 $W_1 \in \mathbb{R}^{d_\text{model}\times d_\text{ff}}$은 차원을 일시적으로 4배 정도(가령 512→2048) 늘리고, $W_2$가 다시 줄인다. FFN의 핵심은 “토큰끼리는 절대 섞지 않는다”는 것이다 — 토큰 간 정보 교환은 오직 MHA에서만 일어난다. FFN은 각 토큰이 자기 안에서 비선형 변환을 거치는 단계다.

잔차 연결(residual)과 LN의 역할은 깊은 네트워크에서의 학습 안정성과 그래디언트 흐름이다. 이 블록 구조는 PT v1·v2·v3에서도 거의 그대로 살아남는다.

Input embedding + Pos-enc Multi-Head Self-Attention 토큰끼리 정보 교환 Add & LayerNorm residual Feed-Forward (token-wise MLP) d → 4d → d, GELU Add & LayerNorm residual 한 블록 안에서: ① 토큰들끼리 한 번 섞고 ② 각 토큰이 비선형 변환 N개 블록 쌓으면 전체 인코더 완성.
Figure 7.1 한 인코더 블록. 사실상 PTv3의 “Block” 단위도 이 골격을 따른다. 다만 MHA를 “Patch Attention”으로 대체할 뿐.

7.2위치 정보의 주입 — Positional Encoding

self-attention은 순열 등변이라 했다. 그런데 자연어, 이미지, 점군 모두에 “위치”라는 정보가 의미를 갖는다. 따라서 입력에 위치 정보를 직접 더해 모델이 그것을 활용하게 한다. 원 논문은 사인·코사인의 결합으로 정의된 절대 위치 인코딩을 사용했다.

(7.3) $$ \text{PE}_{(p, 2i)} = \sin\!\left(\frac{p}{10000^{2i/d}}\right),\; \text{PE}_{(p, 2i+1)} = \cos\!\left(\frac{p}{10000^{2i/d}}\right). $$

여기서 $p$는 시퀀스 내 위치, $i$는 차원 인덱스. 차원이 다른 두 위치는 서로 다른 주파수의 사인·코사인을 갖게 되어, 모델이 “두 위치의 차이”를 선형 변환만으로 표현 가능하다.

점군에서는 위치가 연속 좌표(x, y, z)이므로 사정이 다르다. PT v1은 두 점의 좌표 차이 $p_i - p_j$를 작은 MLP에 통과시킨 상대 위치 인코딩을 사용하고, PTv3는 직렬화 자체에 위치 정보를 녹여낸다(뒤에서 본다).

§ 08 — Detour

잠시 — Vision Transformer

Transformer가 자연어에서 이미지로 옮겨가는 가장 단순한 방법이 ViT(Dosovitskiy 2020)다. PTv3가 ViT의 한 핵심 아이디어 — 입력을 “패치”로 잘라 시퀀스로 다룬다 — 를 점군에 옮겨오므로, 30초만 짚고 가자.

📖
An Image is Worth 16×16 Words
Dosovitskiy et al. · ICLR 2021 · arXiv:2010.11929

이미지를 16×16 patch로 나눠 각 patch를 “토큰”으로 보고, 표준 Transformer 인코더에 통과시킨다. 큰 데이터에서 CNN을 능가함을 보였다.

이미지 (224×224 → 14×14 패치) 각 패치를 1차원 토큰으로 펼침 + 위치 임베딩 ⇒ 표준 Transformer 인코더로 입력
Figure 8.1 ViT는 “이미지를 토큰의 시퀀스로 보는” 한 가지 트릭으로, 자연어에서 쓰던 Transformer를 그대로 가져왔다.

이미지가 “격자에서 잘라낸 16×16 패치들의 시퀀스”라면, 점군은 “1차원으로 정렬된 점들의 시퀀스” — 가 될 수 있을까? 이 생각이 PTv3의 출발점이다.

§ 09 — Geometry

포인트 클라우드의 기초

이제 시각을 점군으로 옮긴다. PTv3가 다루는 데이터의 모양을 또렷이 해두자.

9.1형식적 정의

점군은 $N$개의 점을 모은 집합으로, 각 점은 좌표와 (선택적으로) 특징을 갖는다.

(9.1) $$ \mathcal{P} \;=\; \bigl\{ (p_i,\, f_i) \bigr\}_{i=1}^{N}, \quad p_i \in \mathbb{R}^3,\; f_i \in \mathbb{R}^{C}. $$

$f_i$에는 색(RGB), 반사도(intensity), 법선 벡터, 기타 측정값이 포함될 수 있다. 우리가 학습으로 알고 싶은 양은 보통 두 가지다.

분류
전체 점군 → 단일 라벨 (예: 의자/책상)
분할
각 점 → 라벨 (예: 벽/바닥/사람)

9.2점군이 어디서 오는가

실용적 맥락 한 줄. LiDAR(자율주행), RGB-D 카메라(실내 매핑), 구조광·라인 트라이앵귤레이션 센서(예: Micro-Epsilon scanCONTROL — 용접 검사에 흔히 쓰인다), MVS(다중뷰 스테레오), 3D 스캐너 등이 모두 점군을 만든다. 이미지가 “격자 위에 놓인 색”인 것에 대해 — 점군은 “3D 공간 어디든 흩뿌려진 측정”이다.

9.3점군 학습의 핵심 요구

모델이 다음 셋을 만족하도록 설계해야 한다.

① 순열 불변 f({x₁,x₂,x₃}) = f({x₃,x₁,x₂}) 순서를 바꿔도 결과는 같아야 함 ② 변환에 강건 회전 / 이동 에 따라 결과가 바뀌지 않거나 예측 가능하게 변해야 (equivariance / invariance) ③ 지역 구조 포착 가까운 점들이 함께 만들어내는 표면·구조 의미 밀도가 달라도 잘 작동해야
Figure 9.1 점군 학습 모델은 이 셋을 동시에 만족해야 한다. PointNet은 ①을, PointNet++는 ①+③을, Point Transformer 계열은 셋 모두를 어텐션으로 통합한다.
§ 10 — PointNet

PointNet — 모든 것의 시작

점군 위에서 작동하는 “신경망다운 신경망”의 첫 모델이다. PT 시리즈로 가는 길의 첫 정류장이며, 핵심 아이디어 — 대칭 함수로 순서를 지운다 — 가 이후 모든 모델에서 변주된다.

📖
PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation
Qi et al. · CVPR 2017 · arXiv:1612.00593

“집합”에 적용 가능한 신경망의 보편 근사 정리(universal approximation)를 제시. PointNet++로, 이후의 모든 점군 학습으로 이어졌다.

10.1핵심 정리 — 대칭 함수의 보편 근사

저자들은 다음을 증명했다(요지). 어떤 연속이고 순열 불변인 집합 함수 $f: 2^{\mathbb{R}^3} \to \mathbb{R}$도, 충분히 큰 신경망 $h$$\gamma$에 대해

(10.1) $$ f(\{x_1, \dots, x_N\}) \;\approx\; \gamma\!\Bigl(\;\underset{i=1,\dots,N}{\text{MAX}}\;\bigl\{\,h(x_i)\,\bigr\}\Bigr). $$

여기 MAX는 채널별 최댓값(element-wise max). $h$는 점 하나하나에 똑같이 적용되는 MLP, $\gamma$는 풀링 결과를 받는 또 다른 MLP. 이 식은 다음 두 의미가 있다.

왜 순열 불변인가
MAX는 입력 순서에 상관없는 대칭 함수
왜 충분한가
개별 점 → 고차원 임베딩 → 최댓값으로 “요약”하는 구조면 어떤 순열-불변 함수든 근사 가능
N개의 점 (3D) x₁ = (px,py,pz) x₂ x_N 공유 MLP h 3 → 64 → 128 → 1024 (점마다 동일하게 적용) MAX (채널별) N×1024 → 1024 대칭 함수 MLP γ 1024 → 512 → C 분류 점수 이 구조 자체가 “순열 불변”을 보장한다 — 약속의 절반.
Figure 10.1 PointNet 분류 모델. 점마다 같은 MLP를 통과시킨 뒤 채널별 MAX로 요약, 다시 MLP로 분류. 단순하면서 강력한 골격.

10.2왜 MAX인가 — 다른 대칭 함수와의 비교

대칭 함수의 후보로는 SUM, AVG, MAX 등이 있다. 그런데 신경망의 근사 능력을 살리려면 하나의 점만으로도 충분히 강한 “시그널”이 다른 점에 의해 가려지지 않는 풀링이 좋다. MAX는 “가장 두드러진 특징”을 그대로 보존한다. 실제 실험에서도 SUM·AVG보다 분류 정확도가 안정적으로 높았다.

10.3점별 분할(segmentation)은 어떻게 만드나

분류는 “집합 → 단일 라벨”이지만 분할은 “집합 → 점마다의 라벨”이다. PointNet은 풀링 직전의 “전역 1024차원 벡터”를 모든 점에 다시 붙여(concat) 점별 MLP로 라벨을 낸다. 즉, 각 점의 결정에 “나만의 특징 + 전체의 요약”이 모두 들어간다.

10.4한계 — “지역(local) 구조”가 없다

여기서 끝나면 좋겠지만 — PointNet은 점 하나에서 곧장 “전체 요약”으로 점프한다. 중간 단계의 지역 패턴 — “이 작은 영역의 점들이 모여 모서리를 이룬다”거나 “이 표면 조각이 평면이다” — 이 없다. 이것이 CNN의 “계층적 수용장(receptive field)”에 비해 약한 이유였다.

불충분

PointNet은 “점 → 전체”의 두 단계만 있다. 다음 모델 PointNet++는 그 사이에 여러 단계의 지역 PointNet을 끼워 넣는다 — CNN이 깊이를 쌓아 수용장을 키운 것과 정확히 같은 발상이다.

§ 11 — PointNet++

PointNet++ — 계층적 학습

아이디어 한 줄: “PointNet을 작은 영역에 반복 적용하고, 그 결과를 다시 더 큰 영역에 적용한다.” CNN의 점진적 풀링과 동일한 효과를 점군에서 만든다.

📖
PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space
Qi et al. · NeurIPS 2017 · arXiv:1706.02413

Set Abstraction (SA) 모듈 — Sampling → Grouping → PointNet — 을 반복 쌓아 계층 표현을 학습한다.

11.1Set Abstraction (SA) — 세 단계

한 SA 모듈은 입력 점들 $\mathcal{P}_\text{in}$ 을 받아, 더 적은 수의 “센터 점”과 그 점들의 더 풍부한 특징 벡터로 이루어진 $\mathcal{P}_\text{out}$ 을 만든다.

단계 — Sampling → Grouping → PointNet
  1. Sampling — Farthest Point Sampling (FPS). 입력에서 가장 “고르게 퍼진” $M$개의 센터 점을 뽑는다. 첫 점은 임의, 그 다음부터는 “지금까지 뽑힌 점들로부터 가장 먼 점”을 반복적으로 선택. 결과는 점군의 형상에 적응한 균일한 다운샘플링.
  2. Grouping — Ball Query. 각 센터 점 주변 반경 $r$ 안의 점들을 묶어 “지역 패치”를 구성. 패치당 점의 수는 K로 잘라(필요 시 패딩) 텐서 형식으로 통일.
  3. PointNet on Patch. 각 패치(K개의 점, 각각 d차원 특징)에 PointNet을 적용해 단일 벡터로 요약. 이 벡터가 그 센터 점의 새로운 특징이 된다.
① 입력 점군 ② FPS로 센터 선택 ③ Ball Query (반경 r) ④ 그룹마다 PointNet PointNet → f₁' PointNet → f₂' PointNet → f₃' PointNet → f₄' 결과: M개의 센터 점 + 풍부해진 d′차원 특징
Figure 11.1 Set Abstraction 한 단계. CNN의 “stride-2 conv + pooling”과 정신적으로 같은 일을, 점군의 비격자 위에서 수행한다.

11.2다단 SA로 수용장이 자라난다

SA 모듈을 여러 번 쌓으면, 매 단계마다 (a) 점의 수가 줄고 (b) 점의 특징이 더 큰 영역을 요약한다 — CNN에서 stride 2 conv를 반복할 때와 동일한 “수용장 키우기”다. 분할 작업에서는 그 후 거꾸로 점 수를 다시 키워 원래 해상도로 돌아간다(Feature Propagation 단계).

11.3그래도 남은 한계

PointNet++는 지역 구조를 잡지만, 한 패치 내부에서 일어나는 일은 여전히 “점마다 동일한 MLP + MAX”다. 각 점이 이웃 안에서 누구를 더 비중 있게 볼지는 학습되지 않는다. CNN의 한계와 똑같은 문제 — “이웃 안에서 모두를 똑같이 본다”. 이 자리에 어텐션을 넣으면? 그 답이 바로 Point Transformer다.

§ 12 — Point Transformer V1

Point Transformer V1

“PointNet++의 ‘이웃 안에서 동일 가중치’ 자리에 어텐션을 넣자.” 정확히 그 한 줄짜리 발상을 깔끔하게 구현한 모델이다.

📖
Point Transformer
Zhao et al. · ICCV 2021 · arXiv:2012.09164

점의 k-NN 이웃에 대해 벡터 어텐션을 정의해 점군 위 트랜스포머의 표준 구조를 제시. 다음에 본다.

12.1스칼라 어텐션과 벡터 어텐션

지금까지 우리가 본 어텐션은 “Q·K → 스칼라 점수”를 만든 뒤 그것을 V에 곱했다. 점군에서는 그 대신 벡터 어텐션을 쓴다 — 점수가 채널마다 다르게 나오는 “채널별 가중치 벡터”다.

두 점 $x_i$ (질문하는 점)와 $x_j$ (그 이웃)에 대해, PT v1은 다음과 같이 출력 $y_i$를 계산한다.

(12.1) $$ y_i \;=\; \sum_{x_j \in \mathcal{N}(x_i)} \rho\!\Bigl(\;\gamma\bigl(\,\varphi(x_i) - \psi(x_j) + \delta_{ij}\,\bigr)\;\Bigr) \;\odot\; \bigl(\alpha(x_j) + \delta_{ij}\bigr). $$

표기를 풀면:

$\mathcal{N}(x_i)$
k-NN 이웃 (공간상 가장 가까운 k개의 점)
$\varphi, \psi, \alpha$
선형 매핑 (각각 Q, K, V 역할)
$\delta_{ij}$
상대 위치 인코딩 = MLP($p_i - p_j$)
$\gamma$
2층 MLP (차이 벡터 → 채널별 가중치)
$\rho$
softmax over j (이웃에 대해 정규화)
$\odot$
원소별 곱 (채널마다 가중치 다름)

12.2한 줄로 풀어 쓰면

“i와 j의 차이”를 작은 MLP에 넣어 “채널마다 다른 비중”을 뽑고, 그것으로 j의 값을 채널별로 골라 모은다. 거기에 두 점의 위치 차이도 함께 더해 넣는다.

점 i 와 그 k-NN 이웃 i 한 이웃 j에 대해 계산되는 양 ① 차이 φ(x_i) − ψ(x_j) + δ_ij ② 매핑 γ(...) : 2층 MLP — 채널별 가중치 벡터 ③ 정규화 ρ = softmax over j (이웃에 대해) ④ 값 α(x_j) + δ_ij ⑤ 합 y_i = Σ_j ρ(γ(...)) ⊙ (α(x_j) + δ_ij) — 채널마다 다른 비중으로 “고른 평균”
Figure 12.1 PT v1의 벡터 어텐션. k-NN 이웃 안에서, 점 쌍의 차이로부터 채널별 가중치를 뽑아 V에 곱한다.

12.3왜 “벡터”인가 — 채널별 가중치의 의미

표준 어텐션은 한 쌍에 대해 “하나의 점수”를 낸다. 벡터 어텐션은 한 쌍에 대해 “채널 수만큼의 점수”를 낸다. 점군에서 두 점의 관계는 채널마다 다르게 의미를 가질 수 있다 — 예를 들어 한 채널은 “이 둘이 같은 표면 위에 있는가”, 다른 채널은 “이 둘 사이에 모서리가 있는가”를 학습할 수 있다. 채널별 가중치는 이런 다양한 관계를 동시에 인코딩한다.

12.4전체 네트워크 — U-Net의 점군판

PT v1의 전체 네트워크는 PointNet++가 그랬듯 인코더-디코더 (U-Net) 구조다. 차이는 “Set Abstraction에서 PointNet 대신 Point Transformer Block을 쓴다”는 것뿐이다. 인코더로 내려가며 점 수가 줄고, 디코더로 올라오며 점 수가 회복된다. 분할에서는 디코더 끝단에서 점별 라벨을 낸다.

12.5비용 — k-NN과 N의 곱

한 점이 k-NN 이웃만 보므로 어텐션 자체는 $O(N k)$로 줄었다. 그런데 두 가지 무거운 비용이 남아 있다.

k-NN 검색
매 forward에서 모든 점에 대해 k-NN을 다시 계산
불규칙 메모리 접근
scatter-gather 패턴 — GPU에서 비효율적

이 두 항이 PTv2와 PTv3가 각자 다른 방식으로 공격하는 표적이다.

§ 13 — Point Transformer V2

Point Transformer V2 — 짧은 다리

PTv2는 PT v1과 PTv3 사이의 중요한 디딤돌이다. 본격은 PTv3이지만, “v3가 무엇을 버리고 무엇을 단순화했는가”를 이해하려면 v2가 시도한 것을 알아야 한다.

📖
Point Transformer V2: Grouped Vector Attention and Partition-based Pooling
Wu et al. · NeurIPS 2022 · arXiv:2210.05666

벡터 어텐션의 채널을 그룹으로 묶어 효율을 올리고(GVA), 이웃 풀링을 “격자 분할” 기반으로 바꿔 안정성을 개선했다.

13.1핵심 변경 1 — Grouped Vector Attention (GVA)

PT v1의 벡터 어텐션은 채널 수만큼의 가중치를 만들어 메모리·연산이 비싸다. GVA는 채널을 g개의 그룹으로 묶고, 그룹 내부 채널은 같은 가중치를 공유하게 한다. 즉 가중치 벡터의 길이를 d → g로 줄인 셈이다.

(13.1) $$ \text{(PT v1)}\;\; w \in \mathbb{R}^{d}, \qquad \text{(PT v2 GVA)}\;\; w \in \mathbb{R}^{g},\; g \ll d. $$

이는 standard scalar attention($g=1$)과 v1 vector attention($g=d$) 사이의 절충점이다. 속도와 표현력의 균형을 보다 잘 맞춘다.

13.2핵심 변경 2 — Partition-based Pooling

PointNet++의 FPS+Ball-Query는 학습 가능하지 않고 비용이 크다. PTv2는 공간을 균일한 격자(voxel grid)로 분할해, 같은 voxel에 떨어진 점들을 한 번에 풀링한다. 격자 분할은 (a) 결정적이고 (b) 메모리 접근이 정렬된 패턴을 가진다 — GPU 친화적.

13.3그러나 여전히 — k-NN의 그림자

풀링은 격자로 바뀌었지만, 어텐션 자체는 여전히 각 점의 k-NN 이웃에서 일어난다. PT v1의 가장 무거운 비용 — 매 layer마다 k-NN을 다시 만들어야 한다 — 이 그대로 남아 있다. PTv3는 이 마지막 못을 뽑는다.

관전 포인트

지금까지 본 모든 점군 트랜스포머의 비용은 “이웃을 어떻게 정의하느냐” 에서 발생한다. PTv3의 통찰은 — “점들을 1차원으로 정렬해 두면, ‘이웃’은 그냥 시퀀스 상의 인접 구간이 된다”는 것.

§ 14 — Point Transformer V3

Point Transformer V3 — 본론

📖
Point Transformer V3: Simpler, Faster, Stronger
Wu, Jiang, Park, Zhao et al. · CVPR 2024 · arXiv:2312.10035

점들을 공간 채움 곡선으로 정렬한 뒤 패치 단위로 어텐션을 적용해, 단순함·속도·정확도를 동시에 거머쥔 설계.

14.1출발점 — “정밀도가 아니라 규모(Scale)”

PT v1·v2는 “이웃을 더 정밀하게 정의하면 더 좋은 모델이 된다”는 가정을 따랐다. PTv3 저자들은 이를 정면으로 뒤집는다.

정밀한 이웃 한 줌보다, 단순한 이웃 한 무더기가 낫다. 단순해야 더 큰 모델·더 큰 데이터로 확장된다(scale).

이 철학을 따라 PTv3는 k-NN을 완전히 폐기하고, 그 자리를 “직렬화 + 패치 어텐션”이라는 두 단어로 메운다. 결과 — PTv2 대비 처리량 약 3배, 메모리 약 1/10. 그러면서 정확도는 더 높다.

PT v1·v2의 비용 핵
k-NN 검색 + scatter/gather 메모리 패턴
PTv3의 대체
공간채움곡선 직렬화 + 패치 단위 attention
결과
~3× 빠름, ~10× 가벼움, 정확도 더 높음

14.2아이디어 1 — 직렬화 (Serialization)

점군의 각 점에는 3D 좌표 $(x, y, z)$ 가 있다. 이를 1차원 정수 인덱스로 바꾸어 점들을 한 줄로 세운다. 단, 무작정 세우면 의미가 없다 — 3D 공간에서 가까웠던 점들이 1D에서도 가까워야 한다. 이것이 가능한가? 가능하다. 공간 채움 곡선(space-filling curve)이 그 도구다.

14.2.1 Z-order curve (Morton order)

가장 단순한 공간 채움 곡선. 좌표의 비트(bit)를 교차로 끼워 넣어(interleave) 단일 정수로 만든다. 2D 좌표 $(x, y) = (5, 3)$ 을 예로 보자.

예제 — (x, y) = (5, 3) 의 Z-order 인덱스 계산
  1. 각 좌표를 이진수로 적는다. $x = 5 = 101_2$, $y = 3 = 011_2$.
  2. 비트를 교차로 배치. 결과의 비트 위치를 낮은 자리부터 적으면: $y_0,\, x_0,\, y_1,\, x_1,\, y_2,\, x_2$.
  3. 대입: $y_0=1,\, x_0=1,\, y_1=1,\, x_1=0,\, y_2=0,\, x_2=1$ → 결과 $= 101101_2$.
  4. 10진수 변환: $1\cdot32 + 0\cdot16 + 1\cdot8 + 1\cdot4 + 0\cdot2 + 1\cdot1 = 45$.
  5. 3D에서는 비트가 $z, y, x$ 의 순서로 교차된다 — 같은 원리.

이 방식의 장점은 (a) 인덱스 계산이 비트 연산만으로 $O(\log_2 \text{coord})$ 시간이고, (b) 인덱스가 가까운 점들이 공간상 같은 “Z 모양” 셀에 들어 있다는 점이다. 단점은 셀 경계에서 “급격한 점프”가 일어날 수 있다는 것 — 두 점이 공간상 매우 가깝지만 Z-인덱스가 멀어질 수 있다.

Z-order (Morton) 계산이 빠르나, 셀 경계에서 점프 Hilbert curve 국지성이 더 좋으나, 계산이 더 무겁다
Figure 14.1 두 공간 채움 곡선. 둘 다 3D 공간을 1D로 연결하지만, Hilbert가 인접성 보존이 더 우수하다.

14.2.2 Hilbert curve

Hilbert curve는 임의의 두 점이 곡선 상에서 가까우면 공간상에서도 거의 항상 가깝다는 더 강한 국지성을 갖는다. 계산은 Z-order보다 비싸지만 — 미리 한 번 계산해 인덱스를 캐싱해두면 학습 내내 비용은 0이다.

14.2.3 PTv3가 사용하는 4종류의 직렬화

PTv3는 4가지 직렬화를 번갈아 사용한다 — Z-order, Z-order-trans (좌표 축을 회전한 버전), Hilbert, Hilbert-trans. 매 어텐션 layer마다 이 중 하나를 선택해 적용한다. 한 layer에서 같은 패치에 속하지 못한 두 점이 다음 layer에서는 같은 시퀀스에 묶일 수 있도록 — 정보 흐름의 다양성을 만든다. ViT의 Swin Transformer가 “shifted window”로 한 일을, PTv3는 “shifted curve”로 한다.

# 의사 코드 — 한 layer의 직렬화 / Pseudocode for per-layer serialization
def serialize(points, mode):
    # points: (N, 3) raw xyz
    # mode  : 'z' | 'z_trans' | 'hilbert' | 'hilbert_trans'
    if mode.startswith('z'):
        idx = morton_encode(points, transposed=mode.endswith('trans'))
    else:
        idx = hilbert_encode(points, transposed=mode.endswith('trans'))
    order = argsort(idx)            # 정렬 순서 / sorted order
    return points[order], order     # 정렬된 점과 원-인덱스 매핑
왜 “여러 곡선”인가

한 종류의 곡선만 사용하면 그 곡선이 깨는 자리(cell boundary)의 두 점은 영원히 한 패치에 들어가지 못한다. 매 layer마다 다른 곡선을 돌려쓰면, 깊이가 쌓이면서 모든 가능한 “이웃 관계”가 결국에는 정보로 연결된다. 다양한 시각의 지역성을 시간에 따라 결합한다고 봐도 좋다.

14.3아이디어 2 — Patch Attention

점들이 1차원 시퀀스로 정렬되었다. 이제 어텐션은 어떻게 적용하나? 답은 단순하다 — 시퀀스를 고정 길이의 패치로 자르고, 패치 안에서만 어텐션을 한다. ViT가 이미지 패치 안에서 어텐션을 했던 것의 1D 버전이다.

(14.1) $$ \text{Patch}_p \;=\; \bigl\{\, x_{(p-1)K + 1},\; x_{(p-1)K + 2},\; \dots,\; x_{p K} \,\bigr\}, \quad K = \text{patch size}. $$

한 패치 안의 K개 점들 사이에 표준 multi-head self-attention을 한 번 돌린다. 비용을 따져보자 — 패치 수는 $N/K$, 패치마다의 비용은 $O(K^2 d)$, 따라서 총 비용은

(14.2) $$ \frac{N}{K}\,\times\,O(K^2 d) \;=\; O(N\,K\,d). $$

K는 보통 1024로 고정. 즉 비용은 $N$에 대해 선형이다. PT v1·v2의 어텐션이 가졌던 “k-NN 이웃 수 × 차원” 비용과 같은 차수지만, 차이가 둘 있다.

① k-NN이 없다
한 번 정렬해두면 인덱스 슬라이싱으로 끝
② 메모리 패턴
정렬된 연속 메모리, GPU에 매우 유리
직렬화된 시퀀스 (한 layer 분) Patch 1 Patch 2 Patch 3 패치마다 표준 multi-head self-attention Attn(Patch 1) K=1024 토큰 사이 밀집 K×K Attn(Patch 2) 병렬 Attn(Patch 3) 총 비용 = (N/K) × O(K² d) = O(NKd) · k-NN 없이 GPU 친화적
Figure 14.2 패치 어텐션. 시퀀스를 잘라 각 조각 안에서만 어텐션. 패치마다 독립이라 자연스럽게 병렬화된다.

14.3.1 패치 그룹화 — Shifted Patches와 곡선 회전

같은 패치 분할을 모든 layer에서 쓰면 패치 경계의 두 점은 영원히 만나지 못한다. PTv3는 두 가지 방법을 결합한다 — (a) 매 layer마다 다른 직렬화 곡선을 사용 (4종류 회전), (b) 시퀀스 시작점을 layer마다 시프트. 여러 layer를 거치며 점들 사이의 모든 가능한 “이웃 관계”가 결국 직간접으로 연결된다.

14.3.2 패딩 처리

현실에서 $N$이 $K$의 배수가 아닐 때, 마지막 패치는 더미 토큰으로 채워진다. attention mask로 더미 위치의 영향을 0으로 만들면 된다. 토큰 수 N이 들쭉날쭉한 점군에서 흔히 일어나는 일이라, PTv3 구현은 이 처리를 한 번에 묶어 GPU 친화적인 batched attention으로 돌린다(flash-attnxformers와 결합 가능).

14.4아이디어 3 — Conditional Position Encoding (xCPE)

패치 어텐션은 시퀀스 인덱스만으로는 “3D 위치”를 충분히 알지 못한다. PT v1·v2는 이를 어텐션 안에 $\delta_{ij} = \text{MLP}(p_i - p_j)$ 로 넣었다. PTv3는 더 단순한 방법을 쓴다 — sparse convolution 한 번을 어텐션 앞에 둔다. 이 sparse conv가 “3D 좌표 정보”를 특징 안으로 자연스럽게 주입하는 위치 인코딩 역할을 한다(conditional — 입력에 따라 적응한다).

(14.3) $$ \text{Block}(X, P)\;:\quad X' = X + \text{SparseConv}_{3\times 3\times 3}(X,\,P), $$ $$ Y = \text{LN}(X' + \text{PatchAttn}(X')), \quad Z = \text{LN}(Y + \text{FFN}(Y)). $$

sparse conv는 voxel 격자 위에서만 동작하므로, 점들을 voxel로 양자화한 표현 위에서 한 번 돌린다. 점 자체는 그대로 유지되고, voxel feature가 다시 점에 매핑된다. PTv3가 의존하는 sparse conv 라이브러리는 spconv 또는 torchsparse다.

이 한 줄짜리 변경의 의미가 크다 — PT v1·v2의 비싼 상대 위치 인코딩($\delta_{ij}$ 계산)을 통째로 대체한다. “가까운 점들의 정보 한 번 섞기”를 sparse conv가 빠르게 해주고, 그 다음 패치 어텐션이 “더 넓고 다양한 관계”를 책임진다. conv와 attention의 깔끔한 분업이다.

X (점 특징) xCPE SparseConv 3×3×3 Patch Attention 직렬화 + window FFN d→4d→d Z residual residual + LayerNorm
Figure 14.3 PTv3 한 Block. xCPE(sparse conv)로 위치 정보를 주입하고, 패치 어텐션으로 이웃 관계를 학습하고, FFN으로 채널별 비선형 변환. Vaswani 2017의 골격이 그대로 살아 있다.

14.5전체 아키텍처 — U-Net 백본

PTv3의 전체 네트워크는 PointNet++가 그랬듯, 5단계의 인코더와 4단계의 디코더로 이루어진 U-Net이다. 각 단계는 [Block × N] 으로 구성되며, Block은 위에서 본 “xCPE → Patch Attn → FFN”의 세 부품이다. 단계 사이의 다운/업샘플링은 voxel 격자 단위의 풀링으로 수행된다(공간을 (2×2×2) voxel로 합치며 점 수가 ~1/2~1/8로 줄어든다).

Points Stage 1 N · d=32 Block ×2 Stage 2 N/4 · d=64 Block ×2 Stage 3 N/16 · 128 Block ×6 Stage 4 N/64 · 256 Block ×2 Stage 5 N/256 · 512 bottleneck Up 4 N/64 Up 3 N/16 Block ×2 Up 2 N/4 Block ×2 skip connections head 각 Stage 안의 Block 수와 채널 수, 다운샘플 비율은 PTv3 paper Table에서 옴 옥내(ScanNet)와 옥외(nuScenes) 설정에서 일부 하이퍼만 다르고 골격은 같다
Figure 14.4 PTv3 전체 백본. 5단계 인코더 — 4단계 디코더의 비대칭 U-Net. Block 단위로만 patch attention을 사용, 다운/업샘플링은 voxel 격자 풀링으로.

14.5.1 하이퍼파라미터 한 묶음

요소비고
Patch size K1024한 attention 내부의 토큰 수
Stage 별 채널 수32 → 64 → 128 → 256 → 512전형적 U-Net
Stage 별 Block 수2 → 2 → 6 → 2 → 2중간 stage가 가장 두텁다
Heads 수2 → 4 → 8 → 16 → 32채널당 64 유지
FFN 확장표준 Transformer와 동일
ActivationGELUBatchNorm 대신 LayerNorm
Voxel size2 cm (실내) / 5 cm (실외)xCPE의 sparse conv 기준
직렬화 4종 순환z → z' → h → h'매 layer마다 변경

14.5.2 핵심을 30줄로 — 학습용 PyTorch 의사 코드

# PTv3의 한 Block을 단순화한 의사 코드 / Simplified PTv3 block
import torch, torch.nn as nn

class PTv3Block(nn.Module):
    def __init__(self, dim, heads, patch_size=1024, ffn_ratio=4):
        super().__init__()
        # 위치 정보 주입용 sparse conv / position-encoding sparse conv
        self.xcpe = SparseConv3d(dim, dim, kernel_size=3)
        self.norm1 = nn.LayerNorm(dim)
        self.attn  = nn.MultiheadAttention(dim, heads, batch_first=True)
        self.norm2 = nn.LayerNorm(dim)
        self.ffn   = nn.Sequential(
            nn.Linear(dim, dim*ffn_ratio), nn.GELU(),
            nn.Linear(dim*ffn_ratio, dim))
        self.K = patch_size

    def forward(self, x, coords, order):
        # x: (N, C) features, coords: (N, 3) xyz, order: (N,) serialization indices
        # 1) xCPE — 가까운 점끼리 한 번 섞기 / mix nearby points once
        x = x + self.xcpe(x, coords)

        # 2) 직렬화 순서로 정렬 / sort by curve order
        x_sorted = x[order]                                  # (N, C)
        N, C = x_sorted.shape
        K = self.K

        # 3) 패딩 후 패치 단위로 자르기 / pad to multiple of K, reshape
        pad = (-N) % K
        x_pad = torch.cat([x_sorted, x_sorted.new_zeros(pad, C)], 0)
        mask  = torch.arange(N+pad) >= N                     # True = padded
        x_pad = x_pad.view(-1, K, C)                         # (P, K, C)
        mask  = mask.view(-1, K)                             # (P, K)

        # 4) 패치 안에서 attention / attention inside each patch
        h = self.norm1(x_pad)
        h, _ = self.attn(h, h, h, key_padding_mask=mask, need_weights=False)
        x_pad = x_pad + h
        x_pad = x_pad + self.ffn(self.norm2(x_pad))

        # 5) 평탄화 → 원래 순서로 복원 / flatten and unsort
        x_sorted = x_pad.view(-1, C)[:N]
        out = torch.empty_like(x_sorted); out[order] = x_sorted
        return out

실제 구현은 flash-attn이나 xformers의 메모리 효율 attention을 끼워 넣고, 직렬화 인덱스는 torch_scatter의 정렬 보조 함수로 빠르게 만든다. 그리고 인코더-디코더의 풀링·언풀링은 voxel 그리드 인덱스를 통해 처리되므로 여기서는 생략했다.

14.6성능 — “더 빠르고 더 가볍고 더 정확한” 것의 의미

PTv3 논문의 핵심 비교(요약). 동일 모델(또는 그에 가까운 변종) 하나로 옥내·옥외·합성·실측을 모두 휩쓴다.

벤치마크지표이전 SOTAPTv3
ScanNet v2 (val)mIoU~76.4 (PTv2)77.5
S3DIS Area-5mIoU~71.673.4
nuScenes (val)mIoU~80.280.4
SemanticKITTImIoU~70.371.2
처리량(throughput) vs PTv2~3.3×
최대 메모리 vs PTv2~0.1×

특히 “여러 데이터셋을 하나로 묶어 함께 학습할 때(multi-dataset joint training)” 정확도가 더 오른다는 점이 중요하다. 이는 PTv3의 단순한 골격이 데이터의 다양성을 그대로 흡수할 수 있다는 증거다 — 곧 scale의 약속이 실현되었음을 보여준다.

실무 메모

옥외 자율주행 데이터(nuScenes, SemanticKITTI)에서는 한 프레임당 점 수가 수십만에 달한다. PTv2까지는 이 규모에서 학습이 매우 무거웠지만, PTv3는 단일 GPU 24GB에서도 batch size를 의미 있게 키울 수 있어 학습 사이클이 짧아진다. 산업 검사 데이터(예: 라인 트라이앵귤레이션 LVS 센서로 얻은 용접 비드 점군)도 같은 이유로 다루기 좋다.

14.7왜 그렇게 단순한 변경이 그렇게 큰 차이를 만드는가

마지막으로 한 번 응축한다.

① k-NN 제거
매 layer 검색 비용이 0 — 학습·추론 모두 가속
② 정렬된 메모리
scatter/gather 대신 contiguous slice — GPU 친화
③ 표준 attention 사용
flash-attn 등 모든 가속을 그대로 활용
④ Conv·Attention 분업
위치 인코딩이 단순해짐 — 학습 안정성 향상
⑤ Scale 친화 설계
데이터·파라미터를 키울수록 이득이 누적
§ 15 — Coda

정리 — 한 장으로 보는 흐름

다섯 정거장이었다. 각각이 이전 모델의 어떤 한계를 정확히 짚어 풀었는지 되짚어보자.

CNN 격자 + 좁은 이웃 ⨯ 비격자 입력 ⨯ 먼 의존성 Transformer 집합 + 모든 쌍 ⨯ N² 비용 ⨯ 점군 적용 불명 PointNet MLP + MAX ⨯ 지역 구조 없음 PointNet++ 계층 SA ⨯ 이웃 안에서 동등 PT v1 k-NN VA ⨯ k-NN ↑ PT v2 (NeurIPS 2022) Grouped VA + voxel pooling ⨯ k-NN 비용 잔존 PTv3 (CVPR 2024) 직렬화 + 패치 attention + xCPE ✓ 단순 · 빠름 · 정확 · 확장 각 단계는 “바로 앞 모델의 한 가지 약점”을 정확히 풀었다. PTv3는 “정밀도 대신 규모”라는 패러다임 전환으로 그 사슬의 매듭을 푼 것.
Figure 15.1 다섯 정거장의 진화. 각 모델은 이전 모델의 가장 무거운 한계를 정확히 짚어 풀었다.

15.1한 줄 요약

CNN의 “격자 + 좁은 이웃”은 self-attention의 “집합 + 모든 쌍”으로 일반화되었고, 그 결과는 점군에서 “k-NN으로 좁힌 이웃”으로 한 번 다시 좁혀졌다가, PTv3에서 “직렬화로 만든 1D 시퀀스의 패치”로 한 번 더 일반화되었다. 매 단계의 진보는 단순함을 향했다.

15.2다음 단계 — 더 읽으면 좋은 것

Sonata (CVPR 2025)
PTv3의 self-supervised 버전
Concerto (NeurIPS 2025)
PTv3 위의 2D-3D crossmodal pretraining
Pointcept
PTv3 등을 포함하는 점군 모델 라이브러리
FlashAttention
패치 어텐션 가속의 실용 도구

15.3생각해볼 만한 질문

  • 왜 “정렬”이 어텐션에 도움이 되는가? 토큰 위치만이 아니라 “어떤 토큰끼리 가까이 놓이는가”가 표현 학습에 영향을 준다는 점.
  • 패치 크기 K와 모델 깊이 사이의 균형은? 큰 K는 한 번에 더 많은 점을 보지만 K²의 비용. 작은 K는 더 깊은 층이 필요.
  • 4가지 직렬화 외에 다른 곡선은? Gilbert curve, Peano curve, learned curve … 아직 열린 문제.
  • 비정형(unstructured) 메쉬에서도 같은 발상이 통할까? 메쉬는 위상 구조가 있어 직렬화가 자명하지 않다. 그래프 spectral 정렬이 후보.

— 끝까지 함께 와줘서 감사. 좋은 점군과 좋은 모델이 있기를.