
💡 1분 핵심 요약 (TL;DR)
- ✅ 로지스틱 회귀 — 합격/불합격처럼 참(1)과 거짓(0) 중 하나를 고르는 문제에서, 직선 대신 S자 곡선을 긋는 방법
- ✅ 시그모이드 함수 — y = 1 / (1 + e−(ax+b)). a는 S자의 경사도, b는 좌우 이동을 정함
- ✅ 교차 엔트로피 오차 — 실제 값이 1이면 −log h, 0이면 −log(1−h). 합치면 −{y log h + (1−y) log(1−h)}
- ✅ 케라스 실습 — Dense(1, activation='sigmoid') + loss='binary_crossentropy'. 7시간 공부 → 합격 확률 약 60%
- ✅ 퍼셉트론 — 입력에 가중치를 곱해 더한 값(가중합)이 기준을 넘으면 1, 아니면 0을 내는 최초의 학습하는 인공 신경망(1957)
- ✅ XOR 문제 — 직선 하나로는 XOR의 0과 1을 나눌 수 없음 → 퍼셉트론의 한계. 다층 퍼셉트론과 오차 역전파로 해결(7주차)
📚 부산디지털대학교 '파이썬 기반의 AI프로그래밍' 6주차 강의노트를 바탕으로 정리한 학습 노트입니다. (출처는 글 하단 참고)
01 로지스틱 회귀란?
1강 · 참과 거짓 중 하나를 고르는 미니 판단 장치
딥러닝 내부에서는 전달받은 정보를 놓고 참과 거짓 중 하나를 판단해 다음 단계로 넘기는 장치들이 쉬지 않고 작동합니다. 딥러닝은 겉으로 드러나지 않는 이런 미니 판단 장치들을 이용해 복잡한 연산을 해낸 끝에 최적의 예측 값을 내놓는 작업입니다. 이 판단 장치의 원리가 바로 로지스틱 회귀(logistic regression)입니다.
직선으로는 안 되는 데이터
3~5주차에서는 공부한 시간과 성적(점수) 사이의 관계를 직선으로 표현했습니다(선형 회귀). 그런데 점수가 아니라 합격과 불합격만 발표되는 시험이라면 어떨까요?
| 공부한 시간 | 2 | 4 | 6 | 8 | 10 | 12 | 14 |
| 합격 여부 | 불합격 | 불합격 | 불합격 | 합격 | 합격 | 합격 | 합격 |
| 좌표 값 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
합격을 1, 불합격을 0으로 놓고 좌표에 찍으면 점들이 0과 1 두 줄에만 모여 있습니다. 이 점들의 특성을 일차 방정식(직선) 하나로 잘 나타낼 수 있을까요?
| ❌ 직선 y = ax + b · 1과 0 사이의 값이 없으므로 직선으로 표현하기 어려움 · 직선은 끝없이 올라가거나 내려가 0보다 작거나 1보다 큰 값도 나옴 |
✅ S자 곡선 · 0 근처에 머물다가 어느 지점에서 1로 올라감 · 점들의 특성을 정확하게 표현 가능 · 값이 항상 0~1 사이 → 확률처럼 읽을 수 있음 |
📖 로지스틱 회귀 (logistic regression)
직선이 아니라, 참(1)과 거짓(0) 사이를 구분하는 S자 형태의 선을 그어 주는 작업

❌ 시험 함정 — 로지스틱 회귀가 쓰이는 문제
로지스틱 회귀는 여러 문제를 예측하는 상황 중에서도 Yes 또는 No처럼 좁은 범위의 선택을 해야 할 때 적용합니다. 참과 거짓 중 하나를 내놓는 과정이며, S자 형태의 시그모이드 함수를 바탕으로 한 오차 공식과 경사 하강법을 이용합니다. 점수처럼 연속적인 값을 예측하는 것은 선형 회귀의 몫입니다.
02 시그모이드 함수
S자 곡선을 만드는 식, a는 경사도 · b는 좌우 이동
S자 형태로 그래프가 그려지는 함수를 시그모이드 함수(sigmoid function)라고 합니다. 1주차 수학에서 미리 만나 본 함수이고, 2주차에서는 출력층의 활성화 함수로도 등장했습니다. 관련 식은 다음과 같습니다.
y = 1 / (1 + e−(ax+b))
아래 코드도 이 식으로 계산
| 값 | 그래프에서 하는 일 | 바뀌면? |
| a | 그래프의 경사도 | a가 커지면 경사가 커지고(가파른 S), a가 작아지면 경사가 작아짐(완만한 S) |
| b | 그래프의 좌우 이동 | b가 크고 작아짐에 따라 그래프가 왼쪽·오른쪽으로 이동 |
직접 계산해 보면 a와 b의 역할이 숫자로 보입니다. 공부 시간 2~14시간에 대해 세 가지 a, b 조합으로 시그모이드 값을 구했습니다.
a와 b를 바꿔 가며 시그모이드 값 구하기
import numpy as np
def sigmoid(z):
return 1 / (1 + np.exp(-z)) # 시그모이드 함수 식
x = np.array([2, 4, 6, 8, 10, 12, 14])
for a, b in [(1, -7), (3, -21), (1, -9)]:
print(f"a={a}, b={b} →", np.round(sigmoid(a * x + b), 3))
▶ 실행 결과 (x = 2 ~ 14)
a=1, b=-7 → [0.007 0.047 0.269 0.731 0.953 0.993 0.999]
a=3, b=-21 → [0. 0. 0.047 0.953 1. 1. 1. ]
a=1, b=-9 → [0.001 0.007 0.047 0.269 0.731 0.953 0.993]
a를 1에서 3으로 키우자 0.047에서 0.953으로 한 번에 확 뛰는 가파른 S자가 되었고, b를 −7에서 −9로 바꾸자 같은 값들이 한 칸(2시간)씩 오른쪽으로 밀렸습니다. 그래프로 그리면 더 분명합니다.
a와 b의 역할을 그래프로 비교하기
import matplotlib.pyplot as plt
xs = np.linspace(0, 14, 200) # 0~14를 200개로 잘게 나눔
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
for a, b in [(0.5, -3.5), (1, -7), (3, -21)]: # 가운데(x=7)는 그대로, a만 바꾸기
ax1.plot(xs, sigmoid(a * xs + b), label=f"a={a}, b={b}")
for a, b in [(1, -5), (1, -7), (1, -9)]: # a는 그대로, b만 바꾸기
ax2.plot(xs, sigmoid(a * xs + b), label=f"a={a}, b={b}")
ax1.set_title("a : slope"); ax2.set_title("b : shift")
ax1.legend(); ax2.legend()
plt.show()
▶ 실행 결과 (그래프 출력)
(왼쪽은 a가 클수록 가파른 S자 3개, 오른쪽은 b에 따라 좌우로 밀린 S자 3개가 나타남 — 아래 그림 1)

