heheh
히히
heheh
전체 방문자
오늘
어제
  • 히히 (75)
    • AI (14)
      • Model (Study) (3)
      • Model (Paper) (7)
      • Tip! (4)
    • Backend (3)
      • ASP.NET (1)
      • Spring (2)
      • program (0)
      • JAVA (0)
    • Program (11)
      • Docker (3)
      • Github (5)
      • AWS (3)
    • OS (1)
      • Window (1)
      • Linux (0)
    • Python (14)
      • Python Lib (11)
      • Pytorch (1)
      • Tensorflow (1)
      • 크롤링 (1)
    • Spark (3)
      • Scala (2)
      • Pyspark (0)
      • SQL (1)
    • IOS (Swift) (0)
      • 기본 개념 (0)
    • 프로젝트 (3)
      • [AI] GAN (0)
      • [IOS] Swift (3)
      • [AI] 추천시스템 (0)
    • 분석 (1)
    • 알고리즘 풀이 (22)
      • 백준 (22)
    • 기타 (3)
      • 장비세팅 (3)
      • 소개 (0)

인기 글

최근 글

최근 댓글

hELLO · Designed By 정상우.
heheh

히히

[GAN] 다양한 GAN의 이론 설명
AI/Model (Study)

[GAN] 다양한 GAN의 이론 설명

2022. 1. 31. 13:33

 

DCGAN

표준정규분포로 얻어진 벡터를 샘플링하고 컨볼루션 기반의 레이어를 통과.

 

PGGAN

고해상도 이미지를 위해 점진적인 학습 모델을 사용함.

작은, 4x4 resolution g의 첫, d의 마지막 레이어를 가져와서 해당 사이즈를 먼저 학습함.

activation map은

4x4x1024 를 ex.1x1 conv(rgb 로 바꾸기 위함.)를 거쳐 4x4x3으로 변형 후 tanh를 거쳐 -1~1로 변형 후 0~255의 rgb로 매핑

latent space 의 4x4x1024를 rgb형태로 바꿔줌으로써 이미지로 변형.

descr의 인풋으로 넣어주기 위해선, 위에서 나온 레이어를 4x4x필요채널수 (가령 512)로 변형해주는 from RGB 작업을 거치도록 함.

이렇게 한 뒤 더 큰 사이즈의 레이어를 추가하여 기존 레이어로 이니셜하여 학습 시작. 이렇게 lower레이어(?)를 순차적으로 학습하여 많은 렝ㅣ어를 학습할 수 있도록 한다.

gradient vanishng을 해결하도록 해서 고해상도 이미지를 잘 학습할 수 있도록 함!

 

AdaIN (adaptive instant normalization?)

normalization 레이어중 instant norm을 확장한 것

입력 정보의 평균과 분산을 0과 1로 만든 후, 입력값이 가지는 고유 통계정보를 없앤 후 최적이라 생각되는 평균 분산 값을 주어진 입력정보에 주입하여 변형된 정보를 다음 레이어에 전달.

Instant Norm에서 하는 일은, activartion map에서 채널 하나별로 (NxMx채널개수) 발견되는 총 NxM 개의 activation값들의 평균 분산을 계산. 각 acti 값을 x로 볼 때 (x-평균)/분산 의 공식으로 변형하면 평균이 0 분산이 1인 형태로 변환됨. 모든 채널을 이렇게 정규화.

이미 정규화된 평균 분산에, 딥러닝이 최적이라 생각하는 평균 분산을 새로 곱해준다.
-> 고유 평균 분산을 제거 후 원하는 평균 분산을 적용한다.

A. pretrained 된 특정 conv레이어가 뱉은 activation map인 - 스타일을 주입하고자 하는 입력 이미지와,

B. 스타일을 담고있는 이미지를 학습해 뱉은 activation map이 존재.

A의 평균 분산을 0으로.

B의 채널별 평균 분산을 가져와서 A의 채널 별로 적용 (A의 평균 분산이 B와 같아짐) 후 디코더를 거친다. 그렇게 얻은 이미지가 원하는 스타일로 변형된 이미지이다.

loss function은 디코딩 후 나온 맵이, 입력 이미지를 인코딩한것과 일치하는 학습 and vgg 통과 후 평균 분산을 선형 변환(분산x + 평균)한 것과 일치하는 학습 두가지 진행된다.

 

Style GAN

버전 두가지.

Style GAN

항상 동일한 activation map이 입력데이터로 들어간다. (상수 activation map)

그리고 표준정규 분포로 얻어진 랜덤 샘플링 된 벡터가 입력으로 들어가지 않고, 곁다리로 들어간다. 기존 방식과 다른 부분.

