11장 — 잠재 디퓨전: 작게 줄여 놓고 퍼뜨리기

자주 하는 실수와 요약

자주 하는 실수

실수 나온 문제 바로잡는 법
픽셀 수의 비를 한 변의 비로 셈 1, 2 가로세로가 함께 줄므로 수의 비는 한 변의 비의 제곱이다
버린 정보는 누구에게나 버려도 되는 정보라고 봄 1 무엇이 중요한지는 받는 쪽의 목적이 정한다. 이름표를 읽을 사람에게는 같은 압축이 실패다
PSNR 이 비슷하면 눈에도 비슷하다고 봄 2 PSNR 은 칸마다의 오차를 같은 무게로 더한다. 어디를 틀렸는지는 모른다
디퓨전을 잘 학습하면 압축기가 지운 결도 되살아난다고 봄 3 디퓨전이 만든 잠재는 디코더를 거친다. 압축기의 되살리기가 생성의 천장이다
수를 많이 줄인 요약이 좋은 잠재라고 봄 4 디퓨전 신경망은 칸의 배치로 그림을 읽는다. 줄인 뒤에도 「어디」가 남아야 한다
비중이 작은 KL 항은 빼도 된다고 봄 5 KL 항이 없으면 잠재의 크기를 막을 것이 없다. 10⁻⁶은 끝없이 커지는 것만 막는다
잠재의 수가 많을수록 칸도 많다고 봄 6 칸 수는 압축 배율로 정해진다. FLUX.2 는 수는 가장 많지만 칸은 4분의 1이다
채널을 늘리면 공짜로 좋아진다고 봄 6 되살리기는 좋아지지만 디퓨전이 맞힐 수가 늘어 큰 모델이 필요하다
잡음의 크기가 같으면 어떤 데이터에도 같은 영향을 준다고 봄 7 영향은 데이터 크기와 잡음 크기의 비가 정한다
마지막 걸음이 거의 잡음이면 N(0, I)에서 출발해도 된다고 봄 8 스케일 값을 곱하지 않으면 마지막 걸음에 신호가 12% 남는다. 학습 때 본 적 없는 출발점이 된다
스케일 값 하나로 모든 채널이 표준편차 1이 된다고 봄 9 수 하나는 채널끼리의 크기 비를 바꾸지 못한다. SD 1.x 의 넷째 채널은 0.56이다
비싼 일을 하나 더 넣으면 이득이 사라진다고 봄 10, 11 디코더는 한 장에 한 번이다. 다만 걸음이 적을수록 그 몫이 커진다(4걸음에서 44%)
denoise 를 0에 가깝게 두면 사진이 그대로 돌아온다고 봄 12 압축기를 한 번 왕복하는 것만으로 차이가 생긴다
다 담는 기록이 지어내기 연습에도 좋다고 봄 13 지어낼 때는 담긴 것을 모두 그럴듯하게 맞춰야 한다. 배우기 좋게 정리된 기록이 따로 필요하다
되살리기가 좋은 압축기가 생성에도 좋다고 봄 14 같은 디퓨전 예산에서는 채널을 늘린 압축기 쪽 생성이 나빴다(FID 16.24 → 36.83). 뜻을 따라 정리하는 손실이 그 맞바꿈을 줄인다
생성 그림의 흠을 압축기를 바꿔 다시 뽑아 보며 가림 15 압축기를 바꾸면 디퓨전도 다시 학습해야 한다. 진짜 그림을 같은 크기로 왕복시켜 압축기만 따로 잰다

요약

그림 한 장의 수 대부분은 눈이 알아채지 못하는 촘촘한 결에 쓰인다. 픽셀에서 퍼뜨리는 디퓨전은 그 결까지 칸마다 맞히느라 계산의 대부분을 쓴다. 잠재 디퓨전은 이 일을 둘로 나눈다. 결을 걸러 내는 지각 압축은 미리 학습해 얼려 둔 오토인코더(압축기)가 맡고, 디퓨전은 줄인 공간에서 그림의 뜻만 배운다. 압축기는 합성곱으로 지어 칸의 배치를 지키며 가로세로를 압축 배율 f배 줄이고 칸마다 C개의 수를 담는다(SD 1.x 는 8과 4로 수 48분의 1). 흐리지 않게 되살리려고 칸마다의 오차에 지각 손실과 판별 손실을 더하고, KL 항은 10⁻⁶ 정도로 거의 끈다. 그 대가로 잠재의 크기가 자유로워 표준편차가 5 남짓이 되므로, 스케일 값(SD 1.x 는 0.18215)을 곱해 잡음 일정이 기대하는 크기 1에 맞춘다. 맞추지 않으면 잡음이 신호를 덮는 걸음이 끝의 일부로 몰린다. 학습은 그림마다 인코더를 한 번 돌려 얻은 잠재로, 생성은 잠재 크기의 잡음에서 출발해 끝에 디코더를 한 번 돌린다. 같은 U-Net 한 번이 픽셀 512²에서는 잠재에서보다 679배 무겁다. 압축기의 되살리기는 생성의 천장이라, 뒤의 모델들은 채널을 16, 128로 늘려 천장을 올리고 그만큼 디퓨전 모델을 키웠다. 작게 그린 글자와 손가락은 압축기를 한 번 왕복하는 것만으로 무너질 수 있다. 그런데 채널을 늘려 되살리기를 좋게 하면 같은 예산의 생성은 나빠지는 되살리기와 생성의 딜레마가 있어, 잠재를 그림의 뜻을 따라 정리하는 손실을 더하거나 뜻을 담는 표현 인코더를 얼려 두고 디코더만 붙이는 표현 오토인코더가 나왔다.

flowchart LR
  A["픽셀 디퓨전<br/>결까지 칸마다 맞힌다"] -->|"비트 대부분이<br/>눈에 띄지 않는 결"| B["지각 압축을 압축기에<br/>오토인코더, KL 10⁻⁶"]
  B -->|"칸의 배치를 지킨다"| C["잠재 그림<br/>f = 8, C = 4 → 48분의 1"]
  C -->|"크기가 5 남짓"| D["스케일 값 κ<br/>표준편차를 1로"]
  D --> E["잠재 디퓨전<br/>학습: 인코더 한 번<br/>생성: 디코더 한 번"]
  E -->|"압축기가 천장"| F["채널을 늘린 압축기<br/>16 · 128채널"]
  F -->|"되살리기 ↑ 생성 ↓"| G["뜻을 담는 잠재<br/>특징 맞추기 · 표현 오토인코더"]

막힌 곳

이제 512 × 512 그림을 64 × 64칸에서 만든다. U-Net 한 번이 픽셀에서보다 수백 배 가벼워졌고, 그 덕에 큰 그림도 손에 닿는 계산으로 뽑는다.

그런데 사람들이 바라는 그림은 계속 커진다. 1024 × 1024 그림의 잠재는 128 × 128 = 16,384칸이고, 칸끼리 서로 읽는 쌍은 2억 개가 넘는다. 1024 × 1024 그림을 만드는 SDXL 의 U-Net 은 그래서 가장 고운 128 × 128칸 단계에는 어텐션을 두지 않고 합성곱으로 이웃만 보았다. 멀리 보는 일을 점점 어텐션에 맡기는 흐름이라면, 합성곱 단계를 아예 걷어 내고 어텐션만으로 잠재를 읽을 수는 없을까? 그렇다면 16,384칸을 어떻게 다뤄야 쌍의 수가 감당될까? 압축 배율을 더 키우면 되살리기가 무너지는데, 칸을 줄이는 일을 압축기 말고 신경망 쪽에서 할 수는 없을까?