<신경망>

퍼셉트론 좋은 소식: 복잡한 함수도 표현가능
퍼셉트론 나쁜 소식: 가중치를 설정하는 작업을 사람이 수동으로 함
신경망은 이 나쁜 소식을 해결함.


위의 그림 속 신경망은 3층으로 구성되어있지만 가중치를 갖는 층이 2개이기 때문에 2층 신경망 이라고 한다.

1. 활성화 함수

(activateion function) : 입력 신호의 총합을 출력 신호로 변환하는 함수.
변환된 신호를 다음 뉴런에 전달한다.
입력 신호의 총합이 활성화를 일으키는지를 정하는 역할을 한다.

이 함수는 입력 신호의 가중합을 계산한 후, 그 결과를 다음 층이나 출력으로 변환해주는 역할을 합니다.

a = b+w1x1+w2x2 #가중치가 달린 입력 신호와 편향의 총합
y=h(a) #a를 함수 h()에 넣어 y를 출력

단순 퍼셉트론

: 단층 네트워크에서 계단 함수 (임계값을 경계로 출력이 바뀌는 함수)를 활성화 함수로 사용한 모델

다층 퍼셉트론

: 신경망 (여러 층으로 구성되고 시그모이드 함수 등의 매끈한 활성화 함수를 사용하는 네트워크)

활성화 함수는 인공 신경망에서 입력을 출력으로 변환하는 함수입니다. 주요 활성화 함수에는 여러 가지가 있고, 각각의 함수마다 장단점이 있습니다.

시그모이드 함수 (Sigmoid Function)

장점:
0과 1 사이의 연속적인 출력을 생성하여 확률값과 같이 사용 가능합니다.
경사 하강법을 통한 학습이 잘 되기도 합니다.

단점:
기울기 소실 문제(vanishing gradient problem)가 있어, 역전파 과정에서 기울기가 소실되는 문제가 발생할 수 있습니다.
출력값이 zero-centered가 아니어서 학습 속도가 느려질 수 있습니다.

하이퍼볼릭 탄젠트 함수 (Hyperbolic Tangent Function)

장점:
시그모이드 함수와 비슷하지만 출력 범위가 -1에서 1 사이로 zero-centered이기 때문에 학습이 빠를 수 있습니다.
시그모이드 함수보다 기울기 소실 문제가 덜 발생할 수 있습니다.

단점:
여전히 기울기 소실 문제가 발생할 수 있습니다.

렐루 함수 (Rectified Linear Unit, ReLU)

장점:
학습 속도가 빠르고, 연산 비용이 적게 듭니다.
기울기 소실 문제를 완화해줍니다.

단점:
입력이 음수면 출력이 항상 0이 되기 때문에 dying ReLU 문제가 발생할 수 있습니다. (학습 중 뉴런이 죽는 현상)
입력값이 음수일 때, 해당 부분에서 기울기가 0이 되어 역전파 시 가중치 업데이트가 일어나지 않을 수 있습니다.

리키 렐루 함수 (Leaky ReLU)

장점:
ReLU의 dying ReLU 문제를 해결하기 위해 음수 부분에서 작은 기울기를 가집니다.
음수 영역에서도 기울기가 0이 아니기 때문에 dying ReLU 문제를 완화합니다.

단점:
여전히 입력의 음수 부분에서는 미분값이 0이 아니기 때문에 일정 정도의 정보 손실이 있을 수 있습니다.

소프트맥스 함수 (Softmax Function)

장점:
다중 클래스 분류에 주로 사용되며, 각 클래스에 대한 확률을 반환합니다.

단점:
출력값이 클래스에 대한 확률을 나타내기 때문에 다른 활성화 함수처럼 회귀 문제에는 적용하기 어렵습니다.

(1) 시그모이드 함수 (sigmoid function)

exp(-x)는 e-x, e는 자연상수로 2.7182...
신경망에서는 활성화 함수로 시그모이드 함수를 이용하여 신호를 변환.
변환된 신호를 다음 뉴런에 전달.