제너레이터에 중간중간 삽입되는 형태. 스타일이라는 형태로 반영이 된다. (위의 AdaIN의 주입 형태 레이어.)

채널 별로 다른 평균 분산값이 들어가서 컨트롤 해줌으로써 고품질의 이미지가 생성된다.

상수 맵에 평균은 0, 분산은 아주 작은 퀄터베이션..? 을 추가하며 마이너한 변화들을 넣어 다양한 이미지를 생성할 수 있도록 도와줌. 이 과정은 adain 전에 이루어짐

Style GAN 2 - 다시 공부

몇몇 문제점 지적하며 adain를 간소화하는 방향. 이미지가 조금 부자연스러운 부분을 해결.

activation map을 직접 컨트롤 하는것이 아닌, conv filter 의 가중치 w를 스케일링하는 방법. filter coep

i 입력인덱스 /  j 아웃풋채널인덱스 / k spatial resolution /si : conv filter의 파라미터를 채널 별로 스케일링. modulation -> 평균분산 컨트롤을 비슷하게 모사함. 분산값을 컨트롤할 수 있는 형태.

demodulation : 평균0분산1로 만드는 과정에 대응됨. 입력채널과 spatial resolution들에 대해서 (채널별로 스케일링된 conv fil에 대해서) coep의 길이가 1이 되도록 정규화. 즉 해당 필터하나에 담긴 coep이 슬라이딩으로 적용해 내적을 적용하여 하나의 스칼라로 output activation으로 할 수 있게 되어 해당 아웃풋의 스케일을 조정 가능.

 

Style  Transfer

주어진 이미지에 다른 이미지를 주입하여 스타일이 변환된 이미지를 생성하는 태스크

스타일이라는 정보가 어떤식으로?

입력 : style 이미지(스타일 정보) / content 이미지(변형할 이미지) 두개.

사전 학습된 CNN 모델을 가져온다. 유의미한 정보를 추출하도록 이미 학습되어 있으므로 거기에 style transfer를 적용.

gram matrix : feature들간 correlation한 모든 값을 행렬로 나타냄. 채널 간 양 or 음의 상관관계를 나타내는데(corr의 공식임), 이것이 스타일의 정보를 담고 있다고 생각할 수 있다.

한번에 계산하려면, activtion을 사람 당을 열로 나타내도록 리쉐입한 후 이걸 transpose한걸 곱하게 되면 바로 해당 행렬이 통째로 계산된다.

이 gram mat를 활용하는법은

변형할 이미지의 레이어도 gram mat로 나타내도록 변형하여 스타일 gram mat와 동일해지도록 학습한다.

즉 loss는 1. relu(어떤?)와 2. 동일하도록 학습하는 loss 두개를 같이 사용하여 학습된다.

 

GAN의 조건부 생성 및 변환

예시: 남여

CGAN

여자 조건을 넣어 생성한건 real, 남자 조건을 넣어 생성한건(일반 gan에선 real이지만 여자 이미지를 뽑고 싶은 경우이므로) fake로 판별자가 판단

ACGAN

판별자의 벡터가 늘어남.

real/fake를 뽑고 추가적으로 분류하고 싶은 라벨들 길이만큼 확률을 추출 (ex. real, 남:0.7, 여:0.3)

 

pix2pix

CGAN 사용

먼저 색상을 입힌 결과와 트레인 데이터의 실제 rgb값의 차를 L1 loss를 사용하여 진짜와 가까워지게 학습. (여긴 gan아님. 정답 이미지가 있기에 가능. 그래서 paired setting임)

다음 판별자에서 1. 이미지 자체가 realistic한지. 2. 스케치이미지와 색상이미지를 concat해서 서로 맞는지. 두가지를 판별

이미 본이미지가 있는데 더 품질이 좋아지는 이유는?

판별자의 convolution operation(합성곱)를 통해 각 l1 loss가 잡지 못하는 픽셀 각각의 loss를 구분할 수 있게 된다.

gan : loss를 우리가 설정한 objective function을 통해 가장 최적화된 loss가 학습에 의해 결정된다. (이전엔 하이퍼파라미터 잡듯 입력했음.)

코드구현

decoder에서 unet 사용 : encoder와 레이어별 concat 진행

D 학습 (pred가 붙은 건 D 결과)

fake_pred <-> fake_label 의 MSE

real_pred <-> real_label 의 MSE

두 loss 결합 후 zero_grad 학습

G 학습

fake_pred <-> real_label 의 MSE

fake_b(G거친 결과) <-> 실제이미지 의 L1

두 loss 결합 후 zero_grad 학습

 

 

 

cycle GAN

