Date : 2022.05.20
*The contents of this book is heavily based on Stanford University’s CS231n course.
[퍼셉트론의 상위 개념 : 신경망. Neural Networks.]
신경망은 가중치 매개변수를 데이터로부터 학습할 수 있는 능력이 있다 특징을 가지고 있다.
신경망은 입력층, 은닉층, 출력층으로 구성되어 있다. 은닉층은 다충 퍼셉트론의 숨겨진 여러 개의 층이라고 생각하면 된다. 신경망에서는 활성화 함수가 있다. 퍼셉트론에서도 0과 1 중에서 무엇을 출력할지 정할 때 활성화 함수의 개념을 사용했었다.
활성화 함수는 뉴런 내부에 존재한다. 뉴런 안으로 들어가보자.
퍼셉트론의 대표적인 활성화 함수는 계단 함수이다. 0 혹은 1. 신경망에서는 계단함수 (비선형)의 범주 밖인 선형 함수들을 사용한다.
- 시그모이드 함수 (Sigmoid)
- ReLU 함수 (ReLU)
- 계단 함수 (Step)
[시그모이드 함수]
은닉층 활성화 함수인 시그모이드 함수는 입력 신호 x 를 시그모이드에 통과시킨 값을 출력한다. 계단 함수와 시그모이드 함수를 모두 구현해보자.
계단 함수와 시그모이드 함수의 가장 큰 차이점은 선형이냐 비선형이냐이다. 비선형 함수는 부드러운 곡선으로 입력/출력이 연속적으로 변한다. 시그모이드 함수의 경우 입력 값이 커지면 출력 값이 1에 수렴하면서 입력이 그만큼 영향력 높은 값임을 알려준다.
[ReLU 함수]
Rectified Linear Unit 함수로 다음과 같이 생겼다.
우리가 최종으로 구현하게 될 CNN (Convolutional Neural Network)에서는 Sigmoid와 ReLU를 둘다 사용할 것이다. 중요한 것은 두 함수 모두 뉴런 속에서 입력 값을 출력 값으로 변환하는 활성화 함수라는 사실이다.
[소프트맥스 (Softmax) 함수]
소프트맥스 함수를 설명하기에 앞서 MNIST 데이터셋을 이해해야한다. 우리는 CNN을 구현하기 위해 신경망의 부품들을 하나씩 찍어내고 있다. CNN을 구현하면 우리는 무엇을 할 것인가? MNIST을 이용해서 신경망의 분류 성능을 테스트할 것이다. MNIST는 “숫자 이미지”를 데이터로 담고 있으며, 우리 신경망은 “숫자 이미지"를 받아서 0 ~ 9 사이의 어떤 숫자인지 분류해야한다. 많은 숫자를 정확하게 분류할수록 성능이 높은 것이다. 결론적으로 신경망은 “이미지 → 분류 → 정답 예상”의 순서로 진행된다.
우리의 목적은 “분류”이다. 그리고 소프트맥스 함수는 분류를 담당하는 함수이다. 그리고 앞서 살펴본 활성화 함수는 은닉층에 있는 활성화 함수지만, 소프트맥스는 출력층 뉴런에 존재한다. 소프트맥스 함수는 다음과 같다.
소프트맥스 함수의 분자는 입력신호 a 의 지수 함수, 분모는 모든 입력 신호의 지수 함수의 합으로 구성된다. 식을 보면 직감적으로 확률을 의미한다는 것을 알 수 있다. 실제로 소프트맥스는 입력신호들을 정규화해서 확률로 출력한다.
위의 코드에서 오버플로 대책인 c 변수를 보자. 소프트맥스는 지수 함수 (exponential) 이다. 입력 값이 커질수록 기하급수적으로 증가하기 때문에, 이를 방지하기 위해서 c 라는 정수를 빼주는 것이다.
[소프트맥스 함수 특징]
간단한 예시를 보자.
결과로부터 두 가지 사실을 알 수 있다. 첫 번째는 출력 결과들이 모두 0~1 사이 값이라는 것이다. 두 번째는 출력 값의 합이 1이 된다는 것이다. 확률적으로 해석하면 y[0] = 0.018, y[1] = 0.245, y[2] = 0.736이기 때문에 “2번째 원소의 확률이 73%로 가장 높으니 정답은 2번째 클래스일 것이다”가 된다.
소프트맥스는 확률을 기반으로 한 분류 알고리즘이다. 우리가 설계하고 있는 CNN 신경망 또한 분류를 목적으로 하고 있기 때문에 출력층에서 소프트맥스 함수를 사용하는 것이다.
[MNIST에 적용하기]
MNIST의 이미지 데이터는 28 x 28 크기의 회색조 이미지이며, 각 픽셀은 0에서 255까지의 값을 취한다. 그리고 각 이미지의 정답에 해당하는 숫자가 레이블로 붙어있다.
MNIST 데이터 저장 주소 → http://yann.lecun.com/exdb/mnist/
x_train 을 보자. 형상이 (60000, 784)이다.
row (행) = 60000
column (열) = 784
각 행은 각기 다른 이미지이며 각 이미지를 784 (28x28) 개의 픽셀 정보를 담고 있다. 쉽게 말해서 손글씨 숫자 이미지 한개를 784개의 칸으로 쪼갠다. 쪼개진 각각의 칸들은 “픽셀" 단위이며 픽셀은 0~255까지의 값을 취한다. 위 코드에서 짚고 넘어갈 부분은 load_mnist 함수의 인수 값들이다.
- Normalize : 입력 이미지의 픽셀 값을 0.0~1.0 사이의 값으로 정규화한다. False로 설정하면 입력 이미지의 픽셀은 원래 값 그대로 0~255 사이를 유지한다.
- Flatten : 입력 이미지를 평탄하게 1차원 벡터로 만든다. False인 경우 입력 이미지는 기존의 1x28x28의 3차원 배열이며, 위와 같이 True로 설정하면 784개의 원소로 이루어진 1차원 배열로 저장된다.
- One-hot encoding : 예시로 배열 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0] 에서 정답 인덱스만 ‘1’이고 나머지는 ‘0’으로 구성된 형태이다. 만약 원-핫 인코딩을 하지 않는다면 ‘7’, ‘2’와 같이 실제 숫자를 포함하고 있다.
[MNIST 이미지 확인해보기]
load_mnist 를 통해서 이미지를 로컬에 저장했으니까 이제 실제로 이미지를 확인해볼 것이다.
Python Image Library 모듈을 사용할 것이다. “pip install pillow”로 커맨드에서 설치 할 수 있다.
replit에서는 그래픽 모듈을 지원하지 않기 때문에 실제로 MNIST 사진을 프린트하지 않지만 다른 IDE라면 정상 작동 할 것이다.
[추론 단계 실행하기]
우리가 처음으로 만들 신경망은 “입력층 뉴런 784개, 첫 번째 은닉층 뉴런 50개, 두 번째 은닉층 뉴런 100개, 출력층 뉴런 10개”이다. 신경망은 입력 데이터를 기반으로 0~9까지의 숫자 중 하나로 분류한다.
Pickle File 자료 → https://www.datacamp.com/tutorial/pickle-python-tutorial
for 문을 통해서 x_train 에 저장된 이미지를 1장씩 꺼내서 predict 함수로 분류 한다. Accuracy에 대한 출력값을 보면 93.52% 인 것을 볼 수 있다. 신경망을 더 정교하게 만들어서 99% 정확도까지 올릴 것이다.
[배치 (batch) 처리하기]
위 코드에서 우리는 이미지를 1장씩 처리했다. 하지만 배치를 사용해서 이미지를 100개씩 묶어서 predict 함수에 넘긴다고 생각해보자. 그러면 100장 분량에 대한 결과가 한번에 출력된다. 넘파이 모듈을 사용한 배열 연산은 크기가 클수록 효율적으로 처리한다. 배치를 사용한 신경망은 행렬 연산 조건만 맞춰주면 부드럽게 실행된다.
'Tech Development > Deep Learning (CNN)' 카테고리의 다른 글
Computational Graphs & Backward Propagation (0) | 2022.10.24 |
---|---|
SGD, Epochs, and Accuracy Testing (0) | 2022.10.22 |
Loss Function and Stochastic Gradient Descent (0) | 2022.10.20 |
Perceptrons, Equations, and Gates (0) | 2022.10.08 |
Getting Familiar with Numpy & Matplotlib (0) | 2022.10.08 |
댓글