관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

케라스 4 - 심층 신경망으로 이미지 분류 본문

인공지능/딥러닝

케라스 4 - 심층 신경망으로 이미지 분류

huenuri 2024. 10. 26. 15:56

이번에는 심층 신경망으로 이미지 분류 모델을 생성한다. 이미지 분류 모델을 생성한다. 이미지 분류를 위해 단층이 아닌 더 깊은 층을 쌓아 깊이가 있는 딥러닝 모델을 생성한다(모델에 여러 층을 구성하여 깊이가 있다는 의미에서 딥러닝이라고 부름). 훈련에 필요한 데이터셋은 케라스 내장 데이터셋을 가져와서 사용한다. 분류에 적합한 손실함수를 적용하고 결과를 확인한다.


 

 

 

1. 케라스 내장 데이터셋 로드

케라스는 모델 훈련에 필요한 샘플 데이터셋을 제공한다. 데이터셋은 tensorflow, keras, datasets 서브 패키지에 위치하며 지원하는 목록은 다음과 같다.

  • boston_housing : 보스턴 주택 가격 데이터셋(회귀)
  • cifar 10 : CIFAR 10 이미지 분류 데이터셋(분류)
  • cifar 100 : CIFAR 100 이미지 분류 데이터셋(분류)
  • mnist : mnist 손글씨 데이터셋(분류)
  • fashion_mnist : 의류 데이터셋(분류)
  • imdb : IMDb 영화 데이터셋(분류)
  • reuters : Reuters 뉴스 토픽(분류)

케라스의 datasets 패키지에 있는 데이터를 불러오기 위해 load_data() 메서드를 사용한다. 이 함수는 훈련 데이터셋과 검증 데이터셋을 구분하여 제공한다. mnist 손글씨 데이터셋을 불러오기 위해 datasets 패키지의 mnist 데이터셋을 지정하고 mnist 변수에 대입한다.

 

mnist 변수에 load_data() 메서드를 적용하면 구글의 storage로부터 넘파이 배열로 구성된 데이터셋을 다운로드한다. x_train과 y_train은 각각 훈련 셋의 입력(x)과 출력(y) 데이터를 나타낸다. 마찬가지로 x_test와 y_test는 검증 셋의 입력과 출력 데이터를 저장한다.

 

 

훈련 셋에는 60000, 검증 셋에는 10000개 데이터가 저장되어 있다는 것을 확인할 수 있다. 입력 데이터에 해당하는 x_train, t_test 손글씨 이미지 데이터가 저장되어 있고, 배열의 shape은 28이라는 것을 알 수 있다. 

즉, x_train에는 28 x 28 픽셀 크기의 정사각형 이미지가 6만장, x_test에는 1만 장의 이미지가 저장되어 있는 것이다. 이들이 각각 1차원 벡터 형태로 정리되어 있다.

 

이미지를 시각화해볼 수 있다.

 

mnist 데이터셋은 딥러닝 세계의 "Hello, World"라고 불린다. 1990년대 초반 얀 르쿤은 사람의 손글씨를 인식하는 프로그램을 개발했는데 그 당시 활용했던 손글씨 데이터셋이 지금까지 활용되고 있다. 이 데이터셋은 사람의 필기체로 쓰인 0~9까지의 숫자들로 이루어진 데이터셋이다. 총 10개의 정답 레이블로 구성되어 있다.


 

 

 

2. 데이터 전처리

이미지 데이터에 대하여 정규화를 통해 데이터의 범위를 조절한다. x_train은 넘파이 배열이며, 배열의 각 원소는 이미지를 구성하는 하나의 픽셀 값과 일대일 매칭된다.

데이터를 확인해보면 0~255 범위의 값으로 이루어진 것을 확인할 수 있다. 데이터의 범위를 0~1 사이의 값을 가지도록 정규화하기 위해서는 데이터의 최댓값인 255로 나눈다.

 

 

 

검증 셋에도 동일한 방법으로 정규화 방법을 적용한다.

 

정규화 변환이 완려된 후 데이터를 출력해 보면 0~1 사이의 값이 출력되는 것을 확인할 수 있다.


 

 

 

 

3. Flatten 레이어

정규화가 끝난 x_train의 shape은 (60000, 28, 28)이다. 즉, 정규화를 하더라도 개별 데이터 값의 범위는 축소되지만, 원본 배열의 형태는 그대로 유지된다.

샘플 이미지의 형태는 2차원 입력이므로 Dense 레이어에 입력값으로 넣을 수 있다. Dense 레이어에는 입력값으로 반드시 1차원 배열이 들어가야 한다. 따라서 다음과 같이 이미지 데이터를 1차원으로 전처리해야 한다.

 

 

다음과 같이 Flatten 레이어를 사용하면 다차원 데이처를 1차원으로 펼쳐주는 방법도 있다.

 

Flatten 층을 적용한 결과 shape이 (60000, 784)로 출력되는 것을 확인할 수 있다. 784는 가로 세로 펙실 수를 곱한 값이다(28*28 = 784).


 

 

 

 

4. 활성화 함수

활성화 함수는 입력을 비선형 출력으로 변환해 주는 함수이다. 일반적으로 선형관계를 나타내는 함수에 비선형성을 추가하는 방법으로 표현되기도 한다. 한편, 비선형성을 추가하지 않고 선형 함수로만 층을 구성한다면 모델을 깊게 구성하더라도 결국은 선형함수로 표현된다.

자주 사용되는 활성화 함수로는 시그모이드, 하이퍼볼릭 탄젠트, ReLU, Leaky TeLU 등이 있다.

 

