13장 — 가이던스: 조건 쪽으로 더 세게

과포화: 배율을 올리면 데이터 밖으로 밀려난다

ComfyUI의 cfg 기본값은 8이고, 설명은 「너무 크면 질이 나빠진다」고 경고한다. 낮·밤 장난감에서도 배율 8로 뽑은 그림의 91.0%가 밝기 1을 넘었다. 데이터에서 그 몫은 4.8%다. 그림으로 치면 낮 사진이 하얗게 날아간 것이다. 가이던스가 겨냥하는 분포가 원래 그렇게 생긴 걸까, 아니면 걷는 길에서 무슨 일이 생긴 걸까?

역사: 색이 날아가는 그림

호와 샐리먼스가 세게 이끈 그림에서 포화된 색을 본 것과 같은 일이, 글로 그림을 만드는 큰 모델에서는 더 크게 드러났다. 사하리아(Chitwan Saharia)와 동료들(2022)은 Imagen 논문에서 배율을 올리면 글과 그림이 더 잘 맞지만 그림은 「심하게 포화되고 부자연스러워진다」고 적고, 원인을 학습과 생성 사이의 어긋남에서 찾았다. 학습 때 원래 그림은 언제나 [−1, 1] 안에 있었는데, 큰 배율로 읽은 원래 그림 x̂₀가 그 범위를 넘는다. 신경망은 생성 내내 자기가 만든 출력을 다시 입력으로 받으므로, 한 번 범위를 벗어난 값이 다음 걸음의 입력을 학습 때 본 적 없는 곳으로 끌고 간다.

그들은 두 가지를 시험했다. 걸음마다 x̂₀를 [−1, 1]로 자르는 정적 잘라내기는 그림이 아예 망가지는 것은 막았지만, 배율이 커지면 여전히 과포화되고 결이 뭉개졌다. 그래서 걸음마다 x̂₀의 픽셀 절댓값 가운데 99.5번째 백분위수 s를 구해, s가 1보다 크면 [−s, s]로 자른 뒤 s로 나누는 동적 잘라내기를 내놓았다. 포화 직전의 픽셀을 안쪽으로 당겨 넣는 것이다. 다만 이 방법은 픽셀로 된 그림에만 쓸 수 있다. 잠재 공간에서 퍼뜨리는 모델은 잠재 변수의 범위가 정해져 있지 않다.

걸음마다 읽은 원래 그림

배율 8로 걸을 때 걸음마다 가이던스를 건 x̂₀를 기록해 보자. 첫 걸음(σ = 14.61)에서 x̂₀의 크기는 평균 4.00이다. 잡음이 이렇게 짙으면 낮 조건으로 읽은 원래 그림은 낮 그림의 중심 0.5, 빈 조건으로 읽은 원래 그림은 모든 그림의 중심 0에 가깝고, 0 + 8 × (0.5 − 0) = 4이기 때문이다. 오일러 걸음은 읽은 x̂₀와 잡음을 다음 잡음 크기로 다시 섞는 것이므로, 길 전체가 밝기 4 쪽으로 끌려간다. 잡음이 옅어지면 두 예측이 거의 같아져 미는 힘이 사라지지만, 그때는 이미 1을 넘은 자리에서 걷고 있다. 도착 분포는 평균 1.150, 표준편차 0.125다.

걸음이 거칠어서 생긴 일도 아니다. 같은 배율로 200걸음 걸어도 평균 1.139, 85.2%가 1을 넘는다. 잡음 0에서 겨냥하는 분포 p(x) p(낮 ∣ x)w는 w = 8에서도 1을 넘는 몫이 5.9%뿐이었다. 걸음마다 그 잡음 수준의 두 예측 차이를 키워 걸은 결과는, 잡음 0의 분포를 배율만큼 기울인 것보다 훨씬 멀리 간다. 이렇게 배율을 키운 가이던스가 그림을 데이터의 범위 밖으로 밀어내, 색이나 밝기가 한쪽 끝으로 날아가는 것을 과포화 (가이던스가 그림을 데이터 범위 밖으로 밀어내는 것 / oversaturation)라 한다. 다양성도 함께 준다. 표준편차가 0.280에서 0.125로 절반이 되었다.

Imagen의 정적 잘라내기처럼 걸음마다 x̂₀를 [−1, 1]로 자르면, 1을 넘는 그림은 0%가 되고 평균은 0.787이다. 그런데 0.97과 1 사이에 그림의 16.7%가 몰린다. 데이터에서 그 구간의 몫은 1.1%다. 범위 밖으로 나가는 대신 범위 끝에 쌓인 것이다. 사진이라면 하얗게 날아간 칸이 1.0으로 저장되는 것과 같다.

