포스트

짝지은 이미지 없이 스타일을 바꾸려면: CycleGAN 손실함수와 구현 핵심

서로 짝지어진 정답 이미지가 없어도 두 도메인 사이의 변환과 원상 복구를 함께 학습시키면 CycleGAN으로 스타일을 옮길 수 있습니다. 다만 GAN loss 하나만으로는 입력의 구조가 유지된다고 보장할 수 없으므로 cycle loss와 identity loss의 역할을 분리해 확인해야 합니다. 결과를 고를 때는 보기 좋은 한 장보다 여러 입력에서 내용 보존, 스타일 변화, 불필요한 색 변화가 일관적인지를 봐야 합니다.

Unpaired 변환에서 필요한 세 가지 약속

CycleGAN은 Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks의 줄임말입니다. 여름 사진과 겨울 사진처럼 두 이미지 집합은 있지만, 각 사진에 정확히 대응하는 변환 결과가 없을 때 사용하는 접근입니다.

CycleGAN 모델 구조

이 구조를 이해할 때는 손실의 역할을 분리해서 보는 편이 쉽습니다.

  • GAN loss는 변환된 이미지가 목표 도메인의 실제 이미지처럼 보이도록 압박합니다.
  • Cycle loss는 한쪽 도메인에서 다른 쪽으로 갔다가 돌아온 이미지가 원본과 가까워지게 합니다.
  • Identity loss는 이미 목표 도메인에 속한 입력을 불필요하게 바꾸지 않도록 합니다.

GAN loss만 보면 목표 도메인과 닮은 결과는 만들 수 있어도 입력의 내용이 유지된다는 보장은 약합니다. 반대로 cycle 관계만 맞추는 것으로는 목표 도메인의 질감을 충분히 설명하기 어렵습니다. 세 손실은 같은 역할을 반복하는 것이 아니라 서로 다른 실패를 막습니다.

Residual block과 Instance Normalization을 쓰는 이유

Residual block은 두 번의 convolution과 normalization을 거친 결과를 입력에 다시 더합니다. 아래 표기는 네트워크 전체가 아니라 한 블록의 흐름을 나타내는 구조 조각입니다.

1
2
x -> conv -> norm -> relu -> conv -> norm -> y
return x + y

입력을 우회해 더하는 경로가 있으므로 네트워크는 전체 영상을 처음부터 다시 만드는 대신 바꿔야 할 부분을 학습하는 데 집중할 수 있습니다. Instance normalization은 각 feature map의 채널별로 정규화하며, 배치 크기에 덜 의존해 학습하도록 돕습니다.

Instance normalization 개념

판별 손실에는 sigmoid cross entropy 대신 least squares를 쓰는 LSGAN 구성이 들어갑니다. 원문의 핵심 식은 실제 이미지의 판별값을 1에 가깝게, 가짜 이미지의 판별값을 0에 가깝게 만드는 형태입니다.

1
2
3
4
fake_cost = tf.reduce_mean(tf.squared_difference(fake, 1.0))

real_cost = tf.reduce_mean(tf.squared_difference(real, 1.0))
fake_cost = tf.reduce_mean(tf.square(fake))

이 조각만으로 모델이 실행되지는 않습니다. fakereal을 만드는 생성기, 판별기, optimizer, 데이터 입력이 별도로 필요합니다.

손실 가중치는 무엇을 바꾸나

원문 구현은 256×256 RGB 이미지, 학습률 0.0002, 배치 크기 1을 사용하고 세 가중치를 다음처럼 둡니다.

1
2
3
4
5
6
7
8
9
10
11
img_ch = 3
img_size = 256
learning_rate = 0.0002

gan_w = 1.0
cycle_w = 10.0
identity_w = 5.0

epoch = 2
iteration = 100000
batch_size = 1

최종 생성기 손실은 GAN, cycle, identity 항을 가중 합산합니다. cycle_w가 상대적으로 큰 것은 왕복한 결과와 원본의 차이를 강하게 반영하는 구성입니다. 그렇다고 숫자만 복사해 모든 데이터에 최적이라고 볼 수는 없습니다. 변환 결과가 입력의 구조를 잃는지, 반대로 스타일 변화가 지나치게 약한지를 보며 각 손실이 무엇을 누르고 있는지 확인해야 합니다.

원문 구현의 전체 코드는 CycleGAN 저장소에서 확인할 수 있고, 데이터는 Berkeley CycleGAN 데이터셋을 사용하도록 안내돼 있습니다.

실행 전에 빠뜨리기 쉬운 조건

이 기록의 구현은 Python 3, SciPy, NumPy, tqdm, TensorFlow를 전제로 하며 코드 구조도 여러 파일로 나뉩니다.

  • ops: TensorFlow 연산 유틸리티
  • utils: 이미지 로딩과 저장
  • CycleGAN: 모델 본체
  • train: 학습 흐름 제어

따라서 게시된 하이퍼파라미터와 손실식은 완전한 실행 프로그램이 아니라 핵심 조각입니다. 데이터셋의 두 도메인을 준비하고, 저장소의 파일 구조와 의존성을 갖춘 다음에야 학습 흐름을 확인할 수 있습니다. 결과를 판단할 때도 “목표 스타일과 닮았는가”만 보지 말고, 왕복 변환에서 원래 내용이 유지되는지와 같은 도메인 입력이 불필요하게 변하지 않는지를 함께 살펴봐야 합니다.

결과가 그럴듯해도 실패로 봐야 하는 경우는 무엇인가

