ControlNet (인공지능)
더 많은 작업
- ControlNet; 컨트롤넷
- 사전 학습된 텍스트-이미지 확산 모델을 고정해 둔 채, 윤곽선·깊이·자세 같은 공간 조건으로 생성 결과의 구도를 제어하도록 덧붙이는 신경망 구조
ControlNet(컨트롤넷)은 스테이블 디퓨전 같은 대형 텍스트-이미지 확산 모델에 공간 조건 입력을 추가하는 구조다. 원래 모델의 가중치는 잠그고(locked), 인코더 부분의 학습 가능한 사본(trainable copy)을 만들어 조건 이미지를 받게 한 뒤, 0으로 초기화한 1×1 합성곱("제로 합성곱", zero convolution)으로 두 쪽을 잇는다. 2023년 2월 스탠퍼드 대학교의 장뤼민(Lvmin Zhang), 라오안이(Anyi Rao), 머니시 아그라왈라(Maneesh Agrawala)가 발표했고,[1] 이 논문은 ICCV 2023 최우수 논문상(마르 상)을 받았다.[2]
산업 자동화에 쓰는 ODVA의 필드버스 네트워크 ControlNet과는 다른 것이다.[3]
텍스트만으로는 "사람이 왼손을 들고 오른쪽을 보는" 자세나 건물의 정확한 윤곽을 지정하기 어렵다. ControlNet은 에지 지도, 깊이 지도, 사람 골격 같은 그림을 직접 넣어 구도를 고정하고, 내용과 화풍은 프롬프트로 정하게 해 준다. 조건 종류마다 ControlNet을 따로 학습하지만 원 모델의 가중치는 건드리지 않는다.
신경망 블록 가 특성맵 를 로 바꾼다고 하자. ControlNet은 를 고정하고, 같은 블록을 복제해 학습 가능한 매개변수 를 만든 뒤 조건 벡터 를 더해 넣는다. 두 개의 제로 합성곱 , 로 연결하면 출력은 다음과 같다.[1]
제로 합성곱은 가중치와 편향을 모두 0으로 초기화한 1×1 합성곱이다. 학습 첫 단계에서는 두 항이 모두 0이라 , 곧 원래 모델과 똑같이 동작한다. 학습 사본도 원 모델의 가중치를 그대로 이어받았으므로, 무작위 초기화된 새 층이 내는 잡음이 수십억 장으로 학습한 백본을 망가뜨리지 않는다.
출력이 0인데 학습이 되는 이유는 기울기에 있다. 1×1 합성곱 에서 이어도 는 입력 에 비례하므로 0이 아니다. 그래서 첫 단계에서 바깥쪽 제로 합성곱 가중치가 먼저 0을 벗어나고, 그다음부터 안쪽 학습 사본과 첫 제로 합성곱으로 기울기가 흐른다. 아래 최소 구현에서 이를 확인할 수 있다.
스테이블 디퓨전의 U-Net은 인코더 12블록, 중간 블록 1개, 디코더 12블록으로 되어 있다. ControlNet은 인코더 12블록과 중간 블록의 학습 사본을 만들고, 그 출력 13개를 제로 합성곱을 거쳐 U-Net 디코더의 스킵 연결 12개와 중간 블록에 더한다.[1]
- 조건 이미지는 512×512지만 U-Net은 64×64 잠재에서 동작하므로, 4×4 커널·보폭 2인 합성곱 4층(채널 16, 32, 64, 128, ReLU)으로 된 작은 인코더가 조건을 64×64 특성 공간으로 바꾼다. 이 인코더는 가우스 초기화하고 전체와 함께 학습한다.
- 잠근 부분은 기울기를 계산할 필요가 없어 효율적이다. A100 PCIe 40GB 한 장에서 ControlNet을 붙인 학습은 붙이지 않은 스테이블 디퓨전 미세 조정에 비해 GPU 메모리 약 23%, 반복당 시간 약 34%만 더 들었다.[1]
- 스테이블 디퓨전 1.5와 2.1은 U-Net 구조가 같아 같은 방식으로 붙는다.
학습 목표는 조건을 하나 더 받는 것 말고는 일반 확산 모델과 같다.
는 텍스트 프롬프트, 는 조건 이미지에서 얻은 특성이다. 학습 중 텍스트 프롬프트의 50%를 빈 문자열로 바꿔서, 프롬프트가 없을 때도 조건 이미지만 보고 의미를 알아내게 했다.[1]
논문은 "갑작스러운 수렴"(sudden convergence) 현상을 보고했다. 제로 합성곱 덕분에 학습 내내 모델은 정상적인 이미지를 내지만 조건은 무시하다가, 어느 순간(그림의 예에서는 6,133단계) 갑자기 조건을 따르기 시작한다. 보통 1만 단계가 안 되어 일어난다고 했다.[1] 학습 데이터가 5만 장 미만으로 적어도 100만 장 넘게 많아도 학습이 안정적이었고, 깊이 조건 ControlNet을 RTX 3090 Ti 한 장으로 20만 장, 5일 학습한 결과를 대형 A100 클러스터에서 1,200만 장 이상으로 학습한 스테이블 디퓨전 2 깊이 모델과 비교한 사용자 실험에서 사람들은 둘을 거의 구별하지 못했다(정답률 0.52±0.17).[1]
원 논문과 저자가 공개한 모델이 다룬 조건은 다음과 같다.[1]
| 조건 | 만드는 방법 | 쓰임 |
|---|---|---|
| 캐니 에지(Canny) | 캐니 에지 검출기 | 윤곽선을 그대로 살린 재채색·화풍 변환 |
| M-LSD 직선(허프 직선) | 직선 검출기 | 건물, 실내 구조 |
| HED 소프트 에지 | HED 에지 검출 신경망 | 부드러운 윤곽 유지 |
| 낙서(scribble), 사용자 스케치 | 손그림, 에지 지도 변형 | 대충 그린 그림을 완성된 이미지로 |
| 사람 자세(OpenPose) | 관절 키포인트 검출 | 인물 포즈 지정 |
| 분할 지도(ADE20K) | 의미론적 분할 | 영역별 배치 지정 |
| 깊이 지도 | 단안 깊이 추정 모델 | 공간 구도·원근 유지 |
| 법선 지도(normal map) | 법선 추정 | 표면 방향, 입체감 |
| 만화 선화 | 선화 추출 | 애니메이션풍 채색 |
여러 ControlNet의 출력을 그냥 더하면 여러 조건을 한꺼번에 걸 수 있다(예: 자세 + 깊이). 논문은 별도 가중치나 보간이 필요 없었다고 했다.[1]
분류기 없는 가이던스를 쓸 때 조건 이미지를 조건부·무조건부 예측 양쪽에 넣으면, 프롬프트가 없는 어려운 경우 가이던스가 완전히 사라진다. 반대로 조건부 쪽에만 넣으면 가이던스가 너무 세진다. 논문은 조건부 쪽에만 넣되, ControlNet과 스테이블 디퓨전 사이의 각 연결에 블록 해상도에 따른 가중치 ()를 곱하고 가이던스 세기를 낮추는 "CFG 해상도 가중"을 제안했다.[1]
Hugging Face diffusers의 StableDiffusionControlNetPipeline은 다음 인자를 제공한다.[4]
controlnet_conditioning_scale(기본 1.0): ControlNet 출력을 U-Net 잔차에 더하기 전에 곱하는 값. 여러 ControlNet이면 목록으로 준다.control_guidance_start,control_guidance_end(기본 0.0, 1.0): 전체 단계 중 ControlNet을 적용할 구간의 비율. 초반에만 걸면 구도만 잡고 세부는 자유롭게 둔다.guess_mode: 프롬프트를 지워도 ControlNet 인코더가 입력 이미지의 내용을 알아보게 하는 모드. 문서는 이때guidance_scale을 3.0~5.0으로 권장한다.
PyTorch 2.5에서 실행해, 초기 상태의 출력이 원 블록과 정확히 같고 첫 역전파에서 바깥쪽 제로 합성곱만 기울기를 받는 것을 확인했다.
import copy, torch, torch.nn as nn
def zero_conv(ch):
conv = nn.Conv2d(ch, ch, kernel_size=1)
nn.init.zeros_(conv.weight)
nn.init.zeros_(conv.bias)
return conv
class ControlledBlock(nn.Module):
def __init__(self, block, ch):
super().__init__()
self.trainable = copy.deepcopy(block).requires_grad_(True) # 학습할 사본
self.locked = block.requires_grad_(False) # 원 블록은 고정
self.z1, self.z2 = zero_conv(ch), zero_conv(ch)
def forward(self, x, cond):
return self.locked(x) + self.z2(self.trainable(x + self.z1(cond)))
block = nn.Sequential(nn.Conv2d(8, 8, 3, padding=1), nn.SiLU())
m = ControlledBlock(block, 8)
x, c = torch.randn(1, 8, 16, 16), torch.randn(1, 8, 16, 16)
out = m(x, c)
assert torch.equal(out, block(x)) # 처음에는 원래 모델과 동일
out.sum().backward()
print(m.z2.weight.grad.abs().sum() > 0) # True: 바깥 제로 합성곱이 먼저 학습됨
print(m.z1.weight.grad.abs().sum()) # 0: z2가 0인 동안은 안쪽으로 기울기가 안 감
# diffusers 0.3x~0.41 기준. 최신 판은 torch_dtype 대신 dtype 인자도 받는다.
import cv2, numpy as np, torch
from PIL import Image
from diffusers import ControlNetModel, StableDiffusionControlNetPipeline, UniPCMultistepScheduler
from diffusers.utils import load_image
src = np.array(load_image("input.png"))
edges = cv2.Canny(src, 100, 200) # 저·고 임계값
control = Image.fromarray(np.stack([edges] * 3, axis=-1))
controlnet = ControlNetModel.from_pretrained(
"lllyasviel/control_v11p_sd15_canny", torch_dtype=torch.float16)
pipe = StableDiffusionControlNetPipeline.from_pretrained(
"stable-diffusion-v1-5/stable-diffusion-v1-5", controlnet=controlnet,
torch_dtype=torch.float16).to("cuda")
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
image = pipe(
"a cozy wooden cabin in a snowy forest, golden hour",
image=control,
controlnet_conditioning_scale=0.8, # 제어 세기
control_guidance_end=0.8, # 마지막 20% 단계는 제어 해제
num_inference_steps=30,
).images[0]
SDXL, 스테이블 디퓨전 3, FLUX.1용 ControlNet 파이프라인도 같은 방식으로 쓴다. diffusers 공식 안내서는 FLUX.1 [dev]에 캐니 ControlNet을 붙이는 예를 기본 예제로 싣고 있다.[5]
| 방식 | 추가 구조 | 학습 비용 | 특징 |
|---|---|---|---|
| ControlNet | 인코더 전체의 학습 사본 + 제로 합성곱 | 큼(인코더 크기만큼 매개변수) | 조건 충실도가 높음, 여러 조건 합성 가능 |
| T2I-Adapter[6] | 원 모델을 고정한 채 가벼운 어댑터만 학습 | 작음 | 조합성이 좋고 추론 부담이 적음. ControlNet과 같은 시기(2023년 2월) 발표 |
| LoRA 미세 조정 | 저랭크 가중치 갱신 | 작음 | 화풍·인물 같은 "내용"을 가르치는 데 쓰고 공간 구도 제어용은 아님 |
| 전체 미세 조정(예: 깊이 조건 SD 2) | 입력 채널 추가 후 전체 재학습 | 매우 큼 | 대규모 데이터와 연산 필요 |
| 인페인팅·img2img | 추가 학습 없음 | 없음 | 원본 픽셀을 기반으로 하므로 구도를 바꾸며 유지하기는 어려움 |
diffusers 문서는 새 작업에는 ControlNet을 권하고, T2I-Adapter는 예전 스테이블 디퓨전 계열용 "레거시 어댑터"로 분류해 두었다.[5]
- ↑ 1.00 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 Lvmin Zhang, Anyi Rao, Maneesh Agrawala, 〈Adding Conditional Control to Text-to-Image Diffusion Models〉, ICCV 2023. arXiv:2302.05543
- ↑ Computer Vision Foundation, 〈CVF Awards〉, ICCV Best Paper Award (Marr Prize) 2023 수상 목록. thecvf.com
- ↑ ODVA, 〈ControlNet〉. odva.org
- ↑ Hugging Face, 〈pipeline_controlnet.py〉, diffusers 소스 코드. github.com
- ↑ 5.0 5.1 Hugging Face, 〈ControlNet〉 사용 안내서, diffusers 문서. huggingface.co
- ↑ Chong Mou 외, 〈T2I-Adapter: Learning Adapters to Dig out More Controllable Ability for Text-to-Image Diffusion Models〉, 2023. arXiv:2302.08453