왼쪽: 배율 1, 3, 8로 걸을 때 걸음마다 가이던스를 건 x̂₀ 크기의 평균. 배율 8은 짙은 잡음에서 4까지 치솟았다가 잡음이 옅어지며 내려오지만 1 위에 머문다. 오른쪽: 도착한 밝기. 배율 8은 거의 다 밝기 1(점선) 너머에 있고, x̂₀를 [−1, 1]로 자르면 1 바로 아래에 몰린다.
왼쪽: 배율 1, 3, 8로 걸을 때 걸음마다 가이던스를 건 x̂₀ 크기의 평균. 배율 8은 짙은 잡음에서 4까지 치솟았다가 잡음이 옅어지며 내려오지만 1 위에 머문다. 오른쪽: 도착한 밝기. 배율 8은 거의 다 밝기 1(점선) 너머에 있고, x̂₀를 [−1, 1]로 자르면 1 바로 아래에 몰린다.
직접 움직여 보기걸음마다 읽은 원래 그림이 데이터 범위를 넘는가새 창에서 열기 ↗

ML에서: 넘침을 막는 손잡이들

픽셀에만 쓰이는 잘라내기를 잠재 공간 모델로 넓힌 것이 린(Shanchuan Lin)과 동료들(2023)의 가이던스 크기 다시 맞추기다. 가이던스를 건 출력의 표준편차를 조건으로만 읽은 출력의 표준편차에 맞춰 줄이고, 줄인 것과 줄이지 않은 것을 섞는다. 논문은 섞는 비율 0.7을 권했고, ComfyUI의 RescaleCFG 마디 기본값도 0.7이다. KAIST의 정형진(Hyungjin Chung), 예종철(Jong Chul Ye)과 동료들(2024)은 원인을 다른 곳에서 찾았다. 오일러 걸음은 읽은 원래 그림과 잡음을 다시 섞는데, 보통 가이던스는 다시 섞는 잡음까지 가이던스를 건 것에서 가져온다. 그들의 CFG++는 원래 그림에만 0~1 사이의 배율 λ(람다)로 가이던스를 걸고, 다시 섞는 잡음은 빈 조건에서 읽은 것을 쓴다(ComfyUI의 euler_cfg_pp 같은 _cfg_pp 샘플러). 퀸캐니에미(Tuomas Kynkäänniemi)와 동료들(2024)은 가이던스가 짙은 잡음에서는 해롭고 옅은 잡음에서는 거의 필요 없으며 가운데에서만 이롭다는 것을 보이고, 가이던스를 거는 잡음 구간을 좁혀 가로세로 512픽셀 ImageNet에서 FID를 1.81에서 1.40으로 낮췄다. 사다트(Seyedmorteza Sadat)와 동료들(2024)의 APG는 가이던스 차이를 조건부 예측과 나란한 성분과 수직인 성분으로 나누고, 과포화의 주범인 나란한 성분을 줄인다(ComfyUI comfy_extras/nodes_apg.py).

문제 13. 대비를 8배로

사진의 대비를 「0.5 + 배율 × (밝기 − 0.5)」로 키운다. 밝기는 0~1로 저장되고, 범위를 넘으면 잘린다. (가) 밝기 0.55, 0.6, 0.7인 세 칸은 배율 8에서 얼마가 되는가? (나) 잘린 뒤에도 세 칸을 서로 구별할 수 있는가? (다) 배율 2라면?

김민준 M01
김민준

대비를 키우면 더 선명해지니까 좋은 거 아니에요? 계산하면 0.9, 1.3, 2.1이에요.

선생님 T01
선생님

저장된 값은요?

김민준 M04
김민준

0.9, 1, 1이요. 0.6과 0.7이 똑같이 1이 됐어요. 원래는 달랐는데요.

이서연 S08
이서연

(다)는 0.6, 0.7, 0.9라서 셋이 다 살아 있어. 배율이 크면 밝은 쪽의 차이가 모두 끝값 하나로 뭉개지는 거네. 하얗게 날아간 하늘에 구름 결이 안 보이는 게 그거구나.

김민준 M08
김민준

필터 세기 문제에서 255로 잘린 것과 같은 일이에요. 잘라서 범위 안에 넣어도, 끝에 몰린 칸들은 이미 구별이 안 돼요.

문제 14. 어느 잡음에서 미는가

낮·밤 장난감의 자리 x = 0.3에서 (가) 잡음 크기 σ = 14.61, 1, 0.1일 때 x̂₀(낮)과 x̂₀(∅)를 구하고, w = 8로 가이던스를 건 x̂₀를 구하라. (나) 배율 8의 가이던스를 σ > 2인 걸음에서만 걸 때와 σ < 1인 걸음에서만 걸 때(나머지 걸음은 배율 1), 도착한 밝기의 평균과 표준편차는? (위젯 3의 「문제 14」 단추)

김민준 M01
김민준

자리가 0.3으로 같으니까 잡음 크기가 달라도 두 예측의 차이는 비슷하지 않을까요?

선생님 T01
선생님

계산해 보면요?

김민준 M05
김민준

