본문 바로가기

파이썬 & 머신러닝과 딥러닝

통계기반 데이터 분석 방법, 단순회귀분석, 종회귀모형, 모형의 선택, 모형의 타당성

95% 구간에서 a(확률 구간)을 0.05로 잡게되고

해당 구간에 대한 값들을 위쪽 아래쪽에서 maximum값을 0.025로 세팅하게됨

표준정규분포의 95% 구간에서 Z를 세팅하고

위쪽의 구간을 다른 말로 a/2 구간에 대한 Z구간

Za/2로 정의하게됨

 

신뢰구간(confidence interval)

 

95% 구간에서 a(확률 구간)을 0.05로 잡는다:

  • 여기서 'a'는 유의수준(significance level)을 의미
  • 95% 신뢰구간은 데이터의 95%가 이 구간 안에 포함됨
  • 따라서 나머지 5%는 신뢰구간 바깥에 있고 이를 유의수준 'a'로 나타내며, a = 0.05

해당 구간에 대한 값들을 위쪽 아래쪽에서 maximum값을 0.025로 세팅하게 된다:

  • 5%를 신뢰구간 바깥에 놓아야 하므로, 이를 양쪽으로 나누면 각각 2.5%
  • 따라서, 신뢰구간의 양 끝은 각각 0.025의 확률을 가지게 됨

표준정규분포의 95% 구간에서 Z를 세팅하고:

  • 표준정규분포는 평균이 0이고 표준편차가 1인 분포
  • 95% 신뢰구간을 설정할 때, 표준정규분포의 Z값을 사용하게 됨
  • 이 Z값은 신뢰구간의 경계를 설정하는 데 사용

위쪽의 구간을 다른 말로 a/2 구간에 대한 Z구간:

  • a = 0.05이므로, a/2 = 0.025(신뢰구간의 양쪽 끝에 해당)
  • 즉, 신뢰구간의 상단과 하단을 설정할 때 각각 0.025의 확률을 사용

Za/2로 정의하게 된다:

  • 'Za/2'는 신뢰구간의 상단과 하단을 결정하는 Z값을 의미
  • 표준정규분포에서 P(Z > Za/2) = 0.025가 되는 Z값을 구하고
  • 이 값을 통해 신뢰구간의 경계를 설정 가능

 

결론)

95% 신뢰구간을 설정하기 위해 유의수준을 0.05로 잡고,

이를 양쪽으로 나누어 각 2.5% (0.025)로 분배

표준정규분포에서 Z값을 이용하여 이 구간을 결정하게 됨

즉, Z값이 상위 2.5%와 하위 2.5%에 해당하는 값을 찾아 신뢰구간을 설정하고 Za/2로 정의

표준정규분포에서 Za/2 값은 대략 1.96

따라서, 95% 신뢰구간은 평균 ± 1.96 * 표준오차로 계산됨

 

 

신뢰하한과 신뢰상한

: 신뢰구간의 하단과 상단을 의미

신뢰구간은 어떤 모수(parameter)가 특정 구간 내에 포함될 확률을 나타내는 구간

 

 

  • 신뢰하한 (Lower Confidence Limit, LCL):
    • 신뢰구간의 하단 경계 : 신뢰구간이 시작되는 점으로, 계산된 값 중 낮은 쪽의 값을 의미
  • 신뢰상한 (Upper Confidence Limit, UCL):
    • 신뢰구간의 상단 경계 : 이는 신뢰구간이 끝나는 점으로, 계산된 값 중 높은 쪽의 값을 의미

 

 

신뢰구간 구하기

주어진 점수 데이터에서 표본을 추출하고, 표본 평균과 분산을 계산한 후, 신뢰구간을 구하기

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
data = pd.read_csv('C:/Users/campus4D033/ch4_scores400.csv')
scores = np.array(data['score'])
p_mean = np.mean(scores)
p_var = np.var(scores)
n = 20
sample = np.random.choice(scores, n)
n_sample = 10000
samples = np.random.choice(scores, (n_sample, n))
for i in range(5):
    s_mean = np.mean(samples[i])
sample_means = np.mean(samples, axis = 1)
s_mean = np.mean(sample)
for i in range(5):
    s_var = np.var(samples[i])
sample_vars = np.var(samples, axis=1)
rv = stats.norm()
lcl = s_mean - rv.isf(0.025) * np.sqrt(p_var/n)
ucl = s_mean - rv.isf(0.975) * np.sqrt(p_var/n)
print(lcl, ucl)

 


 

 

