DataAnalysis-회귀분석

10 minute read

회귀분석

회귀분석은 상관분석과 더불어 널리 쓰이는 통계적 방법이다. 상관분석이 상관관계를 알아보기 위함이라면 회귀분석의 경우 인과관계를 파악하는 분석 방법이다.
회귀분석의 대한 자세한 내용은 아래 링크 참조
회귀분석 자세한 내용

회귀 분석 방법

Python으로 회귀분석은 크게 4가지가 가능하다.

  1. make regression
  2. LinearRegression Model
  3. ols
  4. scipy.stats.linregress

MakeRegression

실제로 운영하기에는 현실적으로 무리가 있는 방법이다.
이렇게 사용 가능하다는 것만 알아두자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#Make Regression
print("Make Regression")
from sklearn.datasets import make_regression

np.random.seed(12)
x, y, coef = make_regression(n_samples = 50, n_features = 1, bias = 100, coef = True)
# n_features : 독립변수. bias : 절편 (디폴트=0.0), coef : 기울기
print(x[[range(1,5)]])
print(y[[range(1,5)]])
print(coef) 
# 표본데이터(x) 50개와 그에따른 y값 50개 반환되었다.
y_pred  = 100 + 89.47430739278907 * -1.70073563
# y_pred : 예측에 의한 y값
#bias: 89.47430739278907
#weight:-1.70073563
print(y) 
# 수식에 의해 예측한 값 = -52.17214255248879
# 실제값 = -52.17214291
# make regression을 이용해 x를 입력하면 수식에 의해 예측된 y값을 도출해낼 수 있다.
# 실제로 운영하기에는 현실적으로 다소 무리가 있다.
# 있다는 것만 알고 넘어가자.


Make Regression
[[-0.67794537]
 [ 0.31866529]
 [ 0.13884618]
 [ 0.53513589]]
[ 39.34130801 128.51235594 112.42316554 147.88091341]
89.47430739278907
[ -52.17214291   39.34130801  128.51235594  112.42316554  147.88091341
   96.49178624  103.16885304   36.12820309   89.71761789  190.59412103
  300.58509445  100.45874176    7.88349776   42.07157936  142.32007968
   -8.72638684   77.28210847   65.60976235  147.18272498  142.27276227
   18.23219105  144.90467678   39.0298914   -98.0364801    89.07073235
   48.8313381   220.10640661   -3.28558253   47.63352619 -181.61291334
  119.23482409  -50.47399897   27.79585534  208.24569942  198.05991459
   46.51020834   10.77587732   52.72138937   89.24271248  106.55417864
   90.52804266  167.38693344  121.69210605  -98.50187763  -59.98849467
  356.95405132  219.52258382  -37.31812896  157.33165682   69.79389882]

LinearRegression

sklearn에 있는 패키지를 사용하는 방법이다.
아래 코드를 활용하여 LinearRegression을 import하여 사용할 수 있다.

1
from sklearn.linear_model import LinearRegression

LinearRegression은 n_jobs: cpu에 따라 병렬로 처리할 수 있게 해주는 Option이 존재한다.
LinearRegressio을 활용하여 Model만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#LinearRegression
x1 = x
y1 = y
from sklearn.linear_model import LinearRegression
model = LinearRegression(fit_intercept=True, n_jobs=None)
#n_jobs: cpu에 따라 병렬로 처리할 수 있게 해주는 Option

print(model)
fit_model = model.fit(x1, y1)

print("기울기: ", fit_model.coef_)
print("절편: ", fit_model.intercept_)
y_new = fit_model.predict(x1)
print(y_new)


LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)
기울기:  [89.47430739]
절편:  100.0
[ -52.17214291   39.34130801  128.51235594  112.42316554  147.88091341
   96.49178624  103.16885304   36.12820309   89.71761789  190.59412103
  300.58509445  100.45874176    7.88349776   42.07157936  142.32007968
   -8.72638684   77.28210847   65.60976235  147.18272498  142.27276227
   18.23219105  144.90467678   39.0298914   -98.0364801    89.07073235
   48.8313381   220.10640661   -3.28558253   47.63352619 -181.61291334
  119.23482409  -50.47399897   27.79585534  208.24569942  198.05991459
   46.51020834   10.77587732   52.72138937   89.24271248  106.55417864
   90.52804266  167.38693344  121.69210605  -98.50187763  -59.98849467
  356.95405132  219.52258382  -37.31812896  157.33165682   69.79389882]


Linear Regression을 활용하여 새로운 값 예측

1
2
3
4
5
#Linear Regression을 활용하여 새로운 값 예측
x_new, _, _ = make_regression(n_samples = 5, n_features = 1, bias = 100, coef = True)
print(x_new)
y_pred2 = fit_model.predict(x_new)
print(y_pred2)


[[-0.5314769 ]
 [ 0.86721724]
 [-1.25494726]
 [ 0.93016889]
 [-1.63412849]]
[ 52.44647266 177.59366163 -12.28553693 183.2262176  -46.21251453]


ols

statsmodels 에 있는 패키지를 사용하는 방법이다.
아래 코드를 활용하여 ols을 import하여 사용할 수 있다.

1
import statsmodels.formula.api as smf

ols Model만들기

1
2
3
4
5
6
7
8
9
10
x1 = x.flatten()
#flatten(): 차원 축소
print(x1.shape)
print(y1.shape)
data = np.array([x1, y1])
df = pd.DataFrame(data.T)
df.columns = ["x1", "y1"]
print(df.head(3))
model = smf.ols(formula = "y1 ~ x1", data = df).fit()
print(model.summary())


(50,)
(50,)
         x1          y1
0 -1.700736  -52.172143
1 -0.677945   39.341308
2  0.318665  128.512356
                            OLS Regression Results                            
==============================================================================
Dep. Variable:                     y1   R-squared:                       1.000
Model:                            OLS   Adj. R-squared:                  1.000
Method:                 Least Squares   F-statistic:                 1.905e+32
Date:                Tue, 30 Jul 2019   Prob (F-statistic):               0.00
Time:                        21:12:20   Log-Likelihood:                 1460.6
No. Observations:                  50   AIC:                            -2917.
Df Residuals:                      48   BIC:                            -2913.
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept    100.0000   7.33e-15   1.36e+16      0.000     100.000     100.000
x1            89.4743   6.48e-15   1.38e+16      0.000      89.474      89.474
==============================================================================
Omnibus:                        7.616   Durbin-Watson:                   1.798
Prob(Omnibus):                  0.022   Jarque-Bera (JB):                8.746
Skew:                           0.516   Prob(JB):                       0.0126
Kurtosis:                       4.770   Cond. No.                         1.26
==============================================================================


Model 해석

1
2
3
4
5
6
print("기울기: ", model.params['x1'])
print("절편: ", model.params['Intercept'])
print("pvalue",model.pvalues)
#pvalue(0) <0.05 이므로 통계적으로 유의하다.
print("설명력",model.rsquared)
#설명력은 100%로 설명력이 높다.


기울기:  89.47430739278903
절편:  99.99999999999999
pvalue Intercept    0.0
x1           0.0
dtype: float64
설명력 1.0


Iris Data를 활용하여 단순회귀 분석과 다중회귀 분석을 하는 예제이다.
단순 회귀 분석은 상관계수에 따른 결과 확인을 한다.

단순 회귀 분석(1) 상관계수 낮은 변수 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#Iris를 활용한 단순 회귀 분석
#상관관계에 따른 결과 확인
import seaborn as sns
print("\n#1. 단순회귀분석")
iris = sns.load_dataset("iris")
print(iris.head(3))
print('상관계수',iris.corr())
#sepal_length ~ sepal_width 의 상관계수 = -0.117570

