초록

styleGAN의 특징적인 산물을 살펴보고 모델 아키텍처와 학습 방식을 수정한다. generator normalization을 재설계하고 점진적 학습
을 검토한다. latent 코드에서 이미지로 매핑할 때 good conditioning을 이루도록 generator를 regularize 한다. 이미지의 퀄리티를 개선할 뿐만 아니라 path length regularizer를 통해 generator를 더 쉽게 invert할 수 있게 만든다. 이를 통해 생성된 이미지와 특정 네트워크를 연결할 수 있다. 나아가 generator가 출력 해상도를 얼마나 활용하는지 시각화하고, capacity 문제를 밝힌다.

Removing normalization artifacts

  • 물방울(droplet) 현상 : 최종 이미지에는 보이지 않아도 생성기의 중간 feature map에는 나타남
  • AdaIN 연산으로 인해 발생하는 문제
  • 각 feature map마다 평균과 분산을 이용해 normalize 하기 때문에, feature들 사이 상대적인 magnitude에 대한 정보를 파괴할 수 있음
  • generator가 의도적으로 signal strength 정보 (strength를 위에서 말한 magnitude로 보면 되나?)를 instance normalization 로 유출시킨 결과
  • 통계값에서 확 튀는 스파이크(dominates the statistics)를 생성함으로써 generator가 제멋대로 signal을 스케일링할 수 있게 됨

 

Generator architecture revisited

  • AdaIN 연산을 크게 두 부분으로 나누어 봄 : normalization & modulation
  • 네트워크에서 하나의 style이 작용하는 부분을 하나의 style block이라는 단위로 보기로 함
  • 기존 styleGAN에서는 style block 안에서 bias와 noise를 적용하는데, 그 결과 이들의 상대적인 영향력이 현재 스타일 magnitude에 반비례하게 됨 (현재 스타일의 크기가 클수록, 상대적으로 bias와 noise의 영향력이 작아지는?)
  • 이 연산(bias와 noise 적용하는 것)style block 밖으로 옮겨서 normalized된 데이터에 연산을 적용하도록 했음 (기존에는 normalized 직전에 적용함)
  • normalization과 modulation 연산시 평균을 제외하고 표준편차만 가지고도 충분함
  • 또한 입력 상수에 bias, noise, normalization 적용하지 않아도 됨

 