데이터 읽기, 기본 통계 계산, 데이터 시각화, 표본 추출, 표본 평균 및 분산 계산, 그리고 신뢰구간을 시각화하는 전체 과정

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats

# 데이터 로드 및 기본 통계 계산
df = pd.read_csv('C:/Users/campus4D033/ch4_scores400.csv')
scores = np.array(df['score'])
p_mean = np.mean(scores)
p_var = np.var(scores)

# 데이터 분포 시각화
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111)
xs = np.arange(101)
rv = stats.norm(p_mean, np.sqrt(p_var))
ax.plot(xs, rv.pdf(xs), color='gray')
ax.hist(scores, bins=100, range=(0, 100), density=True)
plt.show()

# 표본 추출 및 출력
np.random.seed(0)
n = 20
sample = np.random.choice(scores, n)
print(sample)
np.random.seed(50)
n_sample = 10000
samples = np.random.choice(scores,
                           (n_sample, n))
print(samples)
# 10, 30, 60, 80, ?

# 표본평균 및 분산 계산
for i in range(5) :
    s_mean = np.mean(samples[i])
    print(f'{i+1}번째 표본평균:{s_mean:.3f}')
sample_means = np.mean(samples, axis=1)
print(np.mean(sample_means))
print(np.mean(np.random.choice(scores, int(1e6))))
s_mean = np.mean(sample)
print(s_mean)
for i in range(5) :
    s_var = np.var(samples[i])
    print(f'{i+1}번째 표본분산:{s_var:.3f}')
sample_vars = np.var(samples, axis=1)
print(np.mean(sample_vars))
u_var = np.var(samples, ddof=1)
print(u_var)

# 신뢰구간 시각화
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111)
rv = stats.norm()
n_samples = 20
ax.vlines(p_mean, 0, 21)
for i in range(n_samples):
    sample_ = samples[i]
    s_mean_ = np.mean(sample_)
    lcl = s_mean_ - rv.isf(0.025) * np.sqrt(p_var/n)
    ucl = s_mean_ - rv.isf(0.975) * np.sqrt(p_var/n)
    if lcl <= p_mean <= ucl:
        ax.scatter(s_mean_, n_samples-i, color='gray')
        ax.hlines(n_samples-i, lcl, ucl, color='gray')
    else:
        ax.scatter(s_mean_, n_samples-i, color='b')
        ax.hlines(n_samples-i, lcl, ucl, color='b')
ax.set_xticks([p_mean])
ax.set_xticklabels(['population mean'])
plt.show()

# 신뢰구간이 모집단 평균을 포함하는 경우의 비율 계산방식 추가
rv1 = stats.norm()
cnt = 0
for sample_ in samples:
    s_mean_ = np.mean(sample_)
    lcl = s_mean_ - rv.isf(0.025) * np.sqrt(p_var/n)
    ucl = s_mean_ - rv.isf(0.975) * np.sqrt(p_var/n)
    if lcl <= p_mean <= ucl:
        cnt += 1
print(f'이 수치만큼 모평균 포함 : {cnt / len(samples)}')

 

 

단일표본, 다중표본, 첫 5개 표본의 평균, 단일 표본 평균, 첫 5개 표본의 분산,

전체 표본 분산 평균, 표본들의 분산, 뢰구간이 모집단 평균을 포함하는 경우의 비율 출력

 

 


 

여러 표본의 분산을 카이제곱 분포로 변환하여 시각화 + 표본분산에 대한 신뢰구간

# 표본분산을 카이제곱 분포 변환
sample_u_vars = np.var(samples, axis=1, ddof=1)
np.mean(sample_u_vars)

sample_y = sample_u_vars * (n-1) / p_var

fig = plt.figure(figsize = (10, 6))
ax = fig.add_subplot(111)

xs = np.linspace(0, 40, 100)
rv = stats.chi2(df=n-1) # 자유도
ax.plot(xs, rv.pdf(xs), color = 'gray')
hist, _, _ = ax.hist(sample_y, bins = 100, 
                     range = (0,40), density = True)

plt.show()

# 표본 분산에 대한 신뢰구간을 계산
rv2 = stats.chi2(df=n-1)
lcl = (n-1) * u_var / rv2.isf(0.025)
hcl = (n-1) * u_var / rv2.isf(0.975)