unpaired setting. 정답 이미지가 없음.

얼룩말을 갈색말로 생성한 후, 판별자는 학습용으로 모은 갈색말 이미지와 대조하여 real 판별.

문제점 : 학습용 갈색말 중 특정한 판별이 쉬운 사진으로 고정되어 판별하도록 모델이 조작되면, 얼룩말 데이터의 포즈등의 정보는 전혀 담기지않은. 잘못된 학습이 일어날 수 있음. 그래서 cycle구조를 추가.

기존 모델 구조에, 변환된 갈색말을 다시 얼룩말로 변환한 후 입력 얼룩말과 동일하도록 학습하는 구조가 추가됨. (이부분은 픽셀별 L1 loss 사용) 이 과정에서 입력 이미지에서 보존할 수 있는 정보는 최대한 보존하도록 함. 이것과 동시에 갈색말의 스코어도 올려야 함.

Q. 두 loss와 스코어가 모두 100을 찍는 방향은 없을거같은데.. 아닌가? 얼룩말은(이론상) 100찍을수 있겠다. 갈색말은 스코어를 올리는 방향.

- 속성 개수 만큼의 모델이 필요함

코드구현

서로 다른 도메인의 두 데이터 셋이 필요

각 도메인 변경 방향에 따라 G 2개 D 2개 필요함

d 학습

도메인1 D가 real 이미지 1로 예측 loss + 도메인2 D가 real 이미지 1로 예측 loss 

두 loss 결합 후 zero_grad 학습

도메인1 D가 g 이미지 0로 예측 loss + 도메인2 D가 g 이미지 0로 예측 loss

두 loss 결합 후 zero_grad 학습

g 학습

mnist에 대해

g 결과 D 값이 1이 되도록

g 결과 다시 g 에 넣어서 (recon_mnist) mnist - recon_mnist 가 미니마이즈되게

두 loss 결합 후 zero_grad 학습

svhn에 대해
동일하게 실행 후 zero_grad

 

 

starGAN

하나의 생성 모델로 다양한 속성 정보 변환. -multi domain 이미지 변환 모델

ACGAN 채택

G : 입력 이미지 + 도메인 정보 D : 판단

출력 : real/fake , 머리색/성별

도메인 정보를 원핫으로 원하는만큼 늘려서 각 채널에 배정

cycle loss 채용

mask vector

코드 구현

dataloader : CelebA   는 기본 제공 로더가 없어서 조금 복잡하게 구현해야함. 참고 및 공부~

Residual Block : resnet 모델에서 나온 개념. 일반적인 vgg 모델 구조에서 중간에 residiual connection이라는 연결 다리를 넣어주어 f(x)+x를 만들어 빠른 학습과 좋은 성능을 가능하게 함. InstanceNorm을 시퀀셜 사이에 추가하여 Residual Block 함수를 추가함.

conv 정의

deconv 정의

 

Generator

: 중간에 bottle neck layer추가 - 작은 사이즈 resolution에서 더 다양한 레이어를 깊게 쌓아 g의 capability를 늘려주는 역할 

conv (down-sampling)

res (bottle neck)

deconv, conv, tanh (up sampling)

 

Forward

타겟 이미지를 입력 이미지와 동일한 사이즈로 만들어준 뒤 concat하여 모델에 입력.

후 generator 구조와 동일

 

Discriminator

1. generator아웃풋 or real 이미지가 리얼인지 페이크인지 맞추는 gen (batch, 1) scalar

2. 이미지가 가지는 도메인이 어떤 도메인을 가지는지 구분하는 cls (batch, 도메인크기)

두가지로 구분됨.

 

gredient penalty - 인풋이미지와 결과의 l2norm이 1이 되도록 하는 loss (= norm결과 -1  **2 가 최소화되도록 로직 구성)

 

 학습

D

real을 1로 분류하는 loss + 진짜 이미지에서 도메인 분류 cls loss 

G 거친 fake 이미지를 fake로 예측하는 loss

진짜 이미지와 가짜 이미지를 일정한 비율로 섞어서 d에 입력하고 gradient_penalty 값을 loss로 사용하도록 함.

이 모든게 합쳐지면 D의 loss. zero_grad 적용

G

g에 넣어 fake이미지를 만들고 d에 넣었을 때 이미지가 리얼이라고 판단하고(out_src), 타겟 도메인 정보를 담고 있어야 함(out cls).

오리지널 domain정보를 넣으면 원래 이미지처럼 되어야 한다. l1 loss가 minimize되는 방향.

다 더하면 g_loss가 되며 zero_grad 적용

 

 

 

 

멀티 모달 이미지 투 이미지

