• Home
  • About
    • Yerim Oh photo

      Yerim Oh

      Happy and worthwhile day by day :)

    • Learn More
    • Email
    • LinkedIn
    • Instagram
    • Github
    • Youtube
  • Posts
    • All Posts
    • All Tags
  • Projects

[02] Deep learning 1: 신경망 구성 (활성화 함수)

11 Mar 2020

Reading time ~8 minutes

Table of Contents
  • 목차
  • 전체 딥러닝 학습과정
  • INTRO
  • 활성화 함수(activation function)
  • 퍼셉트론에서 이용하는 활성화 함수
    • 계단 함수 step function
  • 신경망에서 이용하는 활성화 함수
    • 비선형 함수
    • sigmoid function(시그모이드 함수)
    • ReLU 함수
  • 3층 신경망 구현하기
  • 출력층 설계
    • 항등 함수 identity function
    • 소프트맥스 함수 softmax function
      • 소프트맥스 함수 구현 시 주의점
      • 출력층의 뉴런 수 정하기

목차

  • 활성화 함수(activation function)
  • 퍼셉트론에서 이용하는 활성화 함수
    • 계단 함수 step function
  • 신경망에서 이용하는 활성화 함수
    • 비선형 함수
    • sigmoid function(시그모이드 함수)
    • ReLU 함수
  • 3층 신경망 구현하기
  • 출력층 설계
    • 항등 함수 identity function
    • 소프트맥스 함수 softmax function
      • 소프트맥스 함수 구현 시 주의점
      • 출력층의 뉴런 수 정하기


👀, 🤷‍♀️ , 📜
이 아이콘들을 누르시면 코드, 개념 부가 설명을 보실 수 있습니다:)



전체 딥러닝 학습과정

이번 포스트에선 어딜 배울까?
바로 신경망이다.
기계가 데이터를 받아서 어떻게 처리하고, output을 내는지를 볼 것이다.

1

이 신경망이 input 데이터에서 중요한 특징을 추출하기 위해 데이터를 걸러내는 역할을 하는데 핵심이 되는 구성이 활성화 함수이다.

자세한 내용을 알아보러가자



INTRO

신경망 성질: 가중치 매개변수의 적절한 값을 데이터로부터 자동으로 학습하는 능력이다.

11 [위 신경망의 특징]

  • ‘2층 신경망’: 가중치를 갖는 층은 2개뿐이기 때문
  • 뉴런이 연결되는 방식은 앞 장의 퍼셉트론과 같다.
  • 은닉층의 뉴런: (입력층이나 출력층과 달리) 사람 눈에 보이지 않는다.

⛔ 그렇다면 모든 경우에서 입력층의 데이터가 출력층까지 다 넘어갈까??
⭕ 아니다! 1) 모든 화살표에서 계산이 일어나고
2) 그 계산을 바탕으로 활성화할지 정한다

그러 그 계산을 더 알아보자


[퍼셉트론의 계산 식]
아래의 그림을 보면 알겠지만 은닉층에서 계산을 한다고 무조건 넘어가는 것(활성화 되는 것)은 아니다
이를 쉽게하기 위해 출력층 하나를 줄여보고, ⭕의 계산 식을 정의해보자
1) \(𝒚=𝒉(𝒃+𝒘,𝒙_𝟏+𝒘_𝟐 𝒙_𝟐 )\)
2) \(𝒉(𝒙)\)

  • 이것이 활성화 할지정하는 함수이다(이제 이 함수의 종류를 알아볼 것이다.)
  • 지금 이 활성화 함수는 임의로 정한 것이다

(활성화 되는 경우)
aa

(활성화 되지 않는 경우)
non

즉 이 넘어가는 기준을 정해주는 함수가(\(𝒉(𝒙)\)) 활성화 함수이다.


활성화 함수(activation function)

[등장]

  • 의의: 조금 전 h(x)라는 함수가 등장했는데, 이처럼 입력 신호의 총합을 출력 신호로 변환하는 함수
  • 역할: 입력 신호의 총합이 활성화를 일으키는지를 정함


    1단계) 가중치가 곱해진 입력 신호의 총합을 계산
    2단계) 그 합을 활성화 함수에 입력해 결과를 냄

image

이해를 돕기 위해 기존 뉴런의 원을 키우고, 그 안에 활성화 함수의 처리 과정을 명시적으로 그려 넣어봤다

a 노드(가중치 신호를 조합한 결과)가 활성화 함수 h ( )를 통과하여 y라는 노드로 변환되는 과정이 분명히 드러난다

퍼셉트론에서 신경망으로 가기 위한 길잡이

  • 단순 퍼셉트론
    단층 네트워크에서 계단 함수(임계값을 경계로 출력이 바뀌는 함수)를 활성화 함수로 사용한 모델
  • 다층 퍼셉트론
    신경망(여러 층으로 구성되고 시그모이드 함수 등의 매끈한 활성화 함수를 사용하는 네트워크)을 뜻함

  • 활성화 함수
    h(x)와 같이 임계값을 경계로 출력이 바뀌는 함수

퍼셉트론에서 이용하는 활성화 함수

