15장 — 그림으로 조건 걸기: 참조 이미지 여러 장

자주 하는 실수와 요약

자주 하는 실수

실수 나온 문제 바로잡는 법
ControlNet 은 참조 그림의 대상을 어디에나 옮겨 그리게 한다고 봄 1, 2 복제 인코더의 출력은 같은 해상도의 같은 칸에 더해진다. 조건 그림과 결과는 칸이 맞는다
0 합성곱 대신 작은 무작위 값으로 이어도 비슷하다고 봄 2 첫 걸음부터 모든 건너뛰기 연결에 낯선 값이 더해진다. 0에서 시작해야 첫 모델이 원래 모델 그대로다
ControlNet 출력을 조건 예측에만 넣으면 가이던스가 알맞다고 봄 3 그 차이가 배율만큼 커져 지나치게 세진다. 두 예측 모두에 넣고 프롬프트가 비면 차이가 0이 된다
참조 그림 토큰을 글 토큰 줄에 이어 붙이면 충분하다고 봄 5 하나의 softmax 에서 참조 토큰 넷이 글 토큰들과 비중 1을 나눠 갖는다. 글이 길수록 묻힌다
위치 없는 참조 토큰 여러 장으로 「A 의 이것, B 의 저것」을 가를 수 있다고 봄 6 열쇠·값의 순서를 바꿔도 어텐션 출력은 같다. 참조 토큰 줄은 주머니다
채널로 겹쳐 잇는 쪽이 늘 가볍고 낫다고 봄 8 토큰 수는 그대로지만 참조와 결과의 칸이 맞아야 하고, 크기가 다르거나 여러 장이면 불편하다
참조 토큰 자리에서도 손실을 재야 한다고 봄 9 참조에는 잡음을 섞지 않았으니 맞힐 정답 속도가 없다. 출력과 손실은 생성 그림 자리에서만
참조 토큰이 깨끗하다는 것을 변조로 알리지 않는 길은 틀렸다고 봄 9 어느 길이 맞는지는 모델이 무엇으로 학습했느냐에 달렸다
번호 축이 생성 칸과 참조를 완전히 떼어 놓는다고 봄 10, 11 고른 성분의 평균으로는 번호 하나 차이가 점수를 1% 남짓만 바꾼다. 얼마나 갈라 볼지는 학습이 정한다
참조를 여러 장 넣을 때 번호를 1, 2, 3 으로 매기는 쪽이 늘 맞다고 봄 12 한 장으로 배운 모델에는 번호 1 에 옆으로 펼치는 쪽이 학습 때 본 좌표에 가깝다. 모델이 배운 방법에 맞춘다
그림 토큰 수만큼 위치 번호도 나아간다고 봄 14 세 축 위치에서는 그림의 가로세로 칸 수만큼만 나아간다. 768토큰 그림이 32칸을 쓴다
시각언어모델로 읽는 길이 가벼우니 늘 낫다고 봄 15 토큰 하나가 32 × 32 픽셀을 맡고 뜻 쪽으로 정리된 값이라 결은 덜 남는다. 이중 인코딩은 두 길을 함께 쓴다

요약

그림을 조건으로 거는 길은 그림을 무엇으로 바꿔 어디에 넣느냐로 가른다. ControlNet 은 얼린 U-Net 의 내려가는 쪽을 복제해 윤곽선·뼈대·깊이 지도를 읽게 하고, 그 출력을 0에서 시작하는 1 × 1 합성곱으로 같은 해상도의 건너뛰기 연결에 더한다. 칸끼리 더하므로 조건 그림과 결과는 자리가 맞는다. 「이 얼굴」처럼 자리와 상관없는 참조는 내용으로 골라 읽어야 하므로, IP-Adapter 는 참조 그림을 CLIP 그림 벡터에서 편 토큰 4개(또는 16개)로 바꿔 원래 크로스 어텐션 곁의 새 크로스 어텐션으로 따로 읽히게 하고, 그 몫에 λ 를 곱해 더한다. 하나의 softmax 에 이어 붙이면 참조가 글 토큰 사이에 묻히기 때문이다. 다만 토큰 몇 개로는 참조의 결이 남지 않고, 위치가 없어 여러 장을 가를 수도 없다.

디퓨전 트랜스포머는 참조를 줄이지 않고 VAE 잠재 토큰 그대로 생성할 그림의 토큰 줄에 이어 붙인다(FLUX.1 Kontext, Qwen-Image-Edit). 참조에는 잡음을 섞지 않고, 출력과 손실은 생성 그림 자리에서만 쓰며, 참조 한 장이 1024 × 1024 면 줄이 4,096토큰 길어진다. 생성 칸과 참조, 참조끼리는 좌표의 첫째 축인 번호 축으로 가른다. Kontext 는 참조에 번호 1을, ComfyUI 의 index 방식은 장마다 1, 2, 3 을, FLUX.2 는 10, 20, 30 을 주고, offset 방식은 번호 1에 참조들을 옆으로 펼친다. 끝으로 「1번 사진의 강아지」처럼 글과 참조의 짝은 시각언어모델이 그림 토큰과 지시문을 한 줄로 함께 읽어 잇는다. Qwen-Image-Edit 은 이 뜻의 길과 잠재의 결의 길을 함께 쓰고, krea.ai 의 Krea 2 는 같은 열두 층 뽑기로 그림 끼운 프롬프트를 조건으로 바꾼다.

flowchart LR
  A["ControlNet<br/>복제 인코더 · 칸끼리 더하기"] -->|"자리와 상관없는<br/>참조는 못 전한다"| B["IP-Adapter<br/>토큰 4개 · 따로 읽기"]
  B -->|"토큰 몇 개로는<br/>결이 남지 않는다"| C["참조 이어 붙이기<br/>잠재 토큰 그대로 같은 줄"]
  C -->|"같은 좌표에<br/>겹친다"| D["번호 축<br/>(번호, 행, 열)"]
  D -->|"글 속 「1번」과<br/>번호의 짝이 없다"| E["그림 끼운 프롬프트<br/>시각언어모델이 함께 읽기"]

막힌 곳

이제 그림 여러 장을 조건으로 넣을 수 있다. 참조마다 번호를 매겨 생성할 그림의 「앞 장면」처럼 줄에 세우고, 글과 참조의 짝은 시각언어모델이 잇는다. 그런데 번호 축을 따라 그림을 줄 세우다 보면, 만들고 싶은 것이 한 장이 아니라 그 줄 전체일 때가 있다. 1초에 열여섯 장, 10초면 160장이 넘는 그림이 시간 순서대로 이어지는 영상이다. 장마다 4,096토큰이라면 줄은 감당하기 어려울 만큼 길어진다. 한 번에 다 만들 수 없어 앞 장면에 이어 다음 장면을 만들어 가면, 앞에서 생긴 작은 어긋남은 뒤로 갈수록 어떻게 될까?