📖 심화 — b만 바꿨는데 왜 좌우로 움직일까?
시그모이드 값이 딱 0.5가 되는 곳은 ax + b = 0, 즉 x = −b / a인 지점입니다. a = 1일 때 b = −5이면 x = 5, b = −7이면 x = 7, b = −9이면 x = 9에서 0.5가 됩니다. 그래서 b가 클수록(−5) S자가 왼쪽, 작을수록(−9) 오른쪽으로 갑니다. 강의노트 그래프에서 b 값이 클 때의 곡선이 가장 왼쪽에 있는 것과 같은 결과입니다. 이 0.5 지점이 합격과 불합격을 가르는 경계가 됩니다.
a · b와 오차의 관계
선형 회귀에서 기울기와 오차가 포물선 관계였던 것처럼(4주차), 시그모이드의 a와 b도 오차와 관계가 있습니다. 강의노트 그래프를 정리하면 다음과 같습니다.
| a와 오차 · a가 작을 때(0에 가까워질 때) → S자가 거의 평평해져 오차가 매우 큼 · a가 커질수록 → 0과 1을 또렷이 나눠 오차가 점점 줄어듦 · 그래프 모양 : 오른쪽으로 갈수록 낮아지는 곡선 |
b와 오차 · b가 너무 작거나 너무 크면 → S자가 엉뚱한 곳으로 밀려 오차가 큼 · 적당한 b에서 오차가 가장 작음 · 그래프 모양 : 이차 함수(포물선) |
03 오차 공식 — 교차 엔트로피
실제 값이 1이냐 0이냐에 따라 다른 로그 그래프를 쓴다
로지스틱 회귀도 선형 회귀처럼 경사 하강법으로 a와 b를 찾습니다. 다만 오차를 재는 방법이 다릅니다.
📖 로지스틱 회귀의 경사 하강법 (강의노트 정리)
① 오차를 구한 뒤 오차가 작은 쪽으로 이동시키는 방법 (선형 회귀와 같음)
② 참과 거짓을 판단하기 위해서는 평균 제곱 오차를 사용할 수 없음
③ 시그모이드 함수를 활용
시그모이드의 예측 값 h는 항상 0과 1 사이입니다. 실제 값도 0 아니면 1이므로, 실제 값이 1일 때와 0일 때를 나눠서 오차를 생각합니다. 이때 쓰는 것이
로그
함수입니다.
| 선 | 언제 쓰나 | 식 | 오차가 0인 곳 → 커지는 곳 |
| 파란 선 | 실제 값이 1일 때 | −log h | 예측 값 1에서 오차 0 → 예측 값이 0에 가까울수록 큰 오차 |
| 빨간 선 | 실제 값이 0일 때 | −log(1 − h) | 예측 값 0에서 오차 없음 → 1에 가까워질수록 오차가 매우 커짐 |
두 식을 실제 값 y 하나로 합치면 다음 공식이 됩니다.
−{ y log h + (1 − y) log(1 − h) }
A 부분 = y log h | B 부분 = (1 − y) log(1 − h) | h : 예측 값(시그모이드 출력)
| 실제 값 y | 사라지는 부분 | 남는 식 | 사용하는 그래프 |
| 1 | B 부분 (1 − y = 0) | −log h | 파란 선 |
| 0 | A 부분 (y = 0) | −log(1 − h) | 빨간 선 |
이렇게 실제 값에 따라 빨간 선과 파란 선을 골라 쓰는 공식으로, 평균 제곱 오차를 대신할 손실 함수를 계산할 수 있습니다. 이것이 교차 엔트로피 오차(cross entropy error) 함수이고, 케라스에서는 binary_crossentropy(이진 교차 엔트로피)라는 이름으로 씁니다.
교차 엔트로피와 제곱 오차 비교하기
def cross_entropy(y, h):
return -(y * np.log(h) + (1 - y) * np.log(1 - h))
for y, h in [(1, 0.99), (1, 0.5), (1, 0.01), (0, 0.01), (0, 0.99)]:
print(f"실제 y={y}, 예측 h={h:<4} → 교차 엔트로피 {cross_entropy(y, h):.3f} / 제곱 오차 {(y - h) ** 2:.3f}")
▶ 실행 결과 (예측 값 5가지)
실제 y=1, 예측 h=0.99 → 교차 엔트로피 0.010 / 제곱 오차 0.000
실제 y=1, 예측 h=0.5 → 교차 엔트로피 0.693 / 제곱 오차 0.250
실제 y=1, 예측 h=0.01 → 교차 엔트로피 4.605 / 제곱 오차 0.980
실제 y=0, 예측 h=0.01 → 교차 엔트로피 0.010 / 제곱 오차 0.000
실제 y=0, 예측 h=0.99 → 교차 엔트로피 4.605 / 제곱 오차 0.980
📖 심화 — 완전히 틀렸을 때 벌점이 다르다
실제로는 합격(1)인데 0.01이라고 거의 확실하게 틀린 경우, 제곱 오차는 0.980으로 1을 넘지 못합니다. 교차 엔트로피는 4.605로 훨씬 큽니다. 확신을 갖고 틀릴수록 오차가 급격히 커지므로, 경사 하강법이 크게 틀린 예측을 더 강하게 바로잡게 됩니다. 반대로 거의 맞힌 경우(0.99)에는 두 방법 모두 오차가 0에 가깝습니다.
파란 선과 빨간 선 그리기
h = np.linspace(0.01, 0.99, 100)
plt.plot(h, -np.log(h), 'b', label='y = 1 : -log h')
plt.plot(h, -np.log(1 - h), 'r', label='y = 0 : -log(1-h)')
plt.xlabel('h (prediction)'); plt.ylabel('loss')
plt.legend()
plt.show()
▶ 실행 결과 (그래프 출력)
(예측 값 h에 따라 왼쪽 위로 치솟는 파란 선과 오른쪽 위로 치솟는 빨간 선이 나타남 — 아래 그림 2)