그럼 이제 활성화 함수의 종류를 알아보자.

계단 함수 step function

: 활성화 함수로 쓸 수 있는 여러 후보 중에서 퍼셉트론은 계단 함수를 채용
: 활성화 함수를 계단 함수에서 다른 함수로 변경하는 것이 신경망의 세계로 나아가는 열쇠

👀코드 보기
def step_function(x):
    if x > 0:
        return 1 
    else: 
        return 0

장점

  • 단순함, 구현하기 쉬움

단점

  • 인수X는 실수만 받아들임
  • 넘파이 배열을 인수로 받아들일 수 없음
  • step_function (np.array ([1.0, 2.0 ] ) ) 불가
👀코드 보기
def step_function(x):          #-> 넘파이 가능
    y = x > 0                  #-> bool형 출력
    return y.astype(np.int)    #-> bool에서 int형으로

파이썬에서 bool을 int로 변환하면 True는 1, False는 0으로

[시각화]

👀코드 보기
import numpy as np
import matplotlib.pylab as plt

def step_function(x):
    return np.array(x > 0, dtype = np.int)

x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x) 
plt.plot(x, y) 
plt.ylim(-0.1, 1.1) # y축의 범위 지정
plt.show()

-> np.arange (-5.0, 5.0, 0.1 ): -5.0에서 5.0 전까지 0.1 간격의 넘파이 배열을 생성

image



신경망에서 이용하는 활성화 함수

비선형 함수

  • 계단 함수와 시그모이드 함수의 공통점
    직선 1개로는 그릴 수 없는 함수
  • 신경망에서는 활성화 함수로 비선형 함수만 사용해야함 -> 선형 함수를 이용하면 신경망의 층을 깊게 하는 의미가 없어지기 때문

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


sigmoid function(시그모이드 함수)

  • \(exp (-x )= e^{-x}\).
  • e는 자연상수로 2.7182…의 값을 갖는 실수

신경망에서는 활성화 함수로 시그모이드 함수를 이용하여 신호를 변환, 그 변환된 신호를 다음 뉴런에 전달한다.
퍼셉트론과 신경망의 주된 차이는 이 활성화 함수뿐이다.

이 함수는 0~1사이의 결과만 내어놓으므로 확률을 표현하기에 적절하다.

[구현]

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) # y축 범위 지정
plt.show()

image


ReLU 함수

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

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

image image

[구현]

👀코드 보기
def relu(x): 
    return np.maximum(0, x)

x = np.arange(-7.0, 7.0, 0.1)
y = relu(x) 
plt.plot(x, y) 
plt.ylim(-2, 7.1) # y축의 범위 지정
plt.show()

-> 여기에서는 넘파이의 maximum 함수를 사용했습니다.
Maximum: 두 입력 중 큰 값을 선택해 반환하는 함수



3층 신경망 구현하기

그럼 이제 간단한 3층 신경망을 구현하면서 위의 개념들이 어떻게 쓰이는지 다시 한번 확인해보자.
아래 그림의 신경망을 구현해 볼 것이다.
image

그 전 다차원 배열의 계산의 개념을 잘 모르면 아래를 클릭하여 기본 지식을 쌓고 보는 것을 추천한다.

📜 다차원 배열의 계산 보기

[배열의 차원 수 확인]

👀코드 보기
#np.ndim ( )         -> 차원수 반환
#or
#함수이름.shape      -> 튜플 반환

>>> B = np.array([[1,2], [3,4], [5,6]]) 
>>> print(B) [[1 2] [3 4] [5 6]] 
>>> np.ndim(B) 
2
>>> B.shape 
(3, 2)

[행렬의 곱]

👀코드 보기
#np.dot(A,B)

>>> A = np.array([[1,2], [3,4]]) 
>>> A.shape 
(2, 2) 
>>> B = np.array([[5,6], [7,8]]) 
>>> B.shape 
(2, 2) 
>>> np.dot(A, B) 
array([[19, 22], 
[43, 50]]) 

유의: 행렬의 곱에서는 대응하는 차원수를 일치시켜야 한다
image

[신경망에서의 행렬의 곱]

image


1️⃣ 변수 설명

image

📜 편향 ?
  • 편향: 오른쪽 아래 인덱스가 하나밖에 없음
    • 회색 노드가 편향
    • 앞 층의 편향 뉴런이 하나뿐이기 때문
      image

image

📜 행렬의 곱을 이용하여 단순화

image

image

구현

image


2️⃣ 활성화 함수를 시그모이드 함수로 사용

image -> 은닉층에서의 가중치 합(가중 신호와 편향의 총합)을 a로 표기
-> 활성화 함수 h ( )로 변환된 신호를 z로 표기
-> 활성화 함수를 시그모이드 함수로 사용

👀코드 보기
Z1 = sigmoid(A1) 
print(A1) # [0.3, 0.7, 1.1] 
print(Z1) # [0.57444252, 0.66818777, 0.75026011]

3️⃣ 1층에서 2층으로의 신호 전달

image

