Sunwoo Kim's Computer Vision, Machine & Deep Learning Blog search

CS231n-Lecture12(Visualizing and Understanding)

|

목차

저번 강의 때는 object detecion 및 segmentation모델에 대해서 학습했었다.

First Layer: visualize filters(weight)

CNN의 시각화에 대해서 배워볼 것이다. 과연 CNN의 내부는 어떻게 생겼을까? 어떻게 문제들을 해결할까/ 어떤 종류의 feature를 갖고 있는것과 같은 질문들에 대해서 다룰 것이다.

우리가 가장 만만하게 접근할 수 있는 것은 첫 번째 레이어이다. Alexnet을 살펴보면 컨볼루션을 통해서 첫번째 레이어에는 64개의 filter가 생기게된다. 첫 번째 conv layer는 이미지와 직접적으로 내적을 수행하기 때문에, 이 필터를 시각화 시키는것 만으로 이 필터가 이미지에서 무엇을 찾고 있는지 알아낼 수 있다.

AlexNet의 필터는 총 64개 이므로, 64개의 11x11이미지를 시각화 시킬 수 있다. 그리고 다른 network들의 첫 번째 레이어들의 모습이다. 단순히 보는 것만으로 무엇을 찾고있는지 예상할 수 있는가? 이것들은 주로 이미지의 엣지를 찾고있는 모습이라고 볼 수 있다. 흰/검의 직선, 사선도 보이고, 다양한 초록색과 분홍색같은 보색도 보인다.

학습된 필터를보면 우리가 첫강의에서 다루었었던 hubel and wiesel의 실험이 떠오른다(인간의 시각체계가 hierarchical 하게 lowlevel 을 인식하고 안쪽으로 갈수록 high level을 인식한다는것.) 인간의 시각체계도 이처럼 겉 피질에서 oriented edges를 감지한다고 말했었다. CNN의 첫 번째 레이어 에서도 이와 비슷하게 작동하는 것 같다. 가장 흥미로운 점은 CNN을 어떤 모델과 데이터로 학습하여도 첫 번째 레이어는 위와 같은 모습을 띤다는 점이다.

위 이미지는 히든레이어의 시각화가 아니고, 가중치를 시각화 한것이다. 그렇다면 왜 가중치를 보아야 하는 것일까? 먼저 CNN의 가중치는 필터라고 불리는것 부터 생각해보자. 우리가 초등학교때 보았던 빨간색 셀로판지를 생각해보자. 빨간색 셀로판지를 보면 세상이 빨갛게 보인다. 왜그런 것일까? 해당 필터가 빨간색 빛만 흡수했기 때문이다. 즉, 필터는 우리가 원하는 특징을 걸러내는 장치인 것이다. 그렇기 때문에, 가중치 행렬을 시각화 시켜보면, 어떤 특징을 얻고자 하는지 알 수 있는 것이다. 조금 더 수학적으로 얘기하자면, 컨볼루션은 필터와 이미지를 내적(matrix 곱 아님)하는 것과 동일한데, 우리는 내적의 값이 최대가 되려면 내적하는 두 벡터가 동일해야 한다는 것을 알고있다. 그러므로, 필터와 이미지의 내적(matrix 곱 아님)이 최대가 되려면 두 값이 동일해야 한다는 것이다.

2,3 Layer: visualize filters(weight)

그렇다면 이러한 개념을 레이어 중간에도 이런 시각화를 동일하게 적용할 수 있을지 살펴보자. 우선 답은 첫 번째 레이어에 했던 시각화 기법과 동일하게 적용하면 우리가 보고 해석하기가 더 어려워진다는 것이다. 위 슬라이드를 보고 해석이 잘 되는가? 잘 되지 않을 것이다. 왜냐하면, 직접적으로 이미지와 연결되어있지 않기 때문이다. 두 번째 레이어의 가중치들은 첫 번째 레이어와 연결되있다. 즉, 우리가 시각화한 내용은 두 번째 히든레이어의 결과를 최대화 시키는 첫 번째 레이어의 출력 패턴이 무엇인지 파악하는 것이다.

하지만 이미지 관점에서 첫 번째 레이어의 출력이 어떻게 생겼는지 감을 잡고 해석하기 쉽지 않은데, 그래서 네트워크 중간 레이어의 필터들이 무엇을 찾고 있는지 알아내려면 좀 더 발전된 방법이 필요하다.