04 로지스틱 회귀 실습
2강 · 케라스로 합격 확률 예측하기
1강의 합격/불합격 데이터를 케라스로 학습시켜 봅니다. 아래는 강의노트 실습 코드 그대로입니다(주석만 조금 정리).
로지스틱 회귀 실습 코드 (강의노트)
#분류 문제를 해결하기 위해 사용되는 통계적 모델
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
x = np.array([2, 4, 6, 8, 10, 12, 14]) #공부 시간
y = np.array([0, 0, 0, 1, 1, 1, 1]) #합격 여부 (0: 불합격, 1: 합격)
model = Sequential()
model.add(Dense(1, input_dim=1, activation='sigmoid'))
model.compile(optimizer='sgd' ,loss='binary_crossentropy')
model.fit(x, y, epochs=5000)
plt.scatter(x, y)
plt.plot(x, model.predict(x),'r')
plt.show()
hour = 7
prediction = model.predict([hour])
print("%.f시간을 공부할 경우, 합격 예상 확률은 %.01f%%입니다" % (hour, prediction * 100))
▶ 실행 결과 (TensorFlow 2.21 · Keras 3.15 / 중간 4,990줄 생략)
.../keras/src/layers/core/dense.py:107: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.
Epoch 1/5000
1/1 ━━━━━━━━━━━━━━━━━━━━ 1s 1s/step - loss: 2.7116
Epoch 2/5000
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 27ms/step - loss: 2.6809
...
Epoch 4999/5000
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 28ms/step - loss: 0.1858
Epoch 5000/5000
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 73ms/step - loss: 0.1858
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 46ms/step
(점 7개와 빨간 예측 곡선이 나타남 — 아래 그림 3)
ValueError: Unrecognized data type: x=[7] (of type <class 'list'>)

