15. 인공신경망

  • 저번시간까지 다양한 머신러닝 알고리즘에 대해 배웠다.
  • 이번 시간부터는 인공신경망에 대해 배워볼 것이다.
  • 오늘부터는 패션MNIST 데이터셋을 이용해 진행해 볼 것이다.
  • 머신러닝과 딥러닝을 처음 배울 때 많이 사용하는 데이터 셋들이 존재한다. 패션MNIST 데이터는 유명한 데이터 이기 떄문에 많은 딥러닝 라이브러리에서 이 데이터를 가져올 수 있다. 여기서는 텐서플로를 사용해 데이터를 불러오겠다. 텐서플로의의 케라스패키지를 임포트 하고 패션 MNIST데이터를 다운로드 해보자.
from tensorflow import keras
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import cross_validate
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import train_test_split
(train_input, train_target), (test_input, test_target) =\
    keras.datasets.fashion_mnist.load_data()
  • keras.datasets.fashion_mnist 모듈 아래 load_data()함수는 훈련 데이터와 테스트 데이터를 나누어 반환한다. 각각의 데이터는 입력과 타깃의 쌍으로 구성되어있다.
  • 해당 데이터의 크기를 확인해보자.
print(train_input.shape, train_target.shape)
(60000, 28, 28) (60000,)
  • 훈련 데이터를 살펴보면 60000개의 이미지로 이루어져 있고 각 이미지는 28x28크기를 가진다. 타깃 데이터도 60000개의 원소가 있는 1차원 배열이다.
  • 테스트 세트도 마찬가지로 확인해보자.
print(test_input.shape, test_target.shape)
(10000, 28, 28) (10000,)
  • 테스트 데이터를 살펴보면 10000개의 이미지로 이루어 져있고 크기는 동일하다. 타깃도 10000개의 원소가 존재하는 1차원 배열인 것을 확인할 수 있다.
  • 맷플롯립 라이브러리를 이용해 샘플을 출력해보자.
fig, axs = plt.subplots(1, 10, figsize=(10,10))
for i in range(10):
    axs[i].imshow(train_input[i], cmap='gray_r')
    axs[i].axis('off')
plt.show()


output_8_0

  • 위와같이 다양한 종류의 옷들이 포함되어 있는 것을 확인할 수 있다. 이 샘플들의 타깃값을 살펴보자. 파이썬 리스트 내포를 나용해 처음 10개의 샘플에 대한 타깃값을 리스트로 만든 후 출력해보자.
print([train_target[i] for i in range(10)])
[9, 0, 0, 3, 0, 2, 7, 2, 5, 5]
  • 패션 MNIST의 타깃은 0~9까지의 숫자 레이블로 구성된다. 마지막으로 넘파이의 unique()함수를 사용해 레이블 당 샘플의 개수를 확인해보자.
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]))

1. 로지스틱 회귀로 패션 아이템 분류하기

  • 이 훈련 샘플은 60000개나 되기 때문에 전체 데이터를 한꺼번에 사용해 모델을 훈련하는 것보다 샘플을 하나씩 꺼내서 모델을 훈련하는 방법이 더 효율적이다. 이런 상황에는 확률적 경사 하강법이 효과적이다.
  • SGDClassifier 클래스의 loss 매개변수를 log로 지정해 로지스틱 손실 함수를 최소화 하는 확률적 경사 하강법 모델을 만들었다. SGDClassifier를 사용할때는 표준화 전처리된 데이터를 사용했다. 왜냐하면 확률적 경사 하강법은 여러 특성 중 기울기가 가장 가파른 방향을 따라 이동한다. 만약 특성마다 값의 범위가 다르면 올바르게 손실 함수의 경사를 내려올 수 없기 때문이다.
  • 해당 데이터는 0~255사이의 정숫값을 가진다. 이런 이미지의 경우는 255로 나누어 정규화를 진행한다.
  • 먼저 reshape()을 이용해 2차원 배열인 각 샘플을 1차원 배열로 펼치도록 한다.
train_scaled = train_input / 255.0
train_scaled = train_scaled.reshape(-1, 28*28)
print(train_scaled.shape)
(60000, 784)
  • 784개의 픽셀로 이루어진 60000개의 샘플을 만들었다. SGDClassifier클래스와 cross_validate 함수를 이용해 데이터에서 교차 검증으로 성능을 확인해보자.
  • 반복횟수(max_iter)를 5로 주었다. 하지만 이를 더 큰 수로 반복횟수를 늘려도 크게 변하지 않는다.
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.8192833333333333


