Machine learning #2 - Image classification, CNN

코딩/Machine learning|2022. 3. 3. 03:01

0. Big picture

이미지 분류의 기본은 CNN(Convolution neural network)이며 대표적으로 LeNet model이 있다. 

(기계학습 - 지도학습 - 분류)

LeNet model

Convolution이란? 

합성곱(合成-), 또는 콘벌루션(convolution)은 하나의 함수와 또 다른 함수를 반전 이동한 값을 곱한 다음, 구간에 대해 적분하여 새로운 함수를 구하는 수학 연산자이다.

 

1. 이미지는 어떻게 분류하는가? - 데이터의 차원

1) 1차원 배열

x1 = np.array([5, 3, 2, 3]) 과 같은 data의 경우

x1.ndim = 1

x1.shape = (4, )

1차원 데이터의 경우 (1, 4)가 아니라 (4, ) 임에 유의

 

2) 2차원 배열

y1 = np.array([x1, x1, x1]) 이라면?

y1 = ([[5, 3, 2, 3], 

         [5, 3, 2, 3],

         [5, 3, 2, 3]]) 

y1.ndim = 2

y1.shape = (3, 4)

 

3) 흑백 이미지

img1 = np.array([[0, 255]

                       [255, 0]])

인 경우에는? 

img1.ndim = 2

img1.shape = (2, 2)

 

-> 하나의 pixel이 0~255 사이의 값을 가지고 있고(회색도 있으므로)

-> 이러한 pixel이 2*2 shape을 가지고 있다.

-> 특정 pixel의 특징을 정의하려면 (0~255 사이의 gray scale), (x축의 위치), (y축의 위치) 3개의 특징이 필요한데

0~255 사이의 값은 1개로 정해 지므로 (2, 2)가 된다.

 

img_set = np.array([img1, img1, img1]

img_set.ndim = 3

img_set.shape = (3, 2, 2)

즉 (2, 2) shape의 원소가 3개 있다는 뜻으로 이해하면 된다. 

 

마찬가지로 img_set 4개를 묶는다면? 4차원 & shape은 (4, 3, 2, 2)

 

MNIST image set

TensorFlow에서 제공하는 흑백 숫자 데이터셋인 MNIST를 살펴보면

28 * 28의 pixel로 이뤄져 있으며, total 60,000장의 이미지가 있어

이 데이터셋의 shape은 (60000, 2, 2)가 된다. 

 

4) 컬러 이미지

기본적으로 흑백 이미지와 같으나, 컬러를 사용하려면 R, G, B 3개의 값에 0~255가 정해 지므로

n * n pixel의 이미지의 데이터 shape은 (n, n, 3)이 된다. 

 

CIFAR-10 Image set

total 50,000장의 32 * 32 pixel 이미지가 준비되어 있다면, CIFAR-10 dataset의 shape은 (50000, 32, 32, 3)이 된다. 

 

2. 이미지 데이터의 처리

위의 기본 제공 이미지 데이터셋의 경우 다음과 같이 사용한다.

MNIST 

(독립, 종속), _ = tf.keras.datasets.mnist.load_data()

독립.shape = (60000, 28, 28)

종속.shape = (60000, )

 

CIFAR-10

(독립, 종속), _ = tf.keras.datasets.cifar10.load_data()

독립.shape = (50000, 32, 32, 3)

종속.shape = (50000, 1)

 

변수를 설정할 때 처음 tuple로 독립변수와 종속변수를 저장하는데

이때 독립변수는 보다시피 image들을 뜻하고

종속변수는 image의 이름을 뜻한다 => MNIST의 경우 실제 숫자 / CIFAR-10의 경우 이미지의 이름(을 숫자로 코딩한 것)

 

왜 두 가지 dataset의 종속변수 shape이 다른가??

왜 MNIST는 (60000, )인데 CIFAR-10은 (50000, 1)인가? 

이해를 위해 세 가지 shape - (5, ), (5, 1), (1, 5)를 비교해보자. 

 

(5, ) => np.array([1, 2, 3, 4, 5])

(1, 5) => np.array([[1, 2, 3, 4, 5]]) 대괄호가 2개이다! 2nd row가 비어있는 것뿐