Instance normalization revisited

  • 기존 styleGAN의 강점 : inference 시에 다른 latent w 를 다른 레이어에 피딩함으로써 style mixing, 생성 이미지 control이 가능했음
  • 실제로는, modulation에서 특정 feature map이 10배나 그 이상(by an order of magnitude or more)으로 증폭됐음
  • style mixing 을 위해서는 샘플 단위로 증폭을 처리해야 했음; 그렇게 하지 않으면 이어지는 레이어들에서 연산이 제대로 이루어지지 않음
  • scale-specific controls 만 포기한다면, 그냥 normalization 만 제거해서 물방울도 없애고 FID 점수도 높일 수 있음
  • (하지만) 우리는 full controllability도 유지하고(scale-specific controls 포기하면 안 돼) 물방울도 없앨 수 있는 대안을 제시할 것임
  • 메인 아이디어는 feature map에 대한 추정 통계값으로 normalization을 하는 것 (but without explicit forcing)
  • conv 레이어 전에 수행되는 modulation의 효과에 대하여 : modulation은 incoming style을 기반으로 convolution의 각 input feature map을 스케일링하는데, 이것은 convolution weights를 스케일링하는 것으로 대체할 수 있음

  • wijk : original weights
  • w`ijk : modulated weights
  • si : i번째 input feature map에 해당하는 scale
  • (i : enumerate the input feature map)
  • j : enumerate the output feature map
  • k : enumerate spatial footprint of the convolutions
# Modulate.
s = dense_layer(y, fmaps=x.shape[1].value, weight_var=mod_weight_var) # [BI] Transform incoming W to style.
s = apply_bias_act(s, bias_var=mod_bias_var) + 1 # [BI] Add bias (initially 1).
ww *= tf.cast(s[:, np.newaxis, np.newaxis, :, np.newaxis], w.dtype) # [BkkIO] Scale input feature maps.
  • instance normalization의 원래 목적은 output feature map 통계값에서 s(input feature map의 scale)의 영향을 근본적으로 제거하는 것
  • input activations(input feature maps)이 단위 표준편차(1)를 가진 i.i.d. random variables (Independent and identically distributed) 독립항등분포 확률변수라고 가정하자.
    • 독립항등분포 : 확률변수(X1 , X2 , ... , Xn)들이 상호독립적이며, 모두 동일한 확률분포 f(x)를 가짐
    • 추정값을 쓴다는 게 이 부분이랑 관련되는 걸까?
  • modulation과 convolution 을 거친 후 output activations(output feature maps)의 표준편차

j : enumerate the output feature map

즉 outputs 는 해당 weight들의 L2 Norm으로 스케일링되는 것 (위에서 평균 필요 없고 표준편차만 가지고 normalization 해도 된다고 했음)

  • 이게 어떻게 표준편차 식이지? 위에서 단위 표준편차를 가진 독립항등분포 확률변수로 가정한 것과 관련이 있어보이는데..

(참고) L2 Norm 계산식

이어지는 normalization의 목표는 outputs의 표준편차를 단위 표준편차(1)로 맞추는 것인데, 각 output feature map j를 1/σj로 스케일링함으로써 이를 달성할 수 있음 => “demodulate

ε : small constant

w``ijk(demodulated output) = w`ijk (output feature map j) * 1/σj(standard deviation of output)

 
# Demodulate.
if demodulate:
    d = tf.rsqrt(tf.reduce_sum(tf.square(ww), axis=[1,2,3]) + 1e-8) # [BO] Scaling factor.
    ww *= d[:, np.newaxis, np.newaxis, np.newaxis, :] # [BkkIO] Scale output feature maps.​
  • 결국 style block 하나는 하나의 conv 레이어로 굳어짐; conv 레이어의 weights는 s(input feature map scale) 기반으로 조정됨
  • instance normalization과 비교했을 때 demodulation은 더 weak한데, feature map들의 실제 값 대신에 signal에 대한 통계적 추정(statistical assumptions)을 사용하기 때문
    • “비슷한 통계 분석 방식이 오늘날 network initializers에서 널리 사용되고 있지만, data-dependent normalization 대신에 이 방식을 사용한 전례는 아는 바 없다”
    • demodulation은 weight normalization과 관련되기도 하는데, weight normalization는 weight tensor를 reparameterize 하는 과정에서 같은 계산을 수행
    • 이 논문이랑 관련되는 듯? <Weight Normalization: A Simple Reparameterization to Accelerate Training of Deep Neural Networks>
  • demodulation 수식에서 활성화 함수를 처리하는 문제를 피하기 위해, 활성화 함수도 스케일링하여 기대 신호 분산(expected signal variance)를 유지함
    • 코드에서 못 찾고 있음

 

Image quality and generator smoothness

  • 인지할 수 있는 이미지 퀄리티와 perceptual path length(PPL) 간 상관관계 발견
    • PPL의 원래 목적 : latent space와 output 이미지 간 매핑의 smoothness를 정량화
    • PPL의 계산 방식 : latent space 상 작은 움직임에 따른 생성 이미지들 간의 평균 LPIPS 거리 측정
  • PPL이 작을수록(매핑이 부드러울수록) 전체적인 이미지 퀄리티가 개선: 다른 metric은 포착하지 못하는 차이
  • 모델의 overall PPL은 결국 이미지별 PPL 점수의 기댓값
  • 어떻게 낮은 PPL 점수가 이미지 퀄리티랑 관련되는 것일까? 학습하면서 discriminator가 깨진 이미지(broken images)들에 패널티를 주면, generator는 latent space에서 좋은 이미지가 나오는 영역을 잡아당김(stretch)으로써 개선하고자 하기 때문
  • 그 결과, 저퀄리티 이미지는 latent space의 작은 (급변) 영역에 짜부(squeezed)된다.
  • 단기적으로는 평균적인 output 퀄리티를 좋게 만들지만, 축적된 왜곡(accumulating distortions)은 학습을 손상시키고 결국에는 이미지 퀄리티도 …
  • 따라서 단순히 PPL을 최소화하는 대신에, 부드러운 generator 매핑을 목표하는 새로운 regularizer 도입