σ = 14.61에서는 0.4999와 0.0005, 차이가 0.4994라 가이던스를 건 값이 4.00이에요. σ = 1에서는 0.4835와 0.0875, 가이던스는 3.26이고, σ = 0.1에서는 0.3200과 0.3153이라 0.353이에요. 잡음이 옅으면 거의 안 밀어요.

이서연 S08
이서연

잡음이 옅으면 그림이 이미 거의 보이니까 조건을 넣든 안 넣든 읽은 원래 그림이 비슷하지. 잡음이 짙을 때는 그림이 안 보이니까 두 예측이 각자의 평균, 0.5와 0으로 갈라지고.

김민준 M06
김민준

(나)는 σ > 2에서만 걸면 평균 0.917, 표준편차 0.218이고, σ < 1에서만 걸면 평균 0.854, 표준편차 0.094예요. 앞은 넓이는 덜 줄었는데 한참 오른쪽으로 갔고, 뒤는 덜 옮겨 갔는데 폭이 확 좁아졌어요.

선생님 T02
선생님

둘이 하는 일이 어떻게 다른 걸까요?

이서연 S09
이서연

짙은 잡음의 가이던스는 구름 전체를 어디에 둘지 정하고, 옅은 잡음의 가이던스는 이미 정한 자리에서 폭을 조여요. 걸음마다 같은 배율을 거는 게 꼭 맞는 건 아니네요. 어느 구간에 걸지도 고를 거리예요.

김민준 M07
김민준

조교님이 기획 단계에서 세게 잔소리하면 주제가 통째로 바뀌고, 마감 직전에 잔소리하면 맞춤법만 고쳐지는 거랑 같네요.

문제 15. 다시 섞는 잡음을 바꾸면

CFG++는 오일러 걸음 xi+1 = x̂₀ + σi+1ε̂에서 x̂₀에는 배율 λ로 가이던스를 걸고(x̂₀(∅) + λ(x̂₀(낮) − x̂₀(∅))), 다시 섞는 잡음 ε̂은 빈 조건에서 읽은 것(x − x̂₀(∅))/σi를 쓴다. (가) λ = 1이면 x̂₀는 낮 조건으로만 읽은 값이다. 그래도 가이던스가 걸리는가? (나) 보통 가이던스 w = 3(평균 0.803, 표준편차 0.167)과 평균이 비슷한 λ는? (다) 논문은 λ를 0과 1 사이에서 고르라고 권했다. 이 장난감에서 λ ≤ 1이면 과포화가 사라지는가? (위젯 3의 「문제 15」 단추)

김민준 M01
김민준

λ = 1이면 조건부 예측을 그대로 쓰는 거니까 그냥 조건부 생성이죠. 평균 0.5쯤 나오겠죠.

선생님 T01
선생님

걷는 식 전체를 보면요? 무엇이 조건부 생성과 다르죠?

김민준 M04
김민준

다시 섞는 잡음이요. 돌려 보니 평균 1.024, 표준편차 0.145예요. 51.6%가 1을 넘어요. 보통 가이던스 w = 5와 8 사이쯤이에요.

이서연 S08
이서연

빈 조건의 잡음은 「모든 그림의 중심 0에서 지금 자리까지」를 잡음으로 읽은 거야. 그걸 낮 그림의 원래 그림에 다시 섞으면, 걸음마다 그 차이만큼 낮 쪽으로 한 번 더 밀리겠지. 배율이 원래 그림에만 붙어 있어도 다시 섞는 잡음이 가이던스 몫을 하는 거네.

김민준 M06
김민준

(나)는 λ = 0.5에서 평균 0.783, 표준편차 0.181이에요. 보통 가이던스 w = 3보다 평균은 조금 낮고 폭은 조금 넓어요. λ = 0.7이면 0.893이고요.

선생님 T02
선생님

(다)는요? 논문이 1에서 멈추라고 한 까닭은 원래 그림 x̂₀가 두 예측 사이에만 있게 하려는 거였어요.

이서연 S09
이서연

λ ≤ 1이면 읽은 원래 그림은 0과 0.5 사이, 곧 두 예측 사이에 머물러요. 그래도 λ = 1에서 절반이 1을 넘었으니, 이 장난감에서는 넘침이 사라지지 않아요. 같은 세기끼리 견주면 폭이 조금 넓게 남는 정도예요. 논문이 말한 효과는 그림의 결이 망가지는 문제라, 숫자 하나짜리 장난감으로는 다 보이지 않는 것 같아요.

선생님 T13
선생님

맞아요. 대책마다 「무엇이 원인이라고 보았나」가 달라요. 잘라내기는 원래 그림의 범위를, 다시 맞추기는 출력의 크기를, CFG++는 다시 섞는 잡음을, 구간 좁히기는 미는 때를, APG는 미는 방향을 원인으로 봤어요. 장난감 하나로는 그 가운데 일부만 재 볼 수 있어요.

김민준 M07
김민준

「고칠 점만 반영해」라고 했는데 원본 대신 남의 초안을 바탕으로 고치면 결국 남의 초안 쪽으로 가는 거네요.