project:eve
23.01.18 Regression 회귀분석 본문
오늘은 간단한 회귀분석과 분류분석을 해봤다.
회귀분석 : 독립변수들의 값 변화가 종속변수의 값 변화에 얼마나 영향을 미치는지?
이 값의 변화를 선으로 그릴 수 있다면 선형 회귀, 그릴 수 없다면(규칙성이 없다면) 비선형 회귀를 사용한다.
데이터는 sklearn의 샘플 데이터인 보스턴 집값 데이터를 사용했다.
(깃허브에서 데이터를 쓰면 ethical problem이라며 사용할 수 없다고 뜨는데 주피터 노트북에서는 사용이 잘 된다)
1) 데이터 가져와서 살펴보기
from sklearn.datasets import load_boston
boston = load_boston()
df_boston = pd.DataFrame(boston.data, columns=boston.feature_names)
df_boston['result'] = boston.target


데이터는 총 506개, 결측값은 없고 전부 float형식이다. 결측값 처리를 따로 별도로 할 필요는 없는 것 같다.
독립변수는 0부터 12까지의 컬럼, 종속변수는 result다.

이 데이터들은 위의 표와 같은 의미를 각각 가지고 있다. 주로 비율 값이 많고 boolean이나 개수, 거리 단위도 있다. 그래서 분석에 사용할 데이터를 추려낸 다음에 정규화 작업을 해야 할 것 같다.
2) EDA
먼저 각 독립변수가 종속변수와 어떤 관계를 가지고 있는지 알아보기
features = df_boston.columns.difference(['result'])
fig, axs = plt.subplots(figsize=(18,10), ncols=4, nrows=4, constrained_layout=False)
for i, feature in zip(range(13), features):
row = int(i/4)
col = i%4
sns.regplot(x=feature, y=df_boston['result'], data=df_boston, ax=axs[row][col])

하나의 그래프가 하나의 독립변수와 종속변수의 관계를 표시할 수 있도록 해보았다. 표를 보면 대부분 선형관계를 가지고 있는데 boolean값인 CHAS는 선형 관계라고 보기에는 좀 애매하고, RAD도 애매한 것 같아서 이 두 변수는 제외하고 나머지로 분석을 해보면 좋을 것 같다.
각 독립변수가 어떤 분포를 가지고 있는지 알아보기
for i, feature in zip(range(13), features):
row = int(i/4)
col = i%4
sns.histplot(df_boston[feature], ax=axs[row][col])

