[AI/ML] 다중 선형 회귀

PyTorch를 이용한 다중 선형 회귀 구현 방법을 소개합니다. 행렬 연산으로 여러 입력 변수를 효율적으로 처리하고, 경사하강법으로 최적화하는 과정을 다룹니다.

[AI/ML] 다중 선형 회귀
Photo by Pawel Czerwinski / Unsplash

개요

AI에 대한 기초를 다시 정리하고자 아래 내용을 읽고 정리했습니다.

다중 선형 회귀(Multivariable Linear Regression)

<단순 선형 회귀 차이>

현실 세계에서는 하나의 요소만 결과에 영향을 주지 않습니다. 즉 다양한 요소가 예측에 영향을 주게 되는데 이처럼 여러 입력을 사용하는 것을 다중 선형 회귀라고 표현합니다.

수식은 선형 회귀와 유사합니다. 각 요소별로 가중치(w)가 붙으며 입력되는 변수의 개수에 따라 확장됩니다.

  • H(x) = w₁x₁ + w₂x₂ + w₃x₃ + ... + b

기본 구현 (변수 개별 선언)

<기본 설정>

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

torch.manual_seed(1)

<x1_train, x2_train, x3_train / w1, w2, w3 개별 선언>

훈련 데이터 입력시 x가 1,000개라면 x1_train, x2_train, ... x1000_train , w도 w1, w2, … , w1000으로 작성해야하는 불편함이 존재합니다. 문제를 해결하기 위해 Pytorch에서는 행렬 곱셈 연산을 사용할 수 있습니다.

즉 변수가 많아지면 불편합니다.

# 훈련 데이터
x1_train = torch.FloatTensor([[73], [93], [89], [96], [73]])
x2_train = torch.FloatTensor([[80], [88], [91], [98], [66]])
x3_train = torch.FloatTensor([[75], [93], [90], [100], [70]])
y_train = torch.FloatTensor([[152], [185], [180], [196], [142]])
# 가중치 w와 편향 b 초기화
w1 = torch.zeros(1, requires_grad=True)
w2 = torch.zeros(1, requires_grad=True)
w3 = torch.zeros(1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)

<행렬 연산으로 개선하기>

Notion Image
  • H(x) = w₁x₁ + w₂x₂ + w₃x₃

행렬을 통해 표현하면 x가 몇 개든간에 X라는 변수 하나와 W라는 변수 하나로 표현할 수 있게 됩니다.

전체 훈련 데이터에서 셀 수 있는 1개의 단위를 샘플(sample)이라고 합니다. 각 샘플에서 y를 결정하게 하는 독립 변수(x) 하나하나를 특성(feature)라고 합니다. X 변수를 정의할 때 (샘플의 수 x 특성의 수)를 사용합니다. 원본 예시에서 Quiz 1, 2, 3과 5개의 샘플 데이터가 있다면 흔히 (5 x 3) 아래 이미지처럼 표현 가능합니다. 여기에 가중치(w)를 곱하고 편향을 추가하면 X, W, B변수 3개로 다중 선형 회귀의 가설 연산을 표현 가능합니다.

Notion Image

예시는 다음과 같습니다.

# 샘플 데이터
x_train  =  torch.FloatTensor([[73,  80,  75], 
                               [93,  88,  93], 
                               [89,  91,  80], 
                               [96,  98,  100],   
                               [73,  66,  70]])  
y_train  =  torch.FloatTensor([[152],  [185],  [180],  [196],  [142]])

# 가중치와 편향 선언
W = torch.zeros((3, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

optimizer = optim.SGD([W, b], lr=1e-5)

곱셈은 다음과 같습니다. 다만 곱셈 좌측의 행렬 열 크기와 곱셈 우측 행렬 행 크기가 일치해야 합니다.

  • (5×3) @ (3×1) = (5×1) → matmul
hypothesis = x_train.matmul(W) + b

이후의 계산은 선형 회귀와 동일합니다.

# H(x) 계산
hypothesis = x_train.matmul(W) + b

# cost 계산(오차)
cost = torch.mean((hypothesis - y_train) ** 2)

# cost로 H(x) 개선
optimizer.zero_grad() # -> 현재 기울기 초기화
cost.backward() # -> 오차를 미분해서 기울기 계산
optimizer.step() # -> W, b 업데이트

다중 선형 회귀 한계점

다중 선형 회귀 역시 한계점이 존재합니다. 만약 두 개의 독립 변수 x1, x2가 같이 움직인다면 둘 중 뭐가 진짜 영향을 주는 건지 구분하지 못하는 다중공선성 문제가 발생합니다.

또한 비선형 관계를 표현 할 수 없어 곡선이거나 복잡한 패턴이면 정확한 예측에 한계가 존재합니다.