중간에 질문이 나왔다. 질문에 대한 답은 필터의 값은 원래 [0-255]가아니지만 시각화를 위해서 normalizing 되었으며, bias는 고려하지 않았기 때문에 시각화 결과를 있는 그대로 믿지 말라는 답변이 왔다.

Last Layer: visualizing

이제 CNN의 마지막 레이어를 살펴보자. CNN의 마지막 FC layer를 시각화 시키는데 필요한 방법중 하나는 nearest neighbor를 이용한 방법이다.

Nearest Neighbors

맨 왼쪽의 그림은 CIFAR-10의 데이터를 픽셀공간에서 nearest neighbor를 한 결과이다. 꽤 비슷한 이미지 들이 모였다. (색, 형태, 텍스쳐 등이 성질이 되서 그 거리를 비교하는것 같다. 자세한 방법은 잘 모르겠다.) 하지만 이번에 nearest neighbor를 할 것은 CNN에서 나온 4096-dim의 벡터 공간에서 계산을 할 것이다.

그 결과가 중간에 나온 그림이다. 이 결과를 보면 확실히 픽셀 공간에서의 nearest neighbor와 다른것을 볼 수 있다. feature 공간에서 nearest neighbor의 결과를 보면 서로 픽셀 값의 차이가 큰 경우도 있다. 하지만 픽셀 값의 차이는 커도, 특징 공간 내에서는 아주 유사한 특징을 지닌다는 것을 알 수 있다.

두 번째 줄에 있는 코끼리의 예를 살펴보자. 테스트 이미지를 보면 코끼리가 왼쪽 앞에 서있고, 풀이 있다. 그런데 끝에서 세번 째 사진을보면 코끼리가 오른쪽에 서있는 것을 볼 수 있다. 왜냐하면 코끼리가 왼쪽에 서있는 이미지와 오른쪽에 서있는 이미지의 픽셀 값은 완전히 다를 것이기 때문이다. 하지만 네트워크가 학습한 특징 공간 내에서는 서로 비슷한 벡터로 맵핑이 된다. CNN이 semantic 한 내용을 잘 캐치해냈다고 볼 수 있다. 이처럼 nearest neighbor를 통한 시각화 기법은 어떤 일이 일어나는지 살펴보기 아주 좋은 방법중 하나이다.

Dimensionality Reduction

PCA를 통해서 해당 결과를 좀 더 fancy하게 시각화 시킬 수 있다. PCA는 차원 축소 방법 중 하나인데, 이 경우 2-dim으로 차원 축소를 시킨 것이다. PCA로 이런 일을 할 수 있지만, t-SNE(t-distributed stochastic neighbor)라는 방법을 사용하면 더욱 파워플하게 이 작업을 수행할 수 있다. 위 슬라이드들이 t-SNE를 이용한 시각화 결과이다.

t-SNE에 관해서 아주 좋은 질문들이 나왔다.

  • 2차원 공간에서 대강 얼마나 많은 데이터를 표현할 수 있을까?

    잘 모르겠다. 정확히 얼마나 표현할 수 있을지 모르겠다. t-SNE는 비선형 차원축소 기법이라 상당히 복잡하다.

  • 이미지들이 차원축소 과정에서 서로 겹쳐지지 않을까?
    물론 겹칠 수 있다. regular grid를 기준으로 nearest neighbor, 즉 각 gride point에 가장 가까운 이미지를 뽑아낸다. 따라서 t-SNE는 특징 공간 분포의 모양을 보여주는것이 아니다.

MIddle layer: visualizing(neuron or patch)

Visualizing Activations

중간 레이어에 있는 가중치를 시각화 해도 해석하기 쉽지 않다고 했는데, activation map을 시각화 해보면 일부 해석할 수 있다. 지금 보고 있는 툴은 Jason Yasenski가 만들었다. 대부분의 grid 들은 뭐를 하고 있는지 모르겠지만, 초록색으로 확대해놓은 부분을 보면 웬지 사람을 형상화 시켜놓고 있는것 같다. 즉, 네트워크의 어떤 레이어에서는 사람의 얼굴을 찾고 있을지 모른다는 것이다.