CycleGAN의 실패는 단순히 이미지가 흐린 경우만이 아닙니다. 생성기가 입력과 관계없는 목표 도메인 이미지를 만들어도 판별기를 속일 수 있으므로, 사람, 건물, 경계처럼 유지돼야 할 구조가 사라지는지 먼저 봐야 합니다. 왕복 이미지가 원본과 비슷하더라도 중간 변환이 원하는 의미를 보존했는지는 별도의 샘플로 확인해야 합니다.

두 도메인의 데이터 차이가 스타일을 넘어 내용 구성까지 다르면 모델이 엉뚱한 상관관계를 배울 수 있습니다. 예를 들어 한 집합에는 특정 배경이 반복되고 다른 집합에는 다른 구도가 반복된다면, 목표 스타일 대신 배경이나 구도를 바꾸는 지름길을 택할 수 있습니다. 따라서 학습 전에 해상도와 색 공간뿐 아니라 장면 구성의 편향도 비교해야 합니다.

검토용으로는 같은 입력들의 원본, 정방향 변환, 왕복 복원, identity 출력을 한 줄에 놓는 방식이 유용합니다. 스타일 변화가 약하면 GAN 항과 데이터 구분 가능성을 보고, 내용이 무너지면 cycle 항과 변환 난도를 봅니다. 목표 도메인 이미지를 넣었는데 색이 크게 달라지면 identity 항이 의도한 제약을 주는지 확인합니다.

함께 읽으면 이해가 이어지는 글

자주 묻는 질문

CycleGAN은 짝지어진 원본과 정답 이미지가 없어도 되나요?

네. 두 도메인의 이미지 집합은 필요하지만 이미지별 일대일 대응은 요구하지 않습니다. 대신 양방향 변환과 원상 복구를 함께 학습해 입력 내용이 사라지는 문제를 제한합니다.

cycle loss가 낮으면 변환도 성공한 것인가요?

반드시 그렇지는 않습니다. 왕복 복원은 잘돼도 목표 도메인의 질감이 약할 수 있으므로 GAN 결과와 함께 봐야 하며, 같은 도메인 입력이 불필요하게 바뀌는지도 identity 결과로 확인해야 합니다.

글의 가중치 1, 10, 5를 다른 데이터에도 그대로 쓰면 되나요?

출발점으로 비교할 수는 있지만 최적값으로 단정할 수 없습니다. 구조 보존이 무너지면 cycle 항을, 색이나 질감까지 불필요하게 바뀌면 identity 항을 중심으로 결과를 비교해야 합니다.

학습 전에 두 도메인을 어떻게 점검해야 하나

먼저 두 폴더에서 같은 수의 샘플을 무작위로 뽑아 해상도, 구도, 피사체 종류, 배경, 밝기를 나란히 봅니다. 목표가 계절이나 질감 변환인데 한쪽에는 실내 사진만 있고 다른 쪽에는 실외 사진만 있다면 모델은 스타일이 아니라 장소 차이를 학습할 수 있습니다. 두 집합의 파일 수가 같다는 사실만으로 내용 분포가 대응하는 것은 아닙니다.

전처리도 양쪽에 같은 의미로 적용되는지 확인합니다. Resize나 crop이 피사체의 중요한 구조를 잘라 내면 cycle loss가 원래 의도와 다른 복원을 배울 수 있습니다. 색상 범위와 normalization이 생성기 출력 범위와 맞지 않으면 손실 숫자는 계산돼도 저장 이미지가 비정상적으로 보일 수 있습니다. 학습 전에 한 batch를 복원해 원본과 비교하는 단계가 필요합니다.

평가 샘플은 학습에 사용한 이미지와 분리하고, 쉬운 장면과 어려운 장면을 함께 둡니다. 각 입력마다 원본, 변환, 역변환, identity 결과를 고정된 순서로 저장합니다. 한 방향만 보기 좋고 반대 방향이 무너지거나, 중앙 피사체는 유지되지만 가장자리가 반복해서 변형되는지도 기록합니다.

가중치를 비교할 때는 같은 checkpoint 시점과 같은 입력을 사용합니다. 스타일 강도, 구조 보존, 색상 유지, 반복 artifact를 각각 메모하면 cycle loss 한 숫자로 가려지는 차이를 볼 수 있습니다. 목표가 무엇인지 정하지 않은 채 가장 선명한 결과만 고르면 데이터 편향을 성공으로 오해하기 쉽습니다.

학습 중에는 생성기와 판별기 loss가 존재한다는 사실만 보지 말고 고정 샘플의 변화도 함께 저장합니다. 판별기가 지나치게 쉽게 구분하면 생성기에 유용한 신호가 부족할 수 있고, 생성 결과가 한 형태로 반복되면 다양한 입력을 반영하는지 의심해야 합니다. 숫자와 이미지를 같은 시점에 남겨야 실패를 재현할 수 있습니다.

저장 이미지는 파일명에 방향과 학습 시점을 표시합니다. A→B와 B→A를 섞거나 서로 다른 checkpoint 결과를 나란히 놓으면 가중치 변화의 효과를 잘못 판단할 수 있습니다. 같은 검토 표를 유지하는 것이 화려한 예시 몇 장보다 유용합니다.

THE END / OPSOAI

여기까지 읽었습니다

핵심 장면을 한 번 더 떠올려 보세요. 이해가 남았다면 이 책은 제 역할을 다했습니다.

다른 책 고르기
표지 1

키와 좌우 스와이프를 지원합니다. 읽던 페이지는 이 기기에 저장됩니다.

CONTENTS

이 책의 목차

    8개 장 16 분읽는 시간