CS231n 12강 요약
CNN Layer들의 Data를 시각화 하는 방법에 대해 알아보자!
0. Today’s Goal
- ConvNet 안에서는 어떤 일이 일어나고 있을까?
- Gradient Ascent
- Feature Inversion
- Neural Style Transfer
1. 강의 및 강의 자료
강의를 들어볼 수 있는 링크와 강의 자료를 pdf형식으로 준비했다.
한글 자막이 필요하신 분은 다음의 링크를 확인해주세요. :)
- 한글 자막을 첨부하고 싶으면 여기를 눌러주세요.
2. ConvNet 안에서는 어떤 일이 일어나고 있을까?
오늘은 ConvNets 안에서는 어떤 일들이 일어나고 있는지,
도대체 어떤 모습들을 보고 딥러닝 모델이 잘 작동을 하고 있는지
알아보는 시간을 가질 것이다.
이러한 Visualizing이 중요한 이유는 다음과 같다.
- 딥러닝이 잘 작동하는 이유를 시각화하여 설명하기 위해
- 딥러닝이 잘 작동 되어도 딥러닝을 믿지 못하는 연구자들에게 딥러닝 내부 동작을 보여줌으로써 해석 가능한 부분이 있다는 것을 알려주기 위해
위와 같은 이유들로 딥러닝 내부를 시각화 하려는 노력들이 있었다.
첫 번째 layer는 입력 이미지와 필터의 Weight 값을 내적하여 만든 layer이다.
따라서, 우리 눈으로 보았을 때 엣지 성분이 많이 검출되는 것을 확인할 수 있다.
AlexNet을 예로 들면 First Layer에서는 가로가 11, 세로가 11이고 채널이 3개이고 필터의 수가 64개가 있는 것을 뜻한다.
ResNet-18(18은 Layer의 수를 뜻한다.)은 가로가 7, 새로가 7이고 채널이 3개인 필터의 수가 64개가 있는 것을 뜻한다.
이처럼 첫 번째 Layer에서는 엣지 성분처럼 보이는 것들을 확인할 수 있는데, 그렇다면 더 깊숙한 Layer를 시각화 한다면 어떨까?
Layer가 깊어지면 깊어질수록 우리가 직관적으로 해석할 수 있는 부분이 적어진다.
그 이유는 두 번째 Layer의 결과를 보면 첫번째 Layer의 결과를 Input으로 넣고 필터 Weight들의 내적을 시킨 값이기 때문이다.
슬라이드의 예시에서 보면 Channel의 갯수도 16개로 늘어난 것을 확인 할 수 있는데, 3채널은 RGB 이미지로 한번에 우리가 표현을 할 수 있지만, 16개의 채널을 한 번에 표현하기란 참 어렵다..
그래서 Grayscale 이미지를 16개로 표현을 하였다.
여기서 주의해야 할 점은 시각화를 위해 Normalized 작업을 거쳤다는 것이다.
실제로는 다른 값들을 가지지만, 0~255 사이의 값으로 Normalized 작업을 해줌으로써 시각화를 가능하게 한다.
마지막 Layer에서는 어떤 일들이 일어나고 있을까?
AlexNet을 기준으로 Softmax를 거치기 전 Fully Connected 7 Layer에서 특징 vector들을 한 번 살펴보자.
한 이미지에 4096 차원의 특징 벡터들이 존재하는데
각 이미지 마다 특징 벡터들을 Nearest Neighbor Algorithm을 돌리게 되면,
(Nearest Neighbor Algorithm에 대한 설명은 CS231n 2강 요약에서 확인할 수 있다.)
유사한 이미지들이 검출이 되는 것을 확인 할 수 있다.
4096차원의 특징 벡터를 PCA Algorithm이나 t-SNE Algorithm으로
2차원으로 차원 축소를 하게 되면
슬라이드에 나온 그림 처럼 군집화 된 모습을 볼 수 있는데,
위 예시는 MNIST dataset을 가지고 2차원으로 군집화한 것을 나타낸 것이다.
중간의 Layer들은 우리가 직관적으로 봤을 때 해석을 하기 어렵다고 언급했었다.
그러나 모든 Layer가 그런 것은 아니다.
Activation Map을 통과시킨 Layer의 모습을 시각화 하게 되면
사람의 얼굴이 있는 부분이 활성화된 Layer가 있다는 것을 확인할 수 있다.
모든 Layer에서 그런 것이 아니라 일부의 Layer에서 저런 모습이 관찰 된다.
지금까지는 고정적인 이미지(하나의 이미지)가 들어왔을 때,
각 Layer에서 어떤 반응을 보이는 지 관찰을 했었다.
그렇다면 일반적인 이미지(General한 이미지)가 들어왔을 때,
어떤 이미지가 들어와야 각 뉴런들의 활성화가 최대화가 되는지
알아볼 수 있지 않을까?
이러한 방법으로 Visualization한 방법을 Maximally Activating Patches라고 한다.
이 슬라이드의 경우 17번째 Channel에서 이미지의 일부분을 시각화한 것을 나타냈다.
오른쪽 위의 사진을 보면 이 Channel은 푸르스름하고 눈같이 생긴 이미지에 크게 활성화 된다는 것을 추측 할 수 있다.
오른쪽 아래의 사진을 보면 좀 더 깊은 Layer에서 추출한 이미지인데,
더 깊은 Layer에서 추출을 한다면 더 큰 구조를 추출 한다는 것을 확인 할 수 있다.
또 다른 방법으로는 Occlusion Experiments라는 방법이 있는데
입력의 어떤 부분이 Classification을 결정했는지 알아보기 위해 사용한 방법이다.
입력 이미지의 일부분을 가린 후 분류를 잘 하는지 확인하는 작업을 거치는 것이다.
만약 입력 이미지의 일부를 가렸는데 네트워크 스코어에 변화가 있다면 네트워크는 그 부분을 분류를 하는데 크게 본다고 해석을 할 수 있다.
다른 방법으로 Saliency Maps라는 방법도 있는데
이는 어떤 픽셀을 보고 이미지를 분류했는지 알아보는 방법이다.
이 슬라이드 처럼 개의 이미지를 Saliency map으로 나타내면 개의 윤곽처럼 나타내는 것을 볼 수 있다.
그렇다면 이런 Saliency map을 가지고 segmentation 작업을 진행할 수 있지도 않을까?
가능은 하지만 성능이 그렇게 좋지는 않다… :(
중간에 있는 뉴런을 하나 뽑아서 입력 이미지의 어떤 부분이 내가 선택한 뉴런에 영향을 주는지 한 번 알아보자.
우리가 네트워크를 구성할 때 ReLU를 이용하여 Activation function을 구성하는 일이 많은데,
ReLU의 positive gradient만 살려서 gradient 값을 구하면 훨씬 더 선명하게 활성화 된 위치(?)를 확인할 수 있다.
3. Gradient Ascent
Gradient를 구할 때 Backpropagation 방법으로 구하는 경우가 많았다.
이 방법은 입력 이미지가 들어왔을 때,
Weight값을 update시키기 위해 사용했던 방법인데
이것과는 반대(?)의 개념이 Gradient Ascent 방법이다.
네트워크의 Weight를 고정을 시킨 후,
해당 뉴런을 활성화 시키는 General한 입력 이미지를 찾아내는 방법이다!
여기서도 Regularization function을 추가하는데
이미지가 특정 뉴런의 값을 최대화시키는 방향으로 update 되는데
좀 더 자연스러운 이미지를 만들기 위해서 추가해준 것이라 이해하면 쉽다.
저 위 식에서 만들어진 $I^*$가 이미지의 픽셀 값을 나타내는 것이다.
그렇다면 어떻게 이미지를 만들어내는지 알아보자!
- 처음 이미지를 0으로 초기화 시킨다. (노이즈로 초기화 시켜도 됨!)
- Image의 현재 score를 계산한다.
- Image pixel 단위에서 Backpropagtion을 통해 gradient 값을 구한다.
- 이미지를 특정 뉴런이 최대화할 수 있도록 픽셀 단위로 update를 진행한다.
여기서 Regularization function으로 L2 norm을 사용했는데
일반적으로 쓰는 Regularization function이기 때문에
여기서 사용을 했다고 설명했다.
결과를 한 번 살펴보면,
Dumbbell을 가장 잘 찾는 network를 Gradient Ascent 방법을 통해서
가장 최적화된 그림을 보면
마치 Dumbbell이 있는 듯한(?) 그림이 나타나는 것을 볼 수 있다.
이 때 색깔이 다채롭게 나타나는 이유는 실제 딥러닝 모델은 constrained optimization 과정으로 만들어지는데 여기 있는 이미지는 그러한 제약이 없어서 다채로운 색깔의 이미지가 만들어 졌다고 설명했다.
크게 색깔에는 신경을 쓰지 않아도 된다.
Deep Dream
구글에서 ‘Deep Dream’이라는 포스팅이 소개된 적이 있다.
Deep Dream의 목적은 재미있는 이미지를 만드는 것이다.
방법을 한 번 살펴보면
- 입력 이미지를 CNN의 중간 Layer까지 통과를 시킨다.
- 해당 gradient를 activation value 값으로 저장을 시킨다.
- Backpropagation을 통해서 이미지를 update한다.
- 위의 내용을 반복한다.
해당 Layer의 어떤 특징이 있던지 그 특징을 가지고 gradient를 계산하면 이는 네트워크가 이미 뽑아낸 특징들을 더욱 증폭시키는 역할을 하는 것이다.
만약 하늘 이미지를 가지고 알고리즘을 수행하면
다음과 같은 결과가 나온다.
이런 결과물은 네트워크를 학습시킨 데이터와 관련이 있는데
여기서는 개의 모양을 띈 형체가 많이 나타나는 것을 확인할 수 있다.
또 다른 Layer, 즉 얕은 Layer로 수행을 할 경우 다음과 같은 결과를 뽑을 수 있다.
엣지 성분들이 많이 나타나는 것을 확인할 수 있다.
4. 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
텍스처 합성은 구조적 컨텐츠를 활용하여 작은 디지털 샘플 이미지에서 큰 디지털 이미지를 알고리즘적으로 구성하는 과정이다. (By 위키피디아)
일반적인 텍스처 합성은 딥러닝으로 하지 않아도 잘 수행되지만,
글자를 이용하여 텍스처 합성을 하는 경우는 쉽지 않다.
글자가 깨지고 엉망으로 텍스처가 복사된다.
따라서 딥러닝 모델을 이용해서 텍스처 합성을 하는 방법들이 제안되었는데,
특정 Layer에서 Activation Map을 가져온 다음 Gram Matrix를 생성한다.
Gram Matrix란 서로 다른 공간 정보에 있는 Channel들을 가지고 외적을 계산하여 새로운 Matrix를 만드는 것을 말한다.
이 Matrix는 특징 벡터간 다양한 상관 관계를 한 번에 나타낼 수 있도록 만들어졌다.
강의에서 Gram Matrix 대신 공분산 행렬을 써도 되지만 계산량에서 이득을 보기 위해 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를 이용해야 텍스처 합성에 잘 활용할 수 있다!
5. 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도 최소화하도록 만들어진 이미지이다.
Style Transfer는 Deep Dream에 비해서 이미지를 생성할 때 Control할 것들이 많아진다.
하지만 Neural Style Transfer는 수많은 forward, backward 과정을 반복해야 하므로 굉장히 느리다는 단점이 있다..
따라서 Style Transfer를 위한 또 다른 네트워크를 학습시키는 방법이 있다.
합성하고자 하는 이미지의 최적화를 전부 수행하는 것이 아니라
Content Image만을 입력으로 받아서 단일 네트워크를 학습시키는 방법이다.
이 네트워크 학습시에는 content loss와 style loss를 동시에 학습시키고 네트워크의 가중치를 업데이트를 시킨다.
학습은 좀 오래걸리지만 한 번 학습을 시키고 나면 이미지를 네트워크에 통과시키면 결과를 바로 볼 수 있다.
지금까지 말한 Style Transfer의 단점은 네트워크 하나당 하나의 Style Transfer만을 만들 수 밖에 없다는 점이다.
따라서 구글에서는 Content Image와 Style Image를 동시에 넣는 방식으로 다양한 스타일을 만들어 내는 논문을 제안했다.
오늘의 강의를 슬라이드로 요약을 하면 다음과 같다.
처음 강의를 소개할 때 Data Visualization으로 소개를 했는데,
강의에는 이미지를 재구성하는 것과 관련된 내용이 많은 것 같다..ㅎ
댓글남기기