브로드캐스트 기능

: 넘파이 배열과 스칼라값의 연산을 넘파이 배열의 원소 각각과 스칼라값의 연산으로 바꿔 수행한다.

import numpy as np
import matplotlib.pylab as plt

def sigmoid(x):
  return 1/(1+np.exp(-x))

x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
#브로드캐스트
#넘파이 배열과 스칼라값의 연산을 넘파이 배열의 원소 각각과 스칼라값의 연산으로 바꿔 수행

plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()


: 실수를 돌려준다. -> 연속적인 실수가 흐른다.

(2) 계단 함수

: 0과 1 중 하나의 값만 돌려준다. -> 뉴런 사이에 0 혹은 1이 흐른다.
임계값을 경계로 출력이 바뀜

import numpy as np
import matplotlib.pylab as plt
        
def step_function(x):
	return np.array(x>0, dtype=np.int)
	##numpy 배열을 인수로 넣을 수 있게 하는 방법
    #x = np.array([-1.0, 1.0, 2.0])
    #y = x>0
    #y를 출력하면 0보다 큰 x값은 True로, 0보다 작거나 같은 값은 False로 나온다.
    #booleaan값을 int형으로 변환시키면 True는 0, False는 1이다.
        
x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) 
plt.show()

(3) 비선형 함수

: 직선 1개로는 그릴 수 없는 (선형이 아닌) 함수.
계단 함수와 시그모이드 함수 모두 비선형 함수

선형함수: 출력이 입력의 상수배만큼 변하는 함수. f(x) = ax + b
선형함수의 문제는 '은닉층이 없는 네트워크'로 똑같은 기능을 할 수 있음.
층을 쌓는(딥러닝) 혜택을 얻고 싶다면 활성화 함수로 반드시 비선형함수를 사용해야 함.

계단 함수와 시그모이드 함수의 차이점

매끄러움의 차이
계단함수 : 시시오도시
시그모이드 : 물레방아

계단 함수와 시그모이드 함수의 공통점

입력이 중요하면 큰 값을 출력하고 입력이 중요하지 않으면 작은 값을 출력한다.
(입력이 작을 때의 출력은 0에 가깝고 혹은 0이고,
입력이 커지면 출력이 1에 가까워지는 혹은 1이 되는 구조이다.)

(입력이 아무리 작거나 커도) 출력은 0에서 1사이이다.

비선형 함수(직선 1개로는 그릴 수 없는 함수)이다.

선형함수의 문제: 층을 아무리 깊게 해도 ‘은닉층이 없는 네트워크’로도 똑같은 기능을 할 수 있다. 즉 선형 함수를 이용해서는 여러 층으로 구성하는 이점을 살릴 수 없다.

(4) ReLu 함수 (rectified linear unit)

: 입력이 0을 넘으면 그 입력을 그대로 출력하고 0이하이면 0을 출력하는 함수

import numpy as np
import matplotlib.pyplot as plt

def relu(x):
  return np.maximum(0, x)		# maximum 함수: 두 입력 중 큰 값을 선택해 반환하는 함수

x = np.arange(-5.0, 5.0, 0.1)
y= relu(x)
plt.plot(x, y)
plt.show()

2. 다차원 배열

: N차원으로 나열하는 것.

np.ndim(): 배열의 차원 수 확인
배열.shape: 배열의 형상 확인

import numpy as np

#1차원 배열
A = np.array([1,2,3,4])
np.ndim(A)
A.shape 			#튜플로 반환(2차원이면 (4,3)과 같은식

#2차원 배열 = 행렬
B = np.array([[1,2], [3,4], [5,6]])
np.ndim(B)
B.shape         

2차원 배열 은 특히 행렬 이라 부른다.

행렬의 곱

np.dot() : 입력이 1차원 배열이면 벡터를, 2차원 배열이면 행렬 곱을 계산한다.
np.dot(A, B)와 np.dot(B, A)는 다른 값이 될 수 있다.