B, CRIM, ZN처럼 값 분포가 고르지 않은 것은 있지만 이상치가 존재하는 데이터는 없는 것 같다.
3) 전처리
이 데이터는 결측값이 없어서 별도 처리는 하지 않아도 될 것 같다.
다만 아까 적은 대로 독립 변수들의 값 단위가 서로 다르기 때문에 스케일링을 하는 과정이 필요하다. 스케일러는 MinMaxScaler를 사용해보기로 했다.
이 스케일러는 데이터들을 모두 0~1 사이의 값으로 변환해준다.
이외에도 평균과 표준편차를 사용하는 standardscaler, 중앙값과 IQR을 사용하는 robustscaler가 있다.
스케일러를 사용할 때 기술통계 값을 사용하다 보니 이상치가 있으면 영향을 많이 받는다고 한다.
(*그런데 어떤 상황에 무슨 스케일러를 쓰면 더 좋은지, 어떤 차이가 있는지는 잘 모르겠다)
이런 경우에는 로그나 제곱근 함수를 쓰면 성능이 향상될 수도 있다고 한다.
독립 변수나 종속 변수가 심하게 한쪽으로 치우친 분포를 보이는 경우
독립 변수와 종속 변수간의 관계가 곱셈 혹은 나눗셉으로 연결된 경우
종속 변수와 예측치가 비선형 관계를 보이는 경우
(*독립변수 중에 이상치가 큰 변수가 있는 경우 스케일링과 로그/제곱근 함수 둘 다 쓸 수 있는 건가? 코드 순서가 어떻게 되는건지..)
스케일링을 하기 전에 train_test_split으로 데이터를 분할해야 한다. 훈련 데이터를 적합시키고 테스트 데이터에 적용하는 순서로 진행한다.
(*왜 전체 데이터를 스케일링하지 않고 따로따로 하는지 잘 모르겠다. 어차피 데이터 정규화하는 것 자체는 같이 해야 하지 않나?)
➡️ 테스트 데이터를 완전히 새로운 데이터로 취급해서 예측하는 자료로 써야 하기 때문이라고 한다. 예를 들어 전체 데이터를 MinmaxScaler로 스케일링하고 나서 30%로 분할하면 실제 데이터에서 30%를 가져오는 것이 아니라 0~1 사이로 분포된 데이터에서 가져오는 것이기 때문에 예측 자료로 사용하는 의미가 없다고 한다.
from sklearn.model_selection import train_test_split
X_features = df_boston.columns.difference(['result', 'RAD', 'CHAS'])
X = df_boston[X_features]
Y = df_boston['result']
train_x, test_x, train_y, test_y = train_test_split(X, Y, test_size=0.2, random_state=42)
from sklearn.preprocessing import MinMaxScaler
MmScaler = MinMaxScaler()
MmScaler.fit(train_x)
train_x_sc = MmScaler.transform(train_x)
test_x_sc = MmScaler.transform(test_x)
3) 회귀모델 학습하고 예측하기
스케일링한 데이터를 가지고 회귀모델에 적합해본다. 스케일링과 똑같이 모델을 훈련 데이터로 적합하고 테스트 데이터로 예측하면 된다.
from sklearn.linear_model import LinearRegression
Lr = LinearRegression()
Lr.fit(train_x_sc, train_y)
y_pred = Lr.predict(test_x_sc)
4) 모델 성능 평가하기
적합한 모델의 성능을 평가하기 위해 특정한 지표를 쓴다.
MAE(평균절대오차) : 예측값과 실제값을 뺀 절대값
MSE(평균제곱오차) : 예측값과 실제값을 뺀 제곱값
RMSE(평균제곱근오차) : MSE에 제곱근을 더한 값
R2(결정계수) :
회귀모델이 주어진 자료에 얼마나 적합한지를 평가하는 지표y의 변동량대비 모델 예측값의 변동량
0~1의 값을 가지며, 상관관계가 높을수록(=값이 비슷할수록) 1에 가까워진다
ex) 결정계수에 대해 말할 때 R2=0.3인 경우 '30%의 설명력을 가진다' 라고 할 수 있다
음수 값이 나오면 모델의 성능이 떨어진다는 의미
결정계수는 독립변수가 많아질 수록 값이 커지기때문에, 독립변수가 2개 이상일 경우 조정된 결정계수를 사용해야 함
from sklearn.metrics import mean_absolute_error as mae, mean_squared_error as mse, r2_score
y_test_pred = Lr.predict(test_x_sc_2)
MAE = mae(test_y, y_pred)
MSE = mse(test_y, y_pred)
RMSE = np.sqrt(MSE)
r2 = r2_score(test_y, y_pred)

예를 들어 MAE의 값이 3.27이면 실제값과 예측값의 차이가 평균 3.27 정도 발생한다고 해석할 수 있다.
그리고 r2의 값이 0.66이므로 이 모델은 결정계수가 0.66이고, 66%의 설명력을 가지고 있다고 볼 수 있다.
5) 모델 성능 평가하기(2)
4)번까지가 간단한 회귀분석의 과정이고, 독립변수가 2개 이상일 경우에는 단순한 결정계수 대신 수정된 결정계수를 사용해야 한다. 왜냐하면 일반 결정계수는 독립변수가 많을수록 증가하기 때문에 지금 데이터셋을 분석하는 경우 값을 신뢰할 수 없다.
수정된 결정계수는 따로 제공되는 메서드가 없어 이렇게 function으로 직접 만들어서 사용해야 한다(LinearRegression쪽에는 없음. OLS를 사용하면 메서드가 있는데 그건 나중에 따로 배워봐야겠다)
r2는 결정계수, n과 p는 각각 독립변수 데이터의 행과 열 수이다.
def adj_r2(r2, n, p):
return 1 - (1-r2)*(n-1)/(n-p-1)
print('adj_r2 : ',adj_r2(r2, test_x_sc_2.shape[0], test_x_sc_2.shape[1]))
출력하면 약 0.61이 나온다. 이전에 계산했던 결정계수보다 값이 조금 낮아졌다.
결정계수는 1에 가까울수록 좋은 것이긴 하지만, 분야에 따라서 아래처럼 신뢰할 수 있는 기준이 있다고 한다.

보스턴 집값 데이터는 사회과학에 해당하기 때문에 결정계수가 0.3이면 신뢰할 수 있는 모델로 본다. 이 모델은 결정계수가 0.61이기 때문에 아주 신뢰할 수 있는 모델이라고 할 수 있다.
'Daily' 카테고리의 다른 글
| 23.01.28 SVM 서포트 벡터 머신 (0) | 2023.01.29 |
|---|---|
| 23.01.28 Logistic Regression로지스틱 회귀 (0) | 2023.01.29 |
| 23.01.27 Lasso, Elasticnet 라쏘, 엘라스틱넷 (0) | 2023.01.28 |
| 23.01.25 Linear Regression, Ridge 경사하강법, 릿지 회귀 (0) | 2023.01.25 |
| 23.01.24 Classification 분류분석 (0) | 2023.01.24 |