#모분산을 알지 못할 때의 신뢰구간 구하는 방법
rv = stats.t(df=n-1)
lcl = s_mean - rv.isf(0.025) * np.sqrt(u_var/n)
ucl = s_mean - rv.isf(0.975) * np.sqrt(u_var/n)
print(lcl, ucl)

print(lcl, hcl)

 


 

실습예제 문제제기
A 학생은 학교에서 돌아오는 길에 종종 편의점에 들어 감자튀김을 구매한다. 이 감자튀김의 무게는 평균 130g으로 알려져 있지만, 어느 날 스 학생이 감자튀김의 무게를 측정해보았더니 122.02g밖에 되지 않았다. 이 편의점에서 파는 감자튀김의 무게가 실제로는 평균인 130g보다 적게 나가는게 아닌가 의구심이 들기 시작한 A 학생은, 그날부터 2주간 매일 감자튀김을 사서 무게를 측정하였다. 그리고 2주 후, 그동안 구매한 14개 표본의 평군을 계산한 결과 128.451g이 나왔다.14개 표본의 핑균 무게가 130g보다 적다고 확신한 A 학생은 편의점에 향의했지만, 편의점 측은 그저 우연일 뿐이 라고 일축해버렸다. 14개 표본의 평균이 128.451g으로 나온 건 정말 우연이었을까?

 

 

  • 귀무가설: 감자튀김의 평균 무게는 130g이다.
  • 대립가설 : 감자튀김의 평균 무게는 130g보다 작다.

 

 

표본 평균을 이용한 가설 검정

import pandas as pd
import numpy as np
from scipy import stats

np.random.seed(1111)


en_f = pd.read_csv('C:/Users/campus4D033/potato.csv')
en_df = np.array(en_f['무게'])

s_mean = np.mean(en_df)# 데이터의 평균 계산

# n(130, 9) -> N(130, 9/14)
# 표본평균 p(bar X <= x) = 0.05
rv = stats.norm(130, np.sqrt(9/14))
print(rv.isf(0.95))

# p(bar X <= 128.681) = 0.05
z = (s_mean - 130) / np.sqrt(9/14)
print('검정통계량 : ', z) 

rv = stats.norm()
print('임계값', rv.interval(0.95))

 

검정통계량 값이 임계값 보다 크다

-> 주어진 데이터로부터는 모집단의 평균이 130과 다르다고 결론 내릴 수 없으며, 귀무가설을 채택

 


 

가설 세우기 - 유의수준 - 검정통계량 - p 값 계산

  • p값 > 유의수준 : 귀무가설 채택
  • p값 < 유의수준 : 귀무가설 기각

 

유의수준 

  • 귀무가설을 기각하는 기준을 제시
  • 예를 들어, 유의수준을 0.05로 설정하면, 오류를 범할 확률이 5% 이내라는 의미

 

검정통계량 (Test Statistic)

  • 검정통계량은 주어진 데이터를 사용하여 가설 검정을 수행할 때 계산되는 값
  • 검정통계량은 보통 표본 평균, 표본 비율, 두 집단 간의 평균 차이 등을 나타내며, 이 값이 얼마나 귀무가설과 일치하지 않는지를 보여줌

p 값 (p-value) 계산

  • p 값은 주어진 데이터에서 얻은 검정통계량의 결과를 바탕으로, 귀무가설이 참일 때 표본에서 관측된 결과 또는 그보다 극단적인 결과가 발생할 확률
  • p 값이 유의수준보다 작으면, 우연히 얻은 결과가 아니라고 판단하여 귀무가설을 기각 -> 즉, 관찰된 데이터가 귀무가설과 모순된다는 강력한 증거가 됨
  • 반대로, p 값이 유의수준보다 크면, 귀무가설을 기각할 충분한 증거가 부족하므로 귀무가설을 채택 -> 이는 관찰된 데이터가 귀무가설과 일치한다는 것을 나타냄

 


 

이진 분류 모델

 

  • TP (True Positive)
    • 의미: 실제로 Positive인 샘플을 Positive로 올바르게 분류한 경우
  • FN (False Negative)
    • 의미: 실제로 Positive인 샘플을 Negative로 잘못 분류한 경우
  • FP (False Positive)
    • 의미: 실제로 Negative인 샘플을 Positive로 잘못 분류한 경우
  • TN (True Negative)
    • 의미: 실제로 Negative인 샘플을 Negative로 올바르게 분류한 경우입

 

 


 

특이도 ( TNR ) : TNR은 실제로 Negative인 샘플들 중에서 모델이 올바르게 Negative로 예측한 비율

TNR = TN /TN+FP

 

