본문 바로가기
📁study archive/ML DL

딥러닝2차시

by Hush 2022. 8. 28.

퍼셉트론(perceptron)이란?

다수의 신호를 입력 받아 하나의 신호를 출력한다.

출력하는 신호는 1 또는 0으로, "흐른다"와 "흐르지 않는다"를 표현한다.

입력신호가 뉴런에 보내질 때 각각 고유한 가중치가 곱해진다.

그 후 뉴련에서 보낸 신호의 총합이 정해진 한계(threshold)를 넘어설 때만 1을 출력한다.

예를 들어 AND 게이트의 경우 w1, w2, theta 를 0.5, 0.5, 0.7로 설정하면 퍼셉트론으로 구현 가능하다.

not AND게이트의 경후 w1, w2, theta의 부호를 AND 게이트에서 전부 뒤집으면 구현 가능하다.

OR게이트 또한 비슷한 방식으로 구현 가능하다.

 

theta 를 -b 로 치환하면 다음과 같이 0을 기준으로 퍼셉트론을 표현할 수 있다.

이때 b를 편향(bias)라고 한다.

numpy의 산술계산과, 원소들의 총합을 구해주는 함수 np.sum() 등을 활용하면  퍼셉트론을 쉽게 구현할 수 있다.

 

단층 퍼셉트론의 한계

우리가 지금까지 논의한 퍼셉트론으로는 XOR게이트 등을 구현할 수 없다.

이를 해결하기 위해 퍼셉트론을 다층으로 구성하면 한계를 해결할 수 있다.

 

 

신경망이란

신경망은 입력층, 은닉층, 출력층으로 구성된다.

0층이 입력측, 마지막층이 출력층이고 그 사이에 존재하는 것들이 은닉층이다.

뉴런 연결 방식은 퍼셉트론과 동일하다.

 

활성화 함수

입력 신호의 총합을 출력 신호로 변환하는 함수를 활성화 함수(actication function)이라고 한다.

w1x1+w2x2+b 값을 활성화함수에 입력해 얻은 결과가 y까 되는 것이다.

이 과정을 그림으로 표현해 보면 다음과 같다.

계단 함수와 시그모이드 함수

활성화 함수로 사용되는 계단함수는 임계값을 경계로 출력이 바뀌는 함수로, 펴셉트론에서 사용하였다.

시그모이드 함수는  신경망에서 활성화함수로 사용되며, 수식은 다음과 같다.

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

 

선형 함수와 비선형 함수

선형 함수는 입력값에 따라 결과값이 선형적으로 출력되는 함수이다.

비선형 함수는 선형 함수가 아닌 모든 함수이다.

계단 함수, 시그모이드 함수는 모두 비선형 함수에 속한다.

활성화함수로 선형 함수를 사용하게 되면 여러 층을 쌓아도 선형 형태를 벗어날 수가 없다는 한계에 봉착한다.

따라서 층을 쌓아 심층적인 기능을 할 수 있도록 하기 위해서는 활성화함수로 반드시 비선형 함수를 사용해야 한다.

 

ReLU(Rectified Linear Unit)함수

시그모이드 함수를 신경망 분야에서 오래전부터 사용해왔으나, 최근에는 ReLU함수를 주로 이용한다.

ReLU함수는 입력이 0 을 넘으면 그대로, 0 이하면 0을 출력하는 함수이다.

 

다차원 배열이란

다차원 배열이란 숫자의 집합을 N차원으로 나열한 것으로, 특히 2차원 배열을 행렬이라고 부른다.

np.ndim() 함수를 통해 배열의 차원 수를 확인할 수 있다.

 

행렬의 곱

행렬의 곱을 계산하라면 np.dot()함수를 활용해야한다.

행렬곱은 교환법칙이 성립하지 않음에 유의하자.

다음 신경망을 행렬 곱을 이용하여 구현해보자.

import numpy as np

def calc(input_arr):
    W = np.array([[1, 3, 5],[2, 4, 6]])
    return np.dot(input_arr, W)
    
calc(np.array([1,2]))

 

3층 신경망 구현

가중치와 결과값의 위 첨자는 해당 값이 몇 층에 해당하는지를 나타낸다.

또한 가중치의 아래첨자는 '다음 층 번호, 앞 층 번호'순서로 표기한다.

이제 행렬의 곱을 이용하면 1층의 '가중치 부분'을 다음과 같이 간소화된 식으로 표현할 수 있다.

이를 numpy를 활용하여 다음과 같이 간단히 구현할 수 있다.

import numpy as np

X = np.array([1.0, 0.5])
W = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
B = np.array([0.1, 0.2, 0.3])

Y = np.dot(X,W)+B

 

1층에서 2층으로 가는 과정또한 유사하다.

 

2층에서 출력층으로 신호가 전달되는 과정도 거의 동일하지만, 활성화 함수 하나만 차이가 있다.

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

결과값을 예측하는 회귀문제는 항등함수를 사용하고,

두 개의 클래스를 분류하는 문제에는 sigmoid 함수를 사용하며, 

여러 클래스를 분류할 때는 softmax 함수를 사용한다.

 

이를 한번에 구현하려면

init_network() 함수를 통해 가중치와 편향을 한 딕셔너리에 저장하고,

forward() 함수로 입력 신호를 출력으로 변환하는 처리 과정을 구현한다.

import numpy as np

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

def identity_function(x):
    return x

def init_network():
    network = {}
    network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    network['b1'] = np.array([0.1, 0.2, 0.3])
    network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
    network['b2'] = np.array([0.1, 0.2])
    network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
    network['b3'] = np.array([0.1, 0.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])
y = forward(network, x)
print(y) # [0.31682708 0.69627909]

 

출력층의 설계도 유사하지만 추가로 알아야 할 개념이 있다.

 

기계학습 문제는 크게 분류(classification) 문제와 회귀(regression) 문제로 나뉘는데, 신경망은 두 경우 모두 사용 가능하다.

 

분류는 데이터가 어느 class에 속하는지 구분하는 문제로, 사진 속 인물의 성별을 구분하는 문제 등이 해당된다.

일반적으로 softmax함수를 사용한다.

회귀는 입력 데이터를 바탕으로 특정 수치를 예측하는 문제이다. 사진 속 인물의 몸무게를 예측하는 문제 등이 해당된다.

일반적으로 항등 함수를 사용한다.

 

항등 함수는 입력을 그대로 출력하는 함수이니 딱히 구현이랄 것도 없다.

softmax 함수의 식은 다음과 같다.

 

입력신호 a = [0.3, 2.9, 4.0]일때 softmax함수를 구현하면 다음과 같다.

import numpy as np

A = np.array([0.3, 2.9, 4.0])

def softmax(input_arr):
    return np.exp(input_arr)/np.sum(np.exp(input_arr))

print(softmax(A))

다만 softmax를 컴퓨터가 계산하는 과정에서 오버플로가 발생할 수 있다.

이를 위해 입력 신호 중 최댓값을 모든 항에 빼주는 테크닉을 사용한다.(그래도 값은 동일하니까)

이를 구현하면 다음과 같다

c = np.max(a)
softmax(a - c) # 게산 가능

 

softmax 함수를 이용하는 분류 문제의 뉴런 수는 분류하고 싶은 class의 수로 설정하는 것이 일반적이다.

예를 들어, 손글씨 이미지를 숫자 0부터 9까지로 분류하는 문제라면 출력층의 뉴런은 10개로 설정한다.

 

'📁study archive > ML DL' 카테고리의 다른 글

딥러닝1차시  (0) 2022.08.28
파이썬 텐서플로우, 머신러닝 기초  (0) 2022.03.27

댓글