강의자료 : [통계] 데이터 분석을 위한 통계학 입문 5
실습자료 : 선형회귀.ipynb - Colab
공부자료 : 통게학 세션_5회차.ipynb - Colab
이때까지 배웠던 모델들을 에제를 통해 복습하고 선형회귀에 대해 배웠습니다.
자유도
데이터를 분석하거나 모델링할 때 얼마나 많은 독립적인 정보가 있는지를 나타냄
각 행의 합과 각 열의 합이라는 제약 조건들이 있기 때문
데이터 타입별 모델
- 범주형 - 범주형 : 카이제곱 검정
- 범주형 - 수치형 : 아노바, t 검정
- 수치형 - 범주형 : 로지스틱(이진 분류)
- 수치형 - 수치형 : 선형회귀
예제
1. 제품의 생산 온도가 높아질수록 제품의 길이가 일정한 비율로 변화한다
=> 선형 회귀 (수치형-수치형)
2. 특정 불량 유형은 작업조 혹은 기계 라인에 따라 발생 빈도에 차이가 있는가
=> 아노바(범주형-수치형)
귀무 가설 : 서로 독립적이다
대립가설 : 독립적이지 않다
-> p-value 값 사용
3. 공장 습도나 온도 등의 환경 조건이 제품 불량(합격/불합격) 발생 확률에 유의미한 영향을 미치는가
=>로지스틱 회귀(분류)
수치형-범주형
합격/불합격을 0과1로 할 수 있음
4. 세 가지 다른 작업자 교육 프로그램에 따라 생산 속도(또는 공정 시간)가 유의미하게 차이가 있는가
=>아노바분석(범주형-수치형)
5. 설비 가동 시간(기계 마모도)이 증가함에 따라 생산된 부품의 치수가 변동된다
=>선형회귀(수치형-수치형
6. 제품 불량 카테고리(A,B,C)와 생산되는 지역 (공장 A,B,C )이 서로 연관성이 있는가
=>카이제곱(범주형-범주형)
7. 작업자 숙련도 점수가 높아질수록 불량 발생 확률이 낮아지는가
=>확률이 0/1이면 로지스틱(수치형-범주형)
=>확률로 주어지면 선형회귀(수치형-수치형)
예제를 보고 어떤 모델을 써야할지 아직은 바로 떠오르지 않고 헷갈린다...
선형 회귀
- 독립 변수 (X) 가 종속 변수 (Y) 에 미치는 영향을 직선 (혹은 초평면) 형태로 모델링하는 기법

- 예측을 위해 회귀선을 그음
- 단순회귀
- 독립 변수가 1개인 경우

- 다중회귀
- 독립 변수가 2개 이상인 경우

주요 가정 (전제 조건)
선형회귀 분석을 사용하기 위해 충족되어야 할 가정
- 선형성: 독립 변수 (X) 와 종속 변수 (Y) 사이에 선형적인 관계가 있어야 합니다.
- 독립성: 오차 (잔차) 들은 서로 독립적이어야 합니다. (자기 상관 X)
- 등분산성: 모든 X 에 대해 잔차의 분산이 동일해야 합니다.
- 정규성: 잔차 (오차항) 가 정규 분포를 따라야 합니다. -> QQ Plot
- 다중 공선성: 독립 변수들 간의 상관 관계가 매우 높으면 회귀 계수 추정이 불안정해집니다.
cf) 다중공산성
- 상관관계가 높은 독립변수들이 다중으로 모델에 들어가 있을 때 발생
- 즉, 독립변수들이 강한 선형관계가 있을 때 발생
- 보통 다중회귀 방정식에서 다중공산성 문제가 발생
수학적 배경
1. 최소 제곱법 (Ordinary Least Squares, OLS)
- 실제 종속 변수 yi와 예측값 간 오차 제곱합 (SSE) 을 최소화하는 β 계수를 찾음

2. 결정 계수 (R^2)

