카테고리 없음
[파이썬] 전진선택법과 F-Test 의미
FDG
2025. 4. 12. 00:20
출처 : 여러 AI.
F-검정의 의미 (OLS에서)
OLS 회귀에서의 F-검정은 다음과 같은 **귀무가설(H₀)**과 **대립가설(H₁)**을 테스트합니다:
- H₀ (귀무가설): 모든 설명변수의 회귀계수는 0이다.β1=β2=⋯=βk=0\beta_1 = \beta_2 = \dots = \beta_k = 0
- H₁ (대립가설): 적어도 하나 이상의 회귀계수는 0이 아니다.∃ βj≠0\exists \, \beta_j \ne 0
즉,
**"이 모델에 포함된 변수들이 전혀 도움이 안 되는가?"**를 검정하는 겁니다.
왜 F-검정이 필요할까?
회귀계수에 대한 개별 t-검정은 각 변수의 영향력을 따로 평가합니다.
하지만 F-검정은 모델 전체가 통계적으로 의미 있는지 한꺼번에 보는 방식이에요.
전진선택법에서 F검정을 사용하는 이유
전진선택법은 회귀 모델을 구축할 때 독립 변수를 하나씩 추가하며 모델의 성능을 개선하는 방법입니다. 이 과정에서 F검정은 다음과 같은 이유로 사용됩니다:
- 변수의 유의성 평가: F검정은 추가된 독립 변수가 모델의 설명력을 유의미하게 증가시키는지 평가합니다. 이를 통해 불필요한 변수를 배제하고, 모델의 간결성과 해석력을 높일 수 있습니다15.
- 모델 비교: F검정은 현재 모델과 새로 추가된 변수로 확장된 모델 간의 분산비를 비교하여, 새로운 변수가 통계적으로 유의미한지 판단합니다5.
- 전체 모델 평가: F검정은 단일 변수뿐만 아니라 전체 모델에 대한 검정을 수행하여 모든 변수가 유의미한지 확인하는 데도 사용됩니다5.
✅ 해석 방법
- F값이 크다 → 설명력이 높고, 모델이 유의미할 가능성이 높음.
- p-value가 작다 (ex: < 0.05) → 귀무가설 기각 → 적어도 하나의 설명변수는 의미 있음.
- p-value가 크다 (ex: > 0.05) → 설명변수들이 유의미하지 않음 → 모델의 유용성에 의문.
In [1]:
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
import statsmodels.api as sm
from scipy import stats
# 예제 데이터 생성
np.random.seed(0)
X = np.random.rand(100, 1)
y = 3 * X.squeeze() + 2 + np.random.randn(100)
# sklearn을 사용하여 회귀 분석
model = LinearRegression().fit(X, y)
y_pred = model.predict(X)
# 직접 OLS 회귀 분석 수행
X_with_const = np.hstack([np.ones((X.shape[0], 1)), X]) # 상수항 추가
beta_hat = np.linalg.inv(X_with_const.T @ X_with_const) @ X_with_const.T @ y # 회귀 계수 추정치
# 예측값 계산
y_hat = X_with_const @ beta_hat
# 잔차 계산
residuals = y - y_hat
# 잔차 제곱합 (RSS) 계산
RSS = residuals.T @ residuals
# 총 제곱합 (TSS) 계산
TSS = ((y - y.mean()) ** 2).sum()
# 결정계수 (R^2) 계산
R_squared = 1 - RSS / TSS
# F-검정값 계산
n = X_with_const.shape[0] # 샘플 수
k = X_with_const.shape[1] - 1 # 설명 변수 수 (상수항 제외)
F_value = (R_squared / k) / ((1 - R_squared) / (n - k - 1))
# p-값 계산
p_value = 1 - stats.f.cdf(F_value, k, n - k - 1)
print(f"직접 계산한 F-검정값: {F_value}")
print(f"직접 계산한 p-값: {p_value}")
# statsmodels를 사용하여 F-검정값과 p-값 계산
ols_model = sm.OLS(y, X_with_const).fit()
f_value_sm = ols_model.fvalue
p_value_sm = ols_model.f_pvalue
print(f"statsmodels를 사용하여 계산한 F-검정값: {f_value_sm}")
print(f"statsmodels를 사용하여 계산한 p-값: {p_value_sm}")
직접 계산한 F-검정값: 70.79542664388778 직접 계산한 p-값: 3.291811268013589e-13 statsmodels를 사용하여 계산한 F-검정값: 70.79542664388782 statsmodels를 사용하여 계산한 p-값: 3.2921578936794127e-13
In [2]:
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
import statsmodels.api as sm
from scipy import stats
# 예제 데이터 생성
np.random.seed(0)
X = np.random.rand(100, 5) # 기울기를 나타내는 변수 5개
y = 3 * X[:, 0] + 2 * X[:, 1] + 1.5 * X[:, 2] + X[:, 3] + 0.5 * X[:, 4] + np.random.randn(100)
# sklearn을 사용하여 회귀 분석
model = LinearRegression(fit_intercept=False).fit(X, y) # 따로 추가함
y_pred = model.predict(X)
# 직접 OLS 회귀 분석 수행
X_with_const = np.hstack([np.ones((X.shape[0], 1)), X]) # 상수항 추가
beta_hat = np.linalg.inv(X_with_const.T @ X_with_const) @ X_with_const.T @ y # 회귀 계수 추정치
# 예측값 계산
y_hat = X_with_const @ beta_hat
# 잔차 계산
residuals = y - y_hat
# 잔차 제곱합 (RSS) 계산
RSS = residuals.T @ residuals
# 총 제곱합 (TSS) 계산
TSS = ((y - y.mean()) ** 2).sum()
# 결정계수 (R^2) 계산
R_squared = 1 - RSS / TSS
# F-검정값 계산
n = X_with_const.shape[0] # 샘플 수
k = X_with_const.shape[1] - 1 # 설명 변수 수 (상수항 제외)
F_value = (R_squared / k) / ((1 - R_squared) / (n - k - 1))
# p-값 계산
p_value = 1 - stats.f.cdf(F_value, k, n - k - 1)
print(f"직접 계산한 F-검정값: {F_value}")
print(f"직접 계산한 p-값: {p_value}")
# 변수들의 신뢰구간 계산 (0.05 유의수준)
alpha = 0.05
t_critical = stats.t.ppf(1 - alpha/2, df=n-k-1)
se_beta_hat = np.sqrt(np.diag(np.linalg.inv(X_with_const.T @ X_with_const) * RSS / (n - k - 1)))
conf_intervals = [(beta_hat[i] - t_critical * se_beta_hat[i], beta_hat[i] + t_critical * se_beta_hat[i]) for i in range(len(beta_hat))]
print("직접 계산한 변수들의 신뢰구간 (0.05 유의수준):")
for i, ci in enumerate(conf_intervals):
print(f"변수 {i}: {ci}")
print('-'*80)
# statsmodels를 사용하여 F-검정값과 p-값 및 신뢰구간 계산
ols_model = sm.OLS(y, X_with_const).fit()
f_value_sm = ols_model.fvalue
p_value_sm = ols_model.f_pvalue
conf_intervals_sm = ols_model.conf_int(alpha=0.05)
print(f"statsmodels를 사용하여 계산한 F-검정값: {f_value_sm}")
print(f"statsmodels를 사용하여 계산한 p-값: {p_value_sm}")
print("statsmodels를 사용하여 계산한 변수들의 신뢰구간 (0.05 유의수준):")
print(conf_intervals_sm)
직접 계산한 F-검정값: 30.23389809617568 직접 계산한 p-값: 1.1102230246251565e-16 직접 계산한 변수들의 신뢰구간 (0.05 유의수준): 변수 0: (-0.6962665226372509, 0.7688584867514046) 변수 1: (2.2189217444448666, 3.7697197198594523) 변수 2: (0.9843709751045249, 2.4970850311748136) 변수 3: (1.2701926127242382, 2.7484982586485147) 변수 4: (0.306292094179635, 1.6899780450545847) 변수 5: (-0.558582804153395, 0.8498608309643273) -------------------------------------------------------------------------------- statsmodels를 사용하여 계산한 F-검정값: 30.23389809617567 statsmodels를 사용하여 계산한 p-값: 3.3658080941707118e-18 statsmodels를 사용하여 계산한 변수들의 신뢰구간 (0.05 유의수준): [[-0.69626652 0.76885849] [ 2.21892174 3.76971972] [ 0.98437098 2.49708503] [ 1.27019261 2.74849826] [ 0.30629209 1.68997805] [-0.5585828 0.84986083]]
In [3]:
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
import statsmodels.api as sm
from scipy import stats
# 예제 데이터 생성
np.random.seed(0)
X = np.random.rand(100, 5) # 기울기를 나타내는 변수 5개
y = 3 * X[:, 0] + 2 * X[:, 1] + 1.5 * X[:, 2] + X[:, 3] + 0.5 * X[:, 4] + np.random.randn(100)
# sklearn을 사용하여 회귀 분석
model = LinearRegression().fit(X, y)
y_pred = model.predict(X)
# 직접 OLS 회귀 분석 수행
X_with_const = np.hstack([np.ones((X.shape[0], 1)), X]) # 상수항 추가
beta_hat = np.linalg.inv(X_with_const.T @ X_with_const) @ X_with_const.T @ y # 회귀 계수 추정치
# 예측값 계산
y_hat = X_with_const @ beta_hat
# 잔차 계산
residuals = y - y_hat
# 잔차 제곱합 (RSS) 계산
RSS = residuals.T @ residuals
# 총 제곱합 (TSS) 계산
TSS = ((y - y.mean()) ** 2).sum()
# 결정계수 (R^2) 계산
R_squared = 1 - RSS / TSS
# F-검정값 계산
n = X_with_const.shape[0] # 샘플 수
k = X_with_const.shape[1] - 1 # 설명 변수 수 (상수항 제외)
F_value = (R_squared / k) / ((1 - R_squared) / (n - k - 1))
# p-값 계산
p_value = 1 - stats.f.cdf(F_value, k, n - k - 1)
print(f"직접 계산한 F-검정값: {F_value}")
print(f"직접 계산한 p-값: {p_value}")
# 변수들의 신뢰구간 계산 (0.05 유의수준)
alpha = 0.05
t_critical = stats.t.ppf(1 - alpha/2, df=n-k-1)
se_beta_hat = np.sqrt(np.diag(np.linalg.inv(X_with_const.T @ X_with_const) * RSS / (n - k - 1)))
conf_intervals = [(beta_hat[i] - t_critical * se_beta_hat[i], beta_hat[i] + t_critical * se_beta_hat[i]) for i in range(len(beta_hat))]
print("직접 계산한 변수들의 신뢰구간 (0.05 유의수준):")
for i, ci in enumerate(conf_intervals):
print(f"변수 {i}: {ci}")
# statsmodels를 사용하여 F-검정값과 p-값 및 신뢰구간 계산
ols_model = sm.OLS(y, X_with_const).fit()
f_value_sm = ols_model.fvalue
p_value_sm = ols_model.f_pvalue
conf_intervals_sm = ols_model.conf_int(alpha=0.05)
print(f"statsmodels를 사용하여 계산한 F-검정값: {f_value_sm}")
print(f"statsmodels를 사용하여 계산한 p-값: {p_value_sm}")
print("statsmodels를 사용하여 계산한 변수들의 신뢰구간 (0.05 유의수준):")
print(conf_intervals_sm)
직접 계산한 F-검정값: 30.23389809617568 직접 계산한 p-값: 1.1102230246251565e-16 직접 계산한 변수들의 신뢰구간 (0.05 유의수준): 변수 0: (-0.6962665226372509, 0.7688584867514046) 변수 1: (2.2189217444448666, 3.7697197198594523) 변수 2: (0.9843709751045249, 2.4970850311748136) 변수 3: (1.2701926127242382, 2.7484982586485147) 변수 4: (0.306292094179635, 1.6899780450545847) 변수 5: (-0.558582804153395, 0.8498608309643273) statsmodels를 사용하여 계산한 F-검정값: 30.23389809617567 statsmodels를 사용하여 계산한 p-값: 3.3658080941707118e-18 statsmodels를 사용하여 계산한 변수들의 신뢰구간 (0.05 유의수준): [[-0.69626652 0.76885849] [ 2.21892174 3.76971972] [ 0.98437098 2.49708503] [ 1.27019261 2.74849826] [ 0.30629209 1.68997805] [-0.5585828 0.84986083]]
In [ ]: