이번에는 실제로 텐서플로우에서 Convolution 데이터와 Pooling이 어떻게 진행되는지에 대해 알아보겠습니다.
먼저 다음과 같이 예시 이미지를 생성합니다.
1 2 3 4 5 6 7 8 9 10 11 12 | import numpy as np import tensorflow as tf import matplotlib.pyplot as plt sess = tf.InteractiveSession() image = np.array([[[[1],[2],[3]], [[4],[5],[6]], [[7],[8],[9]]]], dtype=np.float32) print(image.shape) #-> (1, 3, 3, 1) #show image plt.imshow(image.reshape(3,3), cmap='Greys') | cs |
해당 이미지는 왼쪽 상단에서부터 차례대로 1, 2, 3 ... 9 의 값을 가지고 있습니다. 이미지의 shape인 (1, 3, 3, 1)은 여기를 참고하세요.
그 다음에는 필터를 적용합니다. 필터의 각 weight 값은 편의상 1로 지정했으며, Stride = 1X1입니다.
필터는 image를 훑으며 각각 12, 16, 24, 28의 값을 갖는 output을 생성합니다. filter의 shape (2, 2, 1, 1)는 각각 구조, 색, 필터의 갯수를 의미합니다.
output의 shape는 마찬가지로 각각 사용한 이미지의 갯수인 1, 2X2 구조, 1가지 색이 됩니다.
이것을 텐서플로우에서 구현하면 다음과 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #filter weight = tf.constant([[[[1.]],[[1.]]], [[[1.]],[[1.]]]]) print("weight.shape", weight.shape) # -> (2, 2, 1, 1) #zero-padded NONE conv2d = tf.nn.conv2d(image, weight, strides=[1, 1, 1, 1], padding='VALID') conv2d_img = conv2d.eval() #print image shape print("conv2d_img.shape", conv2d_img.shape) # -> (1, 2, 2, 1) #print image conv2d_img = np.swapaxes(conv2d_img, 0, 3) for i, one_img in enumerate(conv2d_img): print(one_img.reshape(2,2)) # -> [[ 12. 16.], [ 24. 28.]] plt.subplot(1,2,i+1), plt.imshow(one_img.reshape(2,2), cmap='gray') # -> show image | cs |
[output 1 : 필터 1개를 사용하고, zero-padded를 사용하지 않은 모델]
이제 zero-padded section을 이용해서, 원본과 같은 크기인 3X3 output을 생성해보겠습니다. 이를 그림으로 표현하면 아래와 같습니다. ( 텐서플로우에서 원본 크기가 나오도록 자동으로 zero - paded 영역을 설정합니다 )
이것을 텐서플로우에서 구현하는 방법은 어렵지 않습니다. 단지 conv2d의 padding 속성을 VALID -> SAME으로 바꿔주면 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #filter weight = tf.constant([[[[1.]],[[1.]]], [[[1.]],[[1.]]]]) print("weight.shape", weight.shape) # -> (2, 2, 1, 1) #zero-padded USE conv2d = tf.nn.conv2d(image, weight, strides=[1, 1, 1, 1], padding='SAME') conv2d_img = conv2d.eval() #print output shape print("conv2d_img.shape", conv2d_img.shape) # -> (1, 3, 3, 1) #about show image conv2d_img = np.swapaxes(conv2d_img, 0, 3) for i, one_img in enumerate(conv2d_img): print(one_img.reshape(3,3)) # -> [[ 12. 16. 9.], [ 24. 28. 15.], [ 15. 17. 9.]] plt.subplot(1,2,i+1), plt.imshow(one_img.reshape(3,3), cmap='gray') | cs |
[output 2 : 필터 1개를 사용하고, zero-padded를 사용한 모델]
이번에는 필터를 여러 개 사용하는 모델을 적용합니다. 마찬가지로 2X2X1 shape의 필터 3개를 사용합니다. 따라서 weight의 shape는 (2, 2, 1, 3) 입니다.
각각의 필터의 weight 값은 1, 10, -1이고, 따라서 출력되는 output의 개수도 3개가 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #filter weight = tf.constant([[[[1.,10.,-1.]],[[1.,10.,-1.]]], [[[1.,10.,-1.]],[[1.,10.,-1.]]]]) print("weight.shape", weight.shape) # -> (2, 2, 1, 3) #zero-padded USE conv2d = tf.nn.conv2d(image, weight, strides=[1, 1, 1, 1], padding='SAME') conv2d_img = conv2d.eval() #print show image print("conv2d_img.shape", conv2d_img.shape) # -> (1, 3, 3, 3) #about show image conv2d_img = np.swapaxes(conv2d_img, 0, 3) for i, one_img in enumerate(conv2d_img): print(one_img.reshape(3,3)) # -> ... plt.subplot(1,3,i+1), plt.imshow(one_img.reshape(3,3), cmap='gray') | cs |
[output 3 : 필터 3개를 사용하고, zero-padded를 사용한 모델]
이제 마지막으로 Pooling하는 방법에 대해서 알아보겠습니다. 이것 또한 텐서플로우에서 제공하는 함수를 이용해서 다음과 같이 간단하게 구현할 수 있습니다.
(1) zero-padded를 적용하지 않은 경우
1 2 3 4 5 6 | image = np.array([[[[4],[3]], [[2],[1]]]], dtype=np.float32) pool = tf.nn.max_pool(image, ksize=[1, 2, 2, 1], strides=[1, 1, 1, 1], padding='VALID') print(pool.shape) print(pool.eval()) | cs |
(2)zero-padded를 적용한 경우
1 2 3 4 5 6 | image = np.array([[[[4],[3]], [[2],[1]]]], dtype=np.float32) pool = tf.nn.max_pool(image, ksize=[1, 2, 2, 1], strides=[1, 1, 1, 1], padding='SAME') print(pool.shape) print(pool.eval()) | cs |
이것을 활용해서 MNIST 데이터 또한 Pooling할 수 있습니다. 먼저 Convolution 데이터를 만든 후 Pooling을 진행합니다.
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 33 34 35 36 37 38 39 40 41 | #load mnist data from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) #get only 1 image & reshape it img = mnist.train.images[0].reshape(28,28) plt.imshow(img, cmap='gray') sess = tf.InteractiveSession() #reshape image to get color = 1 img = img.reshape(-1,28,28,1) #filter 3X3, count = 5 W1 = tf.Variable(tf.random_normal([3, 3, 1, 5], stddev=0.01)) #zero-padded USE conv2d = tf.nn.conv2d(img, W1, strides=[1, 2, 2, 1], padding='SAME') print(conv2d) sess.run(tf.global_variables_initializer()) #make convoultion data conv2d_img = conv2d.eval() #print converted images conv2d_img = np.swapaxes(conv2d_img, 0, 3) for i, one_img in enumerate(conv2d_img): plt.subplot(1,5,i+1), plt.imshow(one_img.reshape(14,14), cmap='gray') #pooling pool = tf.nn.max_pool(conv2d, ksize=[1, 2, 2, 1], strides=[ 1, 2, 2, 1], padding='SAME') print(pool) sess.run(tf.global_variables_initializer()) pool_img = pool.eval() #print pooling image pool_img = np.swapaxes(pool_img, 0, 3) for i, one_img in enumerate(pool_img): plt.subplot(1,5,i+1), plt.imshow(one_img.reshape(7, 7), cmap='gray') | cs |
<convoultion data>
<pooling data>
다음 포스트에서는 Convolution Neural Network를 활용한 MNIST 데이터 분류에 대해 알아보겠습니다. 모든 소스 코드는 여기에서 확인할 수 있습니다.
'파이썬 > 머신러닝' 카테고리의 다른 글
[#E19] Recurrent Neural Network (RNN - PART 1/3) (0) | 2018.12.16 |
---|---|
[#E18] CNN을 이용한 MNIST 데이터 분류 (0) | 2018.12.14 |
[#E16] Convolution Neural Network (CNN - 준비편) (0) | 2018.12.14 |
[#E15] MNIST 데이터란? (0) | 2018.12.14 |
[#E14] 머신러닝 팁과 용어 해석 (0) | 2018.12.11 |