- 모델이 종속 변수의 변동을 얼마나 잘 설명하는지 나타냄
- 모델의 설명력 (0~1)
ex) 상관관계가 1에 가깝고, 결정계수는 0.8
=> 모델의 설명력이 좋다.
상관관계랑 r 제곱이 중요!
실행 절차
- 데이터 준비: 종속 변수 (Y) 와 독립 변수 (X) 를 정리합니다. 범주형 변수는 더미 변수/원-핫 인코딩 처리합니다.
- 데이터 탐색/시각화: X-Y 산점도, 상관 분석, 이상치 탐색 등을 수행합니다.
- 모형 적합 (회귀 분석 수행): 최소 제곱법 (OLS) 으로 β 를 추정합니다.
- 가정 검토: 잔차 도표 (등분산성, 선형성), 잔차 정규성 (Q-Q plot), Durbin-Watson (독립성), VIF (다중 공선성) 등을 확인합니다.
- 모델 평가: 결정 계수 (R^2), 수정된 R^2, 유의성 검정 (F-test, t-test), AIC/BIC 등을 사용하여 모델을 평가합니다.
- 해석 & 보고: β 계수의 크기, 방향 (+, -), 유의성, 신뢰 구간 등을 제시합니다. 예측 모델의 경우 RMSE, MAE, 교차 검증 등으로 성능을 평가합니다.
단순 선형 회귀 예시(statsmodels)
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
# -------------------------------------------------
# 1) 예시 데이터 생성 (X1, X2 -> Y)
# -------------------------------------------------
np.random.seed(123)
N = 100
X1 = np.random.normal(10, 5, N) # 평균=10, 표준편차=5
X2 = np.random.normal(50, 10, N) # 평균=50, 표준편차=10
true_beta0 = 3.0
true_beta1 = 1.5
true_beta2 = 0.5
noise = np.random.normal(0, 5, N) # 오차
Y = true_beta0 + true_beta1 * X1 + true_beta2 * X2 + noise
df_multi = pd.DataFrame({'X1': X1, 'X2': X2, 'Y': Y})
# -------------------------------------------------
# 2) StatsModels를 이용한 다중회귀
# -------------------------------------------------
model_multi = smf.ols('Y ~ X1 + X2', data=df_multi).fit()
print(model_multi.summary())
# -------------------------------------------------
# 3) Scikit-Learn을 이용한 다중회귀
# -------------------------------------------------
X_features = df_multi[['X1', 'X2']]
y_target = df_multi['Y']
lin_reg = LinearRegression()
lin_reg.fit(X_features, y_target)
y_pred = lin_reg.predict(X_features)
mse = mean_squared_error(y_target, y_pred)
rmse = np.sqrt(mse)
print("\n[Scikit-Learn 결과]")
print(f"Intercept: {lin_reg.intercept_:.3f}")
print(f"Coef X1, X2: {lin_reg.coef_}")
print(f"RMSE: {rmse:.3f}")

