[딥러닝] 인공신경망, 텐서플로, 케라스

3 분 소요



패션 MNIST 데이터 준비하기

패션 mnist 데이터는 워낙 유명해서 많은 딥러닝 라이브러리에서 이 데이터를 가져올 수 있다.

from tensorflow import keras

(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()

텐서플로의 케라스 패키지를 임포트하고 패션 mnist 데이터를 다운로드한다.

print(train_input.shape, train_target.shape)

print(test_input.shape, test_target.shape)
(60000, 28, 28) (60000,)
(10000, 28, 28) (10000,)

훈련 데이터는 60000개의 28*28 크기의 이미지로 되어 있다. 타깃은 60000개의 원소가 있는 1차원 배열이다.

테스트 세트는 10000개의 이미지로 이루어져 있다.

import numpy as np

print(np.unique(train_target, return_counts=True))
(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8), array([6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000]))

|레이블|0|1|2|3|4|5|6|7|8|9| |—|—|—|—|—|—|—|—|—|—|—| |패션 아이템|티셔츠|바지|스웨터|드레스|코트|샌달|셔츠|스니커즈|가방|앵클 부츠|

패션 mnist에 포함된 10개의 레이블의 의미는 다음과 같다.

넘파이 unique함수로 레이블 당 샘플 개수를 확인해보면 정확히 각 샘플 당 6000개씩 들어있다.

train_scaled = train_input / 255.0
train_scaled = train_scaled.reshape(-1, 28*28)

print(train_scaled.shape)
(60000, 784)

2차원을 1차원으로 만든다.



로지스틱 회귀로 패션 아이템 분류

from sklearn.model_selection import cross_validate
from sklearn.linear_model import SGDClassifier

sc = SGDClassifier(loss='log', max_iter=5, random_state=42)

scores = cross_validate(sc, train_scaled, train_target, n_jobs=-1)
print(np.mean(scores['test_score']))
0.8195666666666668

교차검증을 통해 성능을 확인하면 성능이 좋지 않다.



인공 신경망

인공 신경망(artificial neural network, ANN)은 확률적 경사 하강법을 사용하는 로지스틱 회귀와 같다.

인공 신경망은 입력층, 출력층이 있다. mnist 데이터로 예를 들면 입력층은 784개, 출력층은 10개가 된다.

인공신경망은 기존의 머신러닝 알고리즘이 잘 해결하지 못했던 문제에서 높은 성능을 발휘하는 새로운 종류의 머신러닝 알고리즘일 뿐이다.

확률적 경사 하강법을 사용한 로지스틱 회귀 모델이 가장 간단한 인공 신경망이라면 인공 신경망을 만들어도 성능이 좋아지지 않을 것 같다. 하지만 인공신경망 모델을 만드는 최신 라이브러리들은 SGDClassifier에는 없는 몇가지 기능을 제공한다. 이런 기능 덕택에 더 좋은 성능을 얻을 수 있다.



텐서플로와 케라스

텐서플로는 구글이 2015년 11월 오픈소스로 공개한 딥러닝 라이브러리이다.

텐서플로는 2019년 9월 2.0버전이 릴리스되었다.

텐서플로에는 저수준 api와 고수준 api가 있다. 바로 케라스가 텐서플로의 고수준 api이다.

딥러닝 라이브러리가 다른 머신러닝 라이브러리와 다른 점 중 하나는 그래픽 처리 장치인 gpu를 사용하여 인공 신경망을 훈련한다는 것이다.

gpu는 벡터와 행렬 연산에 매우 최적화되어 있기 때문에 곱셈과 덧셈이 많이 수행되는 인공 신경망에 큰 도움이 된다.

케라스 라이브러리는 직접 gpu 연산을 수행하지 않는다. 대신 gpu연산을 수행하는 다른 라이브러리를 백엔드로 사용한다. 예를 들면 텐서플로가 케라스의 백엔드 중 하나이다.

이외에도 씨아노, cntk와 같은 여러 딥러닝 라이브러리를 케라스 백엔드로 사용할 수 있다. 이런 케라스를 멀티-백엔드 케라스라고 부른다.

케라스 api만 익히면 다양한 딥러닝 라이브러리를 입맛대로 골라서 쓸 수 있다.

