티스토리 뷰
3. Convolutional Networks / L2. Convolutional Neural Networks - Convolutional Layers
chrisysl 2018. 9. 6. 10:16Convolutional Layers(Pt. 1)
- locally connected 된 레이어는 공간을 따라 가중치를 공유하기 때문에, 전체 픽셀이 연결된 모델보다
- 훨씬 더 적은수의 가중치를 가지고 학습을 진행한다.
- 이 개념을 공식화하여 convolutional layer를 정의해보자.
- convolutional layer는 hidden layer의 한 종류이며 CNN에서 주요하게 사용된다.
- convolutional layer를 만들기 위해 이미지를 분리하려면,
- convolution window를 결정하는 너비와 높이를 정해야한다.
- 그리고 이 window를 수평으로 그리고 수직으로 옆으로 밀며 local을 지정해준다.
- window가 이동을 하며 이미지를 조각내 단일 hidden layer에 연결할 local을 지정하는 것이다.
- 이 단일 hidden layer를 convolutional layer라 부른다.
- input 노드의 locally designed된 이 작은 단위(컬렉션)가 어떻게 convolutional layer의 노드값에 영향을 미치는지 알아보면
- 화살표에 숫자 값을 줘서 노드를 연결하는 가중치를 나타내보자(위 그림에선 +1 또는 -1).
- 이 input 이미지에 대한 convolutional layer 값을 얻기위해, 이전까지 신경망을 구현한 동일한 과정을 거친다.
- input 노드에 해당 가중치를 곱하고 그 결과를 총합한다.
- 그렇게하면 0이라는 값을 얻게되고, 이전 신경망 구현에서처럼 bias는 0으로 가정할 경우
- 최종 결과값또한 0이 된다.
- convolutional layer에는 항상 ReLU activation function을 적용시키는데,
- 참고로 ReLU function은 양의 값은 그대로 두고 음의값은 모두 0으로 만든다.
- 그럼 이 경우 계산결과인 0은 그대로 0이 된다.
- 이렇게하면 convolutional layer의 첫번째 노드값을 연결할 수 있게 된다.
- 다른 모든 노드들에 대한 연산도 위와 동일한 방식으로 진행한다.
- 다음 window에 대해서도 연산을 수행하면 input * 가중치의 전체 합이 -2가 나오게되고
- 이를 ReLU function에 돌리면 0이 된다. 이렇게 나온 값들을 우측 상단처럼 격자형태 행렬에 값을 담아주는게 좋다.
- 이렇게 각 가중치를 격자형태로 나타낸 것을 filter라 부른다.
- 그리고 이 filter의 크기는 항상 convolutional window의 사이즈와 일치하게 된다.
- 이 경우 필터는 3x3 의 크기를 가짐
- 이제 이렇게되면 hidden layer의 노드들의 값을 계산하는것이 훨씬 직관적이게 된다.
- 3의 경우를 보면, 필터의 1의 값들의 위치가 input layer의 1의 위치와 정확히 일치한다.
- 앞서 input 값들을 0 과 1사이의 값으로 바꿔주었기 때문에 이 3이라는 값은
- 이 convolutional layer에서 해당 필터를 사용하여 얻을 수 있는 가장 큰 값이 된다.
- 이렇게 적용되는 local이 아래쪽에 하나 더 있는데 완전하게 동일함을 인지하고 있어야한다.
- CNN을 사용하며 종종 이 필터를 시각화 해서 보게되면, 필터가 감지해 낼 패턴을 확인할 수 있다.
- 또한 당연하게 이 가중치들은 미리 설정되는것이 아니라 loss function을 최소화 하는 방향으로
- 학습을 거쳐 개선된다.
- 위에서 예시로 확인했던것은 필터 하나에 대한 것인데,
- 다양한 패턴을 생성하려면 다양한 필터가 필요하다.
Convolutional Layers(Pt. 2)
- 이 강아지 사진을 봐보면, 이미지에서 하나의 local에 해당하는 파트는 우리가 감지해 내고자 하는
- 매우 다양한 패턴들로 구성이 되어있다.
- 표시한 영역을 보면, 이빨도 있고 혓바닥도 있고 수염도 있다.
- 이 이미지를 이해하기 위해선 이 세가지 특징을 각각 감지해 낼 수 있는 필터들이 필요하다.
- 필터 하나당 특징 하나씩을 담당한다.
- 다른 패턴을 감지하는 필터를 하나 더 두는데, 이 필터는 앞선 파란색 필터와 그 가중치가 다르다(당연하게도).
- 사실 convolutional layer 내부에 작게는 10개부터 수백개 까지의 컬렉션을 두는것이 일반적이다.
- 물론 각 컬렉션당 그에 맞는 각기 다른 필터가 필요로 된다.
- 이것을 코드로 구현해 낸 다음 최종적으로 확인해보면 각각은 이미지와 같은 형식으로 형성되는것을 확인할 수 있다.
- 즉, 값을 가진 행렬이 얻어지게 된다.
- 실제 이미지를 가지고 작업을 해 보자.
- 4 by 4 필터를 사용할 것인데, 각 필터는 이미지의 높이와 너비에 걸쳐 convolution되며
- convolution layer의 전체 노드 묶음(컬렉션)을 생성한다.
- 이 경우 우리가 4개의 필터가 있기 때문에 4개의 컬렉션이 형성된다.
- 이 네가지 컬렉션은 feature map이거나 activation map이 된다.
- 이 컬렉션들을 시각화 하면 이렇게 나타나게 된다.
- 원본 이미지에서 복잡한 정보를 모두 가져와 각 필터가 적용된 훨씬 간단한 이미지를 출력했다.
- 필터의 구조와 맞물려 생각해보면 필터 1, 2에서 수직정보를 가져와 각 수직 모서리를 잡아냈고
- 필터 3, 4에선 수평정보를 가져와 각 수평 모서리를 잡아냈다.
- 아래 그림에서 흰색으로 표시된 부분이 필터가 이미지로부터 잡아낸 패턴을 나타낸다.
- 실제 이미지를 보면, 이미지의 모서리부분은 밝은 픽셀과 어두운 픽셀의 경계로 표시된다.
- 이 이미지를 예로 들어보면, 동일한 필터를 적용하여 돌렸을 경우 필터에 의해 잡힐 상당히 많은 local들이 있다.
- CNN에서 모서리(edge)를 잡아내는 역할을 하는 필터는 매우 중요하다.
- 지금까진 greyscale 이미지를 다뤘는데, 그럼 컬러이미지는 어떻게 처리해야될까?
- 앞서 그레이스케일 이미지는 컴퓨터에 의해 높이와 너비를 가진 2D 이미지로 인지된다는것을 확인했다.
- 컬러이미지는 높이와 너비와 깊이를 가진 3D 이미지로 컴퓨터에 의해 인지된다.
- RGB이미지의 경우 뎁스가 3이다. 즉, 3D array 의 개념.
- 이것은 2D 행렬이 3개(R, G, B) 쌓여있는 구조로 생각하는것이 좋다.
- 따라서 컬러 이미지에 대해 convolution을 적용하는것은 다음과 같다.
- 그레이스케일에서와 마찬가지로 이미지를 따라 필터를 수평, 수직으로 이동시키는것은 동일하다.
- 다만, 필터 자체가 3D가 되어 각 컬러 채널(R 또는 G 또는 B)에 하나씩 할당된다.
- 각 컬러채널에 대한 값을 갖는 3D 필터가 되는것이다. 이때 3D란 3개의 2차원(2D) 매트릭스를 말한다.
- 이제 이 필터에 할당되는 노드값을 얻기위해서는 이전과 매우 유사하지만,
- 총합(sum)을 해야 할 데이터가 3배가 된다.
- 위의 그림은 컬러 이미지에 대한 하나의 필터 속 convolutional layer의 하나의 노드에 대한 연산을 나타내는 것임.
- 필터 1개 = 1개의 3D array
- 만약 컬러 이미지에 대한 여러개의 필터를 그림으로 보면 위와같다.
- 다시한번, 각각의 3차원 배열은 2차원 배열이 3개 쌓인것으로 생각하는것이 좋다.
- 먼저 R, G, B를 따라 convolutional layer에서 feature map을 형성하고, 그 feature map들을 쌓아 3D array를 얻는다.
- 그 다음, 이 3D array를 또다른 convolutional layer의 input으로 사용하고
- 첫번째로 찾아낸 패턴들의 패턴을 찾아내는 개념이다.
- 이와같은 방식으로 패턴의 패턴을 찾고 그 패턴의 패턴을 또 찾고 등.. 이렇게 중첩시켜 패턴을 찾는 것이
- convolution의 핵심이다.
- dense layer : 한번에 완전히 연결됨. 즉, 이전 레이어와 모두 연결되어 있다.
- convolutional layer : locally connected. 즉, 이전 레이어의 작은 하위집합(local)에만 연결된다.
- 또한 convolutional layer는 파라미터를 공유한다.
- 하지만 둘다 기본개념은 같다. 가중치와 바이어스를 가지고있고 최초 랜덤하게 생성되어 초기화된다.
- convolutional 필터를 거쳐 가중치를 얻어내는 CNN의 경우 그 필터자체가 랜덤하게 생성되고,
- 따라서 초기에 잡아낸 패턴 또한 랜덤하게 잡아내게 된다.
- MLP에서와 마찬가지로 CNN에서 또한 loss function을 계산해내는데,
- 멀티클래스에 대한 분류(multiclass classification)의 경우, 이 loss function은 categorical cross-entropy loss가 된다.
- 그리고 backpropagation을 통해 필터가 매 epoch마다 업데이트 되며, loss function을 최소화 해 나가며 학습이 진행된다.
- 다시말해, CNN은 loss function을 기반으로 잡아내야할 패턴이 어떤 종류인지를 결정한다.
- 여기서 custom-filter를 만들어 볼 수 있음.
** 참고
- 위에서 사용된 코드
- 1. Import the Image
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import cv2 import scipy.misc import matplotlib.pyplot as plt %matplotlib inline # TODO: Feel free to try out your own images here by changing img_path # to a file path to another image on your computer! img_path = 'images/udacity_sdc.png' # load color image bgr_img = cv2.imread(img_path) # convert to grayscale gray_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2GRAY) # resize to smaller small_img = scipy.misc.imresize(gray_img, 0.3) # rescale entries to lie in [0,1] small_img = small_img.astype("float32")/255 # plot image plt.imshow(small_img, cmap='gray') plt.show() | cs |
>>
- 2. Specify the Filters
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | import numpy as np # TODO: Feel free to modify the numbers here, to try out another filter! # Please don't change the size of the array ~ :D filter_vals = np.array([[-1, -1, 1, 1], [-1, -1, 1, 1], [-1, -1, 1, 1], [-1, -1, 1, 1]]) ### do not modify the code below this line ### # define four filters filter_1 = filter_vals filter_2 = -filter_1 filter_3 = filter_1.T filter_4 = -filter_3 filters = [filter_1, filter_2, filter_3, filter_4] # visualize all filters fig = plt.figure(figsize=(10, 5)) for i in range(4): ax = fig.add_subplot(1, 4, i+1, xticks=[], yticks=[]) ax.imshow(filters[i], cmap='gray') ax.set_title('Filter %s' % str(i+1)) width, height = filters[i].shape for x in range(width): for y in range(height): ax.annotate(str(filters[i][x][y]), xy=(y,x), horizontalalignment='center', verticalalignment='center', color='white' if filters[i][x][y]<0 else 'black') | cs |
>>
- 3. Visualize the Activation Maps for Each Filter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | from keras.models import Sequential from keras.layers.convolutional import Convolution2D import matplotlib.cm as cm # plot image plt.imshow(small_img, cmap='gray') # define a neural network with a single convolutional layer with one filter model = Sequential() model.add(Convolution2D(1, (4, 4), activation='relu', input_shape=(small_img.shape[0], small_img.shape[1], 1))) # apply convolutional filter and return output def apply_filter(img, index, filter_list, ax): # set the weights of the filter in the convolutional layer to filter_list[i] model.layers[0].set_weights([np.reshape(filter_list[i], (4,4,1,1)), np.array([0])]) # plot the corresponding activation map ax.imshow(np.squeeze(model.predict(np.reshape(img, (1, img.shape[0], img.shape[1], 1)))), cmap='gray') # visualize all filters fig = plt.figure(figsize=(12, 6)) fig.subplots_adjust(left=0, right=1.5, bottom=0.8, top=1, hspace=0.05, wspace=0.05) for i in range(4): ax = fig.add_subplot(1, 4, i+1, xticks=[], yticks=[]) ax.imshow(filters[i], cmap='gray') ax.set_title('Filter %s' % str(i+1)) # visualize all activation maps fig = plt.figure(figsize=(20, 20)) for i in range(4): ax = fig.add_subplot(1, 4, i+1, xticks=[], yticks=[]) apply_filter(small_img, i, filters, ax) ax.set_title('Activation Map for Filter %s' % str(i+1)) | cs |
>>