여기서 아주 흥미로운 질문이 있다. 만약 ImageNet에 사람의 얼굴이 없다면 어떻게 네트워크가 사람의 얼굴을 인식할 수 있는지 있을까? ImageNet은 다른 이미지 들에 섞여서 사람의 이미지가 많이 등장한다 하지만, 1000개의 카테고리중에 사람은 없다. 이것은 또 아주 흥미로운 사실이다 왜냐하면 ImageNet에 사람이라는 클래스가 없지만 다른 클래스를 잘 분류하기 위하여 유용한 특징들을 알아서 학습한 것이기 때문이다.

Maximally activiating patches

중간 레이어의 특징을 시각화 시킬수 있는 또다른 방법이 있다. 바로 어떤 이미지가 들어와야 각 뉴런들의 활성이 최대화되는지를 시각화해보는 방법이다. 이 예시에서도 다시 한 번 AlexNet의 conv5 layer를 사용한다. 우리는 128x13x13의 activation volume 에서 한 개의 activation map을 선택해 시각화 할 것이다. 이 예시에서는 17번 째 체널을 골랐다. CNN에서 생각해볼때, 한 activation map의 픽셀이 이미지 전체를 보고있지 않다. 특정영역을 보고있다. 그렇기 때문에, 일부 패치 영역을 시각화 시킬것이다. 그리고 특정 레이어의 활성화 정도를 기준으로 패치들을 정렬시키면 된다. 오른쪽에 그 결과가 있다.

  • 특정 레이어의, activation map 선택
  • 여러장 훈련 시키면서 해당 activation map의 value기록
  • 해당 map 전체 혹은 뉴런의 value를 최대화 시키는 순서로 이미지(혹은 뉴런에 대응되는 패치부분)를 정렬.

오른쪽에 보이는 패치들이 바로 해당 레이어의 활성을 최대화시키는 패치들이다. 패치를 보고 무엇을 찾고 있는지 알 수 있다. 눈을 찾거나, 당야한 생삭의 문자를 찾거나, color, orientation을 가진 엣지를 찾는 다거나 여러가지가 있다.

오른쪽 상단의 결과보다 오른쪽 하단의 결과는 더 깊은 레이어를 시각화 한 것이다. 더 깊으면 그만큼 receptive field가 넓기 때문에, 조금 더 넓은 지역의 특징이 드러나는 것을 볼 수 있다.

Occlusion Experiments

새로운 실험에 대해서 살펴보자. 이 실험은 입력의 어떤 부분이 분류를 결정짓는 근거가 되는지에 관한 실험이다. 이미지의 일부를 가리고, 가린 부분을 데이터셋의 평균 값으로 채워버린다. 그 가려진 이미지를 네트워크에 통과시키고, 네트워크가 이 이미지를 에측한 확률을 기록한다. 그리고 전체 이미지에 이와 같은 작업을 반복하면서 계속해서 확률을 기록해나간다. 오른쪽의 히트맵(heatmap)은 가린 patch 위치에 따른 예측 확률의 변화를 시각화 해놓은 것이다. 빨간색은 확률값이 낮고, 노란색 지역은 확률 값이 높은 것을 나타낸다.

Go-kart의 차가 있는 앞쪽을 가렸을 때, 판별 확률이 낮아진 것을 볼 수 있다. (잘 안보이겠지만, go-kart 이미지 뒤쪽에 트랙과, 작은 많은 kart들이 있다고 한다.)

Saliency Maps

이와 관련된 또 하나의 방법은 saliency map을 살펴보는 것이다. 이 방법은 입력 이미지의 각 픽셀들에 대해서, 예측한 클래스 점수의 그라디언트를 계산하는 방법이다. 이것은 일종의 1차 근사적 방법으로 어떤 픽셀이 영향력 있는지를 알려준다. 이것은 이렇게 질문으로 바뀔 수 있다. “입력 이미지의 각 픽셀에 대해서, 우리가 그 픽셀을 조금 바꿨을 때 클래스 스코어가 얼마나 바뀔까?” 이 질문은 어떤 픽셀이 “개”를 분류하는데 있어서 어떤 픽셀들이 필요한지알 수 있는 또 다른 방법이 될 수 있다. 이 방법을 통해 “개” 이미지의 Saliency map을 만들어보면 “개”의 윤곽이 나타남을 알 수 있다.