텐서플로 2.0부터는 케라스 api를 남기고 나머지 고수준 api를 모두 정리했고, 다양한 백엔드를 지원했던 멀티-백엔드 케라스는 2.3.1 버전 이후로 더 이상 개발되지 않아 이제는 케라스는 텐서플로가 거의 동의어가 되었다.



인공신경망으로 모델 만들기

from sklearn.model_selection import train_test_split

train_scaled, val_scaled, train_target, val_target = train_test_split(
    train_scaled, train_target, test_size=0.2, random_state=42)

print(train_scaled.shape, train_target.shape)
print(val_scaled.shape, val_target.shape)
(48000, 784) (48000,)
(12000, 784) (12000,)

훈련 세트에서 20%를 검증 세트로 분리했다.

import tensorflow as tf
from tensorflow import keras

dense = keras.layers.Dense(10, activation='softmax', input_shape=(784,))
model = keras.Sequential(dense)

인공신경망은 밀집층(dense layer)를 사용한다. 이러한 층을 양쪽의 뉴런이 모두 연결하고 있어 완전 연결층(fully connected layer)이라고도 한다.

패션 아이템이 10개이기 때문에 뉴런 개수를 10, 10개의 뉴런에서 출력되는 값을 확률로 바꾸기 위해 소프트맥스 함수를 사용한다.

소프트맥스와 같이 뉴런의 선형 방정식 계산 결과에 적용되는 함수를 활성화 함수라고 한다.



만든 모델로 분류하기

model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')

케라스 모델은 훈련하기 전에 설정 단계가 있다. 손실 함수를 지정한다.

케라스에서는

  • 이진분류 : binary_crossentropy
  • 다중분류 : categorical_crossentropy

이다.

그리고 원-핫 인코딩(one-hot encoding)은 해당 클래스만 1, 나머지는 0인 배열로 만드는 것이다.

따라서 다중 분류에서 크로스 엔트로피 손실 함수를 사용하려면 0,1,2와 같은 타깃값을 원-핫 인코딩으로 변환해야 한다.

하지만 텐서플로에서는 정수로 된 타깃값을 원-핫 인코딩으로 바꾸지 않고 그냥 사용할 수 있다. 정수로된 타깃값을 사용해 크로스 엔트로피 손실을 계산하는 것이 바로 sparse_categorical_crossentropy이다. 빽빽한 배열 말고 정수값 하나만 사용한다는 뜻에서 sparse라는 이름을 붙인 것이다. 만약 타깃값을 원-핫 인코딩으로 준비했다면 compile 메서드에서 손실 함수를 categorical_crossentropy로 지정한다.

케라스는 모델이 훈련할 때 기본으로 에포크마다 손실 값을 출력해준다. 손실이 줄어드는 것을 보고 훈련이 잘되었다는 것을 알 수 있지만 정확도를 함께 출력할 수 있다. metrics 매개변수에 정확도 지표를 의미하는 accuracy를 지정한다.

model.fit(train_scaled, train_target, epochs=5)
Epoch 1/5
1500/1500 [==============================] - 6s 2ms/step - loss: 0.6105 - accuracy: 0.7958
Epoch 2/5
1500/1500 [==============================] - 3s 2ms/step - loss: 0.4796 - accuracy: 0.8396
Epoch 3/5
1500/1500 [==============================] - 3s 2ms/step - loss: 0.4565 - accuracy: 0.8476
Epoch 4/5
1500/1500 [==============================] - 3s 2ms/step - loss: 0.4444 - accuracy: 0.8522
Epoch 5/5
1500/1500 [==============================] - 3s 2ms/step - loss: 0.4363 - accuracy: 0.8544
<keras.callbacks.History at 0x7f27704743d0>

훈련을 한다. 사이킷런의 로지스틱 모델과 동일하게 5번 반복한다.

텐서플로와 같은 딥러닝 라이브러리는 인공 신경망을 만들고 훈련할 때 랜덤하게 동작해 실행할 때마다 결과가 다르게 나온다.

model.evaluate(val_scaled, val_target)
375/375 [==============================] - 1s 2ms/step - loss: 0.4462 - accuracy: 0.8494
[0.44616803526878357, 0.8494166731834412]

evaluate 메서드를 통해 테스트를 할 수 있다.