Ch.14 다중 회귀분석
다중 회귀분석
연속형 종속변수와 두 개 이상의 독립변수 간 선형관계 및 설명력을 확인하는 기법
독립변수가 명목형 변수인 경우 가변수 변환 후 모델 적합
다중공선성
독립변수 간 강한 상관관계가 나타나는 문제
회귀모델 생성 후 분산팽창계수(VIF)를 확인하여 관련 변수를 처리(제거 등)
VIF
import pandas as pd
from patsy import dmatrices
from statsmodels.stats.outliers_influence import variance_inflation_factor as vif
VIF를 계산하는 방법은 공식처럼 되어있는 것 같은데,
1) dmatrices를 써서 원하는 변수를 matrix 형태로 구성하고,
2) columns를 나열하는 열, VIF를 계산하는 열을 각각 추가하여 feature별 VIF를 나타내는 dataframe을 만든다.
y, X = dmatrices(formula_like = "casual ~ season + holiday + weather + workingday + temp+ atemp+ humidity + windspeed",
data = df_sub,
return_type = "dataframe")
formula = "casual ~ " + " + ".join(df_sub.columns[:-1])
y, X = dmatrices(formula_like = formula, data = df_sub, return_type = "dataframe")
우선 1번,
dmatrices의 formula도 "종속변수 ~ 독립변수" 형태로 작성하는데,
여러 개의 독립변수를 사용할 때 + 로 전부 이어줘야 한다.
변수의 개수가 여러개일 경우, 아래처럼
"종속변수 ~ " + " + ".join(df_sub.columns)의 형태로 작성해주면 된다.
이걸 잘 활용하기 위해서는 column의 순서를 바꿀 줄 알아야 할 것 같은데,
df[["casual", "windspeed", "atemp" ... ]]
단순하게 위처럼 바꾸고자 하는 순서대로 컬럼명을 쭉 적어주면 된다.
그리고 2번,
df_vif = pd.DataFrame()
df_vif["colname"] = X.columns
df_vif["VIF"] = [vif(X.values, i) for i in range(X.shape[1])]
df_vif
X 변수의 컬럼명을 나열하는 열,
그리고 VIF를 list comprehension을 활용하여 계산하는 열을 각각 추가해준다
이 코드들은 그냥 외워버리는게 마음이 편할 것 같다.
다중공선성 관련 여러 포스트들을 읽어봐도 거의 유사한 코드를 사용하고 있다.
해당 코드를 돌리면 temp와 atemp의 vif가 높아서 변수 하나를 제거해주어야 하는데,
df_sub2 = pd.concat([df.loc[:, "season" : "temp"], df.loc[:, "humidity" : "casual"]], axis = 1)
formula = "casual ~" + " + ".join(df_sub2.columns[:-1])
y, X = dmatrices(formula_like = formula, data = df_sub2, return_type = "dataframe")
df_vif = pd.DataFrame()
df_vif["Column"] = X.columns
df_vif["VIF"] = [vif(X.values, i) for i in range(X.shape[1])]
df_vif
이렇게 atemp 앞뒤로 dataframe을 자른 다음 concat으로 붙여버리고
동일한 과정을 돌리면 된다.
문제1
Price를 종속변수로 하고 나머지 수치형 변수를 독립변수로 했을 때 다중공선성의 문제가 있다고 판단되는 변수의 개수는?
df = pd.read_csv('diamonds.csv')
formula = "price ~ carat + depth + x + y + z"
y, X = dmatrices(formula_like = formula, data = df, return_type = "dataframe")
df_vif = pd.DataFrame()
df_vif["columns"] = X.columns
df_vif["VIF"] = [vif(X.values, i) for i in range(X.shape[1])]
df_vif
문제2
Price를 종속변수로 하고 carat과 depth를 독립변수로 하여 생성한 회귀 모델을 사용하여 알아본 carat이 1이고 depth가 60, table이 55인 다이아몬드의 가격은 얼마인가?
df = pd.read_csv('diamonds.csv')
from statsmodels.formula.api import ols
model = ols(formula = "price ~ carat + depth", data = df).fit()
df_predict = pd.DataFrame({"carat" : [1], "depth" : [60], "table" : [55]})
model.predict(df_predict)
다중회귀도 단순회귀와 방법은 똑같다.
다만 독립변수를 Dataframe을 직접 만들어서 넣어줘야 한다는 것만 다르다.
문제3
price를 종속변수로 하고 carat, color, depth를 종속변수로 하여 생성한 회귀모델을 사용하여 알아본 carat이 1이고 depth가 50, color가 E인 다이아몬드의 가격은 얼마인가?
df = pd.read_csv('diamonds.csv')
df_sub = df.loc[:, ["price", "color", "carat", "depth"]]
df_dum = pd.get_dummies(df_sub, columns = ["color"], drop_first = True)
model = ols(formula = "price ~ " + " + ".join(df_dum.columns[1:]), data = df_dum).fit()
df_test = df_dum.iloc[[0], :]
df_test["carat"] = 1
df_test["depth"] = 50
model.predict(df_test)
1) 가변수를 생성하면서 변수가 많아지므로 필요한 자료만 필터링해서 가져가기
2) 가변수 생성 후 독립변수는 carat ~ color_J이므로 formula는
"price ~ " + " + ".join(df_dum.columns[1:]) 이어야 함
3) color가 E이다 = {"color_E" : [1], "color_F" : [0], "color_G" : [0], "color_H" : [0], "color_J" : [0]}
가변수를 전부 입력하는 것도 원칙적으로는 가능하나,
df_dum에서 첫줄을 가져온 다음 필요한 데이터를 수정하는 것이 훨씬 빠르고 간편하다.
여러모로 공부할 것이 많았던 문제...