다른 이미지에 적용해봐도 네트워크가 올바른 곳을 보고 있다는 것을 파악이 가능하다.

segmentation task에서 label없이 saliency map만 가지고 segmentation을 수행하는 모습이다. 이 논문에서는 grabcut(interactive segmentation algorithm)을 이용하였다. 즉, saliency map과 grabcut을 잘 조합하면 객체를 segmentation할 수 있다는 것이다. (잘 되지는 않지만.)

이번에는 클래스 점수가 아니라 네트워크의 중간 뉴련을 하나 고른다. 그리고, 입력 이미지의 어떤 부분이, 내가 선택한 중간 뉴런의 값에 영향을 주는 지를 찾는다. 그리고 각 픽셀의 “중간 뉴런”에 대한 그라디언트를 계산하는 것이다. 이 때 guided back propagation이라는 트릭을 가미하면 좀 더 깨끗한 이미지를 얻을 수 있다. 역전파 시, ReLU를 통과할 때 조금의 변형을 가한다. **ReLU를 거칠 시, 역전파된 총 그라디언트가 양수이면 그 다음 역전파를 계속 진행하고, 음수이면 역전파를 멈추는 것이다. ** 그래서 양수인 그라디언트만 고려를 하게 된다. (이 방법이 왜 좋은가에 대해서는 논문을 읽어야 한다.)

Visualizing CNN features: Gradient Ascent

우리는 여태까지 고정된 입력 이미지 또는 패치의 어떤 부분이 해당 뉴런에 영향을 미치는지 살펴보았다. 그렇다면, 넣기만 하면, 어떤 뉴런을 활성화 시킬 수 있는 일반적인 입력이미지가 있을까? 에 대해서도 생각해볼 법 하다. 이 부분에 대해서는 gradient ascent가 해답을 줄 수 있다.

지금까지 loss를 최소하시키기 위하여 gradient descent(GD)를 사용해왔다. 하지만 이제 네트워크의 가중치들을 전부 고정시켜볼 것이다. 그리고 gradient ascent(GA)를 통해 중간 뉴런 혹은 클래스 스코어를 최대화 시키는 이미지의 픽셀들을 만들어 볼거다.

GD가 가중치들을 바꿔준다면, GA는 뉴런, 클래스 점수가 최대화 될 수 있도록 입력 이미지의 픽셀 값을 바꿔주는 방법이다.

또한 regularization term이 필요하다. 가중치를 규제하여 과적합을 방지하기 위해서 썻듯이, 이번 경우에도, 생성된 이미지가 특정 네트워크의 특성에 완전히 과적합 되는 것을 방지하기 위해 사용된다. 그리고 이 term의 목적은 첫 번째, 생성된 이미지가 자연 영상에서 일반적으로 볼 수 있도록 원하는 것, 두 번째, 이미지가 특정 뉴런의 값을 최대화 시키는 방향으로 생성되는 것이다.

Gradient Ascent를 위해서는 초기 이미지가 필요합니다. 이 이미지는 zeros, uniform, noise 등으로 초기화 시켜 준다. 초기화를 하고나면 이미지를 네트워크에 통과시키고 관심있는 뉴런의 스코어를 계산한다($S_c(I)$가 클래스에 대한 스코어가 될수도 있고, 뉴런에 대한게 될수도 있다. 우리가 알고자 하는 대상에 따라 그 대상에 대한 출력값을 구하는 것이다). 그리고 이미지의 각 픽셀에 대한 해당 뉴런 스코어의 그레디언트를 계산하여 back prop을 수행 한다. 여기에서는 Gradient Ascent를 이용해서 이미지 픽셀 자체를 업데이트한다. 해당 스코어를 최대화시키려 한다.

여기서는 단순하게 L2 norm을 regularizer로 넣어준다. 이게 큰 의미가 있는 것은 아니다. 초기 문헌에서 종종 보이는 방법이라고 한다. 생성된 이미지를 보면 덤벨, 컵 거위 등이 중첩되어 있는 모습을 볼 수 있다. 강의에서는 달마시안이 되게 인상깊다고 한다. 검정/흰색 반점의 무늬를 볼 수 있기 때문이다.

