[ML] 지도 학습(1)- 회귀분석(1)

최윤진·2023년 2월 20일
1

ML

목록 보기
1/12
post-thumbnail

전체적 이해를 위해 통계적 개념과 머신러닝에서의 적용을 함께 다룸
회귀분석에 대한 전체적 이론과 실습은 선형 회귀 분석을 중심으로 기술 되어 있음.( 라쏘, 릿지, 엘라스틱 넷 등의 구체적 내용은 다음 게시글을 참고 바람)

📚 이론

📍 회귀분석

회귀분석의 목적은 주어진 데이터를 대표하는 하나의 직선을 찾는 것이다.
그렇다면 회귀분석은 X로 Y를 예측하는 것을 의미한다.

📌 회귀분석의 다양한 유형

회귀는 독립변수의 개수에 따라 단순 선형 회귀, 다항 회귀로 먼저 나뉘어진다.
또한, 회귀 계수가 선형인지 아닌지에 따라 선형 회귀, 비선형 회귀로 나뉘어진다.

  • 선형 회귀(Linear regression)
  • 다중 회귀(Multivariate Regression)
  • 다항 회귀(Polynomial regression)
  • 로지스틱 회귀(Logistic regression)
  • 릿지 회귀(Ridge regression)
  • 라쏘 회귀(Lasso regression)
  • 엘라스틱넷(LeasticNet)

1) 단순 선형 회귀분석

  • 관찰된(알려진) 관련 데이터 값을 기반으로 관찰되지 않은(알 수 없는) 데이터의 값을 예측하는 것을 의미한다.
  • 단순 선형 회귀분석은 독립변수(x)와 종속변수(y) 간의 관계를 하나의 선형 관계식으로 표현한다.
    • 여기서 말하는 선형 관계식이 바로 회귀선이다.
  • 독립변수(x)가 하나이다.
  • y = ax + b
  • 회귀계수는 a

2) 다중 선형 회귀분석

  • 다중 선형 회귀분석은 독립변수(x)가 2개 이상, 종속변수(y)가 1개인 선형 회귀분석이다.
  • y = ax1 + bx2 + ....+ c
  • 회귀계수는 a,b...

3) 다항 회귀분석

  • 독립변수의 차수를 높이는 형태 (2차 함수 이상의 다항 함수를 이용해 두 변수 간의 선형 관계를 설명할 때 사용)
  • y= ax+ bx^2 + cx^3 + ...+d

4) 로지스틱 회귀

종속변수를 0 또는 1 처럼 분류할 때 사용하는 모델이다.
스팸 메일이다, 아니다와 같이 분류할 때 주로 사용된다.

5) 릿지 회귀

모델의 설명력에 기여하지 못하는 독립변수의 회귀계수 크기를 0에 근접하도록 축소시킨다. L2-norm 이라고 부르는 페널티항을 통해 일반 선형회귀 모델에 페널티를 부과하는 방법으로 회귀계수를 축소시킨다.

6) 라쏘 회귀

라쏘회귀모델은 릿지회귀모델과 다르게 설명력에 기여하지 못하는 독립변수의 회귀계수를 0으로 만드는 방법이다.

7) 엘라스틱넷

릿지와 라쏘의 결합으로, L1 norm과 L2 norm을 모두 이용해 패털티를 부과해 회귀 모델을 생성한다.

📌 선형 회귀분석의 기본 가정

  1. 선형성
  • 종속변수와 독립변수 간의 선형 관계를 가지는 성질이다.
    (X와 Y간에 선형인 관계가 없다면? 아무런 의미 없는 분석이 되기 쉽기 때문에 중요한 문제)
  1. 독립성
  • 다중 회귀 모형에 투입된 여러 변수들 간에 특정한 관계가 없는 성질이다.
    EX)식물의 성장속도를 설명하는 화씨 기온, 섭씨 기온, 영양제 양 3개의 변수가 있다면 두 기온을 나타내는 변수간에는 서로 강한 관계가 있기 때문에 모형 학습에 안좋은 영향을 미침
  1. 등분산성
  • 잔차가 균일한, 하나의 분산을 가지고 흩어져 있는 성질이다.
  1. 정규성
  • 잔차가 정규 분포의 형태를 가진다는 것이다.

📌 회귀계수

회귀에서 가장 중요한 것은 회귀계수라고 할 수 있는데,독립변수 x의 변화에 따라 종속변수 y가 변하는 정도가 정의이다. 한마디로 말하자면, 기울기라고 볼 수 있다.

즉, X(독립변수)가 Y(종속변수)에 미치는 영향을 알아내고자 하는 것이다.