(5, 1) => np.array([[1]

                         [2]

                         [3]

                         [4]

                         [5]]) = np.array([[1], [2], [3], [4], [5]])

 

사실 왜?라고 하기에는 그냥 그렇게 설정되어 있을 뿐이지만

추후 one hot encoding 시에 두 데이터셋의 종속변수 차이가 있다는 것을 기억해두자. 

 

 

3. Flatten layer

데이터를 준비할 때 모델이 학습 가능한 형태를 갖추는 것이 중요하다. 

두 가지 방법이 있다.

데이터셋을 reshaping 하여 적절한 모양으로 바꿔서 넣어주는 방법

그대로 넣어주고 모델 내부에 Flatten layer을 만들어서 해결해주는 방법

 

1) Reshaping

변수.reshape method를 이용하여 쉽게 할 수 있다. 

 

예를 들어 28*28 pixel의 이미지가 있다고 하면 흑백인 경우 shape은 (28, 28)의 2차원이다. 

이러한 데이터가 60000장 있다면? 데이터셋의 모양은 (60000, 28, 28)이 된다. 

이때 내가 사용할 모델이 2차원 데이터만 학습 가능하다면, 이를 2차원으로 바꿔주는 과정이 필요하다. 

 

독립.shape = (60000, 28, 28) 일 때,

독립.reshape(60000, 784)를 하면 shape이 (60000, 784)로 바뀐다. 

즉 1개의 (28, 28) 2차원 데이터

[ [3, 4, 5, 6, 6, -----, 3, 3, 3]

  [3, 4, 5, 6, 6, -----, 3, 3, 3]

  [3, 4, 5, 6, 6, -----, 3, 3, 3]

                ---

  [3, 4, 5, 6, 6, -----, 3, 3, 3] ]

이 데이터 하나를 통째로 784 (=28 * 28) 개의 컬럼을 가진 테이블에 순서대로 flattening 하여 

전체 (60000, 28, 28)인 데이터를 Table형태, 즉 2차원 데이터로 변경해주는 것이다. 

 

2) Flatten layer

Input은 [28, 28] shape으로 받되, 

모델 내부에 Flatten layer을 정의하여 해결한다. 

H = tf.keras.layers.Flatten()(X)

 

ex) MLP 모델로 이미지 셋을 학습할 경우

 

4. Convolution

이미지 딥러닝에서 Covolution Filter을 사용하여 이미지의 특징 맵, Feature map을 생성하는 도구로서 쓰인다.

Filter 하나가 Feature map 하나를 만든다!

 

Convolution layer의 코드 형태는 다음과 같다. 

1) Conv2D layer을 사용하기 위해서는 Input layer에서 3차원 data를 받아야 한다. 즉 데이터셋은 4차원으로 준비해야 한다. => 사실 컬러 이미지의 경우 문제가 없고, 흑백 이미지는 reshaping이 필요하다. 

 

2) Convolution hidden layer의 형태

H = tf.keras.layers.Conv2D(3, kernel_size=5, activation='swish')(X)

 

이때 맨 앞 parameter는 필터셋의 갯수, kernel_size는 필터셋의 사이즈 (5 * 5)를 이야기하며

필터셋의 개수 = 해당 layer에서 만들어지는 feature map의 개수와 같다. 이를 채널이라고 한다. 

위에서는 5*5의 filter set 3개를 사용하여 3 채널의 feature map을 만든다. 

 

★이때 필터셋의 shape은 (3, 5, 5)가 아니다!!!

3차원의 필터셋이라고 함은, 개별 필터셋 하나가 3차원 형태라는 것이다.

즉 3개의 필터셋이 있다고 하여 (3, 5, 5)가 아니라!!!

3개의 필터셋 각각이 3차원 형태인 것이며, 각 필터셋은 (5, 5, n)의 형태를 갖는다. 

이때 흑백 필터의 경우 (5, 5, 1)의 필터셋이 3개 있는 것이며

컬러 이미지의 경우 (5, 5, 3)의 필터셋이 3개 있는 것이다. 

 

 

Convolution은 어떻게 이뤄지나?

 

다시 코드를 살펴보면

H = tf.keras.layers.Conv2D(3, kernel_size=5, activation='swish')(X)