result = smf.ols("sepal_length ~ sepal_width", data = iris).fit()
print(result.summary())
print("결정 계수: ", result.rsquared)
#0.013822654141080859 => 설명력이 낮다.
print("p값: ", result.pvalues)
print("실제값: ", iris.sepal_length[0], "예측값: ", result.predict()[0])


#1. 단순회귀분석
   sepal_length  sepal_width  petal_length  petal_width species
0           5.1          3.5           1.4          0.2  setosa
1           4.9          3.0           1.4          0.2  setosa
2           4.7          3.2           1.3          0.2  setosa
상관계수               sepal_length  sepal_width  petal_length  petal_width
sepal_length      1.000000    -0.117570      0.871754     0.817941
sepal_width      -0.117570     1.000000     -0.428440    -0.366126
petal_length      0.871754    -0.428440      1.000000     0.962865
petal_width       0.817941    -0.366126      0.962865     1.000000
                            OLS Regression Results                            
==============================================================================
Dep. Variable:           sepal_length   R-squared:                       0.014
Model:                            OLS   Adj. R-squared:                  0.007
Method:                 Least Squares   F-statistic:                     2.074
Date:                Tue, 30 Jul 2019   Prob (F-statistic):              0.152
Time:                        21:12:20   Log-Likelihood:                -183.00
No. Observations:                 150   AIC:                             370.0
Df Residuals:                     148   BIC:                             376.0
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
===============================================================================
                  coef    std err          t      P>|t|      [0.025      0.975]
-------------------------------------------------------------------------------
Intercept       6.5262      0.479     13.628      0.000       5.580       7.473
sepal_width    -0.2234      0.155     -1.440      0.152      -0.530       0.083
==============================================================================
Omnibus:                        4.389   Durbin-Watson:                   0.952
Prob(Omnibus):                  0.111   Jarque-Bera (JB):                4.237
Skew:                           0.360   Prob(JB):                        0.120
Kurtosis:                       2.600   Cond. No.                         24.2
==============================================================================
결정 계수:  0.013822654141080859
p값:  Intercept      6.469702e-28
sepal_width    1.518983e-01
dtype: float64
실제값:  5.1 예측값:  5.744458836939834


단순 회귀 분석(2) 상관계수 높은 변수 사용

1
2
3
4
5
6
7
8
result2 = smf.ols("sepal_length ~ petal_length", data = iris).fit()
#sepal_length ~ petal_length 의 상관계수 = 0.871754
print(result2.summary())
print("결정 계수: ", result2.rsquared) 
#75% 이므로 충분히 설명력을 가진다.
print("p값: ", result2.pvalues)
#pvalue(2.426713e-100) < 0.05 이므로 통계적으로 유의하다.
print("실제값: ", iris.sepal_length[0], "예측값: ", result2.predict()[0])


                            OLS Regression Results                            
==============================================================================
Dep. Variable:           sepal_length   R-squared:                       0.760
Model:                            OLS   Adj. R-squared:                  0.758
Method:                 Least Squares   F-statistic:                     468.6
Date:                Tue, 30 Jul 2019   Prob (F-statistic):           1.04e-47
Time:                        21:12:20   Log-Likelihood:                -77.020
No. Observations:                 150   AIC:                             158.0
Df Residuals:                     148   BIC:                             164.1
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
================================================================================
                   coef    std err          t      P>|t|      [0.025      0.975]
--------------------------------------------------------------------------------
Intercept        4.3066      0.078     54.939      0.000       4.152       4.462
petal_length     0.4089      0.019     21.646      0.000       0.372       0.446
==============================================================================
Omnibus:                        0.207   Durbin-Watson:                   1.867
Prob(Omnibus):                  0.902   Jarque-Bera (JB):                0.346
Skew:                           0.069   Prob(JB):                        0.841
Kurtosis:                       2.809   Cond. No.                         10.3
==============================================================================

