<INTRO>
최근 몇 년간 diffusion 모델은 엄청 발전했고 특히 text to image generation editing 등등은 엄청 잘한다. 하지만 video gerenation은 여전히 연구해야할 문제로 남아있음. 특히, 일관된 프레임 생성과 텍스트 프롬프트에 내재된 motion 패턴의 이해는 여전히 어려운 문제이다.
최근의 연구들은 비디오 디퓨전 모델을 직접 학습시키거나 제로샷으로 하는것도 있지만 두가지 방법 다 한계가 있다. 일단 training을 시키는건 대규모 라벨링 데이터와 training resource를 필요로 한다. Zero shot의 방법은, 예를 들어 T2V-Zero는 T2I 모델을 변형하여 훈련 없이 consistent 한 비디오를 생성하려고 했지만, 텍스트-이미지 지식을 비디오 도메인으로 전이하는 데에는 한계가 있었다.
LAMP는 fewshot 데이터셋(8~16개)와 단일 GPU를 사용하여 특정 motion 패턴을 학습하도록 T2I 디퓨전 모델을 튜닝하는 fewshot based 프레임워크이다. pretrained 된 T2I모델로 첫 프레임을 생성하고, 첫 frame을 기반으로 다음 frame을 예측하는 방식. 자세한건 밑에서 다룰 예정.
Few-shot-based T2V Generation Setting
N개의 비디오세트로 데이터가 구성되어있으며 각 비디오에는 특정 움직임ㅇ르 설명하는 프롬프트 Pm 이 포함되어있다
학습의 목표는 비디오 콘텐츠가 아닌 공통된 움직임 패턴ㅇ르 학습하는것. 프롬프트 Pm과 비디오세트 V를 통해 모델이 공통된 움직임ㅇ르 파악하도록 하고, 이를 통해 유사한 움직ㅇㅊ임 패턴을 가진 새로운 비디오 V'르 생성할 수 있다.
기존의 T2I모델을 소규모 비디오 세트와 움직임 프롬프트에 맞춰 튜닝하는데, 이 튜닝된 모델은 프롬프트 P를 받았을 때 기존 비디오 세트와 유사한 움직임을 가진 새로운 비디오 V'를 생성할 수 있다.
First-Frame-Conditioned Pipeline
First-Frame-Conditioned Pipeline은 few-shot 으로 비디오 디퓨전모델이 움직임에 집중하도록 설계된 방식이다. 첫 프레임 정보를 유지하면서 나머지 프레임들에 노이즈를 추가하여 비디오 content보다는 움직임 패턴만을 학습하도록 유도다.
주어진 비디오 \( V = \{ f_i | i = 1, \dots, l \} \)는 \( l \)개의 프레임으로 구성된다. 각 프레임은 latent로 encoding되어 \( Z = \{ z_i | i = 1, \dots, l \} \) 형태로 표현된다.
loss function은 다음과 같다
- 모델이 두 번째 프레임부터 \( l \)-번째 프레임까지의 노이즈를 정확히 예측하도록 학습한다
- 움직임 패턴에 집중: 첫 프레임의 정보는 유지되고 나머지 프레임에는 노이즈가 추가되므로, 모델은 첫 프레임의 콘텐츠 정보를 고정한 상태에서 나머지 프레임의 움직임을 예측하게 된다.
inference단계에서는 SD-XL 모델을 사용하여 첫 번째 프레임 \( \hat{f}_1 \)을 생성하고 이를 디코딩하여 \( \hat{z}_1 \)을 얻는다. 이후 [\( \hat{z}_1, \epsilon_2, \dots, \epsilon_l \)]의 순서로 입력하여 전체 비디오를 생성.
최종적으로, 첫 프레임을 기준으로 나머지 프레임의 움직임을 예측하면서 비디오를 생성하는 느낌.
Temporal-Spatial Motion Learning Layers
Temporal-Spatial Motion Learning Layers는 시간적(temporal) 및 공간적(spatial) 움직임 특징을 학습하도록 설계된 layer. 시간적, 공간적 움직임 강도를 효과적으로 분리하여 학습할 수 있도록, 1D 및 2D 컨볼루션 layer를 결합한다
Input 비디오는 프레임 단위로 나뉘며, 각 프레임은 특정 채널, hxw를 가진다.
1. Temporal Branch
이 branch에서는 프레임 간의 움직임을 학습하도록 한다. 이를 위해 텐서를 재구성하여 **1D 컨볼루션**을 적용한다.
구체적으로는
먼저 입력 텐서를 시간 차원에 맞게 \( bhw \times c \times f \) 형태로 변형한다. 여기서 \( bhw \)는 각 프레임을 공간 좌표로 묶어 하나의 공간적 위치를 나타내는 것.
그리고
변형된 텐서에 대해 시간 차원 \( f \)을 따라 **1D 컨볼루션**을 수행하여 프레임 간의 시간적 관계를 학습한다. 그러나 이 1D 컨볼루션은 한 번에 하나의 공간 좌표만을 대상으로 하기 때문에 공간적 정보는 놓ㄹ치게 된다. 그래서 필요한게 spatial branch.
# Temporal Branch: 1D Convolution을 통한 시간적 특징 학습
x_1d = rearrange(x_2d, "b c f h w -> (b h w) c f", f=video_length) # 시간 축에 맞게 재구성
x_1d = self.conv1d(x_1d)[:, :, :-2] # 시간 차원에 1D 컨볼루션 적용
x_1d = rearrange(x_1d, "(b h w) c f -> b c f h w", h=h, w=w) # 원래 텐서 형식으로 복원
2. Spatial Branch
각 프레임 내의 공간적 움직임 강도를 학습하여 공간적 정보를 보완한다. 이를 위해 입력 텐서를 \( bf \times c \times h \times w \) 형태로 변형하고, 2D 컨볼루션을 사용한다.
구체적으로는
2D 컨볼루션의 출력 채널을 1로 설정하여 각 공간 좌표에서 움직임의 강도를 표현하고 시그모이드 함수를 적용하여 각 위치의 중요도를 0과 1 사이로 조절한다
여기서 \( S \)는 움직임 강도를 조절하는 scalar값이고, 시그모이드 \( \sigma \) 함수가 공간적 위치의 중요도를 결정한다. 이 과정으로 움직임이 강한 영역은 1에 가까운 값을, 움직임이 적은 영역은 0에 가까운 값을 갖게 된다.
# Spatial Branch: 공간적 특징 학습
x_gate = rearrange(x_2d, "b c f h w -> (b f) c h w") # 텐서를 각 프레임 단위로 재구성
x_gate = self.sigmoid(self.conv_gate(x_gate)).repeat(1, c, 1, 1) # Conv2D + Sigmoid
x_gate = rearrange(x_gate, "(b f) c h w -> b c f h w", f=video_length)
3. 비디오 prediction기반 1D 컨볼루션
모델이 첫 프레임을 기준으로 다음 프레임을 예측할 수 있도록, 기존의 1D 컨볼루션을 비디오 예측 방식으로 수정했음
기존 1D 컨볼루션은 현재 프레임의 특징을 생성하지만, 이 방식에서는 이전 두 프레임을 기반으로 다음 프레임의 특징을 생성한다. 즉, 커널이 \( \{ f_{i-1}, f_i, f_{i+1} \} \)를 지나갈 때, \( f_i \)가 아닌 \( f_{i+1} \)을 예측한다
이를 통해 모델은 이전 프레임의 정보를 바탕으로 시간적 일관성을 유지하며 자연스러운 비디오 예측을 수행하게 됨.
4. Zero Initialization
새로 추가된 layer들이 기존 T2I 모델의 성능에 영향을 주지 않도록 모든 파라미터를 0으로 초기화한다. 이건 controlnet에서 나왔던거랑 똑같음
Attention Layers in Temporal-Spatial Motion Learning
Attention Layers는 비디오 생성 모델이 일관된 움직임과 시간적 관계를 유지하도록 하기 위해 수정함. 특히, 첫 프레임의 조건을 모든 프레임이 참조하게 하여, 비디오의 각 프레임에서 주요 객체와 특징이 잘 유지되도록 한다.
1. Self-Attention Layer modification
일반적으로 self-attention은 모든 프레임에서 각각의 쿼리 \( Q \), 키 \( K \), 값 \( V \)를 추출하여 상호작용을 한다. 그러나, 여기서는 첫 프레임의 키와 값만을 참조하도록 self-attention을 수정했음.
이 수식을 통해 모든 프레임은 첫 프레임의 키와 값을 참조하여 일관된 조건을 유지하게 된다. 이를 통해 첫 프레임의 주요 객체와 특징이 모든 프레임에 반영되어 비디오의 일관성이 강화된다.
일반적인 Self-Attention: 모든 프레임에서 독립적으로 쿼리 (𝑄), 키 (𝐾), 벨류 (𝑉) 를 계산한다면
수정된 Self-Attention: 모든 프레임에서 첫 번째 프레임의 키 (𝐾1)와 벨류(V1)를 공유
key = rearrange(key, "(b f) d c -> b f d c", f=video_length)
key = key[:, [0] * video_length] # 첫 프레임의 키를 모든 프레임에 반복
key = rearrange(key, "b f d c -> (b f) d c")
value = rearrange(value, "(b f) d c -> b f d c", f=video_length)
value = value[:, [0] * video_length] # 첫 프레임의 값을 모든 프레임에 반복
value = rearrange(value, "b f d c -> (b f) d c")
2. Temporal Attention Layer 추가
이와 함께 **Temporal Attention Layer**가 추가했음. 시간적 차원에서 self-attention을 수행하여 프레임 간의 시간적 관계를 학습하게 한다.
기존 self-attention이 프레임 내 공간적 관계를 학습하는 것과 달리, 프레임 간 시간적 연결을 유지하며 자연스러운 흐름을 만들 수 있고, 이를 통해 모델은 시간 흐름에 따라 변화하는 객체의 움직임을 더 잘 학습하게 된다.
# Temporal-Attention 추가
hidden_states = rearrange(hidden_states, "(b f) d c -> (b d) f c", f=video_length)
norm_hidden_states = (
self.norm_temp(hidden_states, timestep) if self.use_ada_layer_norm else self.norm_temp(hidden_states)
)
hidden_states = self.attn_temp(norm_hidden_states) + hidden_states
hidden_states = rearrange(hidden_states, "(b d) f c -> (b f) d c", d=d)
Shared-noise Sampling During Inference
Shared-noise Sampling During Inference는 비디오 생성 시 프레임 간 일관성을 강화하기 위해 제안된 노이즈 샘플링 기법이다.
비디오 생성의 모든 프레임이 공유된 노이즈를 부분적으로 사용하여 일관성을 높인다.
- 먼저, **공유 노이즈** \( \epsilon_s \)를 정규분포 \( N(0, I) \)에서 샘플링한다
- 그 다음, 각 프레임에 적용할 **개별 노이즈** \( [\epsilon_2, \dots, \epsilon_l] \)를 동일한 분포에서 샘플링한다.
각 프레임의 노이즈 \( \epsilon_i \)는 공유 노이즈 \( \epsilon_s \)와 개별 노이즈 \( \epsilon_i \)의 가중 평균으로 계산한다.
이를 통해 모든 프레임에 공통 요소를 추가하여 프레임 간 유사성을 강화할 수 있다고 한다.
직관적으로는 비디오의 각 프레임이 일정 수준의 유사성을 가지므로, 일관성을 가질 수 있고, 수학적으로 보면 노이즈의 분산이 줄어들어 latent space의 범위가 좁아져 더 안적적이다
Result