loss(교차 엔트로피 오차)가 2.71에서 0.19까지 내려갔고, 빨간 선은 6시간에 약 44%, 8시간에 약 73%로 불합격(0)에서 합격(1) 쪽으로 올라가는 S자를 그립니다. 그런데 마지막 줄에서 오류가 났습니다.
❌ 강의노트 코드를 그대로 쓸 때 주의 — model.predict([hour])
최신 케라스(Keras 3)는 파이썬 리스트 [7]을 입력으로 받지 않아 ValueError: Unrecognized data type 오류가 납니다. 모델은 (데이터 개수, 특성 개수) 모양의 2차원 배열을 기대하므로 np.array([[hour]])처럼 넘겨야 합니다.
또 predict()는 숫자 하나가 아니라 [[0.59…]] 모양의 2차원 배열을 돌려줍니다. 이 배열을 그대로 %.01f에 넣으면 NumPy 버전에 따라 DeprecationWarning 경고(5주차에서 본 경고)가 나거나, 제 실행 환경(NumPy 2.5)처럼 TypeError: only 0-dimensional arrays can be converted to Python scalars 오류가 납니다. prediction[0][0]으로 숫자 하나를 꺼내 쓰면 두 문제가 모두 사라집니다.
✅ 마지막 두 줄 고치기
prediction = model.predict(np.array([[hour]])) # 2차원 배열로 넣기
print("%.f시간을 공부할 경우, 합격 예상 확률은 %.01f%%입니다" % (hour, prediction[0][0] * 100)) # 숫자 하나 꺼내기
▶ 실행 결과 (위 모델에 이어서 실행 · 진행 표시줄 생략)
7시간을 공부할 경우, 합격 예상 확률은 59.6%입니다
| 코드 | 뜻 | 1강 개념과 연결 |
| Dense(1, input_dim=1, activation='sigmoid') | 입력 1개(공부 시간), 출력 뉴런 1개인 완전 연결층, 출력에 시그모이드 적용 | y = 1 / (1 + e−(ax+b)) 가중치 = a, 편향 = b |
| loss='binary_crossentropy' | 이진 교차 엔트로피로 오차 측정 | 03의 −{y log h + (1−y) log(1−h)} |
| optimizer='sgd' | 확률적 경사 하강법 (기본 학습률 0.01) | 오차가 작아지는 쪽으로 a, b 이동 |
| epochs=5000 | 데이터 전체로 5,000번 학습 | 경사 하강 반복 |
| model.predict(x) | 각 공부 시간의 합격 확률(0~1) | 시그모이드 출력 h |
❌ 시험 함정 — 로지스틱 회귀 코드의 빈칸
로지스틱 회귀는 참과 거짓을 내놓는 과정이므로 Dense() 안의 activation은 'sigmoid'로 설정합니다. 그리고 compile() 안의 loss는 'binary_crossentropy'로 설정합니다. 선형 회귀(5주차)의 loss='mse'와 짝을 지어 기억하세요.
✓ 그래프가 매끈한 S자가 아니라 꺾은선처럼 보이는 이유
plt.plot(x, model.predict(x))는 x에 있는 7개 점의 예측값만 직선으로 이었기 때문입니다. np.linspace(2, 14, 100)처럼 촘촘한 x로 predict하면 매끈한 S자가 나옵니다. 또 강의노트 그림보다 완만한 이유는 5,000번 학습 후에도 loss가 계속 줄어드는 중이기 때문입니다. 02에서 본 것처럼 학습이 더 진행되면 a(가중치)가 커지면서 S자가 점점 가팔라집니다. 처음 가중치를 무작위로 정하므로 실행할 때마다 loss와 확률의 끝자리도 조금씩 다릅니다.
덧붙여 model.predict(x, verbose=0)처럼 verbose=0을 주면 예측할 때마다 찍히는 1/1 ━━━━ 진행 표시줄이 나오지 않아 출력이 깔끔해집니다(아래 보충 코드에서 사용).
경고 없이 · 결과가 매번 같게 다시 써 보기
5주차처럼 Input을 맨 앞에 두면 UserWarning이 사라집니다. 시작값(시드)을 고정해 결과를 재현하고, 학습된 가중치와 편향을 꺼내 02의 x = −b / a 경계도 확인해 봅니다.
로지스틱 회귀 — 보충 코드
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Dense
tf.keras.utils.set_random_seed(1) # 실행할 때마다 같은 결과가 나오도록 고정
x = np.array([2, 4, 6, 8, 10, 12, 14])
y = np.array([0, 0, 0, 1, 1, 1, 1])
model = Sequential()
model.add(Input(shape=(1,))) # 입력층 : 특성 1개(공부 시간)
model.add(Dense(1, activation='sigmoid')) # 출력층 : 시그모이드 → 0~1 확률
model.compile(optimizer='sgd', loss='binary_crossentropy')
history = model.fit(x, y, epochs=5000, verbose=0) # 학습 로그 생략
w, b = model.get_weights()
print("마지막 loss :", round(history.history['loss'][-1], 4))
print("가중치 w(a) :", round(float(w[0][0]), 4), " 편향 b :", round(float(b[0]), 4))
print("확률 50% 지점 x = -b/w :", round(float(-b[0] / w[0][0]), 2), "시간")
for hour in [5, 7, 9]:
p = model.predict(np.array([[hour]]), verbose=0)[0][0] # 2차원으로 넣고 숫자 하나 꺼내기
print(f"{hour}시간 공부 → 합격 확률 {p * 100:.1f}%")
▶ 실행 결과 (TensorFlow 2.21 / CPU · 시드 1)
마지막 loss : 0.1893
가중치 w(a) : 0.6116 편향 b : -3.8869
확률 50% 지점 x = -b/w : 6.36 시간
5시간 공부 → 합격 확률 30.4%
7시간 공부 → 합격 확률 59.7%
9시간 공부 → 합격 확률 83.4%
학습된 가중치 0.6116이 시그모이드의 a, 편향 −3.8869가 b입니다. −b / a = 6.36이므로 이 모델은 약 6.4시간을 합격·불합격의 경계(확률 50%)로 판단했습니다. 데이터에서 불합격(6시간)과 합격(8시간) 사이에 경계가 생긴 것입니다.
05 선형 회귀 vs 로지스틱 회귀
무엇을 예측하느냐에 따라 함수와 오차 공식이 바뀐다
| 구분 | 선형 회귀 (3~5주차) | 로지스틱 회귀 (6주차) |
| 예측하는 것 | 연속적인 값 (점수 81, 93 …) | 참(1) 또는 거짓(0) (합격/불합격) |
| 그래프 | 직선 y = ax + b | S자 곡선 y = 1 / (1 + e−(ax+b)) |
| 출력 범위 | 제한 없음 | 0 ~ 1 (확률처럼 읽음) |
| a와 b | a : 기울기 / b : y절편 | a : 경사도 / b : 좌우 이동 |
| 오차 공식 | 평균 제곱 오차(MSE) | 교차 엔트로피 오차 |
| a, b 찾는 방법 | 경사 하강법 | 경사 하강법 |
| 케라스 설정 | activation 기본값(선형) · loss='mse' | activation='sigmoid' · loss='binary_crossentropy' |

