본문 바로가기

데이터 사이언스 공부/딥러닝

TensorFlow 2.0 basic practice 1

 데이터 사이언스는 데이터에서 유용한 정보를 추출하는 것이다. 목적은 다양하지만, 데이터가 어떤 계층에 속할지 '확률'을 추정하는 문제에 주로 관심이 많다. 예측 모델에 사용되는 수학적 알고리즘은 판별식을 사용하여 각 변수에 대한 가중치를 계산하고 목적함수를 통해 이 가중치를 조정하여 최적의 판별식을 구한다. 신경망은 이런 모델을 스택 구조로 쌓아서 복잡한 비선형 함수를 구현한 형태라고 생각할 수 있다. (모델 적합화)

 

 신경망(Neural Network)은 Input Layer, Hidden Layer, Ouput Layer가 스택으로 쌓여있는 구조이다. 각 층은 뉴런으로 구성되며 한 층의 뉴런은 다음 층의 뉴런을 활성화시킨다. 활성화 정도는 data variable과 weight, bias의 선형 조합에 의해 결정된다. 하지만 이 선형식의 결과값을 그대로 사용하지는 않고, 비선형의 활성화 함수(Activation Function)로 값을 변환하여 사용한다. 즉, 다음 층의 뉴런에 보내게 될 신호의 강도는 활성화 함수에 의해 특정 범위의 값으로 rescaling 되어 결정된다. Keras의 Sequential method를 사용하여 각 층의 형태나 특징을 결정하여 모델을 만들 수 있다. 이 단계에서 입력 형태나 뉴런의 개수, 활성화 함수 등을 결정한다.

 

 모델의 학습도는 어떻게 평가할 수 있을까? 신경망이 학습을 잘했는지는 벌점을 부과해서 측정할 수 있다. 신경망에 데이터를 입력하면, 어떤 계층에 속할지에 대한 확률이나 신뢰도를 반환한다. 그리고 반환된 output과 실제 label을 비교하여 오차를 구한다. 모델은 이 오차를 줄이는 방향으로 학습하게 된다. 또한 오차의 제곱의 합계나 평균으로 loss function cost function을 만들 수 있다.

 

 오차를 줄이는 방향은 어떻게 찾을 수 있을까? 벡터 미적분학에서 스칼라 함수의 그레이디언트(Gradient)를 구하면 그 반대 방향이 지역 최솟값으로 향하는 가장 빠른 방향이라는 것을 배웠다. 따라서 오차를 줄이는 방향은 cost function의 그레이디언트의 반대 방향이다. cost의 그레이디언트를 구하게 되면 이 벡터의 element들은 이전 층의 뉴런의 weight들과 대응하게 된다. 그리고 이 값들의 부호와 비율은 각각의 weight의 기여도, 즉 이전 층의 어떤 weight를 어떻게 조정해야 다음 층의 뉴런이 가장 잘 활성화가 되는지를 알 수 있다. 이 방법은 역전파 알고리즘에서 사용하게 된다. Keras에서는 compile method를 사용해서 optimizer, loss function, metrics를 정할 수 있다. optimizer는 가중치를 최적화하는 경사하강법(Gradient Descent)에 대한 속성이고 loss function은 손실 함수를 결정한다. metrics는 평가 지표와 관련된 속성이다.

 

 역전파 알고리즘(Backpropagation Algorithm)은 매우 복잡한 gradient 계산 과정을 더 빠르게 하기 위한 알고리즘이다. 이 알고리즘은 말 그대로 뒤로 돌아가면서 신경망 네트워크를 학습한다. 즉, output layer에서 input layer의 방향으로 이동하며 경사하강법을 사용해 weight 값을 update 한다. backward update를 하는 이유는 경사하강법을 사용할 때 뒤쪽에서 사용된 값들이 앞쪽의 계산 과정에 다시 사용되기 때문이다(chain rule). 역전파는 속도나 메모리의 한계 때문에 한 번의 학습에서 모든 parameter에 대해 gradient를 계산하고 update 할 수 없다. 그래서 training data들을 무작위로 재배치하고 일정 크기로 나누어 계산한다.

 

 정리하자면 초기에 신경망의 가중치나 편향은 무작위로 정해진다. 그리고 forward 방향으로 sigmoid 등의 activation function을 지나며 output layer에서 나온 output과 실제 label을 비교하여 오차에 대한 cost function을 만든다. 이 함수에 대한 gradient descent를 사용해 가중치의 민감도를 구한다. 그리고 backward 방향으로 민감도가 높은 중요한 가중치에 대해 더 큰 비율로 값을 update 한다. 이렇게 순전파와 역전파 과정을 모두 거치면 학습을 한 번 완료하게 되는 것이다. 그리고 이 학습을 반복하면 신경망 네트워크의 오차는 낮아지고 정확도는 높아진다.

 

 Keras에서는 sequential, compile로 만든 모델을 fit method로 training 할 수 있다. fit의 parameter로 train data와 train label, epochs 등의 값을 전달한다. epoch는 forward pass / backward pass를 한 번 완료한 상태이다. epochs 값을 설정하면 학습을 몇 번 수행할지 결정할 수 있다. batch size는 한 번의 epoch 안에서 나누어 계산할 데이터의 크기다. 만약 어떤 모델이 100개의 데이터를 학습하고 batch size가 20이라면 한 번의 epoch에서 5번으로 나누어 계산하게 된다.

 

 