행렬A의 1번째 차원의 원소 수(열 수) 와 행렬 B의 0번째 차원의 원소 수(행 수) 가 같아야 한다.

신경망에서 행렬의 곱

X = np.array([1,2])
X.shape #(2,)

W = np.array([[1,3,5], [2,4,6]])
print(W)
W.shape #(2,3)

Y = np.dot(X, W)
print(Y)

3. 3층 신경망

각 층의 신호 전달 구현

은닉층에서의 가중치 합(가중 신호와 편향의 총합)을 a로 표기하고 활성화 함수 h( )로 변환된 신호를 z로 표현한다.

1층의 '가중치 부분'을 행렬식으로 간소화하면

#입력층에서 1층으로의 신호 전달
X = np.array([1.0, 0.5]) #1*2
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]]) #2*3
B1 = np.array([0.1, 0.2, 0.3]) #1*3

A1 = np.dot(X, W1) + B1 #1*3
#print(A1)

#활성화 함수로 시그모이드 함수를 사용하기로 했을 때
Z1 = sigmoid(A1) #1*3
#print(Z1)

#1층에서 2층으로의 신호 전달
W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]]) #3*2
B2 = np.array([0.1, 0.2]) #1*2

A2 = np.dot(Z1, W2) + B2 #1*2
Z2 = sigmoid(A2) #1*2

#2층에서 출력층으로의 신호 전달
#출력층의 활성화 함수를 identity_function으로 정의
def identity_function(x):
  return x

W3 = np.array([[0.1, 0.3], [0.2, 0.4]]) #2*2
B3 = np.array([0.1, 0.2]) #1*2

A3 = np.dot(Z2, W3) + B3 #1*2
Y = identity_function(A3)

일반적으로 회귀 에서는 출력층의 활성화 함수를 항등함수 로, 2클래스 분류 에서는 시그모이드 함수 로, 다중 클래스 분류 에서는 소프트맥스 함수 로 사용한다.

3층 신경망 구현

def init_network():
  network = {}
  network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]]) #2*3
  network['b1'] = np.array([0.1, 0.2, 0.3]) #1*3
  network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]]) #3*2
  network['b2'] = np.array([0.1, 0.2]) #1*2
  network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]]) #2*2
  network['b3'] = np.array([0.1, 0.2]) #1*2
  
  return network

#신호가 순방향(입력에서 출력 방향)으로 전달됨(순전파)임을 알리기 위함이다.
def forward(network, x):
  W1, W2, W3 = network['W1'], network['W2'], network['W3']
  b1, b2, b3 = network['b1'], network['b2'], network['b3']
  
  a1 = np.dot(x, W1) + b1
  z1 = sigmoid(a1)
  a2 = np.dot(z1, W2) + b2
  z2 = sigmoid(a2)
  a3 = np.dot(z2, W3) + b3
  y = identity_function(a3)
  
  return y

network = init_network()
x = np.array([1.0, 0.5]) #1*2
y = forward(network, x)
print(y)

4. 출력층 설계

기계학습 문제는 분류(classification)와 회귀(regression)로 나뉜다.
일반적으로

회귀에는 항등함수를
분류에는 소프트맥스 함수를
출력층의 활성화 함수로 사용한다.

(1) 항등함수

(identity function): 입력을 그대로 출력하는 함수.

출력층의 활성화 함수를 다음처럼 표시하여 은닉층의 h()와는 다르게 표시.

σ() : 시그마

출력층의 활성화 함수는 풀고자 하는 문제의 성질에 맞게 정함.

(2) 소프트맥스 함수

(softmax function): 소프트맥스 함수의
분자는 입력 신호의 지수함수
분모는 모든 입력 신호의 지수 함수의 합으로 구성

def softmax(a):
  exp_a = np.exp(a)
  sum_exp_a = np.sum(exp_a)
  y = exp_a / sum_exp_a
  
  return y

