[혼공머신] 인공 신경망(Artificial Neural Network)

강민우·2022년 2월 13일
0
post-thumbnail

[혼자 공부하는 머신러닝+딥러닝] 책에 기반한 정리글입니다.
전체 소스코드는 아래 Github 링크에서 확인할 수 있습니다.

Github 링크

0. 개요

이제부터는 tensorflow와 keras를 통한 인공 신경망 모델을 만들어본다.
인공 신경망의 원리와 구조를 이해하고, 로지스틱 회귀 모델과 인공 신경망 모델을 비교해본다.

1. 패션 MNIST 데이터셋 준비하기

딥러닝을 배울 때 많이 쓰는 데이터셋이 바로 MNIST 데이터셋이다.
10종류의 패션 아이템으로 구성되어있다.

keras.datasets.fashion_mnist 모듈 아래 load_data() 함수로 훈련 데이터와 테스트 데이터를 얻을 수 있다.

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

print(train_input.shape, train_target.shape)
print(test_input.shape, test_target.shape)
출력
(60000, 28, 28) (60000,)
(10000, 28, 28) (10000,)

28*28 사이즈의 이미지가 훈련세트에는 6만개, 테스트세트에는 1만개 들어있다.

훈련 데이터에서 몇 개의 샘플을 그림으로 표현해본다.

import matplotlib.pyplot as plt
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()

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 앵클부츠

각 레이블마다 6000개의 샘플이 들어 있다.

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

이 훈련 샘플은 60,000개나 되기 때문에, 전체 데이터를 한꺼번에 사용하여 모델을 훈련시키기보다, 샘플을 하나씩 꺼내서 모델을 훈련하는 방법이 효율적이다.

이 상황에서 가장 잘 맞는 방법은 확률적 경사 하강법이다.
SGDClassifier 클래스의 매개변수 loss='log' 로 지정하여 확률적 경사 하강법 모델을 만든다.

2-1. 데이터를 표준화 전처리하기

확률적 경사 하강법은 여러 특성 중 기울기가 가장 가파른 방향을 따라 이동한다.
특성마다 값의 범위가 다르다면 올바르게 혼실 함수의 경사를 내려 올 수 없다.

이 데이터셋의 각 픽셀은 0~255 사이의 정수값을 가지기 때문에, 255로 나누어 0~1 사이의 값으로 정규화한다.

SGDClassifier는 2차원 입력을 다루지 못해, 1차원으로 만들어야 한다.

train_scaled = train_input / 255.0
train_scaled = train_scaled.reshape(-1, 28*28)
print(train_scaled.shape) #6만개 샘플, 784개의 픽셀
출력 (60000, 784)

2-2. 모델을 만들고 교차검증하기

SGDClassifier 클래스와 cross_validate() 로 교차검증을 진행한다.

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

sc = SGDClassifier(loss='log', max_iter=10, random_state=42)
scores = cross_validate(sc, train_scaled, train_target, n_jobs=-1)

print(np.mean(scores['test_score']))
출력 0.8313333333333333

2-3. 로지스틱 회귀 공식 복습

앞서 배운 로지스틱 회귀 공식은 이렇다.
z = a x Weight + b x lenght + ... + f

이를 MNIST데이터셋에 적용하면 이렇다.
z_티셔츠 = w1 x 픽셀1 + w2 x 픽셀2 + .... + w784 x 픽셀784 + b
z_바지 = w1' x 픽셀1 + w2' x 픽셀2 + .... + w784' x 픽셀784 + b'

이와 같이 10개의 클래스에 대한 선형 방정식을 구한 뒤, 소프트맥스 함수를 통과하여 각 클래스에 대한 확률을 얻을 수 있다.

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

가장 기본적인 인공 신경망은 확률형 경사 하강법을 사용하는 로지스틱 회귀와 같다.

인공신경망에서는 교차 검증을 잘 사용하지 않고, 검증 세트를 별도로 덜어 내어 사용한다. 데이터셋이 충분히 크고, 교차검증에는 오랜 시간이 걸리기 때문이다.

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,)

가장 기본이 되는 층인 밀집층을 만들어본다.
입력층은 784개의 뉴런으로 구성되며, 출력층은 10개의 뉴런으로 구성된다.
밀집층은 각 뉴런이 모두 연결되어야 하기 때문에, 784x10 = 7840개의 선이 포함된다.
이를 완전 연결층 이라고도 부른다.

dense = keras.layers.Dense(10, activation='softmax', input_shape=(784,))
model = keras.Sequential(dense) #밀집층을 가진 신경망 모델

뉴런의 갯수를 10으로 지정하고, 10개의 뉴런에서 출력되는 값을 확률로 바꾸기 위해 소프트맥스 함수를 이용한다. 만약 이진분류라면 activation='sigmoid' 로 입력한다.
이후 밀집층을 가진 신경망 모델을 만들기 위해 Sequential 클래스를 사용한다.

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

케라스 모델은 훈련하기 전 설정 단계가 있다.

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

loss 매개변수에 이진 분류라면 binary_crossentropy, 다중 분류라면 categorical_crossentropy 를 사용한다.

정수로 된 타깃값을 원-핫 인코딩으로 바꾸지 않고 사용하려면 loss='sparse_categorical_crossentropy' , 타깃값을 원-핫 인코딩으로 준비했다면 loss='categorical_crossentropy' 으로 지정한다.

metrics 매개변수는 accuracy 를 지정하면 에포크마다 정확도를 함께 출력해준다.

model.fit(train_scaled, train_target, epochs=5)
출력
Epoch 1/5
1500/1500 [==============================] - 3s 1ms/step - loss: 0.6125 - accuracy: 0.7901
Epoch 2/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4786 - accuracy: 0.8392
Epoch 3/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4556 - accuracy: 0.8475
Epoch 4/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4452 - accuracy: 0.8512
Epoch 5/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4376 - accuracy: 0.8547

epochs 매개변수로 에포크 횟수를 지정할 수 있다.

evaluate() 메서드로 모델의 성능을 평가해본다.

model.evaluate(val_scaled, val_target)
출력
375/375 [==============================] - 1s 3ms/step - loss: 0.4630 - accuracy: 0.8458
[0.46303632855415344, 0.8458333611488342]

fit() 메서드와 비슷한 출력을 보여준다.

profile
어제보다 성장한 오늘

0개의 댓글