라구넹 2025. 6. 7. 22:41

신경망: 퍼셉트론을 다층으로 쌓고 활성화함수를 개선한 것

가장 왼쪽 층을 입력층, 맨 오른쪽 층을 출력층, 중간 층들을 은닉층이라 함

- 은닉충의 뉴런은 사람 눈에 보이지 않음

 

활성화 함수

- 입력 신호의 총합을 출력 신호로 변환하는 함수를 일반적으로 활성화 함수(activation function)라 함

- 활성화라는 이름이 말해주듯 입력 신호의 총합이 활성화를 일으키는지 정하는 역할

가중치가 달린 입력 신호와 편향의 총합을 계산, 이를 a라 함

a를 함수 h()에 넣어 y를 출력하는 흐름

 

1. 시그모이드 함수

신경망에서는 활성화 함수로 시그모이드 함수를 이용하여 그 변환된 신호를 다음 뉴런에 전달

* 시그모이드: S자 형태라는 의미

-> 앞 장의 퍼셉트론은 계단 함수, 신경망은 시그모이드 등의 다른 비선형 함수 사용

 

계단 함수 구현하기

def step_function(x):
  if x > 0:
    return 1
  else:
    return 0
import numpy as np

def step_function(x):
  y = x > 0 #여기까진 불리언이라 인트로 바꿔줘야 함
  return y.astype(np.int)

 

import numpy as np
import matplotlib.pylab as plt

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

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()

 

 

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()

시그모이드 함수

* 브로드캐스트: 넘파이 배열과 스칼라값의 연산을 넘파이 배열의 원소 각각과 스칼라값의 연산으로 바꿔 수행하는 기능

 

시그모이드 vs 계단 함수
- 둘 다 입력이 중요하면 큰 값, 입력이 중요하지 않으면 작은 값을 출력함

- 시그모이드 함수는 부드러운 곡선. 입력에 따라 출력이 연속적으로 변화

- 계단 함수는 0을 경계로 출력이 갑자기 바뀜

- 시그모이드 함수의 매끈함 -> 신경망 학습에서 중요한 역할 (역전파 가능)

 

 

비선형 함수

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

- 출력이 입력의 상수배만큼 변하는 함수 -> 선형 함수

- 수식: f(x) = ax + b      * a, b는 상수

- 선형 함수는 곧은 1개의 직선

- 비선형 함수는 직선 1개로는 그릴 수 없는 함수

 

신경망에서는 활성화 함수로 비선형 함수를 사용해야 함

선형 함수를 쓰면 신경망의 층을 깊게 하는 의미가 없음

- h(x) = cx이면 h(h(h(x))) 는 c*c*c*x 인데 입력에 그냥 h(c^2x) 한 거랑 무슨 차이

 

 

2. ReLU (Rectified Linear Unit) 함수

- 최근엔 신경망에 ReLU를 주로 사용 (역전파 시 기울기 소실 문제 완화)

def relu(x):
  return np.maximum(0, x)

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

입력이 0을 넘으면 그대로 출력, 0 이하이면 0을 출력

* maximum은 두 입력 중 큰 거 고르는 거


 

다차원 배열의 계산

행렬 곱시 대응하는 차원의 수를 일치시키기

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

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

np.dot(A, B)

 

신경망에서의 행렬곱

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

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

 

 

3층 신경망 구현하기

표기법

가중치와 은닉층 뉴런의 오른 쪽 위에 (1)이 있음

이는 1층의 가중치, 1층의 뉴런임을 뜻함

 

하단의 왼쪽 번호: 다음 층 뉴런의 인덱스 번호

하단의 오른쪽 번호: 앞 측 뉴런의 인덱스 번호

* 모든 경우에서 이 규칙을 쓰는 거 아님.

 

1. 입력층 -> 1층

import numpy as np

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

print(W1.shape)
print(X.shape)
print(B1.shape)

A1 = np.dot(X, W1) + B1
A1

 

 

 

Z1 = sigmoid(A1)
Z1

1층의 활성화 함수

 

 

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)
print(W2.shape)
print(B2.shape)

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


1층에서 2층으로 신호 전달

 

def indentuty_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 = indentuty_function(A3)
Y

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

 

 

출력층 설계하기

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

- 회귀: 항등함수

- 클래스 분류: 시그모이드

- 다중 클래스 분류: 소프트맥스

가 일반적임

 

* 분류: 데이터가 어느 클래스에 속하느냐

* 회귀: 입력 데이터에서 연속적인 수치를 예측하는 문제

 

 

소프트맥스 함수 구현

n은 출력층의 뉴런 수, yk는 그 중 k 번째 뉴런임을 뜻함

분자는 입력신호의 지수 함수, 분모는 모든 입력 신호의 지수 함수의 합

 

식을 제대로 표현하고 있지만, 오버플로우 생김

a = np.array([1010, 1000, 990])
np.exp(a) / np.sum(np.exp(a))

 

 

지수 함수 계산 시 어떤 정수를 더하거나 곱해도 결과는 바뀌지 않음

오버플로우를 막기 위해 입력 신호 중 최대값 이용

 

c = np.max(a)
np.exp(a - c) / np.sum(np.exp(a - c))

 

 

소프트 맥스 함수의 특징

- 출력의 총합 -> 1

- 소프트맥스 함수 출력을 확률로 해석 가능

- 확률적인 결론도 낼 수 있다

 

 

출력 층의 뉴런 수

- 푸려는 문제에 적절히.

- 분류 문제면 분류하고 싶은 클래스 수