- Neural Network가 training data를 어떻게 학습하고 무엇을 배우는가
- Visualizing and Understanding의 기술들을 재미있는 application에 적용
Summary
네트워크 내부에서는 과연 어떤 것을 학습할까?
Conv Net의 매우 첫번재 layer에서는 다른 color들과 여러 종류의 edges를 찾는다.
2번째, 3번째 conv layer을 visualize하면 더이상 blobs나 edges를 잘 보기 힘들다. 그래서 어떤 것을 보고 있는지 정확히 알기 힘들다.
실질적으로 conv layers가 어떤 일을 하는지 보려면 중간 layers를 건너뛰고 last fc layer을 살펴봐야한다.1000개의 class scores를 계산하기 전 4096차원의 feature vector을 시각화해보려고 한다.
4096 dim feature vector에 Nearest Neighbors를 적용하였다.
왼쪽 그림은 학습 전에 픽셀 공간에서 Nearest Neighbors를 적용한 것으로 비슷한 이미지들을 묶을 수 있다. 하지만 개의 이미지를 넣었음에도 그저 흰색 덩어리가 있는 다른 이미지들을 가져오기도 한다.
오른쪽 그림은 학습 후에 픽셀 공간이 아니라 CNN에서 나온 4096-dim feature vectors에서 NN을 계산한다. 이를 보면 픽셀 공간에서의 NN과 다르게 픽셀 값의 차이가 커도 feature이 비슷하면 비슷한 이미지로 계산한다. 코끼리를 보면 머리의 방향이 달라 픽셀 값의 차이가 매우 다름에도 같은 코끼리로 학습하여 비슷한 feature을 갖는다.
즉 네트워크가 학습을 통해 이미지의 semantic content features을 잘 포착한 것이다.
NN이 어떻게 계산되는가?
4096-dim을 2-dim으로 축소하여 보기 쉽게 visualize한다. t-SNE
을 통해 차원축소를 한 예시이다.
https://cs.stanford.edu/people/karpathy/cnnembed/
이곳에서 feature space를 확인해볼 수 있다. 서로 다른 sementic categories에 대응하는 이미지들을 확인할 수 있고, 각 class들이 cluster을 이루고 있다.
중간 layers의 가중치들은 시각화하더라도 어떤의미를 갖는지 확인하기 어렵다. 따라서 중간 layers의 가중치가 아니라 Activation map을 시각화 해보면 일부 해석할 수 있는 것들을 볼 수 있다.AlexNet
의 예시를 보면 conv5의 feature map은 128x13x13의 tensor이며 이는 128개의 13x13 2-dim grid로 볼 수 있다. 이를 그레이스케일 이미지로 시각화해보면 conv layer가 입력에서 어떤 features를 찾고 있는지를 짐작해볼 수 있다.
초록색 박스의 feature map을 보면 사람의 얼굴에 활성화되는 것 같아 보인다. 즉 분명 어떤 layer에서는 사람의 얼굴을 찾고 있다는 것이다.
대부분의 filter 값들이 검은색인 이유는 ReLU를 거쳤기 때문이다.
어떤 이미지가 들어와야 각 뉴런들의 활성이 최대화되는지를 시각화해보는 방법이다.conv5를 통과한 후 나온 128x13x13의 activation map중에서 17번째 channel을 보기로 하였다. 많은 이미지를 CNN에 통과시키고 선택한 channel을 max activate시킨 이미지 패치를 visualize한 결과는 오른쪽 그림과 같다.
각 행에 있는 패치들은 하나의 뉴런에서 나온 것이다. 이 패치들은 해당 뉴런의 활성을 최대화시킨 패치들이다. 이들 특징을 통해 해당 뉴런이 무엇을 찾고 있는지 짐작할 수 있다.
여기에서 한 뉴런은 conv5 activation map의 하나의 scalar값이다. conv5는 conv layer이므로 한 channel안의 모든 뉴런들은 모두 같은 가중치를 공유한다. 각 channel 당 하나의 conv filter이 있고, 이에 상응하는 많은 뉴런들(activation map)이 있다.
위 그림에서 아래의 그림은 같은 네트워크의 더 깊은 layer에서 뉴런들을 최대로 활성화시키는 패치들이다. 더 깊은 layer에서 왔으므로 receptive field가 훨씬 더 넓다. 즉, 입력으로부터 훨씬 더 큰 패치들을 기준으로 찾는다.
이 실험에서 알고자 하는 것은 입력의 어떤 부분이 분류를 결정짓는 근거가 되는지에 관한 실험이다.
위 예시에서는 코끼리를 입력으로 받고 이미지의 일부를 가린다. 그리고 가린 부분을 데이터셋의 평균 값으로 채워버린다. 이를 네트워크에 통과시키고 네트워크가 이 이미지를 예측한 확률을 기록한다. 그리고 이 occluded patch
를 전체 이미지에 대해 sliding하여 반복한다.
만약 이미지의 일부를 가렸는데 네트워크 스코어의 변화가 크게 발생한다면 가려진 그 부분이 분류를 결정짓는데 아주 중요한 부분이라는 것이다.
예시를 자세히 보자. 가장 아래 예시를 보면 빨간색 지역은 확률값이 낮음을 의미한다. 앞쪽의 카트부분을 가렸을 때 확률이 매우 감소함을 볼 수 있다. 즉, 네트워크가 이 부분을 많이 고려한다는 사실이다.
Simonyan, Vedaldi, and Zisserman, “Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps”, ICLR Workshop 2014.
개를 입력으로 넣었을 때 네트워크는 이를 개라고 예측할 것이다. 이 때 우리는 네트워크가 픽셀들을 보고서 이미지를 개라고 분류했는지를 알고싶다.
이 방법은 입력 이미지의 각 픽셀들에 대해서 예측한 클래스 스코어의 gradient를 계산하는 방법이다. 어떤 픽실에 영향력있는지를 알 수 있다. 어떤 픽셀이 개를 분류하는데 있어서 중요한지 알 수 있다. 그림 아래의 Saliency map
을 보면 개의 윤곽이 보인다.다른 이미지들의 saliency map
을 보면 위와 같다.
위의 saliency map
을 가지고 segmentation 레이블 없이 semantic segmentation을 수행할 수 있다.이들은 Grabcut Segmentation Algorithm
을 사용한다. Grabcut은 interactive segmentation algorithm이라고 한다.. 이는 자세히 설명하지 않았다.
Saliency map
과 grabcut
을 잘 조합하여 이미지 내에서 객체럴 segmentation할 수 있다. 그러나 supervision이 있을때에 비해 매우 안 좋은 성능을 낸다고 한다.
이번에는 어떤 이미지가 있을 때 클래스 스코어가 아니라 네트워크의 중간 뉴런을 하나 고른다. 그리고 입력 이미지의 어떤 부분이 내가 선택한 중간 뉴런의 값에 영향을 주는지 찾는 것이다.
이 경우에는 이미지의 각 픽셀에 대한 클래스스코어의 gradient를 계산하는 것이 아니라 입력 이미지의 각 픽셀에 대한 네트워크 중간뉴런의 gradient를 계산한다. 이를 통해 어떤 픽셀이 해당 뉴런에 영향을 주는지 알 수 있다.오른쪽의 guided backprop(ReLU의 gradient부호가 양수면 그대로 통과, 음수이면 backprop하지 않음)을 통해 더 좋은 이미지를 얻을 수 있다고 한다.guided backprop을 통해서 어떤 픽셀들이 뉴런들에 영향을 미치고 있는지 확인할 수 있다. 이 방법은 중간 layer가 무엇을 찾고 있는지 이해하기 위한 영상을 합성하는데 아주 유용하다.
그런데.. 이들 방법들은 모두 고정된 입력 이미지의 어떤 부분이 어떻게 영향을 미치는지밖에 말해주지 않는다. 입력 이미지에 의존하지 않는 방법은 없을까?
해당 뉴런을 활성화시킬 수 있는 일반적인입력 이미지가 있을까?
우리는 loss의 최소화를 위해 gradient descent를 사용한다. 그러나 gradient ascent에서는 네트워크 가중치를 전부 고정시키고 gradient ascent를 통해 중간 뉴런 혹은 클래스 스코어를 최대화시키는 이미지의 픽셀들을 만들어낸다. 즉 가중치를 최적화하는 것이 아니라 뉴런 또는 클래스 스코어가 최대화될 수 있도록 입력 이미지의 픽셀값을 바꿔주는 방법이다.이때 regularization term
이 필요한데 생성된 이미지가 특정 네트워크의 특성에 과적합되는 것을 방지하기 위함이다. 이를 통해,
regularization term
의 역할)regularization term
gradient ascent를 위해 초기 이미지가 필요한데 이는 zeros
, uniform
, noise
등으로 초기화한다.
그리고 이를 네트워크에 통과시키고 우리가 선택한 뉴런의 스코어를 계산한다. 그리고 이미지의 각 픽셀에 대한 해당 뉴런 스코어의 gradient를 계산하여 back prop을 한다.스코어를 최대화시키기 위해 이미지 픽셀 자체를 업데이트한다.L2 norm
의 regularize를 진행한 예시이다. 각 클래스의 특징을 나타내는 모양이 있음을 확인할 수 있다.위의 두 사진은 더 좋은 regularizer을 적용한 결과이다. 똑같이 L2 norm을 정용했지만 이미지에 주기적으로 Gaussian blur
을 적용하고 값이 작은 픽셀들을 0으로 만들었다. gradient가 작은 값들도 0으로 만든다.
위와 같이 최종 스코어를 최대화시키는 것이 아니라 중간 뉴련을 최대화시키는 이미지를 생성해보면 아래와 같다.
입력 이미지의 픽셀을 곧장 최적화하기보다 FC6을 최적화하는 것을 기본 아이디어로 하여 발전시켰다고 한다. 이미지 생성 문제에서 prior을 추가하면 아래와 같이 매우 현실적인 이미지를 만들 수 있다.
네트워크를 속이기 위한 이미지를 만들어낸다.
- 임의의 이미지를 고른다.
- 어떤 클래스로 속일지 클래스를 고른다.
- gradient ascent를 통해 선택한 다른 클래스의 스코어를 최대화시키도록 고른 이미지를 변형시킨다.
- 네트워크가 속을때까지 반복한다.
거의 변함없는 두 이미지이지만 코끼리를 코알라로, 범선을 아이팟으로 잘못 분류하고 있는 것을 볼 수 있다. 이들은 그저 아주 조금의 픽셀이 변형되었을 뿐이다.
네트워크의 다양한 layer에서 이미지의 어떤 요소들을 포착하고 있는지를 짐작할 수 있게 해준다.
이를 통해서 이미지의 어떤 정보가 feature vector에서 포착되는지 짐작할 수 있다. 이 방법 또한 regularization
을 추가한 gradient ascent
를 이용한다. 스코어를 최대화시키는 것 대신, feature vector간의 거리를 최소화시키는 방법을 이용한다.
기존에 계산한 feature vector 와,
새롭게 생성한 이미지로 계산한 feature vector
간의 거리를 측정한다.
과제에서도 나오겠지만, 사람들이 자주 사용하는 regularizer
인 total variation
이 있다.
상하좌우 인접 픽셀 간의 차이에 대한 패널티를 부여한다. 이를 통해 생성된 이미지가 자연스럽게 되도록 한다.
Feature Inversion을 통한 시각화 예시를 보자.왼쪽 이미지는 원본 이미지이다.
다양한 layer에서 나온 activation map(feature map)을 가지고 합성한 이미지들을 보고 어떤 정보들을 저장하고 있는지 짐작해볼 수 있다.
relu2_2
를 거쳐 나온 feature vectors를 가지고 이미지를 재구성해보면 원본과 거의 동일하다. 이를 통해 relu2_2
에서는 이미지 정보를 많이 날리지 않는다는 것을 알 수 있다.
그러나 깊은 layer에서 살펴보면 네트워크가 깊어질수록 픽셀 값이 정확히 얼마인지와 같은 low-level 정보들은 사라지고 대신 색이나 텍스쳐와 같은 미세한 변화에 더 강력한 의미론적 정보들을 유지하는 것처럼 보인다.
DeepDream의 목적은 재미있는 이미지를 만드는 것이다. 또한, 모델이 이미지의 어떤 특징을 찾고 있는지를 짐작할 수도 있다.DeepDream에서는 입력 이미지를 CNN의 중간 layer를 어느정도 통과시킨다.
이를 반복하여 네트워크에 의해 검출된 이미지의 features를 증폭시킨다. 해당 layer에 어떤 특징들이 있든지 그 특징들을 gradient로 설정하면 이는 네트워크가 이미지에서 이미 뽑아낸 특징들을 더욱 증폭시키는 역할을 한다.
특정 feature의 activation이 훨씬 커지도록 이미지를 변형한다.
그리고 이는 해당 layer에서 나온 특징들의 L2norm을 최대화시키는 것으로 볼 수 있다.위 이미지는 초기 layer의 feature을 증폭시킨 것으로 edges등이 나타난다.higher layer의 features이다.위 그림은 multi-scale 프로세싱을 수행하여 오래 돌린 결과이다. 작은 이미지로 DeepDream을 수행하고 점점 이미지 크기를 늘린다.다른 데이터셋으로 학습시키면 위와 같은 결과도 얻을 수 있다.
텍스쳐 합성은 어떤 작은 텍스쳐 패치가 있을 때, 이를 갖고 같은 텍스쳐를 갖는 더 큰 이미지를 생성하는 task이다.
이 방법은 신경망 대신에 scan line을 따라 한 픽셀씩 이미지를 생성하는 방법이다.
그러나 이러한 복붙방식의 고전방식은 아래와 같이 복잡한 텍스쳐에서 잘 동작하지 않는다.
텍스쳐 합성에 신경망을 도입한 방법이다.이미지를 네트워크에 통과시키고 특정 layer에서 feature map을 가져온다.
위 그림에서처럼 HxW의 한 점에 있는 C차원 feature vector은 해당 지점에 존재하는 이미지의 특징을 담고있다고 할 수 있다.
우선 feature map에서 서로 다른 두개의 feature vector(red, blue)를 뽑는다. 그리고 이 둘의 외적을 계산하여 CxC행렬을 만든다. 이 CxC행렬은 이미지 내 서로 다른 두 지점에 있는 특징들 간의 co-occurrence를 담고 있다. CxC행렬의 (i,j)번째 요소의 값이 크다면 두 입력 벡터의 i번째, j번째 요소가 모두 크다는 의미이다.
이를 통해 서로 다른 공간에서 동시에 활성화되는 특징이 무엇인지 어느정도 포착할 수 있다.위 과정을 HxW그리드에서 전부 수행하고 결과에 대한 평균을 계산하면 CxC Gram matrix
를 얻을 수 있다. 그리고 이 결과를 입력 이미지의 텍스쳐를 설명하는 텍스쳐 기술자(discripter)로 사용한다.
Gram matrix는 이미지의 각 지점에 해당하는 값들을 평균화시켰기 때문에 공간 정보를 모두 날린다. 대신 특징들 간의 co-occurrence만을 포착한다.
이렇게 텍스쳐 기술자를 만들었으니 이제 이미지를 생성할 차례이다.gradient ascent와 유사한 과정을 거친다. 입력 이미지의 gram matrix를 재구성하도록 한다.
위와 같은 결과를 볼 수 있다.
Neural Style Transfer: Feature + Gram Reconstructiontexture synthesis
와 feature inversion
을 조합하면 흥미로운 결과를 낼 수 있다.
Style Transfer은 두가지 입력을 받는다.
최종 이미지는 content image의 feature reconstruction(feature inversion) loss도 최소화하고,
style image의 gram matrix loss도 최소화하는 방식으로 최적화하여 이미지를 생성한다.
수백번 정도 반복하면 아래와 같은 output image를 얻을 수 있다.
Neural Style Transfer은 DeepDream에 비해 더 많이, 정밀한 조정을 할 수 있다.style/content loss간의 가중치를 조절하면 어디에 더 집중해서 이미지를 생성할지 조절할 수 있다.또한, gram matrix를 계산하기 전 style image를 resizing하여 넣어주면 style image로부터 재구성된 feature scale을 조절할 수 있다.여러 style images를 가지고도 생성할 수 있다.
style transfer은 VGG에서 많은 forward / backward pass가 일어나 매우 느리다.
따라서 style transfer을 위한 또 다른 네트워크를 학습시킨다.style image는 하나로 고정한다. 그리고 content image만을 받아서 결과를 출력할 수 있는 단일 네트워크를 학습시킨다.
그러나 이는 하나의 네트워크가 하나의 style만 생성할 수 있다.
하나의 네트워크로 다양한 Style을 생성할 수 있다. 어떤 방법인지는 자세히 설명되지 않았다.