Lazy regularization

  • 보통은 메인 손실함수와 regularization이 single expression로 쓰여 동시에 optimize되지만, regularization을 메인 손실함수보다 덜 자주 계산해도 된다는 것을 발견: 연산 비용과 메모리 사용을 매우 줄일 수 있음
  • 미니배치 16개마다 한번씩 R1 regularization 수행

Path length regularization

  • W에서 정해진 크기로 움직이면(fixed-size step), 이미지에서도 정해진 크기로 변화가 나타나도록(fixed-magnitude change)
  • image space에서 임의의 방향으로 움직였을 때 그에 해당하는 w gradients를 관찰함으로써, 경험적으로 편차(deviation)를 측정할 수 있음
  • gradients는 w나 image-space 방향과 상관없이 거의 동일한 길이를 나타내야 함 (latent space와 image space의 매핑이 well-conditioned 되었다는 뜻)
  • 하나의 w ∈ W에 있어서 local metric scaling properties of the generator mapping g(w) : W ↦ Y 는 자코비안 행렬로 포착될 수 있다
    • Jw = ∂g(w)/∂w (편미분)

자코비안 행렬 : 미소영역에서 비선형 변환을 선형 변환으로 근사

방향과 상관없이 벡터들의 기대 길이(expected lengths)를 보존자하도록 regularizer를 다음과 같이 수식화

  • y : 픽셀 강도가 정규분포를 이루는(with normally distributed pixel intensities) 임의의 이미지들
    • pixel intensity value is the primary information stored within pixels
  • w ~ f(z) : 정규분포를 이루는 z
  • 고차원에서 Jw가 모든 w에서 직교할 때 이 prior가 최소화된다

∇ : 벡터 편미분

    • 표준 역전파를 사용해 효율적으로 계산할 수 있는 위 항등식을 사용하기로 (AdaGrad)
    • 상수 α : 길이 ||JwTy||2의 장기 지수이동평균(long-running exponential moving average)으로 최적화하면서 역동적으로 조정, 이로써 최적화가 스스로 적절한 전역 스케일을 찾을 수 있도록 함
  • 유한 차분을 사용하는 대신에(근사하는 것) 행렬곱 JwTy을 분석적으로(analytically) 계산
  • path length regularization
    • 모델이 더 신뢰성 있고 일관적으로 작동
    • 더 부드러운 generator가 invert하기 훨씬 쉬움
    • mode를 0으로 밀어넣지 않으면서 이미지별 PPL 점수의 분포를 tighten함
      • mode : 데이터 분포에서 관측치가 높은 부분
mode가 0이 되는 상황이 결국 ‘mode failure/collapse’일 듯 (비슷한 이미지만 내놓는)

Progressive growing revisited

  • 점진적 학습 generator는 디테일한 정보에 대해 강하게 선호하는 위치가 있음 (strong location preference for details)
  • 치아나 눈 같은 feature가 부드럽게 움직이지 않고, 한 위치에 머무르다가 다음 선호 위치로 점프하는 경향이 있음
  • 문제: 점진적 학습에서는 각 해상도가 output 해상도가 되어서 최대 주파수 정보(maximal frequency details)을 생성하게끔 강제
  • 학습된 네트워크가 중간 레이어에서 너무 높은 주파수를 가져 이동 불변성(shift invariance)을 위협하게 됨
    • shift invariance in CNN : if you shift the input in time(shift the entries in a vector), the output is shifted by the same amount
    • What are frequencies in images? 일단은 pixel intensities = frequencey 라고 생각해도 될 듯

 

