MLDL

다중 선형 회귀

DEVDAE828 2022. 2. 8. 11:35

다중 선형 회귀는 선형 회귀를 하나의 입력 변수가 아니라 여러개의 입력 별수를 사용해서 목표 변수를 예측하는 알고리즘이다.

출처: 코드잇

용어 노트

 

출처: 코드잇

다중 선형 회귀 가설 함수

 

출처: 코드잇

선형 회귀와는 다르게 입력변수가 여러 개 있다. (집 데이터에서 집 크기, 지하철까지의 거리, 년식 등)

 

행렬표현

 

출처: 코드잇

이건 아래의 식과 같다.

출처: 코드잇

이 두 벡터를 곱하면 1번 요소끼리 곱하고 2번 요소끼리 곱하고 다 더 하면 기존 함수와 같은 식이 된다. 

출처: 코드잇

Error = 

출처: 코드잇

위의 식은 행렬로 아래의 식으로 변환해 표현 가능 

출처: 코드잇

다중 선형 회귀 경사하강법 구현

import numpy as np

def prediction(X, theta):
    """다중 선형 회귀 가정 함수. 모든 데이터에 대한 예측 값을 numpy 배열로 리턴한다
    위에서 세타 곱하기 X 부분 구현 
    """
    return X @ theta
    

def gradient_descent(X, theta, y, iterations, alpha):
    """다중 선형 회귀 경사 하강법을 구현한 함수
    위에서 full equation 부분 구현 
    """
    m = len(X)  # 입력 변수 개수 저장
    
    for _ in range(iterations):
        prediction_output = prediction(X, theta)
        theta = theta - alpha / m * (X.T @ (prediction_output - y))
        
    return theta
    

# 입력 변수
house_size = np.array([1.0, 1.5, 1.8, 5, 2.0, 2.5, 3.0, 3.5, 4.0, 5.0, 6.0, 7.0, 8.0, 8.5, 9.0, 10.0])  # 집 크기
distance_from_station = np.array([5, 4.6, 4.2, 3.9, 3.9, 3.6, 3.5, 3.4, 2.9, 2.8, 2.7, 2.3, 2.0, 1.8, 1.5, 1.0])  # 지하철역으로부터의 거리 (km)
number_of_rooms = np.array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4])  # 방 수

# 목표 변수
house_price = np.array([3, 3.2, 3.6 , 8, 3.4, 4.5, 5, 5.8, 6, 6.5, 9, 9, 10, 12, 13, 15])  # 집 가격

# 설계 행렬 X 정의
X = np.array([
    np.ones(16),
    house_size,
    distance_from_station,
    number_of_rooms
]).T

# 입력 변수 y 정의
y = house_price

# 파라미터 theta 초기화
theta = np.array([0, 0, 0, 0])

# 학습률 0.01로 100번 경사 하강
theta = gradient_descent(X, theta, y, 100, 0.01)

theta

출처: 코드잇
출처: 코드잇

위와 같은 함수에서 경사하강법을 하면 어느 순간 여러 극소값 중 하나에 가서 경사가 0인 지점에서 하강이 종료 된다. 그렇게 되면 손실 함수의 최저점을 찾을수가 없다. 따라서 이렇게 생긴 함수는 극소 지점이 손실 함수에서 최소 지점이라고 확실하게 얘기할 수 없다. 

아래로 볼록한 함수인 convex 함수는 극소 지점을 찾아 최소 지점이라 할 수 있는데 다행히도 선형 회귀 손실 함수로 사용하는 mse는 항상 convex 함수이다. 그러므로 선형 회귀를 할 때는 경사 하강법을 하거나 정규 방정식을 하거나 항상 최적의 세타 값들을 구할 수 있다. 

# 필요한 라이브러리 import
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

import pandas as pd  

# 당뇨병 데이터 갖고 오기
diabetes_dataset = datasets.load_diabetes()

# 입력 변수를 사용하기 편하게 pandas dataframe으로 변환
X = pd.DataFrame(diabetes_dataset.data, columns=diabetes_dataset.feature_names)

# 목표 변수를 사용하기 편하게 pandas dataframe으로 변환
y = pd.DataFrame(diabetes_dataset.target, columns=['diabetes'])

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=5)

# 코드를 쓰세요
model = LinearRegression()
model.fit(X_train, y_train)

y_test_predict = model.predict(X_test)

# 평균 제곱 오차의 루트를 통해서 테스트 데이터에서의 모델 성능 판단
mse = mean_squared_error(y_test, y_test_predict)

mse ** 0.5

위의 코드는 다중 선형 회귀를 한 코드이다.