민감도 ( TPR ) : 실제로 Positive인 샘플들 중에서 모델이 Positive로 올바르게 예측한 비율

TPR = TP / TP+FN

 

정밀도 ( Precision ) : 모델이 Positive로 예측한 경우 중에서 실제로 Positive인 샘플의 비율

Precision = TP / TP+FP

 

F1 점수 ( F1 Score ) : 정밀도와 재현율의 조화 평균

F1 Score = 2 ⋅ ( Precision+Recall / PrecisionRecall )

 

정확도 ( Accuracy ) : 모든 예측 중에서 올바르게 분류한 샘플의 비율

Accuracy =TP+TN / TP+TN+FP+FN

 


 

통계적 가설 검정을 수행

import pandas as pd
import numpy as np
from scipy import stats

np.random.seed(1111)


en_f = pd.read_csv('C:/Users/campus4D033/potato.csv')
en_df = np.array(en_f['무게'])

s_mean = np.mean(en_df)# 데이터의 평균 계산

# n(130, 9) -> N(130, 9/14)
# 표본평균 p(bar X <= x) = 0.05
rv = stats.norm(130, np.sqrt(9/14))
print(rv.isf(0.95))

# p(bar X <= 128.681) = 0.05
z = (s_mean - 130) / np.sqrt(9/14)
print('검정통계량 : ', z) 

rv = stats.norm()
print('임계값', rv.interval(0.95))
# 검정통계량 값이 임계값 보다 크기 때문에 귀무가설 채택

# p값 기준 검정 방법
print(rv.cdf(z))
print(rv.cdf(z) * 2)

# 제 1종 오류 위험률 계산 방법
rv = stats.norm(130, 3)
c = stats.norm().isf(0.95)
n_samples = 10000
cnt = 0
for _ in range(n_samples):
    sample_ = np.round(rv.rvs(14), 2)
    s_mean_ = np.mean(sample_)
    z = (s_mean_ - 130) / np.sqrt(9/14)
    if z < c:
        cnt += 1
print(cnt / n_samples)

# 제 2종 오류
rv = stats.norm(128, 3)
c = stats.norm().isf(0.95)
n_samples = 10000
cnt = 0
for _ in range(n_samples):
    sample_ = np.round(rv.rvs(14), 2)
    s_mean_ = np.mean(sample_)
    z = (s_mean_ - 130) / np.sqrt(9/14)
    if z >= c:
        cnt += 1
print(cnt / n_samples)

 

 


 

 

단순회귀분석

회귀 분석에서 예측 값과 잔차를 사용하여 오차의 분산, 즉 모분산을 추정

 

쪽지시험의 평균점수가 기말고사 점수에 영향이 있는지

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
import statsmodels.formula.api as smf

df = pd.read_csv('C:/Users/campus4D033/scores_reg.csv')
n = len(df)
print(n)
df.head()

# 단순회귀분석
# 설명변수 : 원인 (독립변수) 쪽지시험 평균점수
# 반응변수 : 결과 (종속변수) 기말고사 점수


x = np.array(df['quiz'])
y = np.array(df['final_test'])
p = 1 # 설명변수의 수를 p로


# 2차원 데이터에 대한 산점도와 회귀직선
poly_fit = np.polyfit(x, y, 1)
poly_1d = np.poly1d(poly_fit)
xs = np.linspace(x.min(), x.max())
ys = poly_1d(xs)
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111)
ax.set_xlabel('quiz')
ax.set_ylabel('final test')
ax.plot(xs, ys, color='gray',
        label=f'{poly_fit[1]:.2f}+{poly_fit[0]:.2f}x') # y절편 + 기울기
ax.scatter(x, y)
ax.legend()
plt.show()

formula = 'final_test ~ quiz' # 반응변수 ~ 설명변수
result = smf.ols(formula, df).fit() # smf.ols 회귀분석
print(result.summary())

  • Intercept : 절편 B0
  • quiz : 기울기 B1
  • coef : 회귀계수 추정값
  • std err : 추정값의 표준오차
  • t : 회귀계수의 t검정 통계량
  • P > |t| : t검정통계량의 P값
  • [0.025와 0.975] : 회귀계수의 95% 신뢰구간

 

점추정

coef 에 출력된 회귀계수의 추정량이 생성한 회귀직선은 데이터에 가장 잘 들어맞는 직선

(= 예측값과 실제값 차이가 가장 적은 직선)