alternative network architectures

  • MSG-GAN : 다중 skip connection을 사용하여 맞는 해상도끼리 generator와 discriminator를 연결, generator는 이미지 대신 mipmap을 출력하도록 수정하고 각 실제 이미지들에 대해서도 비슷한 representation(minmap과 비슷하게 표현)으로 계산
    • 수정 : 해상도에 따른 RGB outputs의 기여도(contributions)를 upsampling하고 sum함으로써 이를 간소화. discriminator에서도 downsampling한 이미지를 각 해상도 block에 제공. upsampling, downsampling 연산에 모두 이중선형 필터링(bilinear filtering)을 사용.
  • 나아가 residual connections을 사용하도록 디자인 수정. 해상도별 discriminator를 제외한 LAPGAN 과 비슷.
  • 점진적 학습을 제거하고, 기존 / skip connections / residual connections + generator / discriminator (총 9개 경우의 수) 의 FID, PPL를 비교한 결과 : skip connections + generator, residual connections + discriminator 가 좋았다

 

 

resolution usage

  • 저해상도 feature에 집중했다가 천천히 세세한 디테일로 포커스를 이동하는 점진적 학습의 방식은 보존하고자 함
  • 이제 generator는 beneficial할 때만 이를 수행하게 될 것 (더이상 강제하지 않으므로)
  • generator가 학습하면서 특정 해상도에 얼마나 의존하는지 정량화하기로 함
    • skip generator는 여러 해상도에서 RGB값을 sum함으로써 이미지를 생성하기 때문에, 레이어들이 최종 이미지에 얼마나 기여하는지 측정함으로써 해당 레이어의 상대적인 중요성을 추정할 수 있음
    • 임의추출한 1024개의 w들을 대상으로 각 tRGB 레이어에서 나온 픽셀값들의 표준편차들을 구하고, 그 값들을 정규화해서 100%로 떨어지게 함 (레이어의 상대적인 중요성을 보기 위해)
    • 학습 초기에 skip generator가 점진적 학습과 유사하게 작동하므로, 가장 높은 해상도가 마지막에 지배적이게 될 거라고 생각
    • 그러나 실제로는 실패했는데, generator가 목표 해상도를 “완전히 활용”하지 못한다는 뜻. 생성된 이미지들을 직접 살펴보았더니 픽셀 수준의 디테일이 부족하다는 것을 발견함
    • 진짜 1024*1024 해상도 이미지라기 보다는 좀더 선명하게 만든 512 * 512 해상도 이미지라고 볼 수 있음
  • 네트워크의 capacity 문제라고 생각하여 generator와 discriminator에서 해상도가 가장 높은 레이어의 feature map 개수를 두 배로 늘렸더니, 해상도가 가장 높은 레이어의 기여도가 유의미하게 증가함

 

 

Projection of images to latent space

  • 주어진 이미지를 latent feature space에서 조종하려면 그 이미지에 맞는 latent code를 찾아야 함
  • 선행 연구에 따르면, 공통 latent code w 를 찾는 것보다 generator의 각 레이어에서 개별 w를 고를 때 결과가 좋았음
  • 이러한 방식으로 latent space를 확장하는 것은 주어진 이미지에 가까운 매칭을 찾을 수 있지만, latent presentation이 없어야 하는 임의의 이미지까지도 project 할 수 있게 됨
  • 따라서 확장되지 않은, 원래의 latent space에서 latent code를 찾는 것에 집중
  • 기존 방식과 다른 점1 : latent space를 완전히 탐색할 수 있도록, 학습하면서 latent code에 ramped-down noise를 추가한다
  • 기존 방식과 다른 점2 : 기존 styleGAN의 stochastic nosie inputs를 최적화, noise inputs을 regularize하여 일관적인 signal 을 가져가지 않게 함
  • regularization : 여러 스케일에 있어서 noise maps의 자기상관 계수단위 가우시안 노이즈(unit Gaussian noise)의 계수로 맞춤

 

