이번 포스트에서는 선형회귀와 로지스틱 회귀에 대해 알아보려 한다.
지도학습 중 분류와 회귀에 해당하는 내용을 먼저 리마인드하자면,
이다.
선형 회귀는 독립 변수 X를 사용해 종속 변수 y(연속값)를 예측하는 회귀 알고리즘이다.
독립 변수와 종속 변수 사이의 관계를 직선(선형 함수) 으로 가정한다.
출력: 실수 전체 범위( −∞ ~ ∞)
예측 대상: 연속값
수식:
y = w x + b
(다변수의 경우: y = wᵀx + b)
즉,
x가 변할 때 y가 어떻게 변하는지를 하나의 직선으로 가장 잘 설명하는 것이 목표다.
단순 선형 회귀 (Simple Linear Regression)
독립 변수 1개
예: MinTemp → MaxTemp
다중 선형 회귀 (Multiple Linear Regression)
독립 변수 여러 개
예: 기온, 습도, 풍속 → 전력 사용량
선형 회귀는 예측값과 실제값의 차이를 최소화한다.
이를 수치화한 것이 평균제곱오차(MSE) 이다.
MSE = (1/n) Σ (yᵢ − ŷᵢ)²
의미:
제곱을 사용하는 이유:
1. 오차의 부호 제거 (+/− 상쇄 방지)
2. 큰 오차에 더 큰 패널티
3. 미분 가능 → 학습(최적화)에 유리
경사하강법은 손실 함수(MSE)가 최소가 되도록 가중치 w, b를 반복적으로 업데이트하는 최적화 알고리즘이다.
선형 회귀의 목표는 아주 명확하다.
예측값과 실제값의 차이가 가장 작아지도록
가중치(θ)를 찾는 것
선형 회귀 모델은 다음과 같이 표현된다.
ŷ = θ₀ + θ₁x₁ + θ₂x₂ + … + θₙxₙ
(벡터 형태: ŷ = θᵀx)
그렇다면 “가장 잘 맞는다”는 것을 어떻게 수치로 표현할까?
-> Cost function(손실 함수) 가 필요하다.
선형 회귀에서 가장 대표적인 cost function은 다음 두 가지다.
수식으로 쓰면:
의미:
-> 학습이란, 이 cost function 값을 최소로 만드는 θ를 찾는 과정이다.
Cost function을 3차원으로 그려보면,
θ 공간 위에 그릇 모양(convex) 곡면이 만들어진다.
따라서 우리는 기울기 방향이 아닌 기울기의 반대 방향으로 이동
이 아이디어가 바로 경사하강법이다.
경사하강법의 기본 업데이트 식은 다음과 같다.
의미를 풀면:
“현재 위치에서 cost를 가장 빠르게 줄이는 방향으로
learning rate만큼 가중치를 업데이트한다”
수식 예시 (SSE 기준):
-> Batch learning에 해당
수식 개념:
-> Online learning에 해당
-> “gradient descent”라고 하면 대부분 mini-batch gradient descent를 의미
| 방식 | 사용 데이터 | 안정성 | 속도 |
|---|---|---|---|
| Batch GD | 전체 데이터 | 매우 안정적 | 느림 |
| SGD | 1개 샘플 | 불안정 | 매우 빠름 |
| Mini-batch GD | 일부 샘플 | 균형 | 빠름 |
Learning rate는
“한 번에 얼마나 크게 이동할지” 를 결정한다.
η = 0.1, 0.01, 0.001 …
ηₜ = η₀ / (1 + k·t)
ηₜ = η₀ · e^(−k·t)
결론적으로,
선형 회귀의 학습이란 MSE로 오차를 정의하고,
경사하강법으로 그 오차를 줄여가는 과정이다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metrics
dataset = pd.read_csv('../chap3/data/weather.csv')
dataset.plot(x='MinTemp', y='MaxTemp', style='o')
plt.title('MinTemp vs MaxTemp')
plt.xlabel('MinTemp')
plt.ylabel('MaxTemp')
plt.show()

→ MinTemp와 MaxTemp 사이에 대략적인 선형 관계 확인
# 독립변수/ 종속변수 설정
X = dataset['MinTemp'].values.reshape(-1, 1)
y = dataset['MaxTemp'].values.reshape(-1, 1)
# 학습 / 검증 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2
)
# 모델 생성 및 학습
regressor = LinearRegression()
regressor.fit(X_train, y_train)
# 예측 수행
y_pred = regressor.predict(X_test)