✓ 2주차와 연결하기
2주차에서 출력층은 문제 종류에 따라 달라진다고 배웠습니다.
이진 분류는 시그모이드 뉴런 1개, 회귀는 선형 함수를 씁니다. 오늘 만든 로지스틱 회귀 모델이 바로 시그모이드 뉴런 1개짜리 이진 분류 신경망입니다.
06 퍼셉트론
3강 · 뇌의 뉴런을 흉내 낸 최초의 학습하는 신경망
인공지능의 시작 — 뉴런
인간의 뇌는 치밀하게 연결된 뉴런 약 1,000억 개로 이루어져 있습니다(강의노트 기준). 뉴런은 서로 긴밀히 연결되어 신경 말단부터 뇌까지 곳곳에서 자신의 역할을 수행하고, 이 복잡하고 어려운 조합의 결과가 바로 생각입니다.
📖 보충 — 뉴런 수는 약 860억 개
오랫동안 널리 인용된 1,000억 개는 다른 측정값에서 어림한 숫자로, 이를 직접 뒷받침하는 논문이 없었습니다. 2009년 아제베두(Azevedo) 연구팀이 성인 남성의 뇌를 실제로 세어 보니 평균 약 861억 개(±81억)였습니다. 현재는 약 860억 개가 더 정확한 값으로 쓰입니다. 시험은 강의노트 기준(약 1,000억 개)으로 답하세요. (근거: MIT CBMM, How many neurons are there in human brain?, 2023)
| ① 자극 뉴런이 자극을 받음 |
→ | ② 시냅스 화학 물질이 나옴 |
→ | ③ 전위 변화 전기적 상태가 바뀜 |
→ | ④ 판단 임계 값을 넘으면 다음 뉴런에 전달 |

임계 값을 넘지 못하면 신호가 전달되지 않습니다. 입력값을 놓고 활성화 함수에 의해 일정한 수준을 넘으면 참, 그렇지 않으면 거짓을 내보내는 로지스틱 회귀와 꼭 닮았습니다. 그래서 과학자들은 생각했습니다. 뉴런과 비슷한 메커니즘을 쓰면 인공적으로 생각하는 무언가를 만들 수 있지 않을까?
인공 신경망의 탄생
| 1943년 맥컬럭-월터 피츠 신경을 그물망으로 연결하면 뇌처럼 동작할 수 있다 |
→ | 1957년 프랑크 로젠블랫 실제 장치로 구현 → 퍼셉트론 |
→ | 3년 후 아달라인 경사 하강법 도입 최적의 경계선 |
→ | 이후 SVM 등 머신러닝 알고리즘으로 발전 + 시그모이드 → 로지스틱 회귀 |

