[python] 회귀분석

GROOTY·2023년 5월 10일
0

📖회귀분석

변수 간의 인과관계를 분석하며, 사용범위가 넓은 분석방법이다. 이는 변수 들의 관련성 규명을 위해 어떤 수학적 모형을 가정하고, 이 모형을 측정된 변수들의 데이터로부터 추정하는 통계방법이다.
독립변수의 값에 의해 종속변수의 값을 예측할 수 있다.

📖선형회귀분석

각각의 데이터에 대한 잔차 제곱합이 최소가 되는(cost optimizer, cost minimizer)추세선을 만들고,
이를 통해 독립변수(x)가 종속변수(y)에 얼마나 영향을 주는지 인과관계를 분석

  • 기본 충족 조건 : 선형성, 잔차정규성, 잔차독립성, (독립변수가 2개이상일 경우 = 등분산성, 다중공선성)
    과거의 데이터를 기계학습 한 후 정량적인 모델을 생성

✍️선형회귀분석에는 다양한 방법이 있지만 대표적으로 4가지만 추려서 확인해보겠다.

📖방법 1 : make_regression을 사용

model 생성은 되지 않는다.

from sklearn.datasets import make_regression
import numpy as np

# 난수 고정
np.random.seed(1)

# n_samples = 샘플 수, n_features= 기능의 수, coef = 기울기, bias = 절편
x, y, coef = make_regression(n_samples=50, n_features=1, bias=100, coef=True)
print(x[:3])
>>
[[-0.19183555]
 [-1.07296862]
 [-0.17242821]]

print(y[:3])
>> [82.66953946  3.06780917 84.4228027 ]
print(coef)	# 기울기
>> 90.34019152878835

회귀식 y = wx + b
위에 내용으로 회귀식이 만들어졌다. ( y = 90.34019152878835 * x + 100 )
새로운 값이 예측 가능해졌다.

# y = 90.34019152878835 * x + 100 에서 x에 하나씩 대입해보았다.

y_pred = 90.34019152878835 * -0.19183555 + 100
print('y_pred : ', y_pred)
>> y_pred :  82.66953967096954
# 위의 y의 1번째 값과 비슷하게 결과값이 나왔다.

y_pred = 90.34019152878835 * -1.07296862 + 100
print('y_pred : ', y_pred)
>> y_pred :  3.0678093648202776
# 위의 y의 2번째 값과 비슷하게 결과값이 나왔다.

# 미지의 새로운 값 예측, 원하는 x(=33)값을 넣어서 알고 싶었던 y값을 예측
y_pred_new = 90.34019152878835 * 33 + 100
print('y_pred_new : ', y_pred_new)
>> y_pred_new :  3081.2263204500155

📖방법 2 : LinearRegression을 사용

모델 생성 O

일반 최소 제곱 선형 회귀.
LinearRegression은 계수 w = (w1, …, wp)를 사용하여 선형 모델에 적합하여
데이터 세트에서 관찰된 대상과 선형 근사로 예측된 ​​대상 사이의 잔차 제곱합을 최소화합니다.

from sklearn.linear_model import LinearRegression

# 위의 x 샘플과 y 샘플을 그대로 사용하겠다.
model = LinearRegression().fit(x, y)

# Weight와 bias 구하기
print('기울기(Weight) : ', model.coef_)
#>> 기울기(Weight) :  [90.34019153]
print('절편(bias) : ', model.intercept_)
#>> 절편(bias) :  100.0

# 회귀식 생성 , y = 90.34019153 * x + 100

LinearRegression 의 fit() 메소드를 사용하여 모델을 생성하면
predict() 메소드로 모델 검정이 가능하다!!
❗이 때 주의할 점으로 사이킷런의 입력값으로 x값은 2차원으로, y값은 벡터 타입으로 입력해야한다.

📖predict()

# !!중요!! : 사이킷런의 입력값으로 x값은 2차원으로, y값은 벡터 타입으로 입력해야한다. !!!
y_new = model.predict(x[[0]])
print('y_new :', y_new)
>> y_new : [82.66953946]    # 기존 자료와 비슷하게 나온것을 확인

# 새로운 자료로 예측
y_new = model.predict([[5]])
print('y_new :', y_new)
>>y_new : [551.70095764]

📖방법 3 : ols를 사용

모델 생성 O

# 동일하게 위의 x 샘플과 y 샘플을 그대로 사용하겠다.
import statsmodels.formula.api as smf
import pandas as pd

# x 확인
print(np.shape(x))
#>> (50, 1)

# ols 는 2차원의 파라미터를 사용하지 않으므로 차원을 축소할 필요가 있다.
x1 = x.flatten()
print(x1.shape) # (50,)
y1 = y
print(y1.shape) # (50,)

# DataFrame 으로 데이터 가공
data = np.array([x1, y1])
df = pd.DataFrame(data.T)
print(df.head(3))
'''
          0          1
0 -0.191836  82.669539
1 -1.072969   3.067809
2 -0.172428  84.422803
'''

model2 = smf.ols(formula='y1 ~ x1', data=df).fit()
print(model2.summary()) # OLS Regression Results 제공(!중요(이유: 보고서 만들때 좋다))