회귀 => 항등함수
2클래스 분류 => 시그모이드 함수
다중 클래스 분류 => 소프트맥스 함수

시그모이드 함수와 소프트맥스 함수는 활성화 함수로 사용되는데, 몇 가지 공통점과 차이점이 있습니다.

공통점:

출력값의 범위:

둘 다 입력값을 확률값으로 변환하여 출력합니다. 시그모이드 함수는 0과 1 사이의 값으로, 소프트맥스 함수는 각 클래스에 대한 확률값으로 출력됩니다.

비선형성:

둘 다 비선형 함수입니다. 이는 신경망의 비선형성을 추가하여 다양한 함수를 근사할 수 있도록 도와줍니다.

차이점:

시그모이드 함수는 각 클래스에 대한 확률값출력함(확률에따라 0인지1인지 출력)으로 모든확률값을 더하면 1보다 큰값이 나온다. 반면, 소프트맥스 함수는 모든클래스에 대한 확률값을 출력함으로 모든확률값을 더하면 1이된다.

시그모이드는 주로 은닉층의 활성화 함수로 쓰이고, 소프트맥스함수는 주로 출력층에 쓰인다.

모델이 역전파를 사용해 가중치(파라미터값)을 조정할때 시그모이드 함수는 독립적으로 값을 조정하게되고, 소프트맥스 함수는 모든 클래스에 대한 확률값이기때문에 동시다발적으로 업데이트가 가능하여 학습이 더욱 효율적이다.

출력의 개수:

가장 큰 차이점은 출력의 개수입니다.
시그모이드 함수는 단일 뉴런의 출력을 위한 활성화 함수로 주로 이진 분류(binary classification)에서 사용됩니다.
반면 소프트맥스 함수는 다중 클래스 분류(multi-class classification)에서 출력 레이어에서 각 클래스에 대한 확률값을 계산하기 위해 사용됩니다. 소프트맥스 함수는 다중 출력을 갖는 신경망에서 많이 사용됩니다.

출력값의 관계:

소프트맥스 함수는 다중 클래스 분류 문제에서 각 클래스에 대한 확률값을 출력합니다. 이 확률값들의 합은 1이 되어, 각 클래스에 속할 확률을 나타냅니다. 하나의 샘플에 대해 여러 클래스 중 하나로 분류될 확률을 제공합니다.

시그모이드 함수는 각 뉴런마다 독립적으로 0과 1 사이의 값을 출력하며, 주로 이진 분류 문제에서 각 클래스에 속할 확률을 제공합니다.

(2-1) 소프트맥스 함수 주의점

지수함수를 사용하는 소프트맥스 함수는 '오버플로'의 문제가 발생해
수치가 '불안정'해질 수 있는 문제점이 있다.

오버플로(overflow) : 표현할 수 있는 수의 범위가 한정되어 너무 큰값은 표현할 수 없다.

(2-2) 소프트맥스 함수 구현 개선

-> 소프트맥스의 지수 함수를 계산할 때 어떤 정수를 더해도(혹은 빼도) 결과는 바뀌지 않는다.
-> C '에 어떤 값을 대입해도 상관없지만
오버플로를 막기 위해 입력 신호 중 최댓값을 이용하는 것이 일반적이다.

def softmax(a):
  c = np.max(a)
  exp_a = np.exp(a-c)
  sum_exp_a = np.sum(exp_a)
  y = exp_a / sum_exp_a
  
  return y

(2-3) 소프트맥스 함수 특징

출력값은 0에서 1.0 사이의 실수이다.
출력의 총합은 1이다. -> 확률로 해석 가능

신경망으로 분류할 때는 출력층의 소프트맥스 함수를 생략해도 된다.
이유: 신경망을 이용한 분류에서는 일반적으로 가장 큰 출력을 내는 뉴런에 해당하는 클래스로만 인식하게 되는데, 소프트맥스 함수를 적용해도 출력이 가장 큰 뉴런의 위치는 달라지지 않기 때문