강의를 들으면서 느낀거지만 스탠포드 분들의 수준이 높은것 같다. 지식뿐 아니라, 모든 부분에 대해서 궁금해하려는 그 태도가 놀라운것 같다.

  • 왜 이미지들이 무지개 색을 띠는가?

    이 시각화 방법을 통하여 실제 색상을 시각화 하려면 굉장히 까다롭다. 실제 모든 이미지들은 [0, 255]의 값을 지녀야한다. 이는 constrained optimization 문제다. 하지만 GA와 같은 일반적인 방법들은 unconstrained case이다. 그러므로 Projected gradient descent 와 같은 알고리즘을 사용하고 마지막에 rescale한 경우라면 시각화 할 때 나타나는 색상에 대해서는 크게 상관할 필요가 없다.

  • regularizer를 사용하지 않으면 어떻게 될까?

    score를 최대화 시키는 어떤 이미지가 생성 되기는 하나, 랜덤 노이즈처럼 보여 아무것도 아닌것 처럼 보일 것이다. 그래도 그 이미지 자체가 가지는 흥미로운 특징이 있다고 한다. 하지만, 네트워크가 무엇으 찾고있는지 이해하기는 힘들것이다. 즉, 자연스럽게 생성하기 위하여 regularizer를 사용하는게 좋다.

  • Multimodality를 다루는 다른 방법은 없는가?

    당연히 있다. 시각화에 대한 얘기는 이제 시작이다.

Jason Yesenki의 논문이 있는데 아주 인상적인 그라디언트를 추가했다. L2 norm은 여전히 존재한다. 그리고 여기다가 최적화 과정에서 이미지에 일정 주기로 가우시안 블러를 적용한다. 또 주기적으로 값이 작은 픽셀들은 모두 0으로 만든다. 낮은 그라디언트 값도 0으로 만든다. 이는 일종의 projected Gradient descent라고 볼 수 있다. 이는 생성된 이미지를 더 좋은 특성을 가진 이미지 집합으로 주기적으로 매핑시키는 방법이다. 이처럼 regularizer에 따라서 이미지가 더 깔끔해질 수 있다는 것을 보여준다. 이 과정은 최종 스코어에만 적용하는게 아니라 중간 뉴런에도 적용해볼 수 있습니다. “당구대” 클래스의 스코어를 최대화시키는 것이 아니라 중간의 뉴런을 최대화시키는 이미지를 생성해볼 수도 있다.

이를 통하여 중간 뉴런이 무엇을 찾고 있는지 짐작해볼 수 있는데, 네 번째 레이어의 경우에는 나선형의 무언가, 어떤 거는 애벌레 같은 것들을 찾고 있는것 같다. 예제 이미지가 더 클수록 receptive fields가 더 큰 뉴런들이다(즉 깊은곳에 위치한 뉴런).

방금 전 누군가가 질문한 multimodality 를 이 논문에서 아주 잘 다루고 있다. 이 논문에서는 최적화 과정 속에 multimodality를 아주 명시적으로 다루고 있다. 각 클래스마다 클러스터링 알고리즘을 수행한다. 한 클래스 내 서로 다른 모드들 끼리 다시 한번 클래스가 나뉜다. 그리고 나뉜 모드들과 가까운 곳으로 초기화를 해주는 것이다 . 이 방법을 통해서 multimodality를 다룰 수 있는 것이다.

직관적으로 보면, 가령 여기 있는 여덟개의 이미지는 모두 식료품점(grocery store) 이다(Later5, Layer4). 가장 상위의 이미지들(Layer5)은 선반 위에 전시된 물건들을 클로즈업 한 것 같아 보인다. 이들의 레이블은 “식료품점” 이다. 그리고 하단의 이미지들(Layer4)은 사람들이 식료품점을 돌아다니고 있는 모슴인 것 같다. 이 또한 식료품점으로 레이블링된다. 하지만 이 둘은 아주 다르게 생겼다. 많은 클래스들이 이렇게 multimodality를 가지고 있다. 이미지를 생성할 때 이런 식으로 multimodality를 명시하게 되면 아주 좋은 (다양한) 결과를 얻을 수 있게 된다.

