
신경망의 가장 기본 단위, 퍼셉트론의 작동 원리를 코드로 확인합니다
1편: 퍼셉트론 · 2편: ADALINE과 경사 하강법 · 3편: 확률적 경사 하강법(SGD)
퍼셉트론이 뭔가요?
딥러닝, 신경망 이런 단어가 어렵게 느껴질 수 있지만, 시작점은 의외로 단순합니다. 퍼셉트론(Perceptron)은 1957년 프랭크 로젠블라트가 제안한 알고리즘으로, 인공 신경망의 가장 기본이 되는 단위입니다.
사람의 뇌에 있는 뉴런 하나를 모방한 것이라고 보면 됩니다. 여러 입력을 받아서, 각 입력에 가중치를 곱하고, 다 더한 뒤, 특정 기준(임계값)을 넘으면 1을 출력하고, 넘지 못하면 -1을 출력합니다. 이것이 퍼셉트론의 전부입니다.
퍼셉트론의 작동 원리
퍼셉트론이 판단하는 과정을 수식으로 보면 간단합니다.
1단계 — 가중합(net input) 계산: 각 입력 x에 가중치 w를 곱하고 전부 더합니다. 여기에 편향(bias) w₀를 추가합니다.
2단계 — 활성화 함수 적용: 가중합 결과가 0 이상이면 1, 미만이면 -1을 출력합니다. 이것을 단위 계단 함수(unit step function)라고 합니다.
3단계 — 가중치 업데이트: 예측이 틀렸을 때만 가중치를 조정합니다. 조정량은 (실제값 - 예측값) × 학습률로 계산합니다.
파이썬으로 퍼셉트론 구현하기
이제 코드로 구현해봅니다. 퍼셉트론 클래스는 크게 세 가지 메서드로 구성됩니다.
class Perceptron():
def __init__(self, eta=0.01, n_iter=50, random_state=1):
self.eta = eta # 학습률
self.n_iter = n_iter # 전체 데이터 반복 횟수
self.random_state = random_state
eta는 학습률, n_iter는 전체 데이터셋을 몇 번 반복할지(에포크 수)입니다. random_state는 가중치를 처음에 랜덤으로 설정할 때 쓰는 시드값입니다.
def net_input(self, X):
# 입력 × 가중치의 합 + 편향
return np.dot(X, self.w_[1:]) + self.w_[0]
def predict(self, X):
# 0 이상이면 1, 미만이면 -1
return np.where(self.net_input(X) >= 0.0, 1, -1)
net_input은 입력과 가중치의 내적(dot product)을 계산합니다. w_[0]은 편향(bias)이고, w_[1:]이 실제 특성에 대한 가중치입니다. predict는 가중합이 0 이상인지 판단해서 클래스를 분류합니다.
def fit(self, X, y):
rgen = np.random.RandomState(self.random_state)
# 가중치를 표준편차 0.01의 정규분포에서 랜덤 초기화
self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1])
self.errors_ = []
for _ in range(self.n_iter):
errors = 0
for xi, target in zip(X, y):
# 예측이 틀린 만큼 가중치 조정
update = self.eta * (target - self.predict(xi))
self.w_[1:] += update * xi
self.w_[0] += update
errors += int(update != 0.0)
self.errors_.append(errors)
return self
여기가 핵심입니다. 매 에포크(전체 데이터 1회 순회)마다 샘플 하나씩 꺼내서 예측하고, 틀리면 가중치를 조정합니다. update 값이 0이 아니라는 것은 예측이 틀렸다는 뜻이고, 이걸 누적해서 errors_에 기록합니다. 에포크가 진행될수록 이 오류 횟수가 줄어들면 학습이 잘 되고 있다는 의미입니다.
붓꽃 데이터로 학습시켜 보기
구현한 퍼셉트론을 실제 데이터에 적용해봅니다. 머신러닝에서 가장 유명한 Iris(붓꽃) 데이터셋을 사용합니다.
# setosa(0~49번)와 versicolor(50~99번)만 사용
y = df.iloc[0:100, 4].values
y = np.where(y == 'Iris-setosa', -1, 1)
# 꽃받침 길이(0번 열)와 꽃잎 길이(2번 열)만 추출
X = df.iloc[0:100, [0, 2]].values
150개 데이터 중 앞의 100개(setosa 50개, versicolor 50개)만 사용하고, setosa를 -1, versicolor를 1로 레이블링합니다. 특성은 꽃받침 길이와 꽃잎 길이, 두 가지만 사용합니다. 2차원이어야 나중에 결정 경계를 시각화할 수 있기 때문입니다.
ppn = Perceptron(n_iter=10, eta=0.01)
ppn.fit(X, y)
학습률 0.01, 에포크 10회로 학습합니다. 에포크별 오류 횟수를 그래프로 그려보면 학습 진행 상황을 확인할 수 있습니다.
결정 경계 시각화
학습된 퍼셉트론이 데이터를 어떻게 나누는지 눈으로 확인해봅니다. 결정 경계란 두 클래스를 나누는 선(2차원에서는 직선)을 말합니다.
def plot_decision_regions(X, y, classifier, resolution=0.02):
colors = ['red', 'blue']
cmap = ListedColormap(colors[:len(np.unique(y))])
# 특성 범위에 맞게 격자 생성
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(
np.arange(x1_min, x1_max, resolution),
np.arange(x2_min, x2_max, resolution))
# 격자의 모든 점에 대해 예측 → 영역 색칠
Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
이 함수가 하는 일은 간단합니다. 그래프 영역을 아주 촘촘한 격자로 나눈 뒤, 각 점을 퍼셉트론으로 예측합니다. 예측 결과에 따라 빨간색/파란색으로 칠하면, 두 영역의 경계선이 자연스럽게 결정 경계가 됩니다.
퍼셉트론의 한계와 다음 단계
여기까지 보면 퍼셉트론이 꽤 잘 동작하는 것 같지만, 중요한 한계가 있습니다.
이번 실습에서 setosa와 versicolor가 완벽하게 분류된 이유는, 이 두 품종이 꽃받침/꽃잎 길이 기준으로 깔끔하게 분리되는 데이터이기 때문입니다. 현실 데이터는 이렇게 깔끔하지 않은 경우가 훨씬 많습니다.
이 한계를 극복하기 위해 등장한 것이 ADALINE(Adaptive Linear Neuron)입니다. ADALINE은 가중합에 바로 계단 함수를 적용하는 대신, 연속적인 비용 함수를 사용해서 가중치를 더 안정적으로 업데이트합니다.
1편 핵심 정리
퍼셉트론은 입력의 가중합을 계산하고 임계값으로 분류하는 가장 기본적인 신경망 단위입니다.
학습 과정은 예측이 틀릴 때마다 가중치를 학습률만큼 조정하는 것입니다.
한계는 선형 분리가 가능한 데이터에서만 수렴한다는 점입니다.
다음 편에서는 이 한계를 개선한 ADALINE과 경사 하강법을 다룹니다.
👉 2편: ADALINE이란? 경사 하강법으로 학습하는 신경망 구현하기
학습률에 따라 결과가 완전히 달라지는 이유, 표준화가 왜 중요한지 코드로 확인합니다.
신경망 밑바닥부터 구현하기 시리즈 [1편]
'정보 > IT 지식 정보' 카테고리의 다른 글
| 확률적 경사 하강법(SGD)이란?대규모 데이터를 위한 학습 방법 [3편] (0) | 2026.03.26 |
|---|---|
| ADALINE이란? 경사 하강법으로 학습하는 신경망 구현하기 [2편] (1) | 2026.03.26 |
| 프롬프트 엔지니어링, 왜 지금 배워야 하는가?핵심 개념부터 실전 기법까지 완전 정리 (0) | 2026.03.25 |
| [tmux 정리] 터미널 작업이 편해지는 tmux 기본 명령어 완벽 정리 (0) | 2026.03.12 |
| 네트워크 기본 정리 내용 ( 용어, 내용, 프로로토콜 정리) (0) | 2021.01.19 |
댓글