/Users/janghyeseong/Desktop/PR/PR2/lib/python3.9/site-packages/sklearn/linear_model/_stochastic_gradient.py:574: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
  warnings.warn("Maximum number of iteration reached before "
/Users/janghyeseong/Desktop/PR/PR2/lib/python3.9/site-packages/sklearn/linear_model/_stochastic_gradient.py:574: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
  warnings.warn("Maximum number of iteration reached before "
/Users/janghyeseong/Desktop/PR/PR2/lib/python3.9/site-packages/sklearn/linear_model/_stochastic_gradient.py:574: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
  warnings.warn("Maximum number of iteration reached before "
/Users/janghyeseong/Desktop/PR/PR2/lib/python3.9/site-packages/sklearn/linear_model/_stochastic_gradient.py:574: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
  warnings.warn("Maximum number of iteration reached before "
/Users/janghyeseong/Desktop/PR/PR2/lib/python3.9/site-packages/sklearn/linear_model/_stochastic_gradient.py:574: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
  warnings.warn("Maximum number of iteration reached before "

2. 인공신경망

  • 인공신경망에는 출력층, 뉴런, 유닛, 입력층 등의 의미를 알아야 할 필요가 있다.
    • 출력층 : 신경망의 최종 값을 의미한다.
    • 뉴런 : 인공 신경망에서 z값을 계산하는 단위를 말한다. 하지만 뉴런에서 수행하는 일은 선형 계산이 전부이다. 이제는 뉴런 보다는 유닛이라고 부르는 경우가 더 많다.
    • 입력층 : 픽셀값 자체를 말한다. 특별한 계산을 수행하지 않는다.
  • 인공 뉴런은 생물학적 뉴런에서 영감을 얻어서 만들어졌다. 생물학적 뉴런은 수상 돌기로부터 신호를 받아 세포체에 모은다. 신호가 어떤 임곗값에 도달하면 축삭 돌기를 통해 다른 세포에 신호를 전달한다. 하지만 생물학적 뉴런이 가중치와 입력을 곱해서 출력을 만드는 것이아니다. 또한 시그모이드함수와 소프트맥스 함수를 사용하는 것 또한 아니다. 인공 뉴런은 생물학적 뉴런의 모양을 본뜬 수학 모델에 불과하다. 생물학적 뉴런이 하는 일을 실제로 구현한 것이 아니라는 뜻이다.
  • 확률적 경사 하강법을 사용한 로지스틱 회귀 모델이 가장 간단한 인공 신경망이라면 인공신경망을 만들어도 성능이 나아지지 않을것이라 생각할 수 있다. 하지만 인공 신경망 모델을 만드는 최신 라이브러리들은 SGDClassifier에는 없는 몇 가지 기능을 제공한다. 우리는 이제 텐서플로를 사용해 인공 신경망 모델을 만들어 볼 것이다.

1. 텐서플로와 케라스

  • 텐서플로는 구글이 오픈소스로 공개한 딥러닝 라이브러리이다. 텐서플로에는 저수준 API와 고수준 API가 있다. 케라스가 텐서플로의 고수준 API이다. 딥러닝 라이브러리가 다른 머신러닝 라이브러리와 다른 점은 그래픽 처리 장치인 GPU를 사용하여 인공 신경망을 훈련한다는 것이다. GPU는 벡터와 행렬 연산에 매우 최적화되어 있기 때문에 곱셈과 덧셈이 많이 수행되는 인공 신경망에 큰 도움을 준다.
  • 케라스 라이브러리는 직접 GPU연산을 수행하지는 않는다. 대신 GPU연산을 수행하는 다른 라이브러리를 백엔드로 사용한다. 이외에도 씨아노나 CNTK와 같은 여러 딥러닝 라이브러리를 케라스 백엔드로 사용할 수 있다. 이런 케라스를 멀티-백엔드 케라스라고 부른다. 케라스 API만 익히면 다양한 딥러닝 라이브러리를 쓸 수 있다.
  • 그럼 이제 케라스 API를 사용해 패션 아이템을 분류하는 인공신경망을 만들어 보자.

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

  • 여기서는 앞서 로지스틱 회귀에서 만든 훈련 데이터 train_scaled와 train_target을 사용하도록 하겠다. 로지스틱 회귀에서는 교차 검증을 이용해 모델을 평가 했다. 하지만 인공신경망에서는 교차 검증을 잘 사용하지 않고 검증 세트를 따로 두고 사용한다.
  • 이유
      1. 딥러닝 분야의 데이터셋은 충분히 크기 때문에 검증 점수가 안정적이다.
      1. 교차 검증을 수행하기에는 훈련 시간이 너무 오래 걸리기 때문이다.
train_scaled, val_scaled, train_target, val_target = train_test_split(train_scaled, train_target, test_size=0.2, random_state=42)
print(val_scaled.shape, val_scaled.shape)
print(train_scaled.shape, train_target.shape)
(12000, 784) (12000, 784)
(48000, 784) (48000,)
  • 올바르게 20%가 덜어져 검증 세트로 분류된 것을 확인할 수 있다. 훈련세트로 모델을 만들고 검증 세트를 이용해 훈련한 모델을 평가해보도록 하겠다.
  • 먼저 인공신경망의 다양한 층을 만들어 보도록 하자. 케라스의 레이어 패키지 안에는 다양한 층이 준비되어있다. 가장 기본이 되는 층은 밀집층이다. 이런 층을 양쪽의 뉴런이 모두 연결하고 있기 때문에 완전 연결층이라고도 부른다. 케라스의 Dense 클래스를 사용해 밀집층을 만들어보자. 필요한 매개변수는 뉴런의 개수와 뉴런의 출력에 적용할 함수, 입력의 크기이다.
dense = keras.layers.Dense(10, activation='softmax', input_shape=(784,))
  • 첫 번째 매개변수로 뉴런 개수를 10개로 지정한다. 10개의 뉴런에서 출력되는 값을 확률로 바꾸기 위해 소프트맥스 함수를 사용한다. 케라스 층에서는 activation 매개변수로 지정해준다. 이진분류라면 시그모이드 함수를 사용하면 된다. 마지막으로 세 번째 매개변수는 입력값의 크기를 말한다. 각각의 뉴런이 몇개의 입력을 받는지 튜플로 지정한다. 여기서는 784개의 픽셀값을 받는다.
  • 이제 밀집층을 가진 신경망 모델을 만들어야 한다.
model = keras.Sequential(dense)
  • Sequential 클래스의 객체를 만들 때 앞에서 만든 밀집층의 dense를 전달했다. 여기서 만든 model이 인공 신경망 모델이다.
  • 소프트맥스와 같이 뉴런의 선형 방정식 계산 결과에 적용되는 함수를 활성화 함수라고 한다.

4. 인공 신경망으로 패션 아이템 분류하기

  • 케라스 모델은 훈련하기 전에 설정 단계가 있다. 이런 설정을 model 객체의 compile() 메서드에서 수행한다. 손실함수의 종류를 지정해 주고 훈련과정에서 계산하고 싶은 측정값을 지정한다.
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
  • 다중 분류에서 크로스 엔트로피 손실 함수를 사용하려면 0, 1, 2와 같이 정로된 타깃값을 사용해야 한다. 이를 원-핫 인코딩으로 변환해야 한다. 하지만 해당 데이터의 타깃값은 정수형태로 되어있다. 즉 정수형이기 때문에 텐서플로에서는 그냥 사용이 가능하다.
  • 모델 훈련은 fit()을 사용한다. 이는 사이킷런과 매우 비슷하다. 처음 두 매개변수에 입력과 타깃을 지정한다. 그다음 반복할 에포크 횟수를 매개변수로 지정한다. 사이킷런의 모델과 동일하게 5번 반복하도록 한다.
model.fit(train_scaled, train_target, epochs=5)
2021-10-08 14:38:47.654840: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:185] None of the MLIR Optimization Passes are enabled (registered 2)


Epoch 1/5
1500/1500 [==============================] - 2s 938us/step - loss: 0.6091 - accuracy: 0.7938
Epoch 2/5
1500/1500 [==============================] - 1s 913us/step - loss: 0.4787 - accuracy: 0.8402
Epoch 3/5
1500/1500 [==============================] - 1s 924us/step - loss: 0.4564 - accuracy: 0.8495
Epoch 4/5
1500/1500 [==============================] - 1s 918us/step - loss: 0.4440 - accuracy: 0.8520
Epoch 5/5
1500/1500 [==============================] - 1s 909us/step - loss: 0.4362 - accuracy: 0.8558

<keras.callbacks.History at 0x1627f4160>
  • 케라스는 에포크마다 걸린 시간과 손실, 정확도를 출력해준다. 5번 반복에 정확도가 85%를 넘었다. 그렇다면 검증세트를 이용해 모델의 성능을 확인해보자. 케라스에서 모델의 성능을 평가하는 메서드는 evaluate()이다.
model.evaluate(val_scaled, val_target)
375/375 [==============================] - 0s 783us/step - loss: 0.4533 - accuracy: 0.8494

[0.45331835746765137, 0.8494166731834412]
  • evaluate() 메서드도 fit()메서드와 비슷한 출력을 보여준다. 검증세트의 점수는 훈련 세트의 점수보다 조금 낮은 것이 일반적이다. 예상대로 84%정도의 정확도를 보여준다.

5. 마치며

  • 이번 시간에는 케라스를 이용한 인공신경망을 배워보았다. 인공 신경망을 배우면서 이전의 머신러닝 파트에서 배웠던 내용들이 다수 나왔다. 해당 부분을 배운지 시간이 좀 지났다보니 잊어버린 부분이 많았다. 다시 한번 리마인딩이 필요할 것 같다.

Categories:

Updated:

Leave a comment