# 점추정
X = np.array([np.ones_like(x), x]).T
beta0_hat, beta1_hat = np.linalg.lstsq(X, y)[0] # 최소제곱법
print(beta0_hat, beta1_hat)

# 예측값과 잔차 계산
y_hat = beta0_hat + beta1_hat * x
eps_hat = y - y_hat
# 잔차는 오차항에 대응하고 있기 때문에
# 잔차의 분산으로 부터 모분산을 추정 가능

s_var = np.var(eps_hat, ddof = p+1)
print('모분산 추정 : ', s_var)

 

 

잔차

: 실제 데이터 포인트와 회귀 모델에 의해 예측된 데이터 포인트 간의 차이

각 데이터 포인트에 대해 계산되며, 회귀 모델에서 잔차는 오차항의 표본 추정치로 간주됨

 

잔차는 오차항에 대응하고 있기 때문에, 잔차의 분산으로 모분산 추정가능

다만, 잔차의 자유도는 회귀계수의 수 p+1만큼 감소하여 n-p-1이 되므로

모분산의 불편추정량은 n-p-1로 나누어 계산되는 값임

 

오차항

: 모집단에서의 실제 값과 모델의 예측 값 간의 차이 ,

관측되지 않는 값이지만, 잔차를 통해 추정

-> 잔차를 통해 오차항의 분산, 즉 모분산을 추정

 

자유도

: 통계적 추정을 할 때 사용되는 데이터 포인트의 수

잔차의 분산을 계산할 때, 회귀 모델의 회귀계수의 수만큼 자유도가 감소

이는 회귀 모델이 데이터에 적합할 때, 각 회귀계수가 하나의 자유도를 차지하기 때문

 

불편추정량 계산

 

  • n: 전체 표본의 수
  • p: 설명변수(독립변수)의 수
  • n - p - 1: 잔차의 자유도. 이는 전체 표본 수에서 회귀계수(절편 포함)의 수를 뺀 값

 

-> 잔차의 자유도를 조정하여 분산을 계산함으로써, 모분산의 불편 추정량을 얻을 수 있음음

불편 추정량은 표본 분산을 통해 모집단 분산을 더 정확하게 추정

 


 

구간추정

# 구간추정

# C0 절편, C1 기울기
C0, C1 = np.diag(np.linalg.pinv(np.dot(X.T, X)))
print(np.sqrt(s_var * C0), np.sqrt(s_var * C1))

# 신뢰구간 추정
rv = stats.t(n-2) # 자유도 n-2
lcl = beta0_hat - rv.isf(0.025) * np.sqrt(s_var * C0)
hcl = beta0_hat - rv.isf(0.075) * np.sqrt(s_var * C0)

print(lcl, hcl)

# beat1_hat(선형회귀를 사용한 기울기 예측값)
# 귀무가설 : beat1_hat = 0
# 대립가설 : beat1_hat != 0
t = beta1_hat / np.sqrt(s_var * C1)
print(t)
p1 = (1 - rv.cdf(t)) * 2
print(p1)


# beat0_hat(선형회귀를 사용한 절편 예측값)
# 귀무가설 : beat1_hat = 0
# 대립가설 : beat1_hat != 0
t = beta0_hat / np.sqrt(s_var * C0)
print(t)
p2 = (1 - rv.cdf(t)) * 2
print(p2)


# 중회귀분석
# 독립변수 2개 포함되게 모형 만들기
formula1 = 'final_test ~ quiz + sleeptime'
result = smf.ols(formula, df).fit()
print(result.summary())

 

t 검정 beat1_hat(선형회귀를 사용한 기울기 예측값)

  • 귀무가설 : beat1_hat = 0
  • 대립가설 : beat1_hat != 0

 


 

종회귀모형

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
import statsmodels.formula.api as smf

df = pd.read_csv('C:/Users/campus4D033/scores_reg.csv')
n = len(df)
print(n)
df.head()


# 중회귀분석
# 종회귀모형 : 설명변수가 2개 이상인 모형
# 독립변수 2개 포함되게 모형 만들기
formula = 'final_test ~ quiz + sleeptime'
result = smf.ols(formula, df).fit()
print(result.summary())

x1 = df['quiz']
x2 = df['sleep_time']
y = df['final_test']
p = 2

X = np.array([np.ones_like(x1), x1, x2]).T
beta0_hat, beta1_hat, beta2_hat = np.linalg.lstsq(X, y)[0]

y_hat = beta0_hat + beta1_hat * x1 + beta2_hat * x2
eps_hat = y - y_hat