위 슬라이드에 나온 논문은 이미지를 훨씬더 잘 생성해내기 위하여 강력한 사전 정보(prior)를 이용한다. 여기 보이는 이미지들이 모두 ImageNet의 특정 클래스를 최대화하는 이미지를 생성해 낸 것이다. 기본 아이디어는 입력 이미지의 픽셀을 곧장 최적화하는 것 대신에 FC6를 최적화하는 것이다. 이를 위해서는 feature inversion network 등을 사용해야 하지만 자세히 설명하지는 않았다. 논문을 읽어봐야 한다.

Adverserial Exmaple, Fooling Image(Fake image)

위에서 설명한 것처럼 이미지 픽셀의 그라디언트를 이용하여 이미지를 합성하는 방법은 꽤 강력하다. 이를 기반으로 아이디어를 내어 시도해볼 수 있는 아주 재밌는 방법은 네트워크를 속이는 이미지(fooling image)를 만드는 것이다.

코끼리 이미지를 골랐다고 해보자. 이 때, 네트워크가 코끼리를 코알라로 분류하도록 이미지를 조금씩 바꾸어 보자. 이렇게 하다보면 네트워크는 이것을 코알라라고 분류해버린다. 바꾸다 보면 모습이 코알라 같이 변할까 생각이들지만 전혀 그렇지 않다. 육안으로 보기에는 아무 차이가 없다. 오른쪽 그림을 봐도 무언가 랜덤한 노이즈가 추가됬을 뿐인 것 같다.

재밌는 질문이 있었다.

  • 우리가 왜 이런 stuff?를 배워야 하는가? (이거 왜 배워?)

    결국 딥러닝은 흔히 알려져있듯이 blackbox이다. 기계학습은 설명하기 더 쉬운 부분이 있는데 딥러닝은 그러지 못하다. 그래서 딥러닝도 복잡하긴 하지만 보면 해석 가능한 부분들이 있을거야를 보여주고, 딥러닝이 아무렇게나 학습하는게 아니고 의미있고 논리적인 행동을 하고 있음을 증명하기 위해 이런 시각화가 중요하다.

이미지에 그라디언트로 업데이하는 방식으로 가능한 재밌는 아이디어인 Deepdreamdl 이있다. DeepDream의 과학적 가치의 측면에서 보자면 그저 재미만을 위한 것이다. DeepDream의 목적은 “재미있는 이미지를 만드는 것” 이다.

DeepDeram에서는 입력 이미지를 CNN의 중간 레이어를 어느정도 통과시킵니다. 그리고 역전파를 하고, 해당 레이어의 그라디언트를 activation값으로 설정하면서 계속 역전파를 진행하면서 이미지를 업데이트한다. 이 과정을 계속 반복한다.

이는 네트워크에 의해 검출된 해당 이미지의 특징들을 증폭시키려는 것으로 해석할 수 있다. 해당 레이어에 어떤 특징들이 있던지 그 특징들을 그레디언트로 설정하면, 이는 네트워크가 이미지에서 이미 뽑아낸 특징들을 더욱 증폭시키는 역학을 하는 것이다. 그리고 이는 해당 레이어에서 나온 특징들의 L2 norm을 최대화시키는 것으로 볼 수 있다.

DeepDream의 코드는 아주 심플하다. 여기에는 몇 가지 트릭이 존재한다. 트릭 중 하나는 그라디언트를 계산하기에 앞서 이미지를 조금씩 움직이는 것이다(jitter) .원본 이미지를 그대로 네트워크에 통과시키는 것 대신에 이미지를 두 픽셀 정도 이동시킨다. 이는 regularizer 역할을 해서 자연스럽고 부드러운 이미지를 만들어준다. 그리고 여기에 L1 Normalization도 들어갑니다. 이는 이미지 합성 문제에서 아주 유용한 트릭이다. 그리고 픽셀 값을 한번 클리핑(Clipping) 해주기도 한다. 이미지라면 값이 [0, 255] 사이에 있어야만 한다. 이는 일종의 projected gradient decent인데 실제 이미지가 존재할 수 있는 공간으로 매핑시키는 방법이다.

위와 같은 하늘에

