--- title: "Multiple Regression" subtitle: "FMB819: R을 이용한 데이터분석" author: "고려대학교 경영대학 정지웅" format: revealjs: theme: simple transition: fade transition-speed: fast scrollable: true chalkboard: true slide-number: true revealjs-plugins: - revealjs-text-resizer --- ```{r setup, include=FALSE,warning=FALSE,message=FALSE} options(htmltools.dir.version = FALSE) knitr::opts_chunk$set( message = FALSE, warning = FALSE, dev = "svg", cache = TRUE, fig.align = "center", comment = "##" #fig.width = 11, #fig.height = 5 ) # define vars om = par("mar") lowtop = c(om[1],om[2],0.1,om[4]) library(magrittr) # library(plotly) # library(reshape2) # library(haven) # library(tidyverse) library(countdown) # countdown style countdown( color_border = "#d90502", color_text = "black", color_running_background = "#d90502", color_running_text = "white", color_finished_background = "white", color_finished_text = "#d90502", color_finished_border = "#d90502" ) ``` ------------------------------------------------------------------------ ## Today's Agenda - **다중 독립 변수** - **누락 변수 편향** (Omitted Variable Bias) - **조정된** $R^2$ (Adjusted $R^2$) ------------------------------------------------------------------------ ## 복습: 단순 선형 회귀 분석 **Capital Asset Pricing Model 자산가격결정모형** - 자산의 리스크프리미엄을 어떻게 결정해야하는지에 대한 모형 - 포트폴리오 이론에 기반을 둠 - 즉 모든 투자자는 분산이 최대화된 시장포트폴리오에 투자하며, - 개별 자산 고유의 리스크는 제거 될 수 있으므로, 이에 대한 리스크 프리미엄은 0이 됨. - 제거되지 못하는 체계적 위험에 대해서만 리스크 프리미엄이 존재함. - 자산의 체계적 위험은 자산과 시장포트폴리오 간의 공분산으로 측정됨. - '베타'는 이러한 체계적 위험의 크기를 측정: $E(R_i) = R_f + \beta_i (E(R_m) - R_f)$ - CAPM은 “리스크 프리미엄을 베타 하나로 설명하는” **벤치마크** - CAPM을 **완전한 진리**라기보다, **출발점**으로 사용 ------------------------------------------------------------------------ ## CAPM의 활용 - **기업가치평가(DCF)**: 할인율이 필요함 - **프로젝트 투자판단(NPV)**: 프로젝트의 리스크에 맞는 요구수익률이 필요함 - **성과평가(알파/샤프/정보비율)**: "시장을 감안하면 잘했나?"를 평가해야 함 - **포트폴리오/리스크관리**: "이 자산이 시장과 얼마나 연동되는가?"를 알아야 함 - **단순 선형 회귀**를 이용하여 베타를 추정 - 자산의 초과 수익률을 종속 변수로, 시장 포트폴리오의 초과 수익률을 독립 변수로 하는 회귀 분석 수행 ------------------------------------------------------------------------ ## 베타의 추정 ```{r beta1, echo = TRUE, eval = TRUE} # (설치되지 않은 경우 주석 해제하여 설치) # install.packages("tidyquant") # install.packages("tidyr") # install.packages("dplyr") library(tidyquant) library(tidyr) library(dplyr) raw_data <- tq_get(c("^KS200", "006800.KS"), get = "stock.prices", from = "2010-01-01", to = Sys.Date()) # 결측치 정리 (NA 제거): 수정주가(adjusted)를 기준으로 결측치가 있는 행을 제거. clean_data <- raw_data %>% drop_na(adjusted) # 월별 수익률 계산: tq_transmute를 사용하여 일별 주가를 월별 수익률로 변환. monthly_returns <- clean_data %>% group_by(symbol) %>% tq_transmute(select = adjusted, mutate_fun = periodReturn, period = "monthly", col_rename = "monthly_return") # 베타 추정을 위한 데이터 구조 변경 (Wide format) # 선형 회귀(lm) 함수에 넣기 쉽게 두 자산의 수익률을 각각의 열로 배치. returns_wide <- monthly_returns %>% pivot_wider(names_from = symbol, values_from = monthly_return) %>% rename(KOSPI200 = `^KS200`, MiraeAsset = `006800.KS`) %>% drop_na() # 두 지표 모두 데이터가 존재하는 월만 남김 # 베타(Beta) 추정 beta_model <- lm(MiraeAsset ~ KOSPI200, data = returns_wide) # 회귀분석 결과 요약 출력 summary(beta_model) ``` --- ## 베타의 추정: 그래프 ```{r beta1_plot, echo = TRUE, eval = TRUE, fig.width = 10, fig.height = 10} plot(returns_wide$KOSPI200, returns_wide$MiraeAsset, xlab = "KOSPI 200", ylab = "Mireae Asset") abline(beta_model, col = "red", lwd = 2) # 회귀선 덧그리기 (빨간색 굵은 선) eq <- sprintf("y = %.4f * x + %.4f", coef(beta_model)[2], coef(beta_model)[1]) legend("topleft", legend = eq, bty = "n", text.col = "red") ``` ------------------------------------------------------------------------ ## 다중 회귀 분석 모형 - **단순 선형 회귀 모델(Simple Linear Model)** 은 다음과 같이 표현됨: $$ y_i = b_0 + b_1 x_i + e_i $$ - `X`가 `Y`를 **인과적으로(causally) 결정한다고 주장**하려면, - **`X`의 값을 변경했을 때(`X`를 조작), 다른 모든 요인은 동일하게 유지(ceteris paribus)되면서 `Y`가 변화해야 함**. - ⚠️ 만약 $y_i$에 영향을 주는 다른 모든 요인이 $x_i$와 상관관계가 있다면,\ → $b_1$은 인과적 효과(Causal Effect)로 해석될 수 없음. - 이를 해결하기 위해, **모델을 확장하고($y_i$를 동시에 설명하는 다른 요인을 포함)**\ → $y_i$와 $x_i$ 모두와 관련된 변수들을 고려해야 함. ------------------------------------------------------------------------ ## 다중 회귀 분석 모델 확장된 회귀 모델은 다음과 같이 표현됨: $$ y_i = b_0 + b_1 x_{1,i} + b_2 x_{2,i} + b_3 x_{3,i} + \dots + b_k x_{k,i} + e_i $$ - 여기서 $x_1$, $x_2$, ..., $x_k$ 는 $k$개의 독립 변수(regressors)\ - $b_1$, $b_2$, ..., $b_k$ 는 **각 독립 변수에 대응하는 회귀 계수(coefficients)** **추정(Estimation)** - $(b_0, b_1, b_2, ..., b_k)$ 값은 **최소자승법(OLS, Ordinary Least Squares)** 을 사용하여 추정됨.\ - 즉, 다음을 **최소화하는 값**을 찾음: $$ \begin{align} \sum_{i}{e_i^2} &= \sum_{i}{(y_i - \hat{y_i})^2} \\ &= \sum_{i}{[y_i - (b_0 + b_1 x_{1,i} + b_2 x_{2,i} + b_3 x_{3,i} + \dots + b_k x_{k,i})]^2} \end{align} $$ - **OLS는 잔차 제곱합(Sum of Squared Residuals, SSR)** 을 최소화하는 방식으로 최적의 계수를 찾음. ------------------------------------------------------------------------ ## 다중 회귀 분석: 해석 - **절편 (**$b_0$): $x_1, x_2, x_3, ...$ 모든 독립 변수가 0일 때, 예측된 $y$ 값 $\widehat{y}$ - **기울기 (**$b_k$): $x_k$가 1 단위 증가할 때, $y$ 값이 평균적으로 어떻게 변하는지 예측... 단, 다른 모든 독립 변수들은 일정하게 유지! - **다른 모든 변수들을 일정하게 유지한다는 점**이 **단순 선형 회귀(SLM)와 다른 점**.\ - 즉, $x_k$가 $y$에 미치는 개별적인 효과를 고립시켜 분석하는 것. - **인과 추론(Causal Inference)을 유의해야 하는 점** - 다중 회귀 분석에서는 **모델에 포함된 변수들만 일정하게 유지**됨.\ - 하지만, **모델에 포함되지 않은 변수들은 여전히 변할 수 있어, 추정값에 편향을 일으킬 가능성이 있음.** ------------------------------------------------------------------------ ## `R`을 사용한 다중 회귀 분석 - 단순 선형 회귀와 매우 유사함. - `lm()` 함수를 사용하여 다중 회귀 분석 수행 가능. ```r lm(formula = dependent variable ~ independent variable 1 + independent variable 2 + ..., data = data.frame containing the data) ``` ------------------------------------------------------------------------ ## 다중 회귀 분석: 베타 추정 - 한국 상장 기업 수익률이 한국 시장 뿐만 아니라 해외 시장에도 영향을 받을 수 있다면 - 한국 시장 수익률 뿐만 아니라, 미국, 중국, 일본 시장 수익률도 포함하여 회귀 분석을 수행할 수 있음. $KOSPI200 = b_0 + b_1 SP500 + b_2 SSE + b_3 N225 + e$ ## 다중 회귀 분석: 베타 추정 ```{r beta2, echo = TRUE, eval = TRUE} library(tidyquant) # 금융 데이터 수집 및 변환을 위한 패키지 library(tidyr) # 데이터 구조 변경을 위한 패키지 library(dplyr) raw_data <- tq_get(c("^KS200", "006800.KS", "^SP500TR", "000001.SS", "^N225"), get = "stock.prices", from = "2010-01-01", to = Sys.Date()) # 결측치 정리 (NA 제거): 수정주가(adjusted)를 기준으로 결측치가 있는 행을 제거. clean_data <- raw_data %>% drop_na(adjusted) # 월별 수익률 계산: tq_transmute를 사용하여 일별 주가를 월별 수익률로 변환. monthly_returns <- clean_data %>% group_by(symbol) %>% tq_transmute(select = adjusted, mutate_fun = periodReturn, period = "monthly", col_rename = "monthly_return") # 베타 추정을 위한 데이터 구조 변경 returns_wide <- monthly_returns %>% pivot_wider(names_from = symbol, values_from = monthly_return) %>% rename(KOSPI200 = `^KS200`, MiraeAsset = `006800.KS`, SP500 = `^SP500TR`, SSE = `000001.SS`, N225 = `^N225`) %>% arrange(date) %>% mutate(SP500_lag = lag(SP500), SSE_lag = lag(SSE)) %>% # SP500과 SSE, N225의 1개월 지연값 추가 drop_na() # 기존 결측치 및 lead/lag 함수 사용으로 인해 첫째 달과 마지막 달에 발생한 NA 제거 # 베타(Beta) 추정 (Lead, Lag 포함) beta_model <- lm(MiraeAsset ~ KOSPI200 + SP500 + SSE + N225, data = returns_wide) summary(beta_model) ``` ***Questions*** 1. 각 회귀 계수(coefficients)는 어떻게 해석할 수 있는가? 2. 단순 선형 회귀(SLM)와 비교했을 때 KOSPI200 계수는 어떻게 달라졌는가? 3. 미래에셋 수익률을 S&P500 수익률에 대해 회귀 분석을 수행했을 때, 베타는 어떤가? ------------------------------------------------------------------------ ## 다중공선성(Perfect Collinearity) - 추가하는 변수는 반드시 **새로운 정보**를 제공해야 함. - 회귀 모형에 추가하는 변수들은 **완전히 선형결합(linear combination)**이 될 수 없음. $$ x_2 \neq a x_1 + b $$ - 즉, 하나의 독립 변수를 다른 독립 변수들의 조합으로 완전히 표현할 수 있으면 안 됨. - **완벽하게 선형 결합된 경우** → 회귀 분석 수행 불가능 - **높은 상관관계를 가지는 경우**: **각 독립 변수의 개별적 효과(계수)를 정확히 분리하기 어려움** → 추정된 계수의 신뢰도가 낮아질 수 있음 - **관측치 수(Observations) \> 독립 변수 개수(Independent Variables)**: **즉, 너무 많은 변수를 추가하면 과적합(overfitting) 문제가 발생할 수 있음.** → ✅ **반드시 충족해야 하는 조건!** ------------------------------------------------------------------------ ## 다중공선성(Perfect Collinearity) - 다중공선성 문제를 확인하는 방법 - **분산 팽창 계수(Variance Inflation Factor, VIF)**: 일반적으로 VIF 값이 10을 초과하면 다중공선성 문제가 있다고 간주됨. - **상관 행렬**: 독립 변수들 간의 상관 관계를 시각적으로 확인. - **회귀 계수의 부호 변화**: 다중공선성이 존재할 때, 회귀 계수의 부호가 예상과 다르게 나타날 수 있음. - **회귀 계수의 유의성**: 다중공선성이 존재할 때, 회귀 계수의 유의성이 낮아질 수 있음. 이는 모델의 예측 성능을 저하시킬 수 있음. ```{r vif, echo = TRUE, eval = TRUE} library(car) # VIF 계산을 위한 패키지 vif(beta_model) # VIF 값 계산 cor(returns_wide[, c("KOSPI200", "SP500", "SSE", "N225")]) # 상관 행렬 계산 ``` ------------------------------------------------------------------------ ## Task 1 {background-color="#ffebf0"} `r countdown(minutes = 5, top = "20px", right = "10px", font_size = "0.8em", color_border = "blue")` `grades` 데이터: - 학생들의 학업 성취도에 영향을 미치는 요인들을 분석하기 위한 데이터셋 - 학생들의 읽기 점수(avgverb), 수학 점수(avgmath), 학급 규모(classize), 그리고 사회경제적 불리함(disadvantaged) 등의 변수를 포함 - **읽기(Reading) 점수를 종속 변수(Dependent Variable)** 로 설정하여 회귀 분석을 수행 1. `haven` 패키지의 `read_dta()` 함수를 사용하여 데이터를 불러오기. 데이터를 `grades`라는 객체에 저장 ```{r task1_1, echo=FALSE, eval=FALSE} library(haven) grades <- read_dta("https://raw.githack.com/chung-jiwoong/FMB819/refs/heads/main/chapter_slr/data/grade5.dta") ``` 2. avgverb (읽기 점수)를 종속 변수로, classize와 disadvantaged를 독립 변수로 사용하여 회귀분석. 결과를 reg 객체에 저장. 각 계수(coefficient)의 의미는 무엇인가? 단순 선형 회귀와 비교했을 때 계수는 어떻게 달라졌는가? 수학 점수 회귀 분석과 비교했을 때 계수의 차이점은 무엇인가? ```{r task1_2, echo=FALSE, eval=FALSE} reg <- lm(avgverb ~ classize + disadvantaged, data = grades) summary(reg) ``` ------------------------------------------------------------------------ ## 누락변수 편의 (Omitted Variable Bias, OVB) - ***OVB*** 이란, 회귀 분석에서 중요한 **통제 변수(control variable)** 를 제외함으로써 발생하는 **편의(bias)** 을 의미. - 이로 인해 관심 있는 독립 변수의 계수를 **신뢰할 수 없고, 왜곡될 수 있음.** $y$: 종속변수, $x$: 독립변수, $z$: 누락변수인 경우 다음 회귀분석이 가능 **1️⃣ 단순 선형 회귀 모델 (Simple Linear Model)** $$ y = b_0 + b_1x + e $$ - 이 경우, $x$와 $z$가 동시에 $y$에 영향을 미친다면, $z$를 제외하면 $b_1$이 편향될 수 있음. **2️⃣ 다중 선형 회귀 모델 (Multiple Linear Model)**: 만약 $z$ 변수를 포함한다면? $$ y = c_0 + c_1x + \color{#d90502}{c_2}z + e $$ - 이 모델에서는 $x$뿐만 아니라 누락된 변수 $z$도 $y$에 영향을 미침. 즉, $z$를 포함하면, $c_1$이 더 정확한 값을 가질 수 있음. ------------------------------------------------------------------------ ## 누락변수 편의 (Omitted Variable Bias, OVB) **3️⃣ 누락된 변수와** $x$의 관계 (Omitted Variable on Regressor) $$ z = d_0 + \color{#d96502}{d_1}x + e $$ - 이 모델은 $x$와 생략된 변수 $z$가 서로 상관관계가 있을 경우를 나타냄. - 즉, $x$가 $z$에 영향을 미친다면, 단순 회귀 분석에서 $b_1$의 추정치는 신뢰할 수 없게 됨. **📌 OVB 공식** $$ \text{OVB} = \color{#d90502}{c_2} \times \color{#d96502}{d_1} $$ 즉, $$ b_1 = c_1 + OVB $$ 💡 **결론:**\ 만약 $z$를 생략하면, $b_1$은 $c_1$에 OVB가 더해진 값이 되어, 실제 값과 차이가 날 수 있음. ------------------------------------------------------------------------ ## 누락변수 편의 (Omitted Variable Bias, OVB) $$ \text{OVB} = \underbrace{\text{다중 회귀에서 생략된 변수의 계수}}_{\color{#d90502}{c_2}} \times \underbrace{\frac{Cov(x,z)}{Var(x)}}_{\color{#d96502}{d_1}} $$ **OVB의 의미** 1. OVB의 크기(magnitude) - $z$ 변수가 관측되는 경우, OVB의 크기를 직접 계산할 수 있음. 2. OVB의 부호(sign) (양수/음수 여부) - 현실적으로는 $z$ 변수를 관측할 수 없는 경우가 많기 때문에, **OVB의 부호가 더 중요한 분석 요소**가 됨. - OVB가 **양수(+)인지 음수(-)인지**를 판단하면, $x$의 계수가 과대(+) 또는 과소(-) 추정되는지 예측할 수 있음. ::: callout 소득(income)과 교육연수(years of education) 사이의 관계를 분석할 때, 1. 단순 회귀 분석에서 소득을 교육연수에 회귀(regression) 시키면 신뢰할 수 없는 추정치가 나올 가능성이 있다. 왜 그럴까? 2. 어떤 변수가 누락된 변수(omitted variable)일 수 있을까?\ 3. OVB의 부호(+) 또는 (-)는 어떻게 예상할 수 있을까? ::: ------------------------------------------------------------------------ ## 누락변수 편의 (Omitted Variable Bias, OVB): 예제 - 학급 규모(`classize`)가 학생들의 평균 수학 점수(`avgmath`)에 미치는 영향 $$ \text{avg math} = b_0 + b_1\text{size} + e $$ ***단순회귀모형:*** $\text{avg math} = b_0 + b_1\text{size} + e$ ```{r, echo = FALSE, eval=TRUE} library(haven) grades <- read_dta("https://raw.githack.com/chung-jiwoong/FMB819/refs/heads/main/chapter_slr/data/grade5.dta") ``` ```{r, echo = FALSE} reg1 <- lm(avgmath ~ classize, grades) reg1$coefficients ``` ***다중회귀모형:*** $\text{avg math} = c_0 + c_1\text{size} + \color{#d90502}{c_2}\text{ \% disadvantaged} + e$ ```{r, echo = FALSE} reg2 <- lm(avgmath ~ classize + disadvantaged, grades) reg2$coefficients ``` ***누락변수와 독립변수***: $\text{\% disadvantaged} = d_0 + \color{#d96502}{d_1}\text{size} + e$ ```{r, echo = FALSE} reg3 <- lm(disadvantaged ~ classize, grades) reg3$coefficients ``` 따라서: $$b_1 = `r round(reg1$coefficients[2],3)` = \underbrace{`r round(reg2$coefficients[2],3)`}_{c_1} + \underbrace{(`r round(reg2$coefficients[3],3)`)}_{\color{#d90502}{c_2}} \times \underbrace{(`r round(reg3$coefficients[2],3)`)}_{\color{#d96502}{d_1}} = c_1 + OVB$$ ------------------------------------------------------------------------ ## 수정된 결정 계수 (Adjusted $R^2$) - $R^2$ (결정 계수) 는 회귀 모델이 **종속 변수(**$y$)의 변동을 얼마나 설명하는지 나타내는 지표. - 하지만, **새로운 변수를 추가할 때마다** $R^2$ 값은 항상 증가. - 심지어 **의미 없는 변수라도 추가하면** $R^2$이 증가할 수 있음! - 이를 보완하기 위해 **수정된** $R^2$ (Adjusted $R^2$) 개념이 도입 - **불필요한 변수를 추가하는 것을 방지하기 위해 패널티(penalty)를 부과**\ - 하지만, 대부분의 경우 $R^2$와 수정된 $R^2$는 큰 차이가 없음 ------------------------------------------------------------------------ ## Task 2 {background-color="#ffebf0"} `r countdown(minutes = 15, top = "20px", right = "10px", font_size = "0.8em", color_border = "blue")` **STAR 데이터** - STAR(Student Teacher Achievement Ratio) 데이터는 1985년부터 1989년까지 미국 테네시 주에서 진행된 무작위 실험의 결과를 담고 있음. - 학생들을 소규모 학급(small), 일반 학급(regular), 보조 교사가 있는 일반 학급(regular+aide)으로 무작위 배정하여, 학급 규모가 학생들의 학업 성취도에 미치는 영향을 분석하기 위한 데이터셋. 1. **STAR 데이터**를 다운로드 [링크](https://raw.githubusercontent.com/chung-jiwoong/FMB819/refs/heads/main/chapter_causality/data/star_data.csv). 데이터를 `star_df`라는 객체에 저장. NA 값이 있는 행은 제거하시오. `grades`가 "2"인 학생들만 선택하시오. ```{r, echo=FALSE, eval=FALSE} library(dplyr) # 데이터 불러오기 star_df <- read.csv("https://raw.githubusercontent.com/chung-jiwoong/FMB819/refs/heads/main/chapter_causality/data/star_data.csv") # NA 값이 있는 행 제거 star_df <- star_df %>% filter(complete.cases(.)) %>% filter(grade == "2") #star_df <- star_df %>% filter(na.omit(.)) #star_df <- star_df %>% filter(!is.na(.)) ``` 2. `math`를 `school` 변수에 대해 회귀 분석하시오. `school` 변수가 포함하는 값들을 먼저 확인. 회귀 계수를 해석하시오. 누락된 범주 (category)는? 결과가 예상과 일치하는가? 만약 다르다면 왜 그런가? 누락된 변수가 존재할 가능성이 있는가? ```{r, echo=FALSE, eval=FALSE} # school 변수의 값 확인 unique(star_df$school) # math를 school 변수에 대해 회귀 분석 reg_school <- lm(math ~ school, data = star_df) summary(reg_school) ``` 3. `lunch` 변수가 `"free"`인 학생들의 비율을 **학교 위치(school) 별로 계산**하시오. 결과를 보고, **무료 점심 자격 여부(`free`) 변수를 추가하여 이전 회귀 분석을 다시 수행**하시오. `free` 변수를 추가했을 때 회귀 계수는 어떻게 변화하는가? ```{r, echo=FALSE, eval=FALSE} # 학교 위치별로 lunch가 "free"인 학생들의 비율 계산 star_df %>% group_by(school) %>% summarise(free_ratio = mean(lunch == "free")) # free 변수를 추가하여 회귀 분석 수행 reg_school_free <- lm(math ~ school + (lunch == "free"), data = star_df) summary(reg_school_free) ``` 4. `math`를 `star` 변수에 대해 회귀 분석하시오. 다음의 모든 변수를 포함하여 다중 회귀 분석을 수행하시오:\ `math ~ star + gender + ethnicity + lunch + degree + experience + school`. 무작위 실험이 **잘 수행되었다고 판단할 수 있는가?** ```{r, echo=FALSE, eval=FALSE} reg_full <- lm(math ~ star + gender + ethnicity + lunch + degree + experience + school, data = star_df) summary(reg_full) ``` 5. **다중 회귀 분석**에서 얻은 **수정된** $R^2$ 값을 확인하시오. 수정된 $R^2$ 값이 의미하는 바는 무엇인가? 관측 가능한 개별 학생, 교사, 학교 특성이 학업 성취도에 미치는 중요성에 대해 어떤 결론을 내릴 수 있는가? 6. (Optional) `math`를 `gender`와 `experience` 변수에 대해 회귀 분석하시오. 회귀 계수를 어떻게 해석할 수 있는가? 이러한 회귀 분석 결과를 시각적으로 표현한다면 어떻게 보일 것인가? # THE END!