# 결과 비교
# Actual 값과 Predicted 값을 나란히 비교하여 예측 성능을 확인한다.
# 회귀선 시각화
plt.scatter(X_test, y_test, color='gray')
plt.plot(X_test, y_pred, color='red', linewidth=2)
plt.show()

평균제곱오차(MSE)와 루트 평균제곱오차(RMSE)를 사용해 모델을 평가한다.
print('평균제곱법(MSE):', metrics.mean_squared_error(y_test, y_pred))
print('루트 평균제곱법(RMSE):',
np.sqrt(metrics.mean_squared_error(y_test, y_pred)))


RMSE는 원래 y와 같은 단위를 가지므로 해석이 직관적이다.
예를 들어 RMSE ≈ 4.12라면, 평균적으로 약 4도 정도의 오차로 예측하고 있다는 의미다.
선형 회귀의 한계:
로지스틱 회귀(Logistic Regression)는 분석 대상이 두 집단(또는 그 이상)의 범주로 나뉘는 경우, 각 관측치가 어느 집단에 속할 확률을 추정하고 이를 바탕으로 분류를 수행하기 위해 사용되는 통계적 기법이다.
즉,
이 점에서 로지스틱 회귀는 이름과 달리 분류(Classification) 문제를 다룬다.
| 구분 | 일반적인 회귀 분석 | 로지스틱 회귀 분석 |
|---|---|---|
| 종속 변수 | 연속형 변수 | 이산형 변수 (0/1) |
| 목적 | 값 예측 | 범주 분류 |
| 모형 추정 | 최소제곱법 | 최대우도법 |
| 모형 검정 | t-test, F-test | χ²-test |
핵심 차이는 종속 변수의 형태와 모형을 학습하는 기준(손실 함수) 에 있다.
우도(likelihood)는 주어진 결과(Y)가 나타났을 때, 그 결과를 가장 잘 설명하는 가설(모델 파라미터)이 얼마나 그럴듯한지를 나타내는 척도이다.
중요한 관점 전환:
최대우도법은 다음과 같이 정의된다.
즉,
입력 X와 결과 Y가 주어졌을 때
Y가 실제로 관측될 확률을 최대화하는 θ를 찾는 것
관측치들이 서로 독립이라고 가정하면,
전체 우도는 각 샘플 우도의 곱으로 표현된다.
곱셈은 계산이 불안정하므로 로그를 취한다.
-> 이 식이 로지스틱 회귀의 학습 목표이다.
로지스틱 회귀는 선형 결합을 그대로 사용하되,
출력을 시그모이드 함수(sigmoid) 로 변환한다.
시그모이드 함수:
확률 모델:
로지스틱 회귀 분석은 다음 두 단계로 진행된다.
예시:
이 기준은 문제에 따라 조정 가능하다.
이번 예제에서는 사이킷런(sklearn)에서 제공하는 digits 숫자 데이터셋을 사용하여
로지스틱 회귀 모델을 학습하고, 예측 및 성능 평가까지 진행한다.
digits 데이터셋은 0~9까지의 숫자를 손글씨 이미지로 표현한 데이터셋이다.
각 이미지는 8×8 크기의 흑백 이미지이며, 이를 펼쳐서 64차원 벡터로 저장한다.
%matplotlib inline
from sklearn.datasets import load_digits
digits = load_digits() # 사이킷런에서 제공하는 숫자 데이터셋 로드
print("Image Data Shape:", digits.data.shape)
print("Label Data Shape:", digits.target.shape)

import numpy as np
import matplotlib.pyplot as plt
plt.figure(figsize=(20, 4))
for index, (image, label) in enumerate(zip(digits.data[:5], digits.target[:5])):
plt.subplot(1, 5, index + 1)
plt.imshow(np.reshape(image, (8, 8)), cmap=plt.cm.gray)
plt.title('Training: %i\n' % label, fontsize=20)
plt.show()

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
digits.data,
digits.target,
test_size=0.25,
random_state=0
)
from sklearn.linear_model import LogisticRegression
logisticRegr = LogisticRegression()
logisticRegr.fit(X_train, y_train)
logisticRegr.predict(X_test[0].reshape(1, -1))
logisticRegr.predict(X_test[0:10])

-> 10개의 이미지 데이터를 사용한 로지스틱회귀 모델에 대한 예측결과 출력
predictions = logisticRegr.predict(X_test)
score = logisticRegr.score(X_test, y_test)
print(score)

-> 전체 데이터를 사용한 로지스틱회귀 모델에 대한 예측결과 출력 (성능 95%)
즉
선형 회귀는 값을 예측
로지스틱 회귀는 확률을 예측해 분류