궁전, 동물 ,개 등 여러가지가 보인다. 그런데 특정 눈에띄는 클래스들이 있다. 내 눈에는 개와 건물? 정도가 눈에 자주 띤다. 그 이유는 트레이닝 시키는 데이터셋과 관련이 있는데, 이미지넷엣는 개가 200클래스나 차지한다고 한다.

이렇게 합성된 이미지가 생서오디는게 흥미롭고, 개가 자주 섞이는것은 위와 같은 이유이다.

Deepdream의 레이어가 깊지 않다면, low level feature가 섞여 들여가는 모습을 볼 수 있다.

multiscale processing을 하면 위와 같은 결과를 얻을 수 있다고 한다. 작은 이미지로 시작해서 점점 더 큰 이미지로 키워나간다고 한다. (어떻게 이미지를 키운다는 뜻인지 잘 모르겠다.)

Feature inversion

이번에는 스코어를 최대화 시키는것 대신 feature vector간의 거리를 줄이는 방법을 사용할 것이다. 기존의 feature vector와 새롭게 생성한 이미지 간의 거리를 측정하는 것이다.

regularizer는 Total variation regularizer가 있으며, 상하좌우 인접한 픽셀간의 차이에 대한 패널티를 부여하여 spatial smoothness를 더 용이하게만든다.

코끼리이미지와, 사과 바나나 이미지를 VGG-16에 통과시켜 feature vector를 기록하고, 이 feature vector와 차이가 없도록 하는 입력 이미지를 생성한다.

결과를 보면 레이어가 낮을수록 알아보기 쉽고, 깊을 수록 알아보기가 어렵다. 하지만 형체는 유지되고 있는것 같다. 이것은 레이어가 깊어질 수록 low leve feature가 사라진다는 것을 의미한다. 즉 detail은 사라졌지만 그 물체 고유의 형태는 남아있는, 약간의 색이나 텍스쳐의 미세한 변화에 덜 민감한 정보들이 남는 것이다.

Texture synthesis

이 문제는 작은 패턴을 보고 더 큰 이미지 패턴을 생성하는 것이다. 이는 그래픽스에서 오래된 문제라고 한다.

nearest neighbor

nearest neighbor를 이용한 방법도 상당히 좋다고 한다. scan line을 따라서 한 픽셀식 이미지를 생성해 나가는 방식이다. 빨간 선이 scan line 이다. 즉 이미 생성된 주변 픽셀들을 참고해서 그 다음 픽셀을 생성해 나간다. 하지만 이 방법은 신경망을 쓰지 않는 고전적인 방식이다. 간단한 텍스쳐는 잘 생성하지만 복잡해질수록 문제가 생긴다.

gram matrix

2015년에 신경망을 활용해서 텍스쳐 합성을 하려는 시도가 있었다고 한다. 위 슬라이드에 제시된 방법은 neural texture synthesis를 위하여 Gram matrix(그람 행렬)이라는 개념을 사용한다. 위 슬라이드에 나와있듯이, 빨간색 막대, 파란색 막대는 해당 위치에 존재하는 이미지의 특징을 담고있다고 할 수 있다. 그리고 빨간색 막대 벡터와 파란색 막대 벡터를 이용하여 외적을 수행하여 매트릭스(맵)을 만들고 이것을 이용할 것이다. 위 행렬은 두 지역간의 co-occurence를 가지고 있다. (공분산 구할때랑 비슷한 느낌..)

그리고 이 것을 HxW 크기에서 나올수 있는 모든 짝(pair)에 대해서 수행해준다. 그러면, HW(HW-1)(서로 같은위치의 짝은 존재하지 않으므로)개의 CxC 매트릭스 가나 오는데 이것을 평균을 내면, CxC크기의 Gram matrix가 나오게 된다. 이 그람 행렬은 이미지의 텍스쳐를 기술하는 텍스쳐 기술자로 사용된다.

그람 행렬의 흥미로운점은, 공간 정보를 싹 다 날리고, co-occurrence 만을 남겨둔 것이다.

오 공분산 생각했었는데, 강의에 공분산 얘기가 나왔다. 공분산 행렬을 써도 아주 잘 작동하지만 비용적으로 너무 소모가 크다고 한다.