결정 계수:  0.7599546457725151
p값:  Intercept       2.426713e-100
petal_length     1.038667e-47
dtype: float64
실제값:  5.1 예측값:  4.879094603339241


다중 회귀 분석 Model 1

1
2
3
4
5
6
7
8
9
10
11
#Iris를 활용한 다중 회귀 분석
print("\n#2. 다중회귀분석")
# 다중회귀분석 formula = "y ~ x1 + x2 + ..."
result3 = smf.ols(formula = "sepal_length ~ petal_length + petal_width", data = iris).fit()
print(result3.summary())
print("결정 계수: ", result3.rsquared)
print("p값: ", result3.pvalues)
'''
결정 계수:  0.7662612975425306 => 충분한 설명력을 가진다.
p값: 2.092645e-85 < 0.05 => 통계적으로 유의하다.
'''


#2. 다중회귀분석
                            OLS Regression Results                            
==============================================================================
Dep. Variable:           sepal_length   R-squared:                       0.766
Model:                            OLS   Adj. R-squared:                  0.763
Method:                 Least Squares   F-statistic:                     241.0
Date:                Tue, 30 Jul 2019   Prob (F-statistic):           4.00e-47
Time:                        21:12:20   Log-Likelihood:                -75.023
No. Observations:                 150   AIC:                             156.0
Df Residuals:                     147   BIC:                             165.1
Df Model:                           2                                         
Covariance Type:            nonrobust                                         
================================================================================
                   coef    std err          t      P>|t|      [0.025      0.975]
--------------------------------------------------------------------------------
Intercept        4.1906      0.097     43.181      0.000       3.999       4.382
petal_length     0.5418      0.069      7.820      0.000       0.405       0.679
petal_width     -0.3196      0.160     -1.992      0.048      -0.637      -0.002
==============================================================================
Omnibus:                        0.383   Durbin-Watson:                   1.826
Prob(Omnibus):                  0.826   Jarque-Bera (JB):                0.540
Skew:                           0.060   Prob(JB):                        0.763
Kurtosis:                       2.732   Cond. No.                         25.3
==============================================================================


결정 계수:  0.7662612975425306
p값:  Intercept       2.092645e-85
petal_length    9.414477e-13
petal_width     4.827246e-02
dtype: float64
'\n결정 계수:  0.7662612975425306 => 충분한 설명력을 가진다.\np값: 2.092645e-85 < 0.05 => 통계적으로 유의하다.\n'


다중 회귀 분석 Model 2

1
2
3
4
5
6
7
8
9
10
column_selected = "+".join(iris.columns.difference(["sepal_length", "sepal_width", "species"]))
print(column_selected)
result4 = smf.ols(formula = "sepal_length ~ " + column_selected, data = iris).fit()
print(result4.summary())
print("결정 계수: ", result4.rsquared)
print("p값: ", result4.pvalues)
'''
결정 계수:  0.7662612975425306 => 충분한 설명력을 가진다.
p값: 2.092645e-85 < 0.05 => 통계적으로 유의하다.
'''


petal_length+petal_width
                            OLS Regression Results                            
==============================================================================
Dep. Variable:           sepal_length   R-squared:                       0.766
Model:                            OLS   Adj. R-squared:                  0.763
Method:                 Least Squares   F-statistic:                     241.0
Date:                Tue, 30 Jul 2019   Prob (F-statistic):           4.00e-47
Time:                        21:12:20   Log-Likelihood:                -75.023
No. Observations:                 150   AIC:                             156.0
Df Residuals:                     147   BIC:                             165.1
Df Model:                           2                                         
Covariance Type:            nonrobust                                         
================================================================================
                   coef    std err          t      P>|t|      [0.025      0.975]