👀코드 보기
 W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]]) 
 B2 = np.array([0.1, 0.2])

 print(Z1.shape) # (3,) 
 print(W2.shape) # (3, 2) 
 print(B2.shape) # (2,)

 A2 = np.dot(Z1, W2) + B2
 Z2 = sigmoid(A2)

4️⃣ 2층에서 출력층으로 신호 전달

image

👀코드 보기
  def identity _function(x):
    return x

  W3 = np.array([[0.1, 0.3], [0.2, 0.4]]) 
  B3 = np.array([0.1, 0.2])

  A3 = np.dot(Z2, W3) + B3
  Y = identity _function(A3) # 혹은 Y = A3

[구현 정리]

👀코드 보기
   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]
  • 함수정리
    • init_network ( ) 함수 : 가중치와 편향을 초기화하고 이들을 딕셔너리 변수인 network에
      • Network-> 각 층에 필요한 매개변수(가중치와 편향)를 저장
    • forward ( ) 함수: 입력 신호를 출력으로 변환하는 처리 과정을 모두 구현하고 있음


출력층 설계

위에서 활성화된 입력틍의 값들은 아래의 각 활성화 함수의 종류에 따라 변환된 값을 전달된다.

  • 계단 함수: 그 a값 자체를 0또는 1로 변환한다
  • 시그모이드 함수: 그 a값 자체를 0~1사이로 변환한다
  • ReLU 함수: 그 a값 자체를 전달한다

그럼 활성화 되었다는 전제하에 마지막 출력을 할 때 이 값들을 그냥 그대로 전달을 할까??

물론 그대로 출력을 할 수도 있다.(항등함수 identity function)

하지만 각 결과(y)중 확률을 뽑는 등 출력 전 간단한 상관관계 연산을 해서 출력하면 더 보기 좋지 않을까?
즉 마지막 노드에서 y의 각 a값을 출력층에서 자체가 아닌 다른노드들과 계산하여 필요한 값으로 변환하여 출력할 수 있을까?

있다! 소프트맥스 함수 softmax function를 출력 직전에 넣어주면 된다.

그럼 노드들이 최종 출력 이전에 마지막 노드에서 처리하는 함수인 출력층 함수 2개(항등함수 identity function, 소프트맥스 함수 softmax function)를 알아보자

📜 기계학습의 문제는 분류와 회귀로 나뉨

분류 classification

  • 데이터가 어느 클래스 class 에 속하느냐는 문제
  • 사진 속 인물의 성별을 분류하는 문제
    회귀 regression
  • 입력 데이터에서 (연속적인) 수치를 예측하는 문제
  • 사진 속 인물의 몸무게(57.4kg?)를 예측

항등 함수 identity function

입력을 그대로 출력

image


소프트맥스 함수 softmax function

분류에 사용
그 노드가 나올 확률
image

변수 설명

  • n: 출력층의 뉴런 수,
  • \(y_k\): 그중 k번째 출력임을 뜻함

식 설명

  • 내 클래스의 값/각 클래스의 합
  • 즉, 모든값 합하면 1이 나옴

image

소프트맥스의 출력은 모든 입력 신호로부터 화살표를 받음
➡ 분모에서 보듯, 출력층의 각 뉴런이 모든 입력 신호에서 영향을 받기 때문(다합 해서 1이 되어야 하니까(확률))

👀 구현 코드 보기
>>> a = np.array([0.3, 2.9, 4.0]) 
>>> 
>>> exp _a = np.exp(a) # 지수 함수
>>> print(exp _a) [ 1.34985881 18.17414537 54.59815003] 
>>> 
>>> sum _exp _a = np.sum(exp _a) # 지수 함수의 합
>>> print(sum _exp _a) 74.1221542102
>>> 
>>> y = exp _a / sum _exp _a 
>>> print(y) [ 0.01821127 0.24519181 0.73659691]
👀 사용 함수 코드 보기
def softmax(a): 
 exp _a = np.exp(a) 
 sum _exp _a = np.sum(exp _a) 
 y = exp _a / sum _exp _a

 return y

시그모이드 함수와 차이점 image


소프트맥스 함수 구현 시 주의점

  • 오버플로: 지수 함수란 것이 쉽게 아주 큰 값을 내뱉어 이런 큰 값끼리 나눗셈을 하면 결과 수치가 ‘불안정’해짐

[구현개선]

image

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

[특징]

  • 출력: 0에서 1.0 사이의 실수/출력의 총합은 1
    -> 확률로 계산 가능
  • 주의: 소프트맥스 함수를 적용해도 각 원소의 대소 관계는 변하지X
    지수 함수 y = exp (x )가 단조 증가 함수이기 떄문
    -> 신경망으로 분류할 때는 출력층의 소프트맥스 함수를 생략가능

  • 기계학습의 2단계
    학습: 소프트맥스 함수를 사용
    추론: 소프트맥스 함수를 생략

출력층의 뉴런 수 정하기

예를 들어 입력 이미지를 숫자 0부터 9 중 하나로 분류하는 문제라면 아래 그림 처럼 출력층의 뉴런을 10개로 설정하면 된다.
즉 정답이 될 수 있는 경우의 수가 출력층의 뉴런수가 되는 것이다

image



Deep Learning Share Tweet +1