알고리즘
TensorFlow2.0으로 MNIST 숫자분류기 구현
WDmil
2024. 6. 14. 01:13
728x90
import tensorflow as tf
##
# MNIST 데이터를 다운로드
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 이미지들을 float32 데이터 타입으로 변경
x_train, x_test = x_train.astype('float32'), x_test.astype('float32')
# 28*28 형태의 이미지를 784차원으로 flattening 한다.
x_train, x_test = x_train.reshape([-1, 784]), x_test.reshape([-1, 784])
# [0, 255] 사이의 값을 [0, 1] 사이의 값으로 Normalize한다.
x_train, x_test = x_train / 255., x_test / 255.
# 레이블 데이터에 one-hot encoding을 적용한다.
y_train, y_test = tf.one_hot(y_train, depth=10), tf.one_hot(y_test, depth=10)
## 데이터형태를 학습용 데이터로 재가공.
##
# tf.data API를 이용해서 데이터를 섞고 batch 형태로 가져온다.
train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_data = train_data.repeat().shuffle(60000).batch(100)
train_data_iter = iter(train_data)
## 원하는 배치로 데이터를 끊어서 더 효율적으로 사용
##
# tf.keras.Model을 이용해서 SoftMax Regression 모델을 정의한다.
class SoftmaxRegression(tf.keras.Model):
def __init__(self):
super(SoftmaxRegression, self).__init__()
self.softmax_layer = tf.keras.layers.Dense(10,
activation=None,
kernel_initializer='zeros',
bias_initializer='zeros')
def call(self, x):
logits = self.softmax_layer(x)
return tf.nn.softmax(logits)
## 케라스 서브클레싱 방식을 사용해서 생성자로,
# 하위 API로 모델구조를 정의. call에는 인자값으로 인풋, 출력으로 반환으로 하여 %로 볼 수 있게함
##
# cross-entropy 손실 함수를 정의한다.
@tf.function
def cross_entropy_loss(y_pred, y):
return tf.reduce_mean(-tf.reduce_sum(y * tf.math.log(y_pred), axis=[1]))
## 학습가중치에 따른 불일치부분 확인용 손실함수 정의
# 최적화를 위한 그라디언트 디센트 옵티마이저를 정의
optimizer = tf.optimizers.SGD(0.5)
##
# 최적화를 위한 function을 정의.
@tf.function
def train_step(model, x, y):
with tf.GradientTape() as tape:
y_pred = model(x)
loss = cross_entropy_loss(y_pred, y)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
## 그레이시언 디센트를 직접 수행하는 함수 정의
##
# 모델의 정확도를 출력하는 함수를 정의.
@tf.function
def compute_accuracy(y_pred, y):
correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
return accuracy
## 학습이 끝났을 때 정확도를 출력하는 함수
# SoftmaxRegression 모델을 선언
SoftmaxRegression_model = SoftmaxRegression()
##
# 1000번 반복을 수행하면서 최적화를 수행.
for i in range(1000):
batch_xs, batch_ys = next(train_data_iter)
train_step(SoftmaxRegression_model, batch_xs, batch_ys)
## 학습부
# 학습이 끝나면 학습된 모델의 정확도를 출력
accuracy = compute_accuracy(SoftmaxRegression_model(x_test), y_test)
print("정확도(Accuracy): %f" % accuracy)
# 정확도 약 91%
코드 부분을 한부분씩 잘라서 이해해보자.
데이터 전처리
# MNIST 데이터를 다운로드
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 이미지들을 float32 데이터 타입으로 변경
x_train, x_test = x_train.astype('float32'), x_test.astype('float32')
# 28*28 형태의 이미지를 784차원으로 flattening 한다.
x_train, x_test = x_train.reshape([-1, 784]), x_test.reshape([-1, 784])
# [0, 255] 사이의 값을 [0, 1] 사이의 값으로 Normalize한다.
x_train, x_test = x_train / 255., x_test / 255.
# 레이블 데이터에 one-hot encoding을 적용한다.
y_train, y_test = tf.one_hot(y_train, depth=10), tf.one_hot(y_test, depth=10)
https://inradestrt.tistory.com/664
위 MNIST데이터셋을 다운로드하여 사용한다.
데이터타입을 float32형식으로 변환한다.
- 이미지데이터는 기본적으로 uint8형식으로 되어있으나, 신경망 모델은 float32 타입의 데이터를 다루기 때문.
이미지 평탄화(Flattening)
- MNIST이미지는 28x28픽셀 크기의 2D배열 형태이다. 이 이미지를 1D형태로 변환하여 신경만의 입력으로 사용하기 위해 평탄화(flatten)한다.
정규화(Normalize)
- 이미지 픽셀값은 [0, 255](흑백) 값을 가지는데, 모델이 학습할 떄 더 빠르고 안정적으로 학습할 수 있도록 [0, 1] 사이로 정규화한다.
One-Hot 인코딩
- 레이블 데이터는 0에서 9까지의 정수값이다. 이를 신경망 출력과 비교하기 쉽게 One-hot인코딩을 통해 이진벡터로 변환하여 키값을 레이블 해준다.
데이터셋 준비
# tf.data API를 이용해서 데이터를 섞고 batch 형태로 가져온다.
train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_data = train_data.repeat().shuffle(60000).batch(100)
train_data_iter = iter(train_data)
데이터셋 생성
- tf.data.Dataset.from_tensor_slices를 사용하여 x_train과 y_train 데이터를 TensorFlow데이터셋 으로 만든다.
(API에 알맞게 데이터를 정리한다고 이해하면 된다)
반복 및 섞기(shuffle)
- 데이터셋을 무작위로 섞어서 학습의 편향을 줄이고, 무한 반복하여 학습할 수 있도록 설정한다.
(학습의 제한사항을 최대한 여유롭게 풀어준다고 이해하면 된다.)
배치 처리(batch(100))
- 학습 속도를 높이고 메모리 효율성을 높이기 위해 데이터를 일정 크기의 배치로 나눈다. 여기서는 100개씩 묶는다.
모델이 한번에 처리할 수 있는 적당한 크기의 데이터 덩어리를 만든다.
한번에 모든 데이터를 학습하게 되면 너무 느리기 때문에, 부분부분씩 잘라서 학습한다고 생각하자.
이터레이터 생성
- 학습 중에 매번 새로운 배치를 가져오기 위해 이터레이터를 생성한다.
학습때 필요한 배치를 한개씩 꺼내쓰기 위해 연결고리를 만들어놓는다고 이해하자.
모델 정의
class SoftmaxRegression(tf.keras.Model):
def __init__(self):
super(SoftmaxRegression, self).__init__()
self.softmax_layer = tf.keras.layers.Dense(10,
activation=None,
kernel_initializer='zeros',
bias_initializer='zeros')
def call(self, x):
logits = self.softmax_layer(x)
return tf.nn.softmax(logits)
모델 클래스 정의
- 사용자 정의 모델을 생성하기 위해 케라스의 서브클래싱 API를 이용한다.
Dense층 정의
- 10개의 뉴런을 가진 Dense(완전 연결) 층을 추가한다. 각 뉴런은 하나의 클래스(0-9)를 예측하게 된다.
입력데이터에 대해 각 클래스에 대한 점수를 계산하는 층이다.
가중치와 바이어스 초기화
- 가중치와 바이어스를 0으로 초기화한다.
초기값을 정의하여 학습을 통해 최적값을 찾는다.
출력 정의
- Dense층의 출력을 Softmax 함수에 통과시켜 클래스 확률을 계산한다.
각 분포 확률을 얻어 예측할 수 있도록 한다.
손실 함수 정의
@tf.function
def cross_entropy_loss(y_pred, y):
return tf.reduce_mean(-tf.reduce_sum(y * tf.math.log(y_pred), axis=[1]))
손실 함수 정의
- Cross-entropy 손실 함수는 예측값과 실제값 사이의 차이를 측정한다.
모델의 예측이 실제값과 얼마나 다른지 평가하여 수정할 수 있도록 한다.
학습의 불일치 부분을 확인하고 모델의 성능을 향상시키기 위해 생성함.
옵티마이저 정의
optimizer = tf.optimizers.SGD(0.5)
옵티마이저 정의
- 경사 하강법(SGD) 옵티마이저는 손실을 줄이기 위해 모델의 가중치를 업데이트 한다.
학습률(0.5)
- 가중치를 업데이트 할 때의 스텝 크기를 결정한다.
적절한 학습률을 통해 빠르고 안정적인 학습을 유도한다.
학습 단계 정의
@tf.function
def train_step(model, x, y):
with tf.GradientTape() as tape:
y_pred = model(x)
loss = cross_entropy_loss(y_pred, y)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
학습 함수 정의
- train_step함수는 한 번의 학습 단계에서 모델을 업데이트 한다.
모델을 학습시키기 위한 모든 작업을 하나의 함수에 모음
GradientTape(tape.gradient(...))
- 자동으로 미분을 계산하여 손실의 기울기를 추적한다.
모델의 가중치를 업데이트하기 위함.
기울기 계산 및 적용(.apply_gradients(...))
- 손실의 기울기를 계산하고 옵티마이저로 모델 가중치를 업데이트
정확도 계산 함수 정의
@tf.function
def compute_accuracy(y_pred, y):
correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
return accuracy
정확도 함수 정의
- compute_accuracy 함수는 모델 예측 정확도를 계산한다.
API를 쓴다고 이해하자.
모델 학습
# SoftmaxRegression 모델을 선언
SoftmaxRegression_model = SoftmaxRegression()
# 1000번 반복을 수행하면서 최적화를 수행.
for i in range(1000):
batch_xs, batch_ys = next(train_data_iter)
train_step(SoftmaxRegression_model, batch_xs, batch_ys)
모델 인스턴스 생성
- SoftmaxRegression모델을 인스턴스화 하여 학습에 사용한다.
모델을 준비
학습 반복
- 1000번 반복하면서 모델을 학습시킨다.
충분한 반복을 통해 데이터를 학습하고 손실을 최소화하도록 한다.
배치 학습
- 매 반복마다 새로운 배치를 가져와서 train_step함수를 호출한다.
데이터의 일부를 사용하여 모델을 학습시킴으로써 효율적인 학습을 수행한다.
728x90