s_var = np.sum(eps_hat**2) / (n-p-1)
C0, C1, C2 = np.diag(np.linalg.pinv(np.dot(X.t, X)))

rv = stats.t(n-p-1)

lcl = beta2_hat - rv.isf(0.025) * np.sqrt(s_var * C2)
hcl = beta2_hat - rv.isf(0.975) * np.sqrt(s_var * C2)

# 가변수 : 질적변수를 변환하여 양적변수와 동일하게 취급할 수 있게하는 기법

 

 

 

 


 

모형의 선택

적합이 좋은 것

예측이 좋은 것

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
import statsmodels.formula.api as smf

df = pd.read_csv('C:/Users/campus4D033/scores_reg.csv')
n = len(df)
print(n)
df.head()



x = np.array(df['quiz'])
y = np.array(df['final_test'])
p = 1 # 설명변수의 수를 p로


# 2차원 데이터에 대한 산점도와 회귀직선
poly_fit = np.polyfit(x, y, 1)
poly_1d = np.poly1d(poly_fit)
xs = np.linspace(x.min(), x.max())
ys = poly_1d(xs)

fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111)
ax.set_xlabel('quiz')
ax.set_ylabel('final test')
ax.plot(xs, ys, color='gray',
        label=f'{poly_fit[1]:.2f}+{poly_fit[0]:.2f}x') # y절편 + 기울기
ax.scatter(x, y)
ax.legend()
plt.show()

# 독립변수 1개인 경우 (단순선형회귀)
formula = 'final_test ~ quiz' # 반응변수 ~ 설명변수
result = smf.ols(formula, df).fit() # smf.ols 회귀분석
print(result.summary())

#회귀변동, 잔차변동
# 예측값은 result의 fittedvalues 변수에 있음
y_hat = np.array(result.fittedvalues) # 예측값 얻기
eps_hat = np.array(result.resid) # 잔차 얻기
np.sum(eps_hat ** 2) # 잔차제곱합

# 총변동 = 회귀변동 + 잔차변동
# 결정계쑤 = 회귀변동 / 총변동 = 1 - (잔차변동/총변동)
total_var = np.sum((y - np.mean(y)) ** 2)
exp_var = np.sum((y_hat - np.mean(y)) ** 2)
unexp_var = np.sum(eps_hat ** 2)

print(exp_var / total_var)
print(np.corrcoef(x,y)[0,1] ** 2)

# 조건 결정계수
adj_r = 1 - (unexp_var / (n - p - 1)) / (total_var / (n - 1))
print('조건결정계수 : {0:.3f}'.format(adj_r))

# f검정 (모형 전체에 수렴됨)
# F = (회귀변동 / p) / (잔차변동 / (n-p-1)) = 모형의 분산 / 잔차의 분산
f = (exp_var / p)  / (unexp_var / (n - p - 1))
f

# 최대로그우도와 AIC
# AIC : 아카이케의 정보량 기준
rv = stats.f(p, n-p-1)
print(1 - rv.cdf(f))

prob = 0.3
coin_result = [0, 1, 0, 0, 1]
rv = stats.bernoulli(prob)
L = np.prod(rv.pmf(coin_result))
print(L) # 로그우도 계산

prob = 0.4
rv = stats.bernoulli(prob)
mll = np.sum(np.log(rv.pmf([0,1,0,0,1])))

rv = stats.norm(y_hat, np.sqrt(unexp_var / n))
mll = np.sum(np.log(rv.pdf(y)))
mll

# AIC
aic = -2 * mll + 2 * (p+1)
aic

# BIC
bic = -2 * mll + np.log(n) * (p+1)
bic

 

 


 

 

다중공산성

# 필요한 라이브러리 임포트
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats
import statsmodels.formula.api as smf

# 데이터 불러오기
df = pd.read_csv('C:/Users/campus4D033/scores_reg.csv')
n = len(df)  # 데이터의 행 개수
print(n)
df.head()  # 데이터의 첫 5행 출력

# 다중공산성 유발
df['mid_test'] = df['quiz'] * 2  # 기존 'quiz' 변수의 값을 2배한 'mid_test' 변수 생성
print(df)

# 단순선형회귀 분석
formula = 'final_test ~ quiz'  # 종속변수 'final_test'와 독립변수 'quiz'의 관계를 나타내는 회귀모형 공식
result = smf.ols(formula, df).fit()  # 회귀분석 수행
print(result.summary())  # 회귀분석 결과 요약 출력