📖 보충 — 맥컬럭-월터 피츠는 두 사람
강의노트의 맥컬럭-월터 피츠(McCulloch-Walter Pitts)는 한 사람의 이름이 아니라 워런 매컬럭(Warren McCulloch)과 월터 피츠(Walter Pitts) 두 사람입니다. 두 사람이 1943년에 함께 쓴 논문 A Logical Calculus of the Ideas Immanent in Nervous Activity가 켜고 끄는 신경을 그물망으로 연결하는 인공 신경망 아이디어의 출발점입니다. (근거: Wikipedia, A Logical Calculus of the Ideas Immanent in Nervous Activity)
인공 신경망(artificial neural network)은 1943년의 아이디어를 바탕으로, 1957년 프랑크 로젠블랫(Frank Rosenblatt)이 실제 장치로 만든 퍼셉트론(perceptron)에서 본격적으로 시작됩니다. 퍼셉트론은 여러 개의 입력 값을 받아 출력을 만들고, 입력 값의 가중치를 조절할 수 있게 만들어 최초로 학습을 수행했습니다. 3년 후에는 경사 하강법을 도입해 최적의 경계선을 그릴 수 있게 한 아달라인(Adaline)이 개발되었고, 이 흐름은
서포트 벡터 머신
(Support Vector Machine) 같은 머신러닝의 중요한 알고리즘으로 발전했습니다. 시그모이드를 활성화 함수로 사용한 것이 바로 오늘 배운 로지스틱 회귀입니다.
퍼셉트론의 구조
📖 퍼셉트론 (perceptron)
입력 데이터를 받아 처리하고 결과를 출력하는 단순한 알고리즘. 이진 분류 문제를 해결하는 데 사용
| 구성 요소 | 하는 일 |
| 입력층(Input Layer) | 여러 개의 입력 노드로 구성. 각 입력은 하나의 특성(feature)을 표현 |
| 가중치(Weights) | 각 입력 노드에 연결된 값. 입력 신호의 중요도를 표현 |
| 편향(Bias) | 가중치와 함께 더해지는 추가적인 상수 값. 모델의 유연성 조절 |
| 활성화 함수(Activation Function) | 입력의 선형 조합을 비선형적으로 변환하는 함수. 퍼셉트론에서는 주로 계단 함수(step function) 사용 |
📖 가중합 (weighted sum)
입력 값과 가중치를 모두 곱한 후 바이어스(편향)를 더한 값 → w1x1 + w2x2 + b
계단 함수는 가중합이 0보다 크면 1, 아니면 0을 내는 함수입니다. 시그모이드가 0~1 사이를 부드럽게 오가는 S자라면, 계단 함수는 0에서 1로 뚝 끊어 올라가는 계단 모양입니다. 가중치를 직접 정해서 퍼셉트론 하나로 AND와 OR 판단을 해 보겠습니다.
계단 함수 퍼셉트론으로 AND · OR 판단하기
def step(z):
return 1 if z > 0 else 0 # 계단 함수 : 0보다 크면 1, 아니면 0
def perceptron(x1, x2, w1, w2, b):
z = w1 * x1 + w2 * x2 + b # 가중합
return step(z)
for x1, x2 in [(0, 0), (0, 1), (1, 0), (1, 1)]:
print(f"x1={x1}, x2={x2} → AND {perceptron(x1, x2, 0.5, 0.5, -0.7)}, OR {perceptron(x1, x2, 0.5, 0.5, -0.2)}")
▶ 실행 결과 (w1 = w2 = 0.5, AND는 b = −0.7 · OR는 b = −0.2)
x1=0, x2=0 → AND 0, OR 0
x1=0, x2=1 → AND 0, OR 1
x1=1, x2=0 → AND 0, OR 1
x1=1, x2=1 → AND 1, OR 1
가중치는 같고 편향만 바꿨을 뿐인데 AND와 OR가 모두 만들어졌습니다. 둘 다 1이어야 가중합 0.5 + 0.5 − 0.7 = 0.3이 0을 넘으면 AND, 하나만 1이어도 0.5 − 0.2 = 0.3이 0을 넘으면 OR입니다.
퍼셉트론 · 아달라인 · 로지스틱 회귀 비교
| 구분 | 퍼셉트론 | 아달라인 | 로지스틱 회귀 |
| 계산 흐름 (강의노트 그림) |
가중합 → 참? 거짓? | 가중합 → 경사 하강법 → 참? 거짓? | 가중합 → 경사 하강법 → 시그모이드 → 참? 거짓? |
| 경계선 | 조건을 만족하는 선이 여러 개 존재 | 경사 하강법으로 최적의 경계선 | S자 곡선으로 확률 출력 |
| 가중치를 고칠 때 쓰는 값 |
계단 함수를 거친 출력 (0 또는 1) | 계단 함수를 거치기 전의 가중합 (연속적인 값) | 시그모이드를 거친 출력 (0~1 확률) |
| 특징 | 최초로 가중치를 조절해 학습 | 선형 회귀와 비슷한 방식, 연속적인 값 예측에 사용 (강의노트) | 시그모이드를 활성화 함수로 사용 |
📖 보충 — 아달라인도 결국은 참·거짓을 가르는 분류기
강의노트는 아달라인을 선형 회귀와 비슷하게 연속적인 값 예측에 사용한다고 설명합니다. 정확히는 학습할 때만 연속적인 값을 씁니다. 1960년 버나드 위드로(Bernard Widrow)와 마션 호프(Marcian Hoff)가 만든 아달라인은, 계단 함수를 거치기 전의 가중합(연속적인 값)과 정답의 차이를 제곱 오차로 재고 경사 하강법으로 가중치를 고칩니다. 퍼셉트론이 계단 함수를 거친 후의 0·1 출력으로 가중치를 고치는 것과 다른 점입니다. 그리고 최종 판단에서는 가중합을 계단 함수에 넣어 참(1)과 거짓(0)을 판별합니다. 즉 아달라인은 연속적인 오차로 학습하는 분류기이고, 이 방식이 오늘의 경사 하강법 학습으로 이어졌습니다. (근거: Wikipedia, ADALINE)
퍼셉트론이 완성되고 아달라인이 보완하자, 다양한 문제를 해결하는 인공지능이 곧 개발될 것이라는 기대가 커졌습니다. 그러나 퍼셉트론에는 한계가 있었습니다.
07 XOR 문제 — 퍼셉트론의 한계
직선 하나로는 나눌 수 없는 문제
⚠️ 질문
직선의 한쪽 편에는 검은 점만, 다른 한쪽에는 흰 점만 있도록 선을 그을 수 있을까요? 네 점이 검은 점-흰 점-검은 점-흰 점처럼 대각선으로 엇갈려 있으면, 직선을 어떻게 그어도 한쪽에 두 색이 섞입니다.
이 질문을 컴퓨터 논리 회로로 옮긴 것이 AND, OR, XOR입니다. 입력 x1, x2의 네 가지 경우에 대한 결과를
진리표
로 정리하면 다음과 같습니다.
| x1 | x2 | AND (논리곱) 두 개 모두 1일 때 1 |
OR (논리합) 둘 중 하나라도 1이면 1 |
XOR (배타적 논리합) 하나만 1이어야 1 |
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
퍼셉트론이 스스로 가중치를 고치며 세 문제를 학습하게 해 보겠습니다. 예측이 틀리면 틀린 만큼 가중치와 편향을 조금씩 고치는 퍼셉트론 학습 규칙을 20번 반복합니다.
퍼셉트론에게 AND · OR · XOR 학습시키기
def train_perceptron(X, y, lr=0.1, epochs=20):
w = np.zeros(2); b = 0.0
for _ in range(epochs):
for xi, target in zip(X, y):
pred = 1 if np.dot(w, xi) + b > 0 else 0
w += lr * (target - pred) * xi # 틀린 만큼 가중치 수정
b += lr * (target - pred)
return w, b
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
gates = {"AND": [0, 0, 0, 1], "OR": [0, 1, 1, 1], "XOR": [0, 1, 1, 0]}
for name, y in gates.items():
w, b = train_perceptron(X, np.array(y))
pred = [1 if np.dot(w, xi) + b > 0 else 0 for xi in X]
acc = np.mean(np.array(pred) == np.array(y)) * 100
print(f"{name:3} : 정답 {y} / 예측 {pred} / 정확도 {acc:.0f}%")
print(" w =", np.round(w, 2), " b =", round(b, 2))
▶ 실행 결과 (학습률 0.1, 20번 반복)
AND : 정답 [0, 0, 0, 1] / 예측 [0, 0, 0, 1] / 정확도 100%
w = [0.2 0.1] b = -0.2
OR : 정답 [0, 1, 1, 1] / 예측 [0, 1, 1, 1] / 정확도 100%
w = [0.1 0.1] b = 0.0
XOR : 정답 [0, 1, 1, 0] / 예측 [1, 1, 0, 0] / 정확도 50%
w = [-0.1 0. ] b = 0.1
AND와 OR는 100% 맞혔지만 XOR는 50%에 그쳤습니다. 반복 횟수를 늘려도 마찬가지입니다. 직선 하나(w1x1 + w2x2 + b = 0)로 나눌 수 없는 문제는 아무리 가중치를 고쳐도 풀 수 없기 때문입니다. 네 점을 좌표 평면에 그려 보면 이유가 보입니다.
AND · OR · XOR를 좌표 평면에 그리기
import matplotlib.pyplot as plt
lines = {"AND": (0.5, 0.5, -0.7), "OR": (0.5, 0.5, -0.2)} # 06에서 쓴 w1, w2, b
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
for ax, (name, y) in zip(axes, gates.items()):
y = np.array(y)
ax.scatter(X[y == 1, 0], X[y == 1, 1], c='black', s=150) # 결과 1 : 검은 점
ax.scatter(X[y == 0, 0], X[y == 0, 1], c='white', edgecolors='black', s=150) # 결과 0 : 흰 점
if name in lines:
w1, w2, b = lines[name]
xs = np.linspace(-0.5, 1.5, 10)
ax.plot(xs, -(w1 * xs + b) / w2, 'r') # w1*x1 + w2*x2 + b = 0 인 경계선
else:
ax.text(0.5, 0.5, '?', fontsize=30, ha='center', va='center')
ax.set_title(name)
ax.set_xlim(-0.5, 1.5); ax.set_ylim(-0.5, 1.5)
plt.show()
▶ 실행 결과 (그래프 출력)
(AND와 OR는 빨간 직선 하나로 검은 점과 흰 점이 나뉘고, XOR는 대각선으로 엇갈린 점 사이에 물음표가 나타남 — 아래 그림 4)