소프트맥스를 적용해도 각 원소의 대소 관계는 변하지 않음
이유: 단조 증가함수(a<=b일 때 f(a)<=f(b)가 성립하는 함수)이기 때문

단조증가함수는 함수의 값을 증가시키는 특성을 갖는 함수를 의미합니다. 이는 함수의 독립 변수가 증가함에 따라 종속 변수 값이 항상 증가하는 함수입니다. 즉, 함수의 그래프가 왼쪽에서 오른쪽으로 갈수록 높아지는 형태를 보이는 것을 의미합니다.

수학적으로, 함수 f(x)가 증가함수이려면 모든 x와 y에 대해 x < y일 때 f(x) ≤ f(y)를 만족해야 합니다. 이는 어떤 두 점의 x 값이 작은 쪽의 경우, 그에 해당하는 함수값도 작거나 같다는 것을 의미합니다.

예를 들어, f(x) = x^2은 x가 증가함에 따라 항상 증가하는 함수입니다. 어떤 두 x 값에 대해 x가 더 큰 경우, 그에 따라 함수값도 더 크거나 같게 됩니다.

단조증가함수의 반대는 단조감소함수로, 이는 함수의 값을 감소시키는 특성을 갖는 함수입니다. 이 경우에는 x가 증가함에 따라 함수값이 감소합니다.

기계학습의 문제풀이(학습과 추론) 과정에서
학습 시킬 때에는 출력층에서 소프트맥스 함수를 사용하지만,
추론 단계에서는 출력층의 소프트맥스 함수를 생략하는 것이 일반적

(3) 출력층의 뉴런 수 정하기

출력층의 뉴런 수
분류의 경우
분류하고 싶은 클래스 수로 설정하는 것이 일반적

이미지를 숫자 0부터 9 중 하나로 분류하는 문제라면
출력층의 뉴런을 10개로 설정

5. 손글씨 숫자 인식

추론 과정: 신경망의 순전파(forward propagation)

신경망 문제 해결 2단계

  1. 학습 : 훈련 데이터(학습 데이터)를 사용해 가중치 매개변수를 학습한다.
  2. 추론 : 학습한 매개변수를 사용하여 입력 데이터를 분류한다.

신경망의 순전파(forward propagation)

: 이미 학습된 매개변수를 사용하여 입력 데이터를 분류하는 추론 과정

(1) MNIST 데이터셋

28*28 크기의 회색조 이미지(1채널)
각 픽셀은 0~255까지의 값을 취한다.
각 이미지에 실제 의미하는 숫자가 레이블로 붙어 있다.

import sys, os

sys.path.append(os.pardir)		# # 부모 디렉터리의 파일을 가져올 수 있도록 설정
from dataset.mnist import load_mnist

from mnist import load_mnist #mnist.py # 만을 다운받았다면

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)


#normalize: 입력 이미지의 픽셀값을 0.0~1.0 사이의 값으로 정규화할지 정함
#flatten: 입력 이미지를 1차원 배열로 만들지를 정함
#(False: 1*28*28 3차원 배열로 True: 784개의 원소로 이루어진 1차원 배열로)
#one-hot-label: 원-핫 인코딩 형태로 저장할지를 정함
#(False: 숫자 형태의 레이블을 저장 True: 레이블을 원-핫 인코딩하여 저장)

부모 디렉터리의 파일을 가져오고 dataset/mnist.py의 lost_mnist함수를 import함

load_mnist 함수로 데이터셋을 읽음

최초 실행시 인터넷에 연결된 상태여야 함

두 번째부터는 로컬에 저장된 pickle 파일을 읽기 때문에 순식간에 끝남.

load_mnist 함수는 읽은 MNIST 데이터를 "(훈련 이미지, 훈련 레이블), (시험 이미지, 시험 레이블)" 형식으로 반환

load_mnist 인수