--------------------------------------------------------------------------------
Intercept        4.1906      0.097     43.181      0.000       3.999       4.382
petal_length     0.5418      0.069      7.820      0.000       0.405       0.679
petal_width     -0.3196      0.160     -1.992      0.048      -0.637      -0.002
==============================================================================
Omnibus:                        0.383   Durbin-Watson:                   1.826
Prob(Omnibus):                  0.826   Jarque-Bera (JB):                0.540
Skew:                           0.060   Prob(JB):                        0.763
Kurtosis:                       2.732   Cond. No.                         25.3
==============================================================================

결정 계수:  0.7662612975425306
p값:  Intercept       2.092645e-85
petal_length    9.414477e-13
petal_width     4.827246e-02
dtype: float64
'\n결정 계수:  0.7662612975425306 => 충분한 설명력을 가진다.\np값: 2.092645e-85 < 0.05 => 통계적으로 유의하다.\n'


scipy.stats.linregress

scipy.stats 에 있는 패키지를 사용하는 방법이다.
아래 코드를 활용하여 scipy.stats을 import하여 사용할 수 있다.

1
from scipy import stats

scipy.stats.linregress Model 생성 및 해석

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#scipy.stats.linregress
from scipy import stats

score_iq = pd.read_csv("https://raw.githubusercontent.com/wjddyd66/R/master/Data/score_iq.csv")
print(score_iq.head(3))

print("\n score_iq.corr(): \n", score_iq.corr())
x = score_iq.iq
y = score_iq.score

model = stats.linregress(x, y)
print("\n model: ", model)
print("기울기: ", model.slope) #0.6514309527270075
print("절편: ", model.intercept) #-2.8564471221974657
print("상관계수: ", model.rvalue) #0.8822203446134699
print("p값: ", model.pvalue) #2.8476895206683644e-50
print("표준오차: ", model.stderr) #0.028577934409305443
'''
상관계수:  0.8822203446134699 => 매우 높은 양의 상관관계를 가지고 있다.
p값:  2.8476895206683644e-50 < 0.05 => 통계적으로 유의하다.
'''
iq = 140
y_pred = model.slope * iq + model.intercept
print("예측 된 y값: ", y_pred) #88.34388625958358


     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

 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

 model:  LinregressResult(slope=0.6514309527270075, intercept=-2.8564471221974657, rvalue=0.8822203446134699, pvalue=2.8476895206683644e-50, stderr=0.028577934409305443)
기울기:  0.6514309527270075
절편:  -2.8564471221974657
상관계수:  0.8822203446134699
p값:  2.8476895206683644e-50
표준오차:  0.028577934409305443
예측 된 y값:  88.34388625958358


scipy.stats.linregress Model 시각화

1
2
3
4
5
6
7
#결과 시각화하여 살펴보기
plt.scatter(x, y)
plt.xlim([100,150])
plt.ylim([60,100])
plt.plot(x,0.6514309527270075*x-2.8564471221974657,'r')
plt.legend(["regression line", "x y scatter"])
plt.show()



scipy.stats.linregress 을 활용하여 모집단과 표본집단을 사용할 경우로 나누었다.
모집단: 전체 대상 또는 전체 집합
표본집단: 모집단의 부분집합
모집단에서 표본집단을 추출하는 방법은 다음과 같이 4개가 있다.

  1. 단순임의추출: 임의로 추출
  2. 계통추출: 표본 원소에 번호를 부여한 후 표본의 크기 K값 정함 => 난수표를 이용하여 K-1의 숫자중 하나를 선택하고 그 숫자에 K만큼 더해가며 개체를 선택
  3. 층화추출: 그룹의 차이가 존재하는 그룹으로 나눈뒤 그룹에서 선택
  4. 군집추출: 그룹간의 차이가 없는 그룹으로 나눈뒤 그룹에서 선택