같은 도메인 내에서도 다양한 스타일이 존재할 수 있다. 대표 : MUNIT, DRIT

입력 도메인의 인코더를 거쳐 나온 벡터를 사용할 때,

입력 아웃풋 만을 디코더 입력으로 받는 것이 아니라 출력 도메인의 세부 속성정보(스타일 정보)를 추가 입력으로 받아 이를 종합해서 출력 도메인 이미지로 매핑한다. 이는 한 도메인에서도 다양한 정보를 얻을 수 있다.

 

MUNIT

로직 : a. 입력 도메인의 인코더 결과 + b. 출력 도메인의 세부 속성 정보를 뽑는 style encoder -> global avg pooling -> fc -> AdaIN를 거친 결과 -> 두개를 합쳐서 디코더에 입력한다.

content뽑는 encoder , style 뽑는 인코더 두개가 존재한다.

각 도메인 별로 (남, 여 각각. 타겟 도메인을 무엇으로 할것인가의 기준으로.) 디코더 또한 따로 존재.

우선 여성 이미지에서 스타일인코더, 컨텐트인코더, 디코더를 학습하여 (모두 여성 기준) 이 아웃풋은 여자 자신의 이미지가 나와야하고, 힉셀별로 값이 똑같아야 한다는 l1, l2로스등으로 학습 진행. 남성도 동일하게 진행.

그다음 여성에서 남성으로 변환시->

여성 도메인에서 뽑인 이미지에 컨텐트 인코더를 사용해 컨텐트 이미지를 뽑는다. 그다음 남성 도메인 스타일 벡터를 (일단은.) 랜덤하게 스탠다드 가우시안?방식으로 추출한다. 그다음엔 남성 도메인 디코더로 넣어준다. 변환된 남성 이미지를 다시 스타일인코더, 컨텐트인코더를 거치는데 원이미지 컨텐트결과와 동일해야한다의 l1로스 and 앞에서 추출해 주입한 스타일과 동일해야 한다의 로스를 사용하게 된다. (이모습이 사이클과 유사해서 Cycle consistency loss로도 부른다.)

 

이 모델은 다양한 스타일 이미지를 반영해서 이미지를 변환할 수 있다는 특징을 가진다!!!

 

 

 

DRIT

munit과 다른점 3가지

1. 컨텐트 인코더의 w를 공유함 : munit은 다른 도메인별로 인코더가 존재해도 각 아웃풋은 같은 latent space를 가져야 한다. drit도 같은 가정을 가지지만 그 이전 중간 레이어의 아웃풋들도 미리 같은 space로 매핑되어 content vector가 같은 space를 가져야 한다는걸 강제할 수 있게 된다.

2. 스타일코드(풀링된 2차원)를 AdaIN이 아닌 디코딩 과정의 activation map에 채널 방향으로 변환해 concat하여 진행한다.

3. content discriminator 사용. 컨텐트 인코더를 거쳐 나온 컨텐트 코드는 각 도메인별로 나오는데 두개가 같은space에 존재하는, 즉 두개가 공통적으로 가지는 속성정보를 나타내야 한다는 조건을 주입하기 위해, 이 벡터들을 입력으로 받아 어느 도메인에서 나왔는지 discriminator를 거친다. 이때 구분을 하지 못하도록, 즉 같은 latent space에 존재해야 한다는 adversarial loss를 적용한다. (도메인이 0, 1일때 분류가 각각 1/2 로 나타나도록 하는 방식.)

 

결론적으로 나타나는 로스는

두개의 도메인 기준

각 도메인별로 콘텐트벡터, 스타일 벡터 뽑는다. <두 콘텐트 벡터를 같게 하는 loss 발생> 해당 콘텐트와 반대편 스타일 벡터를 결합해 새이미지를 만든다. <각 도메인별로 adv loss 발생> 만든 이미지의 콘텐트벡토와 스타일 벡터를 다시 뽑아, 이번엔 해당 스타일 벡터와 반대편 콘텐트벡터를 결합해 원복 이미지를 만든다. <원복 이미지와 원 이미지를 비교하는 l1 로스 발생>

추가로 스타일 벡터를 뽑지 않고 스탠다드 가우시안 distribution에서 랜덤하게 샘플링한 벡터를 넣으면 스타일 이미지를 주지 않고도, 같은 이미지에 대해서도 서로 다른 다양한 변환 이미지를 얻을 수 있다.

'AI > Model (Study)' 카테고리의 다른 글

[Openpose] 오픈소스 사용  (0) 2022.05.05
NN/DNN/CNN/RNN - 간단 개념과 사용 용어  (0) 2021.01.12
    heheh
    heheh

    티스토리툴바