H = tf.keras.layers.Conv2D(6, kernel_size=5, activation='swish')(H)

 

두 개의 convolution layer에서 흑백 이미지를 학습한다고 할 때

1번 layer에서

(5, 5, 1) filter set이 3개 준비되었고, 이로 인해 학습 후에는 3개의 feature map이 생성되며

feature map의 size는 convolution의 특징에 의해 기존 (28, 28) 이미지를 학습한 후에는 (28-5+1, 28-5+1) 즉 (24, 24)가 되며 feature map들의 total shape은 (24, 24, 3)이 된다. 

 

2번 layer에서

(5, 5, 1) filter set이 6개 준비되었다. 

즉 6개의 feature map이 생성되며 size는 더 줄어서 (20, 20)이 된다. 

즉 학습 후의 data shape은 (20, 20, 6)이 된다. 

 

필터셋의 갯수는 이런 명령과 같다. 필터셋 개수가 3이라면? 

"이 이미지들에서 판단하기 가장 좋은 특징 맵 3개를 찾아줘"

=> 특징 자동 추출기

 

Convolution 연산의 원리

Convolution layer가 (5, 5, 1) feature map을 받았다고 하고

각 pixel의 값을 x_1 ~ x_64라고 하자.

 

준비된 filter는 (3, 3, 1)의 형태이다 -> 3*3, 1 채널

 

filter(kernel)이 Input 데이터를 이동하면서 

filter값과 해당 위치 데이터 값을 곱한 것을 output에 넣어준다. 

그러므로 output shape이 (5-3+1, 5-3+1)이 되는 것이다. 

 

4. MaxPool2D

Convolution layer를 추가한 모델의 문제는 parameter가 너무 많다는 것이다. 

 

tf.keras.layers.MaxPool2D()(H) 처럼

Conv2D layer 뒤에 MaxPool layer을 추가해주면 parameter가 절반 이상 줄어드는데, 그 원리는?

 

(6, 6) 사이즈의 이미지(필터맵)을 (3, 3)으로 절반으로 줄여주는 것

이때 원본을 2*2 영역씩 나누어 해당 4개 픽셀에서 가장 큰 수만 남기는 방식이다. 

 

즉, 가장 큰 수를 유지하면서 사이즈를 줄이는 방식이며

(다른 방식으로는 average pooling 등이 있겠다)

학습 관점에서는 Feature map 자체가 특징이 강한 부분을 나타내는 것이므로, 유의미한 정보만 남기면서 사이즈를 줄일 수 있는 것이다!!!

 

전체 코드는 다음과 같다. 

 

5. LeNet model

LeNet model

위에서 CNN의 한 예로 나왔던 LeNet model을 다시 살펴보자. 

 

1) 32 * 32 데이터를 받는다. 

 

2) C1 : covolution layer를 거쳐 (28, 28, 6) feature map을 만들었다. 

=> 즉 C1의 형태는 (5, 5, 1) 필터를 6개 사용 (32-5+1 = 28 이니까! 또한 흑백 이미지니까!)

 

3) S2 : MaxPooling을 통해 feature map size를 (14, 14)로 줄였다. 

 

4) C3 : convolution layer, 마찬가지로 (5, 5, 1) 필터를 16개 사용했다. 

 

5) S4 : MaxPooling으로 feature map을 (5, 5)로 줄였다. 

 

6) C5 : Flatten layer로 (5, 5, 16)의 feature map set을 flattening 하여 5 * 5* 16 = 400개의 변수로 펼치고

120개의 node를 가진 hidden layer를 사용했다. 

 

7) F6 : 84개의 node를 가진 hidden layer를 사용했다. 

 

8) output dense layer로 10개의 출력을 만들었다. 

 

6. 더 공부할 것

학습에 효율적인 모델은 어떻게 구성하는가?

몇 개의 layer를 계획하는 것이 좋은가?

layer 각각에서는 몇개의 node를 사용하는 것이 효율적인가?

'코딩 > Machine learning' 카테고리의 다른 글

Machine learning #4 Random forest  (0) 2022.03.08
Machine learning #3-1 Decision Tree practice  (0) 2022.03.08
Machine learning #3 Decision tree  (0) 2022.03.08
Machine learning #1 - MLP  (0) 2022.03.03

댓글()