2. 선형회귀분석 (1): 단순선형회귀분석 in python [Advanced Analytics Lab]
앞서 상관관계 분석을 통해 두 변수간 서로 연관성이 있는지 상관계산출과 산점도를 통해 확인해 보았다. 2010년 부터 2016년까지의 삼성전자 주가와 KOSPI 지수의 상관관계 분석 결과 상관계수 0.66으로 삼성전자 주가 변동과 KOSPI 지수의 변동의 뚜렷한 양적 선형 관계가 있음이 증명되었다.
금번 회에서는 단순 선형 회귀분석을 통해 "삼성전자 주가가 1% 증가하면 KOSPI가 몇 % 증가하는가?"에 대한 대답을 확인해 볼 것이다.
회귀분석이란 변수들간의 관계를 파악함으로써 어떤 특정한 변수의 값을 다른 변수들로 설명하고 예측하는 통계적 기법이다. 예측하고자 하는 변수의 값을 종속변수(Dependent Variable)라고 칭하고, 종속변수들을 설명하는 변수들을 독립변수(Independent Variable)라고 부르고, 종속변수와 독립변수의 관계를 도출하는 것을 회귀분석이라 정의한다. 회귀(Regression) 라는 용어의 사전적 정의는 원래 상태로 돌아가는 것을 의미한다. 영국의 인류학자 프랜시스 골턴 경(Sir Francis Galton, 1822~ 1911)은 928명의 성인 자녀의 키와 부모의 키를 조사하여 아래의 표로 정리하였으며, 분석 결과 부모와 자녀의 키 사이에는 선형적 연관관계가 존재하며, 일정한 수준 이상, 또는 이하이면 신장이 무한정 증가하거나 작아지는 것이 아니라 전체 신장의 평균으로 돌아가는 경향이 있다는 것을 밝혔다. 중심으로 돌아가려는 경향(Regress toward mediocrity)을 분석한 이 연구 방법이 "회귀분석"의 어원이 되었다.
프랜시스 골턴 경은 여성의 키에 1.08을 곱하고 부와 모의 키를 평균으로 환산하여 위의 Figure A 왼쪽 그림과 같은 표를 생성하였으며, Figure A 오른쪽 그림과 같이 각 점이 분포 추세를 대표하는 회귀 직선을 생성하였다.
단순 선형 회귀 분석(Simple Linear Regression Analysis)은 Y를 설명하는 변수 X를 한개만 사용하여 오차를 최소화 하는 직선을 생성하는 분석 방법이다. 예를 들어 X와 Y의 관계에서 위와 같은 형태로 점들이 분포하고 있다고 할 때 해당 추세를 가장 잘 설명할 수 있는 직선을 생성하는 것이 단순 선형 회귀분석의 목표이다.
Yi에 대한 회귀 분석 식은 위와 같으며, 그래프로 표현하면 아래와 같다.
최적의 회귀선은 오차항의 총 제곱합을 최소화하는 직선이라고 할 수 있다. 오차의 총 합은 언제나 0이 되기 때문에, 각각의 오차에 제곱을 취하고 오차 제곱들의 총 합을 가 가장 작게 만드는 선이 적합도(Fitness)가 가장 우수한 선이 된다. 오차의 제곱을 최소화 하는 방법을 최소자승법, Ordinary Least Squares Method (OLS) 라고 부른다.
최소자승법에 의해 산출된 최소자승추정량(beta)가 후에 설명할 기본 가정들을 충족한다면, 이 추정량은 불편성(unbiasedness), 효율성(efficiency), 선형성(linearity), 일관성(consistency)를 갖게 되므로, 도출된 beta값을 "최우선형불편추정량" 이라고 표현하며 영어로는 Best Linear Unbiased Estimator (BLUE) 라고 부른다. 즉 오차 (편향, Bias)를 최소화한 직선이라는 말이다. 가우스-마코프 정리(Gauss-Markov Theorem)에서 최소자승법(OLS)으로 추정한 선형추정량은 최우선형불편추정량(BLUE) 임을 밝힌 바 있다.
단순선형회귀분석에서 Least Squares Method를 통해 beta를 추정하는 방법은 아래와 같다.
공분산을 산출하는 수식에서 분모가 n-1 에서 분산으로 바뀌었다. 다음 alpha를 추정해보자.
X평균값에 위에서 산출된 beta값을 곱하고 Y평균값에서 빼주면 alpha가 도출된다.
예제를 통해 산출해 보자. 예제는 기존에 활용했던 KOSPI 지수와 삼성전자 주가로 수행한다. 2010년 1월 5일부터 7일까지 삼성전자 주가와 KOSPI의 로그차분을 통해 산출한 변동률은 아래와 같다 (계산의 편의를 위해 소숫점 두번째 자리에서 반올림을 수행했다.) 로그차분 수행 방법에 대해서는 앞 장(상관관계 분석(3))을 참조하자.
X축에 삼성전자 주가 변동률을, Y축을 KOSPI 변동률로 설정하여 산점도를 그리면 아래와 같은 그림이 나온다.
위 산점도에 오차를 최소화하는 직선을 생성하게 되면 아래와 같은 형태의 직선이 도출될 수 있다.
위와같은 직선을 도출하기 위하여 회귀 분석을 수행해 보자.
(1) 먼저 X와 Y의 평균을 산출하고 각각의 편차(Deviation)를 산출한다.
(2) 산출된 편차를 곱을 하여 총 합을 도출해 분자를 도출한다.
- (1.43)*(-0.08) +(2.12)*(1.12) + (-3.55)*(-1.04) = 5.95
(3) X의 편차를 제곱하여 총 합을 산출해 분모를 도출한다.
- (1.43^2) + (2.12^2) + (-3.55^2) = 19.15
(4) 두 값을 나눠서 beta를 도출한다.
- 5.95 / 19.15 = 0.31
(5) Y 평균값에서 beta에 X의 평균을 곱한 값을 빼준다.
- (-0.25) - (0.31 * 0.16) = (-0.25) - (0.05) = -0.30
세 점에 대한 최적의 직선(Best Linear Unbiased Estimator, BLUE)은 기울기가 0.31이며, x절편이 -0.30인 직선으로 도출되었다. 함수로 표현하면 y = 0.31x - 0.30 가 될 것이다.
위의 예제를 실습데이터를 활용해 진행해 보자. 먼저 필요한 데이터를 pandas_datareader 패키지를 활용해 추출한다.
import numpy as np
import pandas as pd
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import datetime
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2016, 12, 31)
df_KOSPI = web.DataReader("KRX:KOSPI", "google", start, end)
df_SE = web.DataReader("KRX:005930", "google", start, end)
그다음으로 불러온 데이터에 로그 차분을 수행한다.
df_KOSPI["ln_diff"] = (np.log(df_KOSPI["Close"]) - np.log(df_KOSPI["Close"]).shift(1))*100
df_SE["ln_diff"] = (np.log(df_SE["Close"]) - np.log(df_SE["Close"]).shift(1))*100
로그차분을 수행한 후에 2010년 1월 5일부터 7일까지의 세개의 데이터만 추출해 오도록 하겠다.
SE = df_SE.iloc[1:4, 5]
KOSPI = df_KOSPI.iloc[1:4, 5]
추출한 데이터를 활용하여 산점도를 생성한다.
plt.figure(figsize = (8,6))
plt.scatter(SE, KOSPI)
plt.show()
산점도 생성결과 아래와 같은 그림을 얻을 수 있다.
이번에는 회귀 계수 beta와 상수 alpha를 도출해 보자. 단순선형회귀분석은 statmodels 패키지를 통해 수행할 수 있다. 먼저 statmodels.api를 import한다.
import statsmodels.api as sm
다음으로 상수항(alpha)을 회귀식에 추가한다. 상수항은 설명변수에 add_constant 함수를 통해 추가할 수 있다.
SE = sm.add_constant(SE)
최종적으로 모형을 생성하고 모형의 요약에 대하여 출력하면 회귀분석이 완료된다.
model = sm.OLS(KOSPI, SE).fit()
model.summary()
도출된 결과부터 간단히 확인해 보자. Least Squares Method를 활용해 회귀분석이 수행되었으며, X변수인 ln_diff라는 변수는 0.3109의 coefficient를 가졌다. 위의 예제에서 0.31로 계산된 것과 마찬가지의 beta값이 도출되었다. 다음으로는 alpha를 의미하는 const 항목은 -0.3014로 위의 예제에서 계산한 -0.30과 같은 결과가 나왔다.
이번에는 전체 데이터에 적용하여 회귀분석을 수행해 보자. 로그차분을 수행하게 되면 발생하는 최초 관측치가 결측인 현상을 피하기 위해 데이터프레임에서를 0번째 행을 제외한 첫번째 행부터 전체 행까지의 데이터를 추출한다.
SE = df_SE.iloc[1:, 5]
KOSPI = df_KOSPI.iloc[1:, 5]
plt.figure(figsize = (8,6))
plt.scatter(SE, KOSPI)
plt.show()
SE = sm.add_constant(SE)
model = sm.OLS(KOSPI, SE).fit()
model.summary()
2010년부터 2016년까지의 전체 데이터에 적용한 결과 beta값은 0.3752로 도출되었으며, 상수항 x절편은 -0.0071로 나타났다.
마지막으로 산점도에 Linear Regression Line 을 추가해보자.
먼저 numpy에서 제공하는 polyfit함수를 활용하기 위해서 데이터를 numpy array로 변환한다.
SE = np.array(df_SE.iloc[1:, 5])
KOSPI = np.array(df_KOSPI.iloc[1:, 5])
다음으로 polyfit 함수를 활용해 1차 선형회귀 함수를 생성한다.
fit = np.polyfit(SE,KOSPI,1)
print(fit)
다음으로 산점도에 회귀선을 생성한 그래프를 출력하도록 하겠다.
fit_fn = np.poly1d(fit)
print(fit_fn)
plt.figure(figsize = (8,6))
plt.plot(SE, KOSPI,'o', SE, fit_fn(SE), 'r')
plt.show()
그림에서 보는 것과 같이 산점도에 plt.plot() 함수를 활용하여 산점도에 라인을 생성할 수 있다. 이번 회의 목표인 회귀식 도출과 산점도에 회귀선을 생성하는 작업이 모두 끝이 났다.
다시 원점으로 돌아가서, 금번 회를 시작하면서 했던 첫 번째 질문인 "삼성전자 주가가 1% 증가하면 KOSPI가 몇 % 증가하는가?"에 대한 대답을 확인해 보자. 그 대답은 "삼성전자 주가가 1% 증가하면, KOSPI는 0.3752% 증가한다." 이다.
금번 회에서는 단순 선형 회귀분석을 통해 "삼성전자 주가가 1% 증가하면 KOSPI가 몇 % 증가하는가?"에 대한 대답을 확인해 볼 것이다.
회귀분석이란 변수들간의 관계를 파악함으로써 어떤 특정한 변수의 값을 다른 변수들로 설명하고 예측하는 통계적 기법이다. 예측하고자 하는 변수의 값을 종속변수(Dependent Variable)라고 칭하고, 종속변수들을 설명하는 변수들을 독립변수(Independent Variable)라고 부르고, 종속변수와 독립변수의 관계를 도출하는 것을 회귀분석이라 정의한다. 회귀(Regression) 라는 용어의 사전적 정의는 원래 상태로 돌아가는 것을 의미한다. 영국의 인류학자 프랜시스 골턴 경(Sir Francis Galton, 1822~ 1911)은 928명의 성인 자녀의 키와 부모의 키를 조사하여 아래의 표로 정리하였으며, 분석 결과 부모와 자녀의 키 사이에는 선형적 연관관계가 존재하며, 일정한 수준 이상, 또는 이하이면 신장이 무한정 증가하거나 작아지는 것이 아니라 전체 신장의 평균으로 돌아가는 경향이 있다는 것을 밝혔다. 중심으로 돌아가려는 경향(Regress toward mediocrity)을 분석한 이 연구 방법이 "회귀분석"의 어원이 되었다.
프랜시스 골턴 경은 여성의 키에 1.08을 곱하고 부와 모의 키를 평균으로 환산하여 위의 Figure A 왼쪽 그림과 같은 표를 생성하였으며, Figure A 오른쪽 그림과 같이 각 점이 분포 추세를 대표하는 회귀 직선을 생성하였다.
단순 선형 회귀 분석(Simple Linear Regression Analysis)은 Y를 설명하는 변수 X를 한개만 사용하여 오차를 최소화 하는 직선을 생성하는 분석 방법이다. 예를 들어 X와 Y의 관계에서 위와 같은 형태로 점들이 분포하고 있다고 할 때 해당 추세를 가장 잘 설명할 수 있는 직선을 생성하는 것이 단순 선형 회귀분석의 목표이다.
Yi에 대한 회귀 분석 식은 위와 같으며, 그래프로 표현하면 아래와 같다.
최적의 회귀선은 오차항의 총 제곱합을 최소화하는 직선이라고 할 수 있다. 오차의 총 합은 언제나 0이 되기 때문에, 각각의 오차에 제곱을 취하고 오차 제곱들의 총 합을 가 가장 작게 만드는 선이 적합도(Fitness)가 가장 우수한 선이 된다. 오차의 제곱을 최소화 하는 방법을 최소자승법, Ordinary Least Squares Method (OLS) 라고 부른다.
최소자승법에 의해 산출된 최소자승추정량(beta)가 후에 설명할 기본 가정들을 충족한다면, 이 추정량은 불편성(unbiasedness), 효율성(efficiency), 선형성(linearity), 일관성(consistency)를 갖게 되므로, 도출된 beta값을 "최우선형불편추정량" 이라고 표현하며 영어로는 Best Linear Unbiased Estimator (BLUE) 라고 부른다. 즉 오차 (편향, Bias)를 최소화한 직선이라는 말이다. 가우스-마코프 정리(Gauss-Markov Theorem)에서 최소자승법(OLS)으로 추정한 선형추정량은 최우선형불편추정량(BLUE) 임을 밝힌 바 있다.
단순선형회귀분석에서 Least Squares Method를 통해 beta를 추정하는 방법은 아래와 같다.
공분산을 산출하는 수식에서 분모가 n-1 에서 분산으로 바뀌었다. 다음 alpha를 추정해보자.
X평균값에 위에서 산출된 beta값을 곱하고 Y평균값에서 빼주면 alpha가 도출된다.
예제를 통해 산출해 보자. 예제는 기존에 활용했던 KOSPI 지수와 삼성전자 주가로 수행한다. 2010년 1월 5일부터 7일까지 삼성전자 주가와 KOSPI의 로그차분을 통해 산출한 변동률은 아래와 같다 (계산의 편의를 위해 소숫점 두번째 자리에서 반올림을 수행했다.) 로그차분 수행 방법에 대해서는 앞 장(상관관계 분석(3))을 참조하자.
일자 | SE | KOSPI |
2010-01-05 | 1.59 | -0.33 |
2010-01-06 | 2.29 | 0.87 |
2010-01-07 | -3.39 | -1.29 |
X축에 삼성전자 주가 변동률을, Y축을 KOSPI 변동률로 설정하여 산점도를 그리면 아래와 같은 그림이 나온다.
위 산점도에 오차를 최소화하는 직선을 생성하게 되면 아래와 같은 형태의 직선이 도출될 수 있다.
위와같은 직선을 도출하기 위하여 회귀 분석을 수행해 보자.
(1) 먼저 X와 Y의 평균을 산출하고 각각의 편차(Deviation)를 산출한다.
일자 | SE | Avg_SE | Dev_SE | KOSPI | Avg_KOSPI | Dev_KOSPI |
01-05 | 1.59 | 0.16 | 1.43 | -0.33 | -0.25 | -0.08 |
01-06 | 2.29 | 0.16 | 2.12 | 0.87 | -0.25 | 1.12 |
01-07 | -3.39 | 0.16 | -3.55 | -1.29 | -0.25 | -1.04 |
(2) 산출된 편차를 곱을 하여 총 합을 도출해 분자를 도출한다.
- (1.43)*(-0.08) +(2.12)*(1.12) + (-3.55)*(-1.04) = 5.95
(3) X의 편차를 제곱하여 총 합을 산출해 분모를 도출한다.
- (1.43^2) + (2.12^2) + (-3.55^2) = 19.15
(4) 두 값을 나눠서 beta를 도출한다.
- 5.95 / 19.15 = 0.31
(5) Y 평균값에서 beta에 X의 평균을 곱한 값을 빼준다.
- (-0.25) - (0.31 * 0.16) = (-0.25) - (0.05) = -0.30
세 점에 대한 최적의 직선(Best Linear Unbiased Estimator, BLUE)은 기울기가 0.31이며, x절편이 -0.30인 직선으로 도출되었다. 함수로 표현하면 y = 0.31x - 0.30 가 될 것이다.
위의 예제를 실습데이터를 활용해 진행해 보자. 먼저 필요한 데이터를 pandas_datareader 패키지를 활용해 추출한다.
import numpy as np
import pandas as pd
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import datetime
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2016, 12, 31)
df_KOSPI = web.DataReader("KRX:KOSPI", "google", start, end)
df_SE = web.DataReader("KRX:005930", "google", start, end)
그다음으로 불러온 데이터에 로그 차분을 수행한다.
df_KOSPI["ln_diff"] = (np.log(df_KOSPI["Close"]) - np.log(df_KOSPI["Close"]).shift(1))*100
df_SE["ln_diff"] = (np.log(df_SE["Close"]) - np.log(df_SE["Close"]).shift(1))*100
로그차분을 수행한 후에 2010년 1월 5일부터 7일까지의 세개의 데이터만 추출해 오도록 하겠다.
SE = df_SE.iloc[1:4, 5]
KOSPI = df_KOSPI.iloc[1:4, 5]
추출한 데이터를 활용하여 산점도를 생성한다.
plt.figure(figsize = (8,6))
plt.scatter(SE, KOSPI)
plt.show()
산점도 생성결과 아래와 같은 그림을 얻을 수 있다.
이번에는 회귀 계수 beta와 상수 alpha를 도출해 보자. 단순선형회귀분석은 statmodels 패키지를 통해 수행할 수 있다. 먼저 statmodels.api를 import한다.
import statsmodels.api as sm
다음으로 상수항(alpha)을 회귀식에 추가한다. 상수항은 설명변수에 add_constant 함수를 통해 추가할 수 있다.
SE = sm.add_constant(SE)
최종적으로 모형을 생성하고 모형의 요약에 대하여 출력하면 회귀분석이 완료된다.
model = sm.OLS(KOSPI, SE).fit()
model.summary()
Dep. Variable: | ln_diff | R-squared: | 0.793 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.586 |
Method: | Least Squares | F-statistic: | 3.830 |
Date: | Mon, 28 Aug 2017 | Prob (F-statistic): | 0.301 |
Time: | 17:32:52 | Log-Likelihood: | -1.5179 |
No. Observations: | 3 | AIC: | 7.036 |
Df Residuals: | 1 | BIC: | 5.233 |
Df Model: | 1 | ||
Covariance Type: | nonrobust |
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
const | -0.3014 | 0.402 | -0.750 | 0.591 | -5.412 | 4.809 |
ln_diff | 0.3109 | 0.159 | 1.957 | 0.301 | -1.708 | 2.329 |
Omnibus: | nan | Durbin-Watson: | 2.295 |
---|---|---|---|
Prob(Omnibus): | nan | Jarque-Bera (JB): | 0.308 |
Skew: | -0.233 | Prob(JB): | 0.857 |
Kurtosis: | 1.500 | Cond. No. | 2.54 |
도출된 결과부터 간단히 확인해 보자. Least Squares Method를 활용해 회귀분석이 수행되었으며, X변수인 ln_diff라는 변수는 0.3109의 coefficient를 가졌다. 위의 예제에서 0.31로 계산된 것과 마찬가지의 beta값이 도출되었다. 다음으로는 alpha를 의미하는 const 항목은 -0.3014로 위의 예제에서 계산한 -0.30과 같은 결과가 나왔다.
이번에는 전체 데이터에 적용하여 회귀분석을 수행해 보자. 로그차분을 수행하게 되면 발생하는 최초 관측치가 결측인 현상을 피하기 위해 데이터프레임에서를 0번째 행을 제외한 첫번째 행부터 전체 행까지의 데이터를 추출한다.
SE = df_SE.iloc[1:, 5]
KOSPI = df_KOSPI.iloc[1:, 5]
plt.figure(figsize = (8,6))
plt.scatter(SE, KOSPI)
plt.show()
SE = sm.add_constant(SE)
model = sm.OLS(KOSPI, SE).fit()
model.summary()
Dep. Variable: | ln_diff | R-squared: | 0.440 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.440 |
Method: | Least Squares | F-statistic: | 1359. |
Date: | Mon, 28 Aug 2017 | Prob (F-statistic): | 4.97e-220 |
Time: | 17:50:03 | Log-Likelihood: | -1934.7 |
No. Observations: | 1732 | AIC: | 3873. |
Df Residuals: | 1730 | BIC: | 3884. |
Df Model: | 1 | ||
Covariance Type: | nonrobust |
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
const | -0.0071 | 0.018 | -0.398 | 0.691 | -0.042 | 0.028 |
ln_diff | 0.3752 | 0.010 | 36.863 | 0.000 | 0.355 | 0.395 |
Omnibus: | 198.591 | Durbin-Watson: | 1.838 |
---|---|---|---|
Prob(Omnibus): | 0.000 | Jarque-Bera (JB): | 892.240 |
Skew: | -0.459 | Prob(JB): | 1.79e-194 |
Kurtosis: | 6.394 | Cond. No. | 1.75 |
2010년부터 2016년까지의 전체 데이터에 적용한 결과 beta값은 0.3752로 도출되었으며, 상수항 x절편은 -0.0071로 나타났다.
마지막으로 산점도에 Linear Regression Line 을 추가해보자.
먼저 numpy에서 제공하는 polyfit함수를 활용하기 위해서 데이터를 numpy array로 변환한다.
SE = np.array(df_SE.iloc[1:, 5])
KOSPI = np.array(df_KOSPI.iloc[1:, 5])
다음으로 polyfit 함수를 활용해 1차 선형회귀 함수를 생성한다.
fit = np.polyfit(SE,KOSPI,1)
print(fit)
[ 0.37518626 -0.0070747 ]np.polyfit(SE,KOSPI,1) 명령을 통해 x를 삼성전자 주가, Y를 KOSPI로 설정하고 1차함수를 생성하였다. 출력된 함수의 결과값을 확인하면 x의 계수가 0.37518, 상수항이 -0.0071로 statmodels.api 패키지를 활용한 결과와 동일한 것을 알 수 있다.
다음으로 산점도에 회귀선을 생성한 그래프를 출력하도록 하겠다.
fit_fn = np.poly1d(fit)
print(fit_fn)
0.3752 x - 0.007075산점도를 생성하기 위하여 약간의 사전 작업이 필요하다. np.poly1d() 함수는 fit에서 생성된 array를 함수식 형태로 변환시켜주는 numpy의 함수이다. print함수를 사용하여 출력해 보면 먼저 polyfit으로 생성된 계수 (coefficient) 들이 담겨 있는 array가 0.3752 x - 0.007075 형태의 1차 함수식으로 변형된 것을 확인할 수 있다. 자세한 내용은 numpy 매뉴얼 링크(numpy.poly1d) 에서 확인할 수 있다.
plt.figure(figsize = (8,6))
plt.plot(SE, KOSPI,'o', SE, fit_fn(SE), 'r')
plt.show()
그림에서 보는 것과 같이 산점도에 plt.plot() 함수를 활용하여 산점도에 라인을 생성할 수 있다. 이번 회의 목표인 회귀식 도출과 산점도에 회귀선을 생성하는 작업이 모두 끝이 났다.
다시 원점으로 돌아가서, 금번 회를 시작하면서 했던 첫 번째 질문인 "삼성전자 주가가 1% 증가하면 KOSPI가 몇 % 증가하는가?"에 대한 대답을 확인해 보자. 그 대답은 "삼성전자 주가가 1% 증가하면, KOSPI는 0.3752% 증가한다." 이다.
Comments
Post a Comment