미니배치 학습

김선재·2021년 10월 31일
0

Deep Learning

목록 보기
7/13
post-thumbnail

배치란?

  • 입력한 데이터의 묶음

  • 묶음대로 결과물이 나온다

    100개 데이터를 한꺼번에 묶어서 ( 배치를 만들어서 ) 입력을 했으면,
    거기에 대한 결과물이 100개가 한꺼번에 나온다.

  • Loss도 배치를 사용하는 상황에 대해서 대응을 해줘야 한다.

    N 건의 배치에 대한 loss를 각각 구한 다음
    그 값을 모두 더해서 평균을 내면 된다.

미니배치란?

  • 가지고 있는 데이터가 10억건이다.
    💡 과연 신경망이 10억을 모두 사용해서 학습을 하고, 신경망을 평가 할 때 10억건에 대한 모든 손실 함수를 구해서 평균을 구할 필요가 있을까?
  • 1억건만 써도 충분할 수도 있다.
  • 데이터의 양이 굉장히 많은 경우에는 모든 데이터를 다 쓰는 것이 아니고,
  • 데이터의 일부를 무작위로 추려서 그 근사치로 이용할 수 있다.
  • 이 일부가 되는 데이터를 미니배치라고 한다.
import tensorflow as tf
import matplotlib.pyplot as plt
%matplotlib inline

MNIST 데이터셋 로딩

from tensorflow.keras import datasets
mnist = datasets.mnist

(x_train, y_train), _ = mnist.load_data()

데이터 형상 확인 및 전처리

print('x_train의 shape : {} ' .format(x_train.shape))
print('y_train의 shape : {} ' .format(y_train.shape))

~~>
x_train의 shape : (60000, 28, 28) 
y_train의 shape : (60000,) 

데이터 평탄화

TRAIN_IMAGE_COUNT = x_train.shape[0]
x_train = x_train.reshape(TRAIN_IMAGE_COUNT, -1)

x_train.shape

~~>
(60000, 784)

y_train One Hot Encoding

  • y_train의 형상이 (60000, )이기 때문에 One Hot Encoding이 되어 있지 않은 상태
y_train = tf.one_hot(y_train, 10)
y_train = y_train.numpy()	# Tensor 배열을 ndarray 화 시키기

y_train
~~>
array([[0., 0., 0., ..., 0., 0., 0.],
       [1., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 1., 0.]], dtype=float32)
       
y_train.shape

~~>
(60000, 10)

✨ 각 알고리즘 ( CNN, RNN, ANN )등을 사용할 때 마다 받아 들일 수 있는 데이터의 형상( shape )이 상이 하기 때문에 언제나 데이터의 shape을 확인하고 전처리 할 수 있도록 해야한다.

✨ 정답 데이터( t ) 같은 경우에는 텐서플로우나 파이토치 등의 프레임워크를 사용할 때는 딱히 신경을 쓰지 않아도 좋다. 단 t의 형상에 따라서 사용되어지는 loss 함수의 종류는 달라질 수 있다.

✨ 예를 들어 턴서플로우에서 t가

One Hot Encoding이 안되어 있는 경우 : sparse categorical crossentropy를 사용
One Hot Encoding이 되어 있는 경우 : categorical crossentropy를 사용
이진 분류 : binary crossentropy를 사용하는 등의 확인은 필요하다.

미니배치 구현하기

import numpy as np

미니배치 선정하기

  • 훈련 데이터 전체에서 무작위로 10장만 빼내오기
train_size = x_train.shape[0]	# 전체 훈련 데이터셋 크기(60,000개)
batch_size = 10	# 미니 배치의 사이즈 ( 10개를 1묶음으로 )
batch_mask = np.random.choice(train_size, batch_size)	# train_size에서 batch_size 만큼의 정수를 무작위로 추출

batch_mask
~~>
array([37931, 28671, 19284, 36379, 27742, 22532, 54126, 56638, 24002,
       45051])

배치 데이터 만들기