출력된 결과 해석
1. 모델의 전체적인 성능 평가
- R-squared : 모델이 79.3%의 변동성을 설명함(설명력이 높음)
- Adj. R-squared : 변수가 추가된 효과를 반영한 결정계수로 큰 차이가 없으므로 불필요한 변수가 포함되지 않았다고 볼 수 있음
- F-statistic : 전체 회귀 모델이 유의미한지를 검정하는 통계량으로 값이 클수록 좋음
- Prob (F-statistic) : p-value로 매우 작으므로 모델이 유의미함을 의미함
2. 회귀 계수
- 결과에 따른 회귀 방정식 : Y=2.48+1.4486*X1+0.5114*X2
- Intercept(절편) : p값이 0.366(>0.05)로 유의미하지 않으므로 크게 중요하지 않음
- X1과 X2의 회귀 계수 : p값이 0으로 유의미한 변수임
- p-value 해석 (P>|t|) : X1과 X2 변수 모두 Y에 유의미한 영향을 미침, 절편은 유의미하지 않음
3. 잔차 분석 및 모델 적합성 평가
- Durbin-Watson : 잔차의 자기 상관(독립성) 검정 값이 2에 가까울수록 독립성이 높음
- Omnibus / Prob(Omnibus) : 잔차의 정규성 검정으로 p값이 0.05 이상이면 정규성을 만족한다고 볼 수 있음
- Jarque-Bera (JB) / Prob(JB) : 잔차의 정규성 검정으로 p값이 0.05 이상이면 잔차가 정규분포를 따름
- Kurtosis : 잔차의 분포가 정규분포에 가까움
- Cond. No. (조건수) : 다중공선성 확인 보통 30~100이면 괜찮
결과 해석
- 회귀 계수: β가 양수 (+) 이면 X 가 증가할수록 Y 도 증가 (양의 상관), 음수 (-) 이면 반대입니다.
- p-value: p-value 가 유의 수준 (예: 0.05) 보다 작으면 해당 변수의 효과가 통계적으로 유의미합니다.
- F-검정 (모형 유의성): 전체 모델이 유의미한지 확인합니다. p<0.05 이면 "X 들이 Y 를 유의하게 설명한다" 고 해석합니다.
- 결정 계수 (R^2), 수정된 R^2: 모델의 설명력을 나타냅니다. 다중 회귀에서는 변수 개수에 대한 보정이 포함된 수정된 (R^2) (Adjusted R^2) 를 주로 봅니다.
- 잔차 분석: 잔차 vs 적합값 (혹은 vs 독립 변수) 플롯에서 패턴이 없어야 등분산성/선형성을 확인할 수 있습니다. (잔차 정규성 (히스토그램, Q-Q plot), Durbin-Watson (독립성), VIF (공선성) 등)
주의 사항
- 가정 위배: 이상치가 많거나 비선형 관계가 강하면 OLS 추정이 왜곡될 수 있습니다.
- 설명 vs 예측: 통계 분석 (설명) 목적인지, 머신러닝 (예측) 목적인지에 따라 평가 지표, 교차 검증, 정규화 등이 달라집니다.
- 인과 관계: 회귀 분석은 상관 관계를 보여주지만, 인과 관계는 연구 설계 (실험 등) 가 뒷받침되어야 확실히 주장할 수 있습니다.
- 다중 공선성: 독립 변수들 간의 상관 관계가 높으면 회귀 계수 해석이 불안정해집니다.
머신러닝 선형회귀 실습
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error
# 1. 가상의 데이터 생성
# ----------------------
# - X: 기계 가동 시간(단위: 시간)
# - y: 유지보수 비용(단위: 만원)
# 예) 유지보수 비용 = 2.5 * 기계 가동시간 + 100 + 노이즈
np.random.seed(42) # 재현성(실험 결과의 일관성) 유지를 위해 시드 고정
X = 1000 * np.random.rand(100, 1) # 0~1000 사이의 난수 100개 (기계 가동시간)
y = 2.5 * X + 100 + np.random.randn(100, 1) * 50 # 노이즈를 추가한 유지보수 비용
# 2. pandas DataFrame으로 변환
# ---------------------------
df = pd.DataFrame({
'OperatingHours': X.flatten(),
'MaintenanceCost': y.flatten()
})
print("생성된 데이터 일부 확인:")
print(df.head(), '\n')
# 3. 훈련셋과 테스트셋으로 분리
# ----------------------------
X_train, X_test, y_train, y_test = train_test_split(
df[['OperatingHours']], # 독립변수(기계 가동시간)
df['MaintenanceCost'], # 종속변수(유지보수 비용)
test_size=0.2, # 80%를 훈련, 20%를 테스트로 분리
random_state=42
)
# 4. 모델 학습
# ------------
model = LinearRegression()
model.fit(X_train, y_train)
# 학습된 모델 파라미터(기울기 & 절편)
print(f"학습된 기울기(가중치): {model.coef_[0]:.3f}")
print(f"학습된 절편(바이어스): {model.intercept_:.3f}\n")
# 5. 모델 예측
# ------------
y_pred = model.predict(X_test)
# 6. 결과 시각화
# --------------
plt.figure(figsize=(8, 5))
plt.scatter(X_train, y_train, color='blue', label='Train Data') # 훈련 데이터
plt.scatter(X_test, y_test, color='green', label='Test Data') # 테스트 데이터
plt.plot(X_test, y_pred, color='red', linewidth=2, label='Predictions') # 예측값
plt.title("Linear Regression in Manufacturing\n(Operating Hours vs Maintenance Cost)")
plt.xlabel("Operating Hours")
plt.ylabel("Maintenance Cost (in 만원)")
plt.legend()
plt.show()
# 7. 모델 성능 평가
# -----------------
r2 = r2_score(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
print(f"결정계수(R^2): {r2:.3f}")
print(f"MAE (평균 절댓값 오차): {mae:.3f}")
print(f"MSE (평균 제곱 오차): {mse:.3f}")
print(f"RMSE (루트 평균 제곱 오차): {rmse:.3f}")

통계학 선형회귀 실습
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# statsmodels
import statsmodels.api as sm
import statsmodels.formula.api as smf
# 데이터 생성(가상의 예시)
np.random.seed(42) # 재현성 유지
X = 1000 * np.random.rand(100) # 기계 가동 시간(0~1000 시간)
y = 2.5 * X + 100 + np.random.randn(100) * 50 # 유지보수 비용(노이즈 포함)
# pandas DataFrame으로 변환
df = pd.DataFrame({
'OperatingHours': X,
'MaintenanceCost': y
})
# 1) 단순 선형 회귀분석: MaintenanceCost ~ OperatingHours
# -----------------------------------------------------
# statsmodels의 formula API 사용: "종속변수 ~ 독립변수" 형태
model = smf.ols("MaintenanceCost ~ OperatingHours", data=df).fit()
# 결과 요약
print(model.summary())
# 2) 결과 해석 예시
# ----------------
# - coef(OperatingHours): X가 1만큼 증가할 때, 유지보수 비용이 얼마만큼 변동하는지에 대한 추정값
# - P>|t| (p-value): 해당 회귀계수가 통계적으로 유의미한지(0.05 미만이면 유의미)
# - R-squared: 모델이 데이터를 얼마나 잘 설명하는지 (1에 가까울수록 적합도가 높음)
# - Intercept: 절편(독립변수=0일 때 예상되는 유지보수 비용)
# 3) 예측값과 잔차(residual) 시각화
# --------------------------------
# 예측값 (fitted values), 잔차(residuals)
pred_vals = model.fittedvalues
residuals = model.resid
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# (왼쪽) 예측값 vs 실측값
axes[0].scatter(X, y, label='Observed', alpha=0.7)
axes[0].scatter(X, pred_vals, color='red', label='Fitted', alpha=0.7)
axes[0].set_title("Observed vs Fitted")
axes[0].set_xlabel("Operating Hours")
axes[0].set_ylabel("Maintenance Cost")
axes[0].legend()
# (오른쪽) 예측값 vs 잔차
axes[1].scatter(pred_vals, residuals, alpha=0.7)
axes[1].axhline(y=0, color='red', linestyle='--')
axes[1].set_title("Residual Plot")
axes[1].set_xlabel("Fitted Values")
axes[1].set_ylabel("Residuals")
plt.tight_layout()
plt.show()
# 4) 추가 통계 검증(Q-Q Plot 등)
# ------------------------------
# 정규성 가정 확인(Q-Q Plot)
fig = sm.qqplot(residuals, line='45', fit=True)
plt.title("Q-Q Plot for Residuals")
plt.show()


실습한 코드에 대한 자세한 설명은 공부 자료에 들어가면 있습니다!!
'내일배움캠프_QAQC 1기 > 통계학 기초' 카테고리의 다른 글
| [1/21] 데이터 분석을 위한 통계학 입문_4회차 (0) | 2025.01.21 |
|---|---|
| [1/20] 데이터 분석을 위한 통계학 입문_3회차 (0) | 2025.01.21 |
| [1/17] 데이터 분석을 위한 통계학 입문_2회차 (0) | 2025.01.20 |
| 통계학 기초 복습 ① (0) | 2025.01.20 |
| 통게학 기초 6주차 (0) | 2025.01.20 |