이제 이 기술자를 이용하여 이미지를 생성해보자. gradient ascent와 비슷한 과정을 거친다.목표는 gram matirx를 재구성하도록 하는 것이다. 과정은 다음과 같다.

  • pretrained VGGnet을 다운로드 받는다.
  • 이미지를 VGGnet에 통과시키고 다양한 레이어에서 그람 행렬을 계산하고 저장한다.
  • 생성할 이미지를 랜덤으로 초기화하고, 네트워크에 통과시켜 그람행렬을 계산한다.
  • 본 이미지의 그람행렬과 생성 이미지의 그람행렬 간의 L2 norm을 이용하여 loss를 계산한다.
  • 역전파를 통해 생성 이미지 픽셀의 그라디언트를 계산한다.
  • Gradient ascent를 통하여 픽셀을 업데이트 해나간다. (강의에서는 이렇게 말했는데, descent아닌가? loss를 감소시켜야하니까 말이다.. 이부분은 잘 모르겠다.)

결과를 보면 꽤 잘 작동한 모습을 볼 수 있다. 레이어가 깊어질수록 공간정 정보를 더 살려낸듯 보인다.

이 텍스쳐의 입력의 유명 화가의 그림을 사용하면 어떻게 될까? 생성된 이미지의 모습을 보면 흥미롭게 재구성해나가는 모습을 볼 수 있는다. texture synthesis와 feature inversion을 조합하면 아주 흥미로운 일이 벌어지는데, 이 아이디어가 바로 Style transfer이다.

Style transfer

style transfer에는 배경이미지와 텍스쳐를 제공해주는 이미지 이렇게 두 개의 이미지가 입력으로 들어간다. 그리고 배경 이미지에 해당 텍스쳐를 입히게 된다.

style을 옮기기 위해서, gram matrix의 loss를 최소화시키고(neural texture synthesis) 또한,content이미지의 구조를 따오기 위해서 reconstruction loss(feature inversion)까지 최소화(minimize) 시키면 위 슬라이드와 같이 아주 fancy한 이미지가 생성된다.

우리가 항상 multi-task loss와 같이 여러 loss를 합할 때에는 항상 어느쪽에 더 중심을 둘지 가중치를 선택하게된다. 이떄, 어느쪽으로 더 중심을 두냐에 따라 다른 이미지가 생성된다 위 슬라이드를 참고해보자.

또한 여러 장의 style이미지 혹은 content이미지를 가지고도 transfer를 진행해줄 수 있다. 동시에 여러 gram matrix를 계산하는 것이다.

위 슬라이드는 동시에 만든 것은 한 이미지에 다른 style을 덧댄것이다. (즉 그냥 style transfer한 번 했다는것 같다. 동시에 진행하는게 아니고 한 번수행하고 또 수행한다는 뜻. 또 content, style이미지가 어떤 것인가에 따라 또 결과가 달라질것 같다. 그 결과도 위에 슬라이드에 있다.)

위 슬라이드의 그림들은 deepdream과 style transfer를 조합한 것이다.

하지만, style transfer의 단점은 매우 느리다는 것이다. 4k image 하나를 만드는데 엄청 좋은 GPU를 사용하여도 수십 분이 소요된다고 한다(왜냐하면 content나, style 둘 중에 하나만 바뀌어도 다시 훈련시켜 이미지를 만들어내야하기 때문.). 해결책은 style transfer를 위한 다른 네트워크를 학습시키는 것이다.

위와 같은 문제를 해결하기 위해 network에 style image 1장을 학습시키고 그 network를 그대로 이용하는 방법을 제안하였다.. 즉, 한 컨텐츠 이미지에 대해서 여러 style로 전환을 한다거나 한 스타일 이미지에 대해서 여러 컨텐츠 이미지를 만든다거나 할 때, 매번 재학습없이 단순 inference만 하면 되기 때문에, real-time이 가능하다고 한다.

강의에서 보면 실제 오른쪽그림은 webcam으로 실시간 style transfer가 되는 모습을 보여준다.

이 논문에서는 instance normalization이라는 것이 등장한다.

(이 강의를 했던당시 2017년)때 쯤에 나온 google의 논문에는 한 네트워크로 여러가지 style transfer를 하는 논문이 나왔다고 한다. (이는 아주 중요하다. 여러가지 스타일을 만들려고 여러 네트워크를 다 훈련시키에는 비용이 많이 들기 때문이다.)