What’s going on inside ConvNets?
오늘은 ConvNet 안에서는 어떤 일들이 일어나고 있는지,
CNN이 입력 이미지에서 찾고 있는 것이 무엇인지 알아보는 시간을 가질 것이다.
첫 번째 layer는 입력 이미지와 필터의 Weight 값을 내적하여 만든 layer이다.
따라서, 우리 눈으로 보았을 때 edge 성분이 많이 검출되는 것을 확인할 수 있다. (Hubel & Wiesel의 실험과 일치)
AlexNet을 예로 들면 First Layer에서 가로가 11, 세로가 11이고 채널이 3개인 필터의 수가 64개 있는 것을 뜻한다.
ResNet-18은 가로가 7, 세로가 7이고 채널이 3개인 필터의 수가 64개가 있는 것을 뜻한다.
이처럼 첫 번째 Layer에서는 edge 성분들이나 다양한 각도와 위치에서의 보색(opposite colors)들을 확인할 수 있는데, 그렇다면 더 깊숙한 Layer를 시각화하면 어떨까?
Layer가 깊어지면 깊어질수록 우리가 직관적으로 해석할 수 있는 부분은 적어진다.
그 이유는 두 번째 Layer의 결과는 첫 번째 Layer의 결과를 Input으로 넣고 필터의 Weight 값들을 내적시킨 값이기 때문이다.
또한 슬라이드의 예시를 보면 Channel의 개수도 16개로 늘어난 것을 확인할 수 있는데, RGB 이미지로 표현이 가능한 3채널과 달리 16개의 채널을 한 번에 표현하기는 어렵다.
그래서 Grayscale 이미지를 16개로 표현을 하였다.
여기서 주의해야 할 점은 시각화를 위해 Normalized 작업을 거쳤다는 것이다.
실제로는 다른 값들을 가지지만, 0~255 사이의 값으로 Normalized 작업을 해줌으로써 시각화가 가능하다.
그렇다면 마지막 Layer에서는 어떤 일들이 일어나고 있을까?
AlexNet을 기준으로 class score로 변환되기 전 마지막 FC Layer에서의 특징 vector들을 한 번 살펴보자.
한 이미지에 4096 차원의 특징 벡터들이 존재하는데 각 이미지마다 특징 벡터들에 대해 Nearest Neighbors를 계산해 보면, 유사한 이미지들이 검출되는 것을 확인할 수 있다.
4096 차원의 특징 벡터들을 PCA Algorithm이나 t-SNE Algorithm으로 2차원으로 차원 축소를 하게 되면
위 그림처럼 군집화된 모습을 볼 수 있는데, 위 예시는 MNIST dataset을 가지고 2차원으로 군집화한 것을 나타낸 것이다.
우측 하단의 컬러 이미지를 보면, 0~9 사이의 숫자들이 군집화가 잘 된 것을 확인할 수 있다.
중간의 Layer들은 우리가 직관적으로 봤을 때 해석을 하기 어렵다고 언급했는데, 모든 Layer가 그런 것은 아니다.
Activation Map을 통과시킨 Layer의 모습을 시각화하게 되면
사람의 얼굴이 있는 부분에 활성화가 되는 특징 맵이 존재한다는 것을 확인할 수 있다.
모든 Layer에서 그런 것은 아니지만 일부 Layer에서 저런 모습이 관찰된다.
중간 특징들을 시각화시킬 수 있는 또 다른 방법들이 있다.
어떤 이미지가 들어와야 각 뉴런들의 활성이 최대화 되는지를 시각화하는 방법이다.
이러한 방법으로 Visualization하는 방법을 Maximally Activating Patches라고 한다.
이 슬라이드의 경우 17번째 Channel에서 이미지의 일부분을 시각화한 것을 나타냈다.
오른쪽 위의 사진을 보면 이 Channel은 푸르스름하고 동그란 물체를 찾고 있다는 것을 알 수 있다.
오른쪽 아래의 사진을 보면 좀 더 깊은 Layer에서 추출한 이미지인데, 더 깊은 Layer에서 추출을 할 시 더 큰 구조들(structures)을 추출한다는 것을 확인할 수 있다.
또 다른 방법으로는 Occlusion Experiments라는 방법이 있는데 입력의 어떤 부분이 Classification을 결정했는지 알아보기 위해 사용하는 방법이다.
입력 이미지의 일부분을 가린 후 분류를 잘 하는지 확인하는 작업을 거치는 것이다.
만약 입력 이미지의 일부를 가렸는데 네트워크 스코어에 큰 변화가 있다면 네트워크는 그 부분을 분류하는 데 크게 본다고 해석을 할 수 있다.
다른 방법은 Saliency Maps라는 방법도 있는데
예측한 클래스 스코어의 그래디언트를 계산해 어떤 픽셀을 보고 이미지를 분류했는지 알아보는 방법이다.
이 슬라이드처럼 개의 이미지를 Saliency map으로 나타내면 개의 윤곽처럼 나타나는 것을 볼 수 있다.
중간에 있는 뉴런을 하나 뽑아서 입력 이미지의 어떤 부분이 내가 선택한 뉴런에 영향을 주는지 한 번 알아보자.
우리가 네트워크를 구성할 때 ReLU를 이용하여 Activation function을 구성하는 일이 많은데,
ReLU의 positive gradient만 살려서 gradient 값을 구하면 훨씬 더 선명하고 좋은 이미지를 얻을 수 있다. (위 이미지의 guided backpropagation)
Gradient Ascent
하지만 위 방법들은 “고정된” 입력 이미지의 어떤 부분이 해당 뉴런에 영향을 미치는지를 말해준다.
그렇다면 입력 이미지에 의존적이지 않은 방법은 없을까?
해당 뉴런을 활성화시킬 수 있는 “일반적인” 입력 이미지를 찾아내는 방법으로 Gradient Ascent가 있다.
네트워크의 Weight를 고정을 시킨 후, 중간 뉴런 혹은 클래스 스코어를 최대화시키는 General한 입력 이미지를 찾아내는 방법이다.
여기서도 Regularization function을 추가하는데
이미지가 특정 뉴런의 값을 최대화시키는 방향으로 update 되면서
좀 더 자연스러운 이미지를 만들기 위해서 추가해준 것이라 이해하면 좋다.
저 위 식에서 만들어진 가 이미지의 픽셀 값을 나타내는 것이다.
그렇다면 어떻게 이미지를 만들어내는지 알아보자.
- 처음 이미지를 0으로 초기화 시킨다. (노이즈로 초기화 시켜도 됨)
- Image의 현재 score를 계산한다.
- Image pixel 단위에서 Backpropagation을 통해 gradient 값을 구한다.
- 이미지를 특정 뉴런이 최대화될 수 있도록 픽셀 단위로 update를 진행한다.
여기서 Regularization function으로 L2 norm을 사용했는데 일반적으로 쓰는 Regularization function이기 때문에 사용했다고 설명했다.
결과를 한 번 살펴보면,
상당히 정답 클래스를 잘 표현하는 것을 볼수가 있다.
특히 달마시안의 경우, 흰색과 검은색으로 이루어진 얼룩 무늬를 잘 포착한 것이 놀랍다.
Deep Dream
구글에서 ‘Deep Dream’이라는 포스팅이 소개된 적이 있다.
Deep Dream의 목적은 단순히 재미있는 이미지를 만드는 것이다.
방법을 한 번 살펴보면
- 입력 이미지를 CNN의 중간 layer까지 통과시킨다.
- 해당 gradient를 activation value 값으로 저장을 시킨다.
- Backpropagation을 통해서 이미지를 update한다.
- 위의 내용을 반복한다.
해당 Layer에 어떤 특징이 있던지 그 특징을 가지고 gradient를 계산하면 이는 네트워크가 뽑아낸 특징들을 더욱 증폭시키는 역할을 한다.
만약 하늘 이미지를 가지고 알고리즘을 수행하면 다음과 같은 결과가 나온다.
이런 결과물은 네트워크를 학습시킨 데이터와 관련이 있는데
여기서는 개의 모양을 띈 형체가 많이 나타나는 것을 확인할 수 있다. (ImageNet 데이터셋의 1000개 카테고리 중 200개가 개이기 때문이다.)
또 다른 Layer, 즉 얕은 Layer로 수행을 할 경우 다음과 같은 결과를 뽑아낼 수 있다.,
엣지 성분들이 많이 나타나는 것을 확인할 수 있다.
Feature Inversion
Feature Inversion이라는 개념이 있는데 이 방법도 네트워크의 다양한 Layer에서 어떤 요소들을 포착하고 있는지 짐작할 수 있는 방법이다.
이미지의 특정 Layer에서 activation map을 추출한 다음,
이 activation map을 가지고 이미지를 재구성하는 방법이다.
이 방법에서 Gradient Ascent 방법을 활용한다.
스코어를 최대화하는 방법 대신 특징 벡터의 거리가 최소화하는 방향으로 update를 시킨다.
새로 생성한 이미지의 특징 벡터와 기존에 계산해 놓은 특징 벡터(Activation Map에서 추출한 특징 벡터)의 거리를 측정하는 것이다.
위 슬라이드에서 나온 Total Variation Regularizer은 Regularization의 방법 중 하나인데 상하좌우 인접한 픽셀 간의 차이에 대한 패널티를 부여하는 방법이다.
결과를 보면
얕은 Layer에서 Activation Map을 추출하면 원본 영상과 비슷한 이미지를 재구성하게 된다.
하지만 깊은 Layer에서 Activation Map을 추출하면 전체적인 구조만 가지고 이미지를 재구성한다는 것을 볼 수 있다.
Texture Synthesis
텍스처 합성 문제는 컴퓨터 그래픽스 분야에서는 아주 오래된 문제다.
위키피디아의 정의에 따르면 구조적 컨텐츠를 활용하여 작은 디지털 샘플 이미지에서 큰 디지털 이미지를 알고리즘적으로 구성하는 과정이라고 한다.
일반적인 텍스처 합성은 딥러닝으로 하지 않아도 잘 수행되지만,
조금 더 복잡한 텍스처에서는 상황이 조금 다르다. (가령 위 슬라이드의 우측 케이스라던지)
따라서 딥러닝 모델을 이용해서 텍스처 합성을 하는 방법들이 제안되었는데,
특정 Layer에서 Activation Map을 가져온 다음 Gram Matrix를 생성한다.
Gram Matrix란 서로 다른 공간 정보에 있는 Channel들을 가지고 외적을 계산하여 새로운 Matrix를 만드는 것을 말한다.
이 Matrix는 특징 벡터 간 다양한 상관 관계를 한 번에 나타낼 수 있도록 만들어졌다.
Gram Matrix 대신 공분산 행렬을 써도 되지만 계산량에서 이득을 보기 위해 Gram Matrix를 사용한다.
- 공분산 행렬: 특징 맵의 모든 채널 간의 공분산을 계산해야 합니다. 특징 맵이 C개의 채널과 H x W 크기를 가진다고 가정할 때, 공분산 행렬은 C x C 크기를 가지며, 각 요소는 모든 H x W 픽셀에 대한 계산을 포함합니다. 따라서 계산 복잡도는 O(C^2 * H * W)가 됩니다. 즉, 채널 수의 제곱에 비례하여 계산량이 증가합니다.
- Gram Matrix: 특징 맵을 (C, H * W) 크기의 행렬로 변환한 후, 이 행렬과 전치 행렬의 곱을 계산합니다. 계산 복잡도는 O(C * (H * W)^2)으로 보일 수 있지만, 실제로는 행렬 곱셈의 효율적인 알고리즘을 사용하여 이보다 훨씬 빠르게 계산할 수 있습니다. 특히, 채널 수(C)가 H * W보다 훨씬 작은 경우, Gram Matrix의 계산이 훨씬 효율적입니다.
과정을 살펴보면 다음과 같다.
Gradient Ascent 과정과 비슷하다.
- Input Image를 넣고 Pretrained 된 VGG Network에서 다양한 Gram Matrix를 생성한다.
- Random Noise로 초기화 된 Image를 VGG Network를 통과 시켜 Gram Matrix를 생성한다.
- Input Image와 만들어진 Image의 Gram Matrix를 비교하여 L2 distance가 최소가 되도록 Loss값을 계산한다.
- 계산된 Loss 값을 이용하여 Backpropagation을 진행하여 이미지 픽셀의 Gradient를 계산한다.
- Gradient Ascent 방법을 통해 이미지의 픽셀 값들을 update한다.
- 위 단계를 반복하여 입력 이미지와 유사한 이미지가 만들어지도록 한다.
결과를 살펴보면 얕은 Layer에서 생성한 Gram Matrix를 가지고 이미지를 만들 경우, 공간적인 구조를 잘 살리지 못했다는 것을 확인할 수 있다.
좀 더 깊은 Layer에서 생성한 Gram Matrix를 이용해야 텍스처 합성에 잘 활용할 수 있다.
Neural Style Transfer
이러한 텍스처 합성을 예술 쪽에서 적용해보면 어떨까?해서 나온 개념이 Neural Style Transfer이다.
정확하게 말하자면 Gram Matrix를 재구성하는 것과 Feature를 재구성하는 것을 합하여 만들어진 이미지 결과가 Neural Style Transfer이다.
Neural Style Transfer에서는 입력이 두 가지인데,
첫 번째 Content Image는 우리가 최종 이미지가 어떻게 생겼으면 좋겠는지 알려주는 이미지이고,
두 번째 Style Image는 최종 이미지의 Texture가 어떻게 생겼으면 좋겠는지 알려주는 이미지이다.
최종 이미지는 Content Image의 Feature Reconstruction Loss도 최소화하고, Style Image의 Gram Matrix Reconstruction Loss도 최소화하도록 만들어진 이미지이다.
하지만 Neural Style Transfer는 수많은 forward, backward 과정을 반복해야 하므로 굉장히 느리다는 단점이 있다.
따라서 Style Transfer을 위한 또 다른 네트워크를 학습시키는 방법이 있다.
합성하고자 하는 이미지의 최적화를 전부 수행하는 것이 아니라
Content Image만을 입력으로 받아 단일 네트워크를 학습시키는 방법이다.
이 네트워크를 학습시킬 때에는, content/style loss를 동시에 학습시키고 네트워크의 가중치를 업데이트한다.
학습은 좀 오래 걸리지만, 한 번 학습을 시키고 나면 이미지를 네트워크에 통과시킬 시 결과를 바로 볼 수 있다.
지금까지 말한 Style Transfer의 단점은 네트워크 하나 당 하나의 Style Transfer밖에 못 만든다는 점이다.
따라서 구글에서는 Content Image와 Style Image를 동시에 넣는 방식으로 다양한 스타일을 만들어 내는 논문을 제안했다.
이렇게!
참고
‣