모집단 이용하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#모집단 자료(전체) 이용하기
print("\n <모집단 자료 이용하기>")
product = pd.read_csv("https://raw.githubusercontent.com/wjddyd66/R/master/Data/product.csv")
print(product.head(2))
print(product.corr())
model2 = stats.linregress(product["b"], product["c"])

print("model: ", model2)
print("기울기: ", model2.slope)
print("절편: ", model2.intercept)
print("상관계수: ", model2.rvalue)
print("p값: ", model2.pvalue)
print("표준오차: ", model2.stderr)
'''
상관계수:  0.766852699640837 => 매우 높은 양의 상관관계를 가지고 있다.
p값:  0.235344857549548e-52 < 0.05 => 통계적으로 유의하다.
'''



 <모집단 자료 이용하기>
   a  b  c
0  3  4  3
1  3  3  2
          a         b         c
a  1.000000  0.499209  0.467145
b  0.499209  1.000000  0.766853
c  0.467145  0.766853  1.000000
model:  LinregressResult(slope=0.7392761785971821, intercept=0.7788583344701907, rvalue=0.766852699640837, pvalue=2.235344857549548e-52, stderr=0.03822605528717565)
기울기:  0.7392761785971821
절편:  0.7788583344701907
상관계수:  0.766852699640837
p값:  2.235344857549548e-52
표준오차:  0.03822605528717565
'\n상관계수:  0.766852699640837 => 매우 높은 양의 상관관계를 가지고 있다.\np값:  0.235344857549548e-52 < 0.05 => 통계적으로 유의하다.\n'


모집단 Model 시각화

1
2
3
4
5
6
7
#결과 시각화하여 살펴보기
plt.scatter(product["b"], product["c"])
plt.xlim([0,8])
plt.ylim([0,7])
plt.plot(product["b"],0.7788583344701907*product["b"]+0.7788583344701907,'r')
plt.legend(["regression line", "x y scatter"])
plt.show()



표본집단(단순임의 추출) 이용하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#샘플링 자료 이용하기
print("\n <샘플링 자료 이용하기>")
idx = np.random.randint(1, len(product), 150)
print(len(idx))
dataset = product.loc[idx]
print(dataset[:5])
model3 = stats.linregress(dataset["b"], dataset["c"])
print("model: ", model3)
print("기울기: ", model3.slope)
print("절편: ", model3.intercept)
print("상관계수: ", model3.rvalue)
print("p값: ", model3.pvalue)
print("표준오차: ", model3.stderr)
'''
상관계수:  0.7953597521219435 => 매우 높은 양의 상관관계를 가지고 있다.
p값:  5.424928391628453e-34 < 0.05 => 통계적으로 유의하다.
'''


 <샘플링 자료 이용하기>
150
     a  b  c
77   1  1  1
148  3  3  3
234  3  3  3
159  3  4  4
172  2  2  3
model:  LinregressResult(slope=0.7257880124122156, intercept=0.7924220153519537, rvalue=0.7953597521219435, pvalue=5.424928391628453e-34, stderr=0.045465983691246346)
기울기:  0.7257880124122156
절편:  0.7924220153519537
상관계수:  0.7953597521219435
p값:  5.424928391628453e-34
표준오차:  0.045465983691246346
'\n상관계수:  0.7953597521219435 => 매우 높은 양의 상관관계를 가지고 있다.\np값:  5.424928391628453e-34 < 0.05 => 통계적으로 유의하다.\n'


표본집단(단순임의 추출) Model 시각화

1
2
3
4
5
6
7
#결과 시각화하여 살펴보기
plt.scatter(product["b"], product["c"])
plt.xlim([0,8])
plt.ylim([0,7])
plt.plot(product["b"],0.7257880124122156*product["b"]+0.7924220153519537,'r')
plt.legend(["regression line", "x y scatter"])
plt.show()




참조: 원본코드
코드에 문제가 있거나 궁금한 점이 있으면 wjddyd66@naver.com으로 Mail을 남겨주세요.

Leave a comment