# weight은 어떤 뉴런이 다음 뉴런의 활성화에 얼마나 기여를 하는지, 연결되어 있는 강도, 가중치 등으로 생각할 수 있다.

# 활성화 함수에는 비선형 함수인 relu, sigmoid, softmax 등이 있고 각각의 장단점이 있다.

# 활성화 함수는 (0, 1)이나 (-1, 1) 등으로 결과값을 rescaling 한다. 

# loss는 최소제곱법 등의 다양한 함수가 있다. metrics는 평가만 하고 학습에 사용되지는 않는다. loss는 metrics로 사용할 수 있다.

# epochs 값으로 학습 횟수를 조정하여 overfitting이나 underfitting를 방지할 수 있다.

# weight의 민감도가 높다는 것은 값을 조금만 조절해도 활성화 정도가 크게 바뀐다는 뜻이다.

 

 

 

코드:

import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt

data = keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = data.load_data()

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt',
              'Sneaker', 'Bag', 'Ankle boot']

# print(train_images.shape)
# print(len(train_labels))

# plt.imshow(train_images[7], cmap=plt.cm.binary)
# plt.show()

train_images = train_images/255.0
test_images = test_images/255.0

# model의 layer 결정 후에 compile 하기
model = keras.Sequential([
    #2차원 배열을 1차원 배열로 펼치기
    keras.layers.Flatten(input_shape=(28,28)),
    #dense 층으로 가중치 결정.
    #relu는 주로 2개를 분류, softmax는 3개 이상을 분류
    keras.layers.Dense(128, activation='relu'), #128개의 뉴런과 relu 라는 비선형 활성화 함수로 구성
    keras.layers.Dense(10, activation='softmax') #10개의 뉴런과 softmax 비선형 활성화 함수로 구성
    #각 label에 속할 확률을 반환한다. 모두 더하면 1
])

#최적화, 손실, 지표 설정
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

#training
model.fit(train_images, train_labels, epochs=5)

#평가
#test_loss, test_acc = model.evaluate(test_images, test_labels)
#print("Test Accuracy:", test_acc)

prediction = model.predict(test_images)

for i in range(5):
    plt.grid(False)
    plt.imshow(test_images[i], cmap=plt.cm.binary)
    plt.xlabel("Actual: " + class_names[test_labels[i]])
    plt.title("Prediction: " + class_names[np.argmax(prediction[i])])
    plt.show()

 

 위의 예제는 keras로 mnist 데이터를 받아 이미지가 어떤 종류의 옷인지 label를 분류 및 예측하는 예제이다. 우선 data를 train data와 test data로 나눈다. 이 모델의 input layer는 28 by 28 배열을 입력받는다. 아마 이미지 각 픽셀의 밝기 정도에 대한 데이터일 것이다. 다음 hidden layer는 128개의 뉴런과 relu 활성화 함수를 사용한다. 이 층에서는 특정 부분의 패턴을 인식할 것이다. 마지막 output layer는 10개의 뉴런과 softmax 활성화 함수를 사용하고 각 label에 속할 확률을 반환한다. optimizer와 loss, metrics를 설정하고 fit 메서드에 train data를 넣고 학습 횟수는 5회로 한다. prediction 메서드에 test data를 넣고 5개의 실제 값과 예측 값을 화면에 출력한다.

 

 

 

 

 

결과:

 

epoch 횟수가 증가하면서 loss는 감소하고 accuracy는 증가한다. 잘 학습된 것을 확인할 수 있다.

 

 

 

앞의 2개의 test data는 prediction label과 actual label 값이 같은 것을 확인할 수 있다. 코드를 약간 수정하여 100개의 test data 중 실제 label과 예측 label이 다른 데이터를 확인했다. 대부분 sneaker - sandal - boot나 shirt - T-shirt 이런 식으로 비슷한 카테고리 안에서 잘못된 예측이 발생했다.

 

 

 

 

 

참고:

https://www.youtube.com/watch?v=aircAruvnKk&t=2s

https://www.youtube.com/watch?v=6g4O5UOH304&list=PLn6_vibrJjiFKdR1pMxBX2DtDI0yA-

https://www.tensorflow.org/tutorials/keras/classification?hl=ko

 

첫 번째 신경망 훈련하기: 기초적인 분류 문제  |  TensorFlow Core

Note: 이 문서는 텐서플로 커뮤니티에서 번역했습니다. 커뮤니티 번역 활동의 특성상 정확한 번역과 최신 내용을 반영하기 위해 노력함에도 불구하고 공식 영문 문서의 내용과 일치하지 않을 수

www.tensorflow.org

 

 

더 공부해야 할 것: activation function, gradient descent, backpropagation algorithm