전체적 이해를 위해 통계적 개념과 머신러닝에서의 적용을 함께 다룸
회귀분석에 대한 전체적 이론과 실습은 선형 회귀 분석을 중심으로 기술 되어 있음.( 라쏘, 릿지, 엘라스틱 넷 등의 구체적 내용은 다음 게시글을 참고 바람)
회귀분석의 목적은 주어진 데이터를 대표하는 하나의 직선을 찾는 것이다.
그렇다면 회귀분석은 X로 Y를 예측하는 것을 의미한다.
회귀는 독립변수의 개수에 따라 단순 선형 회귀, 다항 회귀로 먼저 나뉘어진다.
또한, 회귀 계수가 선형인지 아닌지에 따라 선형 회귀, 비선형 회귀로 나뉘어진다.
종속변수를 0 또는 1 처럼 분류할 때 사용하는 모델이다.
스팸 메일이다, 아니다와 같이 분류할 때 주로 사용된다.
모델의 설명력에 기여하지 못하는 독립변수의 회귀계수 크기를 0에 근접하도록 축소시킨다. L2-norm 이라고 부르는 페널티항을 통해 일반 선형회귀 모델에 페널티를 부과하는 방법으로 회귀계수를 축소시킨다.
라쏘회귀모델은 릿지회귀모델과 다르게 설명력에 기여하지 못하는 독립변수의 회귀계수를 0으로 만드는 방법이다.
릿지와 라쏘의 결합으로, L1 norm과 L2 norm을 모두 이용해 패털티를 부과해 회귀 모델을 생성한다.
회귀에서 가장 중요한 것은 회귀계수라고 할 수 있는데,독립변수 x의 변화에 따라 종속변수 y가 변하는 정도가 정의이다. 한마디로 말하자면, 기울기라고 볼 수 있다.
즉, X(독립변수)가 Y(종속변수)에 미치는 영향을 알아내고자 하는 것이다.
+) 독립변수 : X값, 원인값, 설명변수, 특성(feature),예측변수
+) 종속변수 : Y값, 결과값, 반응변수, 타겟, 레이블
측정값에서 예측값을 뺀 값을 의미한다.
최적의 회귀 모델을 만든다는 것은 잔차의 합이 최소
가 되는 모델을 만드는 것이라고 할 수 있다. ((왜냐? 실제값과 예측값의 차이가 가장 작은 것이 최적이기 때문!))
잔차의 제곱의 합이 최소가 되도록 하는 직선을 회귀선으로 한다는 것을 의미한다.
평가지표 종 류 | 정의 |
---|---|
MAE | Mean Absoulute Error,실제값과 예측값의 차이를 절댓값으로 변환해 평균한 것, 값이 작을 수록 모델의 성능이 높다고 평가할 수 있음 |
MSE | Mean Squared Error,실제값과 예측값의 차이를 제곱으로 평균한 것, 이상치에 민감함, 값이 작을 수록 모델의 성능이 높다고 평가할 수 있음 |
RMSE | MSE에 제곱근을 씌워 계산해줘야함(참고: 사이킷런은 RMSE를 제공하지 않음) |
MSLE | Mean Squared Log Error, MSE에 로그를 적용한 것. 결정값이 클수록 오류값도 커지기 때문에 일부 큰 오류값들로 인해 전체 오류값이 커지는 것을 막아줌 |
RMSLE | Root Mean Squared Log Error, RMSE에 로그를 적용한 것이다. 결정값이 클수록 오류값도 커지기 때문에 일부 큰 오류값들로 인해 전체 오류값이 커지는 것을 막아줌 |
0과 1사이에 존재,분산 기반으로 예측 성능을 평가, 실제 값의 분산 대비 예측값의 분산 비율(1에 가까울수록 예측 정확도 높음) |
= = = 1-
SST = 총변동
SSR = 설명 가능한 변동
SSE = 설명 불가능한 변동
실제값과 예측값까지의 거리를 회귀 함수의 에러로 표시할 수 있다.
이 값을 제곱한 것이
가 될 것이고, 단순 제곱 오차는 다음과 같다.
결국,
로 표현할 수 있다.
목적함수는 보통 어떤 함수의 최댓값 또는 최솟값을 구하는 함수이다. 그렇다면 회귀 모델을 구현할 때의 목적함수는 ?
👉 평균 제곱 오차를 최소화 하는 함수!
회귀 모델을 구현할 때 최초 회귀 계수를 임의값으로 설정한 후, 경사하강법을 반복적으로 실행해 최소의 평균 제곱 오차를 가지는 회귀 계수를 구한다.
[보스턴 주택 가격 예측]
맨 처음 언급했던 대로 회귀분석은 예측과 분류 모델에 사용된다. 둘 중 하나로 유명한 보스턴 주택 가격 예측 문제를 실습해보려고 한다 다음은 보스턴 주택 가격 예측의 데이터 설명이다. 읽어보고 시작하면 전반적인 이해에 도움이 된다.이미지 출처: http://dator.co.kr/?vid=ctg258&mid=textyle&document_srl=1721307
from sklearn.datasets import load_boston
boston = load_boston() # 데이터세트를 읽어들임
import pandas as pd
df = pd.DataFrame(boston.data, columns = boston.feature_names) # 독립변수(boston.data)를 DataFrame에 저장
df['Price'] = boston.target # 종속변수(boston.target)도 DataFrame에 추가 #price(목표변수)=보스턴 인근의 주택 가격
사이킷런의 보스턴 데이터를 로드하고, 분석하기 용이한 형태인 데이터 프레임으로 변환해준다. 그리고 업로드된 데이터를 확인해본다.
#다음의 코드로 간단히 데이터 확인을 해준다.
boston_df.head()
boston_df.info
boston_df.isnull().sum() #결측값 확인
%matplotlib inline
plt.scatter(df['NOX'],df[['Price']])
plt.xlabel('rm')
plt.ylabel('price')
plt.show()
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score
x = df[['RM']].values
y = df[['Price']].values
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size = 0.8, test_size = 0.2, random_state = 100) # 데이터를 학습용과 검증용으로 분할
lr = LinearRegression() #선형회귀 모델
lr.fit(x_train,y_train) #모델 학습
y_pred = lr.predict(x_test) #x_test(검증)를 통한 예측값
#y_train_pred = lr.predict(x_train) # x_train(학습)를 통한 예측값
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
print('MSE:',np.round(mse,3))
print('RMSE:',np.round(rmse,3))
print('R^2:',np.round(r2_score(y_test,y_pred),3))
print("절편 값:", np.round(lr.intercept_,3)) # y축 절편값
# 회귀 계수(coefficient) : 독립변수의 변화에 따라 종속변수에 미치는 영향력이 크기
print("회귀계수:", np.round(lr.coef_,1))
다음과 같은 결과를 얻을 수 있다.
여기서 R^2 값이 그렇게 유의미하다고 볼 수 없다. 다른 데이터로 회귀분석을 실시할 때 데이터의 전처리(Feature Scailing,각 열의 데이터 크기에 따른 상대적 영향력 차이 제거를 통해 feature의 크기를 비슷한 수준으로 맞춰주는 작업 등)를 거치고 분석하는 것이 좋아보인다.
[타이타닉 생존 예측]
import seaborn as sns
import pandas as pd
import numpy as np
data = sns.load_dataset('titanic')
df = sns.load_dataset('titanic')
df.shape
df.head()
df.isnull().sum() #결측치 확인
age와 deck 변수에 결측치가 존재함을 알 수 있다.
df['age'].fillna(value=df['age'].mean(),inplace=True) #결측치 처리(분석에 필요한 것만 일단 결측치 처리 해줌)
df['sex'] = df['sex'].map({'female':1,'male':0}) # 분석에 용이한 형태로 변환
df['FirstClass'] = df['pclass'].apply(lambda x: 1 if x == 1 else 0)
df['SecondClass'] = df['pclass'].apply(lambda x: 1 if x == 2 else 0)
#lambda 매개변수: 표현식
#x가 1이면 1이고, 아니라면 0이다.(*보통 1=참, 0=거짓)
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
x = df[['sex', 'age', 'FirstClass', 'SecondClass']]
y = df['survived']
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.25)
scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)
lr = LogisticRegression()
lr.fit(x_train,y_train)
print(lr.score(x_train, y_train))
print(lr.score(x_test,y_test))
위의 보스톤 주택 가격 예측 보다 정확도가 높음
print(lr.coef_) #['sex', 'age', 'FirstClass', 'SecondClass']
#sex 1에 가까움= female, age 음수=나이가 많을 수록 생존 확률이 낮음
[참고] random_state의 의미
- 호출할 때마다 동일한 학습/테스트용 데이터 세트를 생성하기 위해 주어지는 난수 값이다.
- train_test_split는 랜덤으로 데이터를 분리하므로 train_test_split를 설정하지 않으면 수행할 때마다 다른 학습/테스트 데이터 세트가 생성된다. 따라서 random_state를 설정하여 수행 시 결과값을 동일하게 맞춰준다.
- random_state에는 어떤 숫자를 적든 그 기능은 같기 때문에 어떤 숫자를 적든 상관없다.
많은 도움이 되었습니다..