attribution of generated images

  • 가짜 이미지를 탐지할 뿐만 아니라, 가짜 이미지의 특정 source를 찾을 수 있어야 : styleGAN에서는 해당 이미지로 합성되는 w가 있는지 찾음
  • 원본과 합성 이미지 사이 LPIPS 거리를 계산함으로써 projection이 얼마나 잘 이루어지는지 측정

 
  • x : 분석 대상이 되는 이미지
  • g̃ -1: approximate projection 연산
  • styleGAN2로 생성된 이미지들은 W로 매우 잘 project되어서 거의 명확하게 생성 네트워크를 출처로 삼을 수 있음
  • styleGAN2는 이미지 퀄리티도 훨씬 좋을 뿐더러 source attribution도 쉬움

 

 

def modulated_conv2d_layer(x, y, fmaps, kernel, 
                           up=False, 
                           down=False, 
                           demodulate=True, 
                           resample_kernel=None, 
                           gain=1, 
                           use_wscale=True, 
                           lrmul=1, 
                           fused_modconv=True, 
                           weight_var='weight', 
                           mod_weight_var='mod_weight', 
                           mod_bias_var='mod_bias'):
                           
    assert not (up and down)
    assert kernel >= 1 and kernel % 2 == 1

    # Get weight.
    w = get_weight([kernel, kernel, x.shape[1].value, fmaps], gain=gain, use_wscale=use_wscale, lrmul=lrmul, weight_var=weight_var)
    ww = w[np.newaxis] # [BkkIO] Introduce minibatch dimension.

    # Modulate.
    s = dense_layer(y, fmaps=x.shape[1].value, weight_var=mod_weight_var) # [BI] Transform incoming W to style.
    s = apply_bias_act(s, bias_var=mod_bias_var) + 1 # [BI] Add bias (initially 1).
    ww *= tf.cast(s[:, np.newaxis, np.newaxis, :, np.newaxis], w.dtype) # [BkkIO] Scale input feature maps.

    # Demodulate.
    if demodulate:
        d = tf.rsqrt(tf.reduce_sum(tf.square(ww), axis=[1,2,3]) + 1e-8) # [BO] Scaling factor.
        ww *= d[:, np.newaxis, np.newaxis, np.newaxis, :] # [BkkIO] Scale output feature maps.

    # Reshape/scale input.
    if fused_modconv:
        x = tf.reshape(x, [1, -1, x.shape[2], x.shape[3]]) # Fused => reshape minibatch to convolution groups.
        w = tf.reshape(tf.transpose(ww, [1, 2, 3, 0, 4]), [ww.shape[1], ww.shape[2], ww.shape[3], -1])
    else:
        x *= tf.cast(s[:, :, np.newaxis, np.newaxis], x.dtype) # [BIhw] Not fused => scale input activations.

    # Convolution with optional up/downsampling.
    if up:
        x = upsample_conv_2d(x, tf.cast(w, x.dtype), data_format='NCHW', k=resample_kernel)
    elif down:
        x = conv_downsample_2d(x, tf.cast(w, x.dtype), data_format='NCHW', k=resample_kernel)
    else:
        x = tf.nn.conv2d(x, tf.cast(w, x.dtype), data_format='NCHW', strides=[1,1,1,1], padding='SAME')

    # Reshape/scale output.
    if fused_modconv:
        x = tf.reshape(x, [-1, fmaps, x.shape[2], x.shape[3]]) # Fused => reshape convolution groups back to minibatch.
    elif demodulate:
        x *= tf.cast(d[:, :, np.newaxis, np.newaxis], x.dtype) # [BOhw] Not fused => scale output activations.
    return x

'인공지능 > computer vision' 카테고리의 다른 글

p2S2p 이해하기  (0) 2022.08.01
styleGAN3 이해하기  (0) 2022.08.01
StyleGAN1 vs. StyleGAN2  (0) 2022.05.31
styleGAN 이해하기  (0) 2022.05.31
PGGAN의 공식 코드 살펴보기  (0) 2022.05.31
복사했습니다!