| ✅ AND · OR · 검은 점과 흰 점을 직선 하나로 나눌 수 있음 · 퍼셉트론 하나로 해결 |
❌ XOR · 같은 색 점이 대각선으로 마주 봄 · 어떤 직선으로도 색이 같은 점끼리 나눌 수 없음 · 퍼셉트론 하나로는 해결 불가 |
📖 XOR 문제는 어떻게 풀었나? (7주차 예고)
선을 하나가 아니라 여러 개 쓰면 됩니다. 퍼셉트론을 여러 층으로 쌓은 다층 퍼셉트론(multilayer perceptron)과, 출력의 오차를 거꾸로 전달하며 각 층의 가중치를 고치는
오차 역전파
(back propagation)로 해결했습니다. 다음 주 주제인 7. 다층 퍼셉트론에서 자세히 다룹니다.

📖 심화 — XOR 문제가 남긴 충격
퍼셉트론의 이 한계를 널리 알린 것은 마빈 민스키(Marvin Minsky)와 시모어 페퍼트(Seymour Papert)가 1969년에 펴낸 책 Perceptrons입니다. 책은 퍼셉트론이 XOR(배타적 논리합) 같은 일부 논리 문제를 풀지 못한다는 점을 지적했고, 이 비판은 인공지능 연구에 큰 영향을 주어 한동안 신경망이 인기 없는 분야가 되었습니다. (근거: Lehigh University Libraries, Perceptrons; an Introduction to Computational Geometry)
❌ 시험 함정 — XOR는 선 하나로 나눌 수 없다
XOR 문제는 진리표대로 좌표 평면에 점을 찍었을 때 선을 그어 색이 같은 점끼리 나누기가 불가능한 문제입니다. 나누기가 가능하다고 하면 틀립니다. AND와 OR는 선 하나로 나눌 수 있지만 XOR는 안 된다는 점, 그리고 해결책이 다층 퍼셉트론과 오차 역전파라는 점을 함께 기억하세요.
08 핵심 정리
시험 직전에 이것만은 꼭
📌 핵심 정리
· 로지스틱 회귀 : 참(1)과 거짓(0) 사이를 구분하는 S자 형태의 선을 그어 주는 작업. Yes/No처럼 좁은 범위의 선택에 적용
· 시그모이드 함수 : S자 그래프 함수. y = 1 / (1 + e−(ax+b)) (강의노트는 1 − e로 오기). a = 경사도(클수록 가파름), b = 좌우 이동
· a·b와 오차 : a가 작을수록(0에 가까울수록) 오차 큼 / b는 너무 작거나 크면 오차 큼(이차 함수 모양)
· 오차 공식 : 참과 거짓 판단에는 평균 제곱 오차 대신 교차 엔트로피 오차. 실제 1 → −log h(파란 선), 실제 0 → −log(1−h)(빨간 선), 합치면 −{y log h + (1−y) log(1−h)}
· 케라스 실습 : Dense(1, input_dim=1, activation='sigmoid') + compile(loss='binary_crossentropy'). 최신 케라스에서는 predict(np.array([[hour]]))로 넣기
· 퍼셉트론 : 여러 입력에 가중치를 곱해 더한 가중합을 계단 함수로 판단. 가중치를 조절해 최초로 학습 수행 (1957, 로젠블랫)
· 구조 : 입력층(feature) · 가중치(중요도) · 편향(유연성) · 활성화 함수(주로 계단 함수)
· 아달라인 : 경사 하강법 도입, 최적의 경계선. 선형 회귀와 비슷, 연속적인 값 예측(강의노트) → 정확히는 학습은 계단 함수 전의 가중합(연속값)으로, 최종 판단은 계단 함수로 하는 분류기
· XOR 문제 : 진리표대로 좌표에 찍으면 선 하나로 같은 색 점끼리 나눌 수 없음 → 다층 퍼셉트론 + 오차 역전파로 해결