normalize 입력 이미지의 픽셀 값을 0.0~1.0 사이의 값으로 정규화할 지 결정

flatten 1차원 배열로 할지 여부. False면 1X28X28의 3차원 배열, True면 784개의 원소로 이뤄진 1차원 배열로 저장

one_hot_lable 원-핫 인코딩(one-hot encoding). 정답을 뜻하는 원소만 1이고 나머지는 모두 0인 배열.

파이썬 pickle: 프로그램 실행 중에 특정 객체를 파일로 저장하는 기능. pickle 파일을 로드하면 실행 당시의 객체를 즉시 복원가능

import sys, os
sys.path.append(os.pardir)
from dataset.mnist import load_mnist
import numpy as np
from PIL import Image



def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))
    #Image.fromarray: 넘파이로 저장된 이미지 데이터를 PIL용 데이터 객체로 변환해야
    pil_img.show()

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)

img = x_train[0]
label = t_train[0]
print(label)

print(img.shape)
img = img.reshape(28, 28)
#flatten=True는 1차원 넘파이 배열로 저장되어 있다
#이미지를 표시할 때 원래 형상인 28*28크기로 다시 변형해야
print(img.shape)
img_show(img)

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)

reshape() 메서드: 원하는 형상을 인수로 지정하면 넘파이 배열의 형상을 변환가능

(2) 신경망의 추론 처리

import numpy as np
import pickle
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax


def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    return x_test, t_test