model2.summary() 를 출력해보면 아래와 같은 내용이 보인다.

💻model2.summary()

                            OLS Regression Results                            
==============================================================================
Dep. Variable:                     y1   R-squared:                       1.000
Model:                            OLS   Adj. R-squared:                  1.000
Method:                 Least Squares   F-statistic:                 1.249e+33
Date:                Wed, 10 May 2023   Prob (F-statistic):               0.00
Time:                        20:50:31   Log-Likelihood:                 1513.8
No. Observations:                  50   AIC:                            -3024.
Df Residuals:                      48   BIC:                            -3020.
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept    100.0000   2.48e-15   4.03e+16      0.000     100.000     100.000
x1            90.3402   2.56e-15   3.53e+16      0.000      90.340      90.340
==============================================================================
Omnibus:                        0.105   Durbin-Watson:                   0.479
Prob(Omnibus):                  0.949   Jarque-Bera (JB):                0.007
Skew:                           0.004   Prob(JB):                        0.996
Kurtosis:                       2.942   Cond. No.                         1.04
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of 
the errors is correctly specified.

OLS Regression Results 에 대한 자세한 내용은 한 사이트를 참조하는게 나을듯 싶다.
https://ysyblog.tistory.com/119

# 예측 
print(x1[:2])
>> [-0.19183555 -1.07296862]

new_df = pd.DataFrame({'x1':[-0.19183555, -1.07296862]})
new_pred = model2.predict(new_df)
print('new_pred')
print(new_pred) 
'''
0    82.669540
1     3.067809
dtype: float64

기존자료 동일 결과값 확인
'''

# 전혀 새로운 값으로 예측
new2_df = pd.DataFrame({'x1':[-1.000, 12]})
new2_pred = model2.predict(new2_df)
print('new2_pred')
print(new2_pred)
'''
0       9.659808
1    1184.082298
dtype: float64
'''

📖단순 선형회귀 분석 모델 작성 방법 4

scipy.stats.linregress() 을 사용하는 방법이다.

# 단순 선형회귀 분석 모델 작성 방법 4
from scipy import stats
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# IQ와 시험성적간의 인과관계를 확인하고 시험 점수 값 예측하기
score_iq = pd.read_csv('../testdata/score_iq.csv')
print(score_iq.head(3))
'''
     sid  score   iq  academy  game  tv
0  10001     90  140        2     1   0
1  10002     75  125        1     3   3
2  10003     77  120        1     0   4
'''

print(score_iq.corr())
'''
              sid     score        iq   academy      game        tv
sid      1.000000 -0.014399 -0.007048 -0.004398  0.018806  0.024565
score   -0.014399  1.000000  0.882220  0.896265 -0.298193 -0.819752
iq      -0.007048  0.882220  1.000000  0.671783 -0.031516 -0.585033
academy -0.004398  0.896265  0.671783  1.000000 -0.351315 -0.948551
game     0.018806 -0.298193 -0.031516 -0.351315  1.000000  0.239217
tv       0.024565 -0.819752 -0.585033 -0.948551  0.239217  1.000000
'''

# iq 와 score 를 x, y 로 가져오기
x = score_iq.iq
y = score_iq.score

# 선형회귀분석 stats.linregress()
model = stats.linregress(x, y)
print(model)
'''
LinregressResult(slope=0.6514309527270075, intercept=-2.8564471221974657, 
rvalue=0.8822203446134699, pvalue=2.8476895206683644e-50, stderr=0.028577934409305443, 
intercept_stderr=3.546211918048538)
'''

# 결과 값 중 원하는 값 선택하여 출력
print('slope :', model.slope)   # 기울기
print('intercept :', model.intercept)   # bias
print('pvalue :', model.pvalue) 
print('stderr :', model.stderr) # 표준오차
'''
slope : 0.6514309527270075
intercept : -2.8564471221974657
pvalue : 2.8476895206683644e-50
stderr : 0.028577934409305443
'''

기울기와 절편값을 구했으니 검정을 해야하나 LinearRegression 이나 ols 처럼 predict() 함수를 제공하지 않아 사용할 수 없다.
대신, numpy 의 polyval([기울기, 절편], x값) 을 사용할 수 있다.

# predict() 제공 X, 대신으로 numpy 의 polyval([기울기, 절편], x값) 을 사용할 수 있다.
print('예측 값 :', np.polyval([model.slope, model.intercept], \
                            np.array(score_iq['iq'][:5])))
print('실제 값 :', score_iq['score'][:5].values)
'''
예측 값 : [88.34388626 78.57242197 75.31526721 85.0867315  65.54380291]
실제 값 : [90 75 77 83 65]

- 얼추 비슷하게 가까운 값이 확인되었다.
'''

# 새로운 iq값으로 성적 예측
new_df = pd.DataFrame({'iq':[55,66,77,88,99,123]})
print('예측 값 :', np.polyval([model.slope, model.intercept], new_df))
'''
예측 값 : 
[[32.97225528]
 [40.13799576]
 [47.30373624]
 [54.46947672]
 [61.6352172 ]
 [77.26956006]]
'''
profile
개발 시작

0개의 댓글