태그 : 로지스틱 회귀란시그모이드 함수 공식선형 회귀 로지스틱 회귀 차이교차 엔트로피 오차케라스 binary_crossentropy로지스틱 회귀 파이썬 예제퍼셉트론이란퍼셉트론 아달라인 차이XOR 문제란계단 함수 활성화 함수
출처 : 이 글은 부산디지털대학교(BDU)의 '파이썬 기반의 AI프로그래밍' 과목 2026년도 강의노트를 참고하여 학습용으로 작성한 글입니다.
보충 자료 (📖 보충·심화 박스의 근거)
· 시그모이드 함수의 표준 식 : Mathwords, Sigmoid Function — Definition, Formula & Graph
· 사람 뇌의 뉴런 수 : MIT CBMM (2023.5.2), How many neurons are there in human brain?, #TeachMeSomething
· 매컬럭과 피츠의 1943년 논문 : Wikipedia, A Logical Calculus of the Ideas Immanent in Nervous Activity
· 아달라인의 학습 방식 : Wikipedia, ADALINE
· 민스키와 페퍼트의 Perceptrons(1969) : Lehigh University Libraries, Perceptrons; an Introduction to Computational Geometry
'학과 수업 노트 > 파이썬 기반의 AI 프로그래밍' 카테고리의 다른 글
| 5. 회귀 모델 - 경사 하강법 실습, 다중 선형 회귀, 텐서블로 기반 (0) | 2026.10.04 |
|---|---|
| 4. 예측선 - 평균 제곱 오차, 실습 코드 분석, 오차를 줄이는 방법 (0) | 2026.10.02 |
| 3. 훌륭한 예측선 - 예측선과 선형회귀, 최소제곱법, 실습 코드 분 (1) | 2026.10.02 |
| 2. 실습 환경 구축 및 분석 - Colab 활용, Git, 딥러닝 계층 구조 (0) | 2026.10.02 |
| 1. 인공지능 - 인공지능 개념, 머신러닝, 딥러닝, 기초 수학 (0) | 2026.10.02 |