def init_network():
    #sample_weight.pkl파일에 저장된 학습된 가중치 매개변수를 읽는다
    #가중치와 편향 매개변수가 딕셔너리 변수로 저장되어 있다.
    with open("sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)

    return network


def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y

#신경망의 정확도(분류가 얼마나 올바른가)를 평가
x, t = get_data()
network = init_network()

accuracy_cnt = 0
for i in range(len(x)):
    y = predict(network, x[i]) #각 레이블의 확률을 넘파이 배열로 반환
    p = np.argmax(y) #배열에서 값이 가장 큰(확률이 가장 높은) 원소의 인덱스를 구함
    if p == t[i]:
        accuracy_cnt += 1

print("Accuracy: "+str(float(accuracy_cnt) / len(x)))

init_network(): pickle 파일인 sample_weight.pkl에 저장된 '학습된 가중치 매개변수'를 읽음

정확도(accuracy, 분류가 얼마나 올바른가) 평가

predict() : 각 레이블의 확률을 넘파이 배열로 반환

np.argmax() : 가장 큰(확률이 가장 높은) 원소의 인덱스를 구함 => 예측 결과

신경망이 예측한 답변과 정답 레이블을 비교하여 맞힌 숫자(accuracy_cnt)를 세고, 전체 이미지 숫자로 나눠 정확도 계산

normalize를 True로 설정. 각 픽셀의 값을 0.0~1.0 범위로 변환.

정규화(normalize) : 데이터를 특정 범위로 변환하는 처리
전처리(pre-processing) : 신경망의 입력 데이터에 특정 변환을 가하여 정리

정규화 예시

단위 길이로 변환: 데이터의 각 특성을 같은 단위로 맞추는 것을 의미합니다. 예를 들어, 길이를 나타내는 변수와 무게를 나타내는 변수가 함께 있을 때, 이들을 동일한 척도로 조정합니다.

범위 조정: 데이터를 일정한 범위로 조정합니다. 가장 일반적으로는 [0, 1] 또는 [-1, 1] 범위로 스케일을 조정합니다.

전처리 예시

데이터 클리닝(Cleaning): 결측치(missing values) 처리, 이상치(outliers) 탐지 및 처리, 오류 데이터 수정 등의 과정을 포함합니다.

데이터 스케일링(Scaling): 변수의 크기를 조정하는 작업입니다. 예를 들어, 변수들 간에 단위가 다르거나 값의 범위가 매우 크게 차이나는 경우에 스케일링을 사용하여 모델의 성능을 향상시킬 수 있습니다.

특성 추출(Feature Extraction): 데이터로부터 유용한 정보를 추출합니다. 예를 들어, 이미지에서 윤곽선을 찾는 것이나 텍스트 데이터에서 단어의 빈도를 계산하는 것 등이 여기에 해당합니다.

차원 축소(Dimensionality Reduction): 고차원 데이터의 특성을 줄이는 작업입니다. 주성분 분석(PCA)이나 t-SNE와 같은 기법을 사용하여 데이터를 더 적은 차원으로 표현할 수 있습니다.

데이터 전체 평균과 표준편차를 이용하여 데이터들이 0을 중심으로 분포하도록 이동시킴

데이터의 확산 범위를 제한하는 정규화를 수행

전체 데이터를 균일하게 분포시키는 데이터 백색화(whitening)

(3) 신경망의 배치 처리

: 각 층의 가충치 형상을 출력

이미지 여러 장을 한꺼번에 입력하는 경우

배치(batch): 하나로 묶은 입력 데이터

(이미지 100개를 묶어 predict() 함수에 한 번에 넘긴 경우)

x[0]와 y[0]에는 0번째 이미지와 그 추론 결과가, x[1]과 y[1]에는 1번째의 이미지와 그 결과가 저장된다.

x, t = get_data()
network = init_network()

batch_size = 100 #배치 크기
accuracy_cnt = 0

#range: 0부터 len(x)까지 batch_size간격으로 증가하는 리스트 반환
for i in range(0, len(x), batch_size):
  x_batch = x[i:i+batch_size] #0~100, 100~200, ...
  y_batch = predict(network, x_batch) #각 레이블의 확률을 넘파이 배열로 반환
  p = np.argmax(y_batch, axis=1) #배열에서 값이 가장 큰(확률이 가장 높은) 원소의 인덱스를 구함
  #axis=1: 1번째 차원을 구성하는 각 원소에서 최댓값의 인덱스를 찾도록
  accuracy_cnt += np.sum(p == t[i:i+batch_size])
  
print("Accuracy: "+str(float(accuracy_cnt) / len(x)))

배치(batch)란: 입력데이터를 하나의묶음으로 묶은것

배치처리 이점 : 이미지 1장당 처리 시간을 대폭 줄임
수치 계산 라이브러리 대부분이 큰 배열을 효율적으로 계산
버스에 주는 부하를 줄임. (CPU, GPU로 순수 계산을 수행하는 비율이 높아짐)

  • 배치 크기(batch size)는 머신러닝 모델을 학습시킬 때 한 번에 처리하는 데이터 샘플의 수를 의미합니다. 배치 크기는 모델 학습의 효율성과 성능에 중요한 영향을 미치는 하이퍼파라미터입니다.

배치 크기에 따른 특징

  • 큰 배치 크기
    : 한 번의 학습 단계에서 많은 데이터를 처리하므로 GPU 등의 병렬 처리 능력을 최대한 활용할 수 있어 학습 속도가 빠릅니다. 하지만, 많은 메모리를 필요로 하고, 각 학습 단계에서 처리하는 데이터가 많아지므로 모델이 훈련 데이터에 과적합될 가능성이 있습니다.**

  • 작은 배치 크기
    : 한 번의 학습 단계에서 처리하는 데이터가 적으므로 메모리 사용량이 적고, 각 학습 단계에서 파라미터 업데이트가 빈번하게 이루어져 모델이 빠르게 수렴할 수 있습니다. 하지만, 처리하는 데이터가 적으므로 학습이 불안정할 수 있고, 학습 속도가 느려질 수 있습니다.

일반적으로 배치 크기는 메모리 용량, 데이터의 특성, 학습 속도 등을 고려하여 설정합니다. 또한, 배치 크기는 하이퍼파라미터 최적화 과정에서 다양한 값으로 실험하여 가장 좋은 성능을 내는 값을 선택하기도 합니다.

profile
Fantivation

0개의 댓글