+) 독립변수 : X값, 원인값, 설명변수, 특성(feature),예측변수
+) 종속변수 : Y값, 결과값, 반응변수, 타겟, 레이블

📌 잔차

측정값에서 예측값을 뺀 값을 의미한다.
최적의 회귀 모델을 만든다는 것은 잔차의 합이 최소
가 되는 모델을 만드는 것이라고 할 수 있다. ((왜냐? 실제값과 예측값의 차이가 가장 작은 것이 최적이기 때문!))

📌 최소제곱법

잔차의 제곱의 합이 최소가 되도록 하는 직선을 회귀선으로 한다는 것을 의미한다.

📍 회귀분석의 평가(metric)

평가지표 종 류정의
MAEMean Absoulute Error,실제값과 예측값의 차이를 절댓값으로 변환해 평균한 것, 값이 작을 수록 모델의 성능이 높다고 평가할 수 있음
MSEMean Squared Error,실제값과 예측값의 차이를 제곱으로 평균한 것, 이상치에 민감함, 값이 작을 수록 모델의 성능이 높다고 평가할 수 있음
RMSEMSE에 제곱근을 씌워 계산해줘야함(참고: 사이킷런은 RMSE를 제공하지 않음)
MSLEMean Squared Log Error, MSE에 로그를 적용한 것. 결정값이 클수록 오류값도 커지기 때문에 일부 큰 오류값들로 인해 전체 오류값이 커지는 것을 막아줌
RMSLERoot Mean Squared Log Error, RMSE에 로그를 적용한 것이다. 결정값이 클수록 오류값도 커지기 때문에 일부 큰 오류값들로 인해 전체 오류값이 커지는 것을 막아줌
R2R^20과 1사이에 존재,분산 기반으로 예측 성능을 평가, 실제 값의 분산 대비 예측값의 분산 비율(1에 가까울수록 예측 정확도 높음)

📌📌 R2R^2 (결정계수)

R2R^2= 설명된변화량총변화량\frac{설명된 변화량}{총 변화량} = SSRSST\frac{SSR}{SST}= 1-SSESST\frac{SSE}{SST}

SST = 총변동
SSR = 설명 가능한 변동
SSE = 설명 불가능한 변동

  • 0<=R2<=10<=R^2<=1
  • R2R^2 = 0이면, X와 Y는 어떠한 선형 상관관계도 없다.
  • R2R^2 = 1이면, X와 Y는 완벽한 선형 상관관계이다.

평균 제곱 오차로 더 나은 회귀 함수 선택하기

실제값과 예측값까지의 거리를 회귀 함수의 에러로 표시할 수 있다.

y=θx    라는  함수가  있다고  가정y=θx\;\;라는\;함수가 \;있다고 \;가정
error=(yiθxi)error = (y_{i}- θx_{i})

이 값을 제곱한 것이

square  error=(yiθxi)2square\;error = (y_{i}- θx_{i})^2

가 될 것이고, 단순 제곱 오차는 다음과 같다.

RSS=i=0n(yiθxi)2RSS = \displaystyle\sum_{i=0}^{n}(y_i-θx_i)^2

결국,

MSE=1ni=0n(yiθxi)2MSE = \frac{1}{n}\displaystyle\sum_{i=0}^{n}(y_i-θx_i)^2

로 표현할 수 있다.

선형회귀의 목적함수

목적함수는 보통 어떤 함수의 최댓값 또는 최솟값을 구하는 함수이다. 그렇다면 회귀 모델을 구현할 때의 목적함수는 ?
👉 평균 제곱 오차를 최소화 하는 함수!

경사하강법

회귀 모델을 구현할 때 최초 회귀 계수를 임의값으로 설정한 후, 경사하강법을 반복적으로 실행해 최소의 평균 제곱 오차를 가지는 회귀 계수를 구한다.

💻 실습 적용

1. Linear Regression 실습

[보스턴 주택 가격 예측]
맨 처음 언급했던 대로 회귀분석은 예측과 분류 모델에 사용된다. 둘 중 하나로 유명한 보스턴 주택 가격 예측 문제를 실습해보려고 한다 다음은 보스턴 주택 가격 예측의 데이터 설명이다. 읽어보고 시작하면 전반적인 이해에 도움이 된다.이미지 출처: 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의 크기를 비슷한 수준으로 맞춰주는 작업 등)를 거치고 분석하는 것이 좋아보인다.

2. Logistic Regression 실습

[타이타닉 생존 예측]

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에는 어떤 숫자를 적든 그 기능은 같기 때문에 어떤 숫자를 적든 상관없다.
profile
yunjin.log

1개의 댓글

comment-user-thumbnail
2023년 2월 21일

많은 도움이 되었습니다..

답글 달기