도찐개찐

[데이터분석] 12. 회귀분석 본문

PYTHON/데이터분석

[데이터분석] 12. 회귀분석

도개진 2023. 1. 2. 13:44

회귀분석

  • 상관분석은 변수들이 얼마나 밀접한 관계를 가지고 있는지 분석하는 통계적 기법
  • 한편, 회귀분석은 (상관분석 + 예측)하는 통계적 기법
  • 수량형 값을 예측하는데 주로 사용되는 통계적 모형
    • 즉, 두 변수간의 선형(직선)관계를 식으로 표현하고
      독립변수 $x$가 주어지면 종속변수$y$의 값이 얼마인지 추정
    • 독립변수와 종속변수 사이의 관계를 선형방정식으로 나타낸 것을 회귀방정식이라 함
      • $ \hat y = ax + b + \epsilon $
      • $a$ : 기울기
      • $b$ : 절편
      • $\epsilon$ : 오차, 잡음(noise)
  • 회귀직선을 그릴때는 최소제곱법 이라는 수학적 기법을 이용하는데, 이는 두 변수의 선형관계를 계량화 한 것임

$$ a = \frac{\sum(x_i - \bar x)(y_i - \bar y)}{\sum (x_i - \bar x)^2} $$

$$ b = \bar y - a\bar x$$

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_boston

회귀분석으로 알수 있는 것

  • 모형적합도 : 모형이 데이터에 얼마나 잘 맞는가?
    • 광고비와 매출액의 관계가 데이터에 잘 맞는지 검증할 수 있음
  • 회귀계수 : 독립변수의 변화가 종속변수를 얼마나 변화시키는가?
    • 광고비가 증가하면 매출액은 얼마나 증가할지 예상할 수 있음

공부시간과 성적에 대한 상관/회귀 분석

time = [2,4,6,8]
score = [81, 93, 91, 97]
plt.scatter(time, score)
plt.grid()
plt.show()

최소제곱법을 이용한 회귀계수 계산

# 변수별 평균 계산
time_m = np.mean(time)
score_m = np.mean(score)
# 기울기 식 분자 : (x - x평균)(y - y평균)의 합
def top(x, mx, y, my):
    sum = 0
    for i in range(len(x)):
        sum += (x[i] - mx) * (y[i] - my)
    return sum
# 기울기 식 분모 : (x - x평균)의 제곱합
def bottom(x, mx):
    sum = 0
    for i in range(len(x)):
        sum += (x[i] - mx) ** 2
    return sum
t = top(time, time_m, score, score_m)
b = bottom(time, time_m)
a = t / b
b = score_m - a * time_m
a, b
(2.3, 79.0)

회귀계수를 이용한 시각화

x = np.arange(2,8+1,1)
y = a * x + b

plt.scatter(time, score)
plt.plot(x, y, color='red')
plt.show()

판촉전화횟수에 따라 판매량간의 회귀 분석

p =  [96, 40, 104, 128, 164, 76, 72, 80, 36, 84, 180, 132, 120, 44, 84]
s = [41, 41, 51, 60, 61, 29, 39, 50, 28, 43, 70, 56, 45, 31, 30]
p_mean = np.mean(p)
s_mean = np.mean(s)

a = np.sum((p - p_mean) * (s - s_mean)) / np.sum((p - p_mean) ** 2)
b = s_mean - (a * p_mean)
a, b
(0.260625, 19.98)
t = top(p, p_mean, s, s_mean)
b = bottom(p, p_mean)

a = t / b
b = s_mean - a * p_mean
a, b
(0.260625, 19.98)
x = np.arange(np.min(p)-5,np.max(p)+5,1)
y = a * x + b

plt.scatter(p, s)
plt.plot(x, y, 'r--')
plt.show()

회귀분석 좀더 자세히 이해하기

  • statsmodels 패키지의 ols함수로 분석
  • 결정계수$R^2$
    • (결정계수는 0.75 이상이 되어야만 의미가 있음)
    • 전체 변동에 대해 모델이 설명하는 변동의 비를 의미함
    • 즉, 설정한 회귀직선에 얼마나 값들이 밀집되어 있는지 알수있음
    • 종속변수의 분산을 독립변수가 얼마나 설명하고 있는지 알수있음
    • $R^2$값이 작으면 회귀직선 주위의 점들이 많이 흩어져 있음을 의미
  • 수정된 결정계수$R^2$
    • 수정된 결정계수는 기본적으로 결정계수와 같은 의미를 내포
    • 단, 독립변수의 갯수가 많아지면 결정계수 값이 커지는 경향이 생김
    • 독립변수의 개수와 표본의 크기를 고려해서 결정계수를 보정함
  • $F$ 통계값
    • (유의확률 0.05 이하가 되어야만 의미가 있음)
    • 회귀 모형에 대한 통계적 유의미성 검증 결과 의미
    • 자유도에 의해 조정된 변동과 그렇지 않는 변동의 비율을 나타낸 것
    • 즉, 이 관계가 선형으로 볼수 있는지 여부를 의미
    • 회귀계수가 유의미한지를 판단
  • 회귀계수 : 분석결과에서 intercept, coef 부분
  • 회귀계수 유의성 여부 : 분석결과에서 P>|t| 부분
!conda install -y statsmodels
Retrieving notices: ...working... done
Collecting package metadata (current_repodata.json): done
Solving environment: - 
from statsmodels.formula.api import ols

회귀모델 분석은 데이터프레임을 대상으로 함

time = [2,4,6,8]
score = [81, 93, 91, 97]
score_df = pd.DataFrame({'time': time, 'score': score})

# 분석 대상컬럼은 종속별수~독립변수 형태의 식으로 작성해야 함
model = ols('score~time', data=score_df).fit()

# 분석 결과 확인은 summary 함수 이용
print(model.summary())
p =  [96, 40, 104, 128, 164, 76, 72, 80, 36, 84, 180, 132, 120, 44, 84]
s = [41, 41, 51, 60, 61, 29, 39, 50, 28, 43, 70, 56, 45, 31, 30]
ps_df = pd.DataFrame({'p':p,'s':s})
model = ols('s~p', data=ps_df).fit()

# 분석 결과 확인은 summary 함수 이용
print(model.summary())

총지불금액별 팁에 대한 회귀모델 분석

tips = sns.load_dataset('tips')
model = ols('tip~total_bill', data=tips).fit()
print(model.summary())

다이아몬드 캐럿당 가격에 대한 회귀모델 분석

dia = sns.load_dataset('diamonds')
model = ols('price~carat', data=dia).fit()
print(model.summary())
728x90
Comments