인공신경망 이해하기
인공신경망(Artificial Neural Network)은 인간의 신경 구조에서 아이디어를 얻어 만든 모델이다. 사람의 신경은 외부 자극을 받아들이고, 그 자극을 전달할지 말지를 판단한 뒤, 다음 신경으로 신호를 넘긴다. 인공신경망도 이와 비슷하게 입력값을 받아 계산하고, 그 결과를 다음 단계로 전달한다.
즉, 인공신경망의 기본 흐름은 다음과 같다.
입력 받기 → 계산하기 → 출력하기
겉으로 보면 복잡해 보이지만, 하나의 인공신경이 하는 일은 비교적 단순하다. 여러 입력을 받아 각각의 중요도를 반영하고, 그 결과를 기준값과 비교한 뒤 출력값을 만들어낸다.
하나의 인공신경은 어떻게 동작하는가
하나의 인공신경은 보통 뉴런(neuron) 또는 노드(node)라고 부른다. 이 노드는 여러 입력값을 받을 수 있다.
예를 들어 어떤 상황을 판단한다고 하자.
친구가 장난을 쳤을 때 “정색할 것인가, 말 것인가”를 결정하는 문제로 비유할 수 있다.
입력값은 다음과 같이 생각할 수 있다.
$$
x_1 = \text{뒤통수를 맞았는가} \\
x_2 = \text{손바닥 하이파이브를 했는가}
$$
각 입력값은 0 또는 1로 표현할 수 있다.
$$
0= \text{해당 자극 없음} \\
1= \text{해당 자극 있음}
$$
그러면 단순하게는 두 값을 더해서 판단할 수 있다.
\( x_1 + x_2 \)
하지만 이렇게 단순히 더하기만 하면 문제가 생긴다.
예를 들어 손바닥 하이파이브는 별일이 아니지만, 뒤통수를 맞는 것은 더 중요한 사건이다. 둘을 같은 중요도로 처리하면 상황을 제대로 판단하기 어렵다.
그래서 필요한 것이 가중치(weight)이다.
Weight: 입력의 중요도를 조절하는 값
가중치는 각 입력이 얼마나 중요한지를 나타내는 값이다.
예를 들어 뒤통수를 맞는 것은 중요도가 크고, 손바닥 하이파이브는 상대적으로 중요도가 작다고 하자.
$$
\begin{aligned}
x_1 &= \text{뒤통수 입력}, \quad w_1 = 10 \\
x_2 &= \text{손바닥 입력}, \quad w_2 = 1
\end{aligned}
$$
그러면 계산은 단순한 덧셈이 아니라 다음과 같이 바뀐다.
\( z = w_1 x_1 + w_2 x_2 \)
즉, 각 입력값에 가중치를 곱한 뒤 더한다.
예를 들어 뒤통수를 맞은 상황이라면, \( x_1 = 1,\; x_2 = 0 \) 이고
계산은 \( z = 10 \times 1 + 1 \times 0 = 10 \) 이렇게 된다.
반대로 단순히 하이파이브만 한 상황이라면, \( x_1 = 0,\; x_2 = 1 \) 이고
계산은 \( z = 10 \times 0 + 1 \times 1 = 1 \) 이렇게 된다.
이렇게 가중치를 사용하면 중요한 입력은 크게 반영하고, 덜 중요한 입력은 작게 반영할 수 있다.
따라서 weight는 단순히 곱해지는 숫자가 아니라, 입력의 중요도를 조절하는 역할을 한다.
Bias: 판단 기준을 조절하는 값
하지만 가중치만으로는 충분하지 않을 수 있다.
어떤 상황에서는 입력값이 조금만 있어도 반응하고, 어떤 상황에서는 꽤 큰 자극이 있어야 반응해야 한다.
이때 필요한 것이 바이어스(bias)이다. Bias는 뉴런의 판단 기준을 조절하는 값이다.
쉽게 말하면 뉴런이 얼마나 민감하게 반응할지를 정하는 값이다.
계산식은 \( z = w_1 x_1 + w_2 x_2 + b \) 이다.
여기서 ( b )가 bias이다.
예를 들어 bias가 음수이면, 뉴런은 더 둔감해진다. 입력값이 어느 정도 커야만 반응하게 된다.
반대로 bias가 양수이면, 뉴런은 더 민감해진다. 작은 입력에도 쉽게 반응할 수 있다.
즉, weight = 각 입력의 중요도이고, bias = 전체 판단 기준이라고 이해하면 된다.
Activation Function: 출력할지 결정하는 함수
가중치를 곱하고 bias를 더하면 하나의 값 ( z )가 나온다. 하지만 신경망은 여기서 끝나지 않는다.
이 ( z ) 값을 그대로 넘길 수도 있지만, 보통은 활성화 함수(activation function)를 통과시킨다.
활성화 함수는 쉽게 말해, 이 신호를 다음으로 전달할 것인가? 를 결정하는 함수이다.
가장 단순한 예시는 Unit Step Function이다.
$$
f(z) =
\begin{cases}
1, & z > 0 \\
0, & z \le 0
\end{cases}
$$
이 함수는 ( z )가 0보다 크면 1을 출력하고, 0 이하이면 0을 출력한다.
즉,
z가 충분히 크다 → 뉴런이 활성화됨 → 1 출력
z가 작거나 음수다 → 뉴런이 비활성화됨 → 0 출력
이라고 볼 수 있다.
하나의 뉴런을 수식으로 정리하면
하나의 인공신경은 \( z = \sum_i w_i x_i + b \) 이라는 과정을 거친다.
그리고 \( y = f(z) \) 값을 활성화 함수에 넣는다.
즉, 전체적으로는 다음과 같다.
\(y = f\left(\sum_i w_i x_i + b\right) \)
이 식이 인공신경 하나의 기본 구조이다.
정리하면 하나의 뉴런은 다음처럼 작동한다.
입력값을 받는다
→ 각 입력에 weight를 곱한다
→ 모두 더한다
→ bias를 더한다
→ activation function을 통과시킨다
→ 출력값을 만든다
여기서 중요한 점은 weight와 bias를 사람이 직접 정하지 않는다는 것이다.
간단한 예시에서는 사람이 “뒤통수는 중요하니까 weight를 크게 주자”라고 정할 수 있다. 하지만 실제 문제는 훨씬 복잡하다.
예를 들어 이미지 분류 문제를 생각해보자.
고양이와 강아지를 구분할 때 어떤 픽셀에 얼마만큼의 weight를 줘야 하는지 사람이 일일이 정하는 것은 불가능하다.
그래서 인공신경망은 데이터를 통해 weight와 bias를 스스로 조정한다.
즉, 딥러닝에서 “학습한다”는 말은 결국 원하는 출력이 나오도록 weight와 bias를 점점 더 좋은 값으로 바꾸는 과정임을 의미한다.
따라서 인공신경망의 학습은 단순히 데이터를 외우는 과정이 아니라, 입력과 출력 사이의 관계를 가장 잘 설명하는 weight와 bias를 찾아가는 과정이라고 볼 수 있다.
여러 뉴런이 모이면 인공신경망이 된다
하나의 뉴런만으로는 복잡한 문제를 해결하기 어렵다.
그래서 여러 개의 뉴런을 연결하여 사용한다.
이렇게 여러 뉴런이 층(layer)을 이루고, 층과 층이 연결된 구조를 인공신경망(Artificial Neural Network)이라고 한다.
인공신경망은 보통 다음과 같은 층으로 구성된다.
Input Layer → Hidden Layer → Output Layer
Input Layer
Input Layer는 데이터를 처음 받아들이는 층이다.
예를 들어 이미지 데이터라면 픽셀값이 입력으로 들어오고, 표 데이터라면 각 컬럼 값이 입력으로 들어온다.
입력층은 보통 계산을 수행한다기보다는, 데이터를 신경망 안으로 전달하는 역할을 한다.
Hidden Layer
Hidden Layer는 입력값을 바탕으로 실제 계산이 이루어지는 층이다.
이 층에서는 각 뉴런이 다음 연산을 수행한다.
weight 곱하기 → 더하기 → bias 더하기 → activation function 통과
Hidden Layer가 여러 층 쌓이면, 신경망은 점점 더 복잡한 패턴을 학습할 수 있다.
예를 들어 이미지 분류에서는 초기 층이 선, 모서리 같은 단순한 특징을 학습하고, 더 깊은 층에서는 눈, 귀, 얼굴 형태 같은 복잡한 특징을 학습할 수 있다.
Output Layer
Output Layer는 최종 결과를 출력하는 층이다.
예를 들어 고양이와 강아지를 분류하는 문제라면, 출력층은 고양이일 확률, 강아지일 확률 또는 이진 분류라면 0 또는 1의 값을 출력할 수도 있다.
결국 인공신경망 전체는 곱하고, 더하고, 활성화하는 같은 연산의 반복이다.
입력값에 weight를 곱한다
→ 모두 더한다
→ bias를 더한다
→ activation function을 통과시킨다
→ 다음 layer로 전달한다
이 과정이 여러 층에서 반복되면서 최종 출력이 만들어진다.
MLP란 무엇인가
여러 층으로 구성된 기본적인 인공신경망을 MLP(Multi-Layer Perceptron)라고 한다.
MLP는 다음과 같은 구조를 가진다.
Input Layer → 하나 이상의 Hidden Layer → Output Layer
여기서 중요한 점은 hidden layer가 최소 한 층 이상 존재해야 한다는 것이다.
입력층과 출력층만 있는 단순한 구조보다, hidden layer가 포함된 구조가 더 복잡한 관계를 학습할 수 있다.
또한 MLP에서는 보통 한 층의 노드들이 다음 층의 노드들과 모두 연결된다. 이런 구조를 Fully Connected Layer라고 한다.
즉, MLP는 여러 개의 fully connected layer로 이루어진 신경망이라고 볼 수 있다.
왜 여러 뉴런이 필요한가
여러 뉴런을 사용하는 이유는 각 뉴런이 서로 다른 특징을 학습할 수 있기 때문이다.
만약 여러 뉴런이 모두 같은 weight를 가진다면, 사실상 같은 계산을 반복하는 것과 다르지 않다. 이 경우 뉴런을 여러 개 둘 필요가 없다.
따라서 여러 뉴런이 의미를 가지려면, 각 뉴런이 서로 다른 weight를 가지고 서로 다른 역할을 수행해야 한다.
예를 들어 이미지 분류에서는 어떤 뉴런은 선의 방향을 감지하고, 어떤 뉴런은 특정 모양을 감지하고, 또 다른 뉴런은 더 복잡한 패턴을 감지할 수 있다.
이처럼 여러 뉴런이 서로 다른 특징을 학습하기 때문에, 신경망은 복잡한 문제를 해결할 수 있다.
앞서 인공신경망은 “입력과 출력을 연결하는 함수”라고 설명했다. 그렇다면 다음 질문이 자연스럽게 등장한다.
해당 함수는 어떻게 찾을까?
회귀(Regression): 입력과 출력의 관계 찾기
딥러닝에서 가장 기본적인 문제는 입력과 출력 사이의 관계를 알아내는 것이다.
이는 회귀(regression)이다.
예를 들어 조회수가 수익으로 이어진다고 해보자(맞는 말이지만).
조회수 -> 수익
1,000 → 1,000원
10,000 → 8,000원
700,000 → 500,000원
위 데이터를 기반으로 우리는 조회수를 입력하면 수익을 예측하는 함수를 찾으려 한다.
가장 단순하게는 다음과 같은 1차 함수로 표현할 수 있다.
$$ y = ax + b $$
여기서 우리의 목표는 a (기울기), b (절편)를 찾는 것이다.
Loss: 함수가 얼마나 틀렸는지 측정하는 기준
그렇다면 어떤 a,ba, b가 “좋은 값”인지 어떻게 판단할까?
이를 위해 사용하는 것이 Loss 함수이다.
Loss는 모델의 예측이 실제 값과 얼마나 다른지를 나타내는 값이라는 의미를 가진다.
예를 들어 어떤 데이터에 대해,
- 실제 값: \( yy
- 모델 예측값: \( y^\hat{y}y^ \)
라고 하면, 오차(error)는 다음과 같다.
\( e = y - \hat{y} \)
이 오차를 모든 데이터에 대해 계산한 뒤, 이를 하나의 값으로 합친 것이 Loss이다.
MSE (Mean Squared Error)
가장 대표적인 Loss 함수는 MSE (Mean Squared Error)이다.
$$
L = \sum_{i=1}^{N} (y_i - \hat{y}_i)^2
$$
이는 1. 실제값과 예측값의 차이를 구하고, 2. 그 값을 제곱한 뒤, 3. 모든 데이터를 더함을 의미한다.
단순히 오차를 더하면 문제가 생긴다.
예를 들어:
+1000 오차
-1000 오차
이렇게 되면 더하면 0이 되어버린다.
이는 잘못된 모델인데도 Loss가 0이 될 수 있음을 의미한다. 이를 방지하기 위해 제곱을 사용한다.
제곱을 사용하면 큰 오차에 더 큰 패널티를 줄 수 있다.
데이터에서 멀리 떨어진 예측을 더 강하게 벌줄 수 있는 것이다.
MAE (Mean Absolute Error)
또 다른 방법으로는 절댓값을 사용하는 방식이 있다.
L = \sum_{i=1}^{N} |y_i - \hat{y}_i|
$$
이 방식은 1. 모든 오차를 동일하게 반영하고, 2. 이상치(outlier)에 덜 민감하다.
Gradient Descent
이렇게 하여 Loss를 최소로 만드는 a,ba, b를 찾는다.
함수 후보 여러개를 찾고, 각각의 loss를 계산하며, 그 중 가장 작은 loss를 가지는 함수를 선택한다.
그러나 문제점이 존재한다.
신경망은 수백, 수천, 수억 개의 파라미터가 있으므로 모든 경우를 직접 계산하는 것은 불가능하다.
이 문제를 해결하기 위해 사용하는 방법이 경사하강법 (Gradient Descent)이다. 이는 현재 위치에서 Loss가 가장 빠르게 줄어드는 방향으로 이동한다는 아이디어를 기반으로 한다.
조금씩 수정 → Loss 감소 → 반복
Gradient는 함수가 가장 빠르게 증가하는 방향을 의미한다.
따라서 우리는 반대로, Gradient의 반대 방향으로 이동하면 된다.
Gradient Descent의 핵심 수식은 다음과 같다.
$$
\theta_{k+1} = \theta_k - \alpha \nabla L(\theta_k)
$$
Learning Rate (학습률)
Gradient는 방향은 정확하지만, 크기는 매우 클 수 있다.
즉, 그대로 이동하면 다음과 같은 문제가 발생한다.
최소값을 지나쳐버리거나, 진동이 발생하거나, 발산 가능하다.
그래서 사용하는 것이 learning rate \( alpha \) 이다.
이 값은 이동 크기를 조절한다. 크면 빠르지만 불안정하고, 작으면 안정적이지만 느리다.
한계: Local Minimum, 계산
하지만 문제도 존재한다.
Gradient Descent는 모든 데이터를 사용해 기울기를 계산하기에 계산량이 많아 매우 느리다.
또한 Gradient Descent는 시작점에서 가장 가까이에 있는 적은 loss를 찾기 때문에 항상 최적(global minimum)을 찾는 것은 아니다.
따라서 gradient descent의 시작점을 '어디로', '어떻게' 잡냐가 중요한 포인트가 되었다.
Weight Initialization
초기 weight를 설정하는 과정을 Weight Initialization이라고 한다.
단순히 아무 값이나 넣는 것이 아니라, weight는 랜덤하게, 0 근처에서 초기화한다.
만약 모든 weight를 동일하게 설정하면 문제가 발생한다.
예를 들어 모든 weight가 0이거나 1이라면 모든 뉴런이 동일한 계산을 수행하므로, 서로 다른 feature를 학습할 수 없다.
이는 신경망이 학습되지 않는다는 것이므로, 반드시 랜덤성이 필요하다.
왜 0 근처인가
weight 값이 너무 크면 문제가 발생한다. actiovation의 출력이 폭발하거나, gradient가 커져서 불안정해지거나, gradient가 0에 가까워져 학습이 진행되지 않는다(vanishing gradient).
따라서 적당히 작은 값으로 초기화해야 한다.
대표적인 Initialization 방법
1. Xavier Initialization
$$
W \sim \mathcal{N}\left(0, \frac{1}{n_{in} + n_{out}}\right)
$$
또는
$$
W \sim \mathcal{U}\left(-\frac{1}{\sqrt{n_{in}}}, \frac{1}{\sqrt{n_{in}}}\right)
$$
특징:
- 입력과 출력 크기 모두 고려
- sigmoid, tanh에서 효과적
2. He (Kaiming) Initialization
$$
W \sim \mathcal{N}\left(0, \frac{2}{n_{in}}\right)
$$
특징:
- ReLU 계열에서 효과적
- 더 큰 분산 사용
3. Lecun Initialization
$$
W \sim \mathcal{N}\left(0, \frac{1}{n_{in}}\right)
$$
특징:
- 비교적 기본적인 방식
- 안정적인 분산 유지
'STUDY > ML DL' 카테고리의 다른 글
| numpy : 배열 연산, 사칙연산, 원소별 곱, 행렬곱 (0) | 2026.05.08 |
|---|---|
| numpy : ndarray, random, randn, rand, shape, dim, size, zeros, ones, arange, linspace (1) | 2026.05.08 |
| SGD와 mini-batch SGD, Momentum과 RMSProp 기반 Adam (0) | 2026.05.08 |
| 강화 학습 Reinforcement Learning (1) | 2026.04.30 |
| 자기지도 학습 Self-supervised Learning, Contrastive Learning (0) | 2026.04.30 |