텐서플로 케라스 레이어에 활성화 함수를 적용하고 싶다면 다음과 같이 설정한다. Dense 레이어에 ReLU 활성화 함수를 적용하기 위해 activation 매개변수에 relu 문자열을 대입하면 된다.

 

다음과 같이 별도의 층처럼 적용할 수 있다. 이 경우 Dense 레이어 다음에 배치 정규화를 적용할 후 활성화 함수를 적용하고자 할 때 많이 사용된다. 즉, 레이어 구성을 조금 더 커스터마이징하고 시 ㅍ을 때 구분하여 처리한다.


 

 

 

 

5. 입력과 출력

딥러닝 모델을 만들 때는 첫 번째 레이어에 입력 데이터의 형태를 나타내는 input_shape 매개변수를 지정하는 것이 일반적이다. 분류 모델의 가장 마지막 레이어는 출력층이다. 출력층의 노드 개수는 반드시 분류해야 할 크래스의 개수와 동일해야 한다. mnist는 0~9까지 총 10개의 클래스로 이루어져 있기 때문에 마지막 출력층의 노드 개수는 10개가 되어야 한다.

 

 

출력층의 노드 개수가 2개 이상인 경우는 softmax 활성화 함수를 적용한다. 즉, 다중 분류 문제에서는 softmax 활성화 함수를 사용해야 한다. 반면 이진 분류 모델의 출력층 노드 개수를 1개로 설정한 경우에는 sigmoid 활성화 함수를 적용한다.


 

 

 

 

6. 손실함수

분류 모델의 손실함수는 모델의 출력층에 따라 올바른 손실함수를 설정해야 모델이 정상적으로 훈련할 수 있다.

 

 

출력데이터가 원핫 벡터인 경우와 아닌 경우에 이와 같이 지정한다.


 

 

 

 

7. 옵티마이저

옵티마이저는 손실을 낮추기 위해서, 신경망의 가중치와 학습률과 같은 신경망의 속성을 변경하는 데 사용되는 최적화 방법이다. 일반적으로 만이 사용되는 알고리즘은 Adam이며 대체적으로 좋은 성능을 발휘하는 것으로 알려져 있다.

 

 

다음과 같이 옵티마이저는 클래스 인스턴스로 지정하거나 문자열로 지정할 수 있다. 문자열로 지정할 때는 클래스 이름을 소문자로 표기하면 된다. 클래스 인스턴스로 지정할 때는 문자열로 지정할 때와 다르게 학습률과 같은 하이퍼파라미터를 직접 설정할 수 있다.


 

 

 

 

8. 평가지표

분류 모델에 대한 평가지표는 정확도를 나태는 accuracy가 가장 많이 사용되며 auc, presision, recall 등의 지표도 많이 사용된다. 모델 컴파일 단계에서 metrics 매개변수에 파이썬 리스트 형태로 하나 이상의 평가지표를 지정하여 여러 지표들을 동시에 참고할 수 있다.


 

 

 

9. 훈련

앞서 선형회귀 모델을 학습시킬 때는 별도의 검증 데이터셋을 만들지 않았다. 한편 mnist 손글씨 데이터셋은 1만 개로 구성된 별도의 검증 셋이 존재한다. 모델을 훈련할 때 검증 셋을 추가 지정하면, 매 epoch마다 훈련 손실과 검증 손실, 각 셋에 대 한 평가지표를 나란히 출력한다. 검증 셋을 지정하는 방법은 validation_data 매개변수에 튜플 형식의 검증 셋을 지정해 주면 된다.


 

 

10. 평가

10회의 epoch가 끝나고 훈련이 종료된 뒤 evaluate() 메서드로 모델 성능을 검증하고 평가 결과를 확인할 수 있다. 이때 검증 셋인 x_test, y_test를 함수에 전달한다.

 

 

evalutate() 메서드는 컴파일 단계에서 지정한 손실과 정확도를 순서대로 반환하며, 그중 정확도만 따로 지정하여 출력해 보면 모델 검증 성능이 약 97.6% 정도 기록했다.


 

 

 

11. 예측

훈련된 모델로 새로운 이미지에 대한 분류 값을 예측하는 작업을 수행할 수 있다. predict() 메서드 이미지 데이터를 넣어주면 모델의 예측 결과를 반환한다. 여기서는 예측에 필요한 새로운 데이터셋이 준비되어 있지 않기 때문에, 검증 데이터셋의 입력 데이터인 x_test를 사용한다.

 

predictions 변수에 모델이 예측한 분류 결과를 넘파이 배열 형태로 저장한다. 첫 번째 입력 이미지에 대한 분류 결과를 출력해 보면 다음과 같이 10개의 확률값들이 출력되는 것을 확인할 수 있다.

 

 

 

softmax 활성화 함수를 거친 10개의 출력 값은 순차적으로 0~9까지의 10개의 개별 클래스에 대한 분류 확률값을 나타낸다. 이중 가장 높은 확률값을 가진 클래스가 최종 예측된 클래스다. 넘파이 배열의 argmax를 활용하여 가장 높은 확률값을 갖는 칼래스 결과를 확인할 수 있다.

 

 

시각화 라이브러리의 imshow() 메서드를 활용하여 15개 예측한 결과에 대한 시각화 코드는 다음과 같다.

 

 


 

 

 

학습을 마치고

드디어 길고 길었던 심층 신경망 이미지 분류 공부를 2시간이 넘게 걸려 마칠 수 있었다. 혼공으로 기초를 다져서 그런지 생각보다 내용을 이해하는데 별로 어렵지 않았다. 방송을 끄고 공부하면 집중력이 2배 이상 올라갈 텐데 오늘은 별로 그러고 싶지가 않았다.