x_batch = x_train[batch_mask]	# batch_mask에 위치한 데이터 추출하기
y_batch = y_train[batch_mask]	# 정답 데이터도 동일한 batch_mask를 이용해서 추출

👉 위의 코드에서는 y라고 되어있지만 실제로는 t( 정답 )이다.

배치용 교차 엔트로피 함수

E=1Nn  ktnklogynkE = -\frac{1}{N}\sum_n\;\sum_{k}t_{nk}\log{y_{nk}}
  • NN : 전체 데이터의 개수
  • nn : n 번째 데이터

version 1

  • t가 One Hot Encoding이 되어있는경우
  • 배치가 없이 데이터가 들어오는 경우 ( 즉, y가 1차원 배열 )
def cross_entropy_error(y, t):
	# 만약에 데이터가 1개만 들어온다면 - 1차원 배열 형태로 데이터가 들어오는 경우 -> 배치를 사용하지 않는 경우
    if y.ndim == 1: 	# y가 1차원 배열 : 배치가 없는 경우
    	t = t[np.newaxis, :]
        y = reshape(1, -1) # 두 방식은 같은 것 편한 것으로 사용하면 된다. 
    
    batch_size = y.shape[0]	# N을 구한 것
    
    # 배치마다의 loss를 합한 다음 batch_size로 나누어 준다 -> loss의 평균
    delta = 1e-7
    
    return -np.sum(t * np.log(y+delta)) / batch_size

version 2

  • t가 One Hot Encoding이 안되어 있는 경우, 배치가 없이 데이터가 들어오는 경우
def sparse_cross_entropy_error(y, t):
	if y.dim == 1:
    	t = t.reshape(1, t.size)	# size : 스칼라 원소의 개수
        y = y.reshape(1, y.size)	
        
    delta = 1e-7
    batch_size = y.shape[0]
    
    return -np.sum(np.log(y[np.arrange(batch_size), t] + delta)) / batch_size
np.log(y[np.arange(batch_size), t])

batch_size = 5
t = [2, 7, 0, 9, 8]	# OHE이 안되어 있는 상태

np.arange(batch_size) : [0, 1, 2, 3, 4]	# batch_size 크기의 배열이 생성 됨

y[[0, 1, 2, 3, 4], [2, 7, 0, 9, 8]]
y[np.arange(batch_size), t] : y[0, 2]
	     		      y[1, 7]
         		      y[2, 0]
         		      y[3, 9]
         		      y[4, 8]

💡 y는 현재 batch_size가 5이기 때문에 5개의 배치 데이터에 대한 소프트맥스의 결과물
👉 y는 이차원 배열이 된다.

y가

y = [
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
]

이라면...

y[0, 2]의 경우 살펴보기
1. np.log(y[np.arange(batch_size), t])
2. np.log(y[0, 2])
3. np.log(0.8)

y[1, 7]
y[2, 0]
y[3, 9]
y[4, 8]

💡 batch가 없고, OHE이 되어있으면?

  • t = np.array([0, 0, 1, 0, 0]) 👉 t.shape = (5, )

💡 batch가 없고, OHE도 안되어 있으면?

  • t = np.array([1]) 👉 t.shape = (1, )

✨ y는 신경망의 추론단계( 순전파 )를 지났기 때문에 항상 softmax가 적용된 결과물

  • 예를들어

    클라스가 3개면 y의 결과물은 3개, 배치가 없는 경우 (3, )

t = np.array([1])
y = np.array([0.1, 0.7, 0.2])

print(t.size)
print(y.size)

print(t.reshape(1, t.size))
print(y.reshape(1, y.size))

~~>
1
3
[[1]]
[[0.1, 0.7, 0.2]]
batch_size = 5
sel = np.array([1, 3, 4])
t = np.array([2, 7, 0])

y = np.array([
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0],
  [0.9, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 0.0, 10],
  [0.1, 0.05, 0.8, 0.05, 0.0, 0.0, 0.0, 0.0, 8, 0.0]
])

y[sel, t]

~~>
array([0.8, 0. , 0.1])

profile
data science!!, data analyst!! ///// hello world

0개의 댓글