선형 회귀와 분류 차이
분류 vs 회귀
분류는 특정 클래스에 해당되는지에 대한 확률을 구하는 것
회귀는 특정 값을 결과로 반환 받는 것
선형 회귀
목표 변수(target variable) : 맞추려고 하는 값
입력 변수(feature) : 맞추는데 사용하는 값
데이터표현법
각자의 로우에 대해서 index를 이용해서 표현한다.
Linear Regression (선형 회귀)
예를 들어 집 값을 예측하는 회귀 분석을 진행하려고 한다.
선형 회귀란 여러 변수들에 대해 구분할 수 있는 가장 적절한 선을 찾아내는 것이라 생각할 수 있다.
통계학에서는 이 선을 ‘최적선’ 혹은 line of best fit이라고 한다.
더불어 집 크기는 Feature, 집 값을 Target Variable 이라고 한다.
가설 함수
선형 회귀에서는 여러 데이터들에 대한 가장 잘 맞는 ‘최적선’을 찾는 것이다. 그럼 이를 어떻게 할까?
최적선을 찾기 위해 여러 선을 의미하는 것이 가설 함수라고 한다.
즉 위의 그림에서는 y= ax + b 라고 말할 수 있다. 여기서 우리는 최적선을 찾기 위해 a,b를 구하는 것이다.
이를 아래처럼 표현할 수 있는데 이때 세타값을 찾아내는 것이다.
MSE = Mean Square Error: 평균 제곱 오차
가설함수가 있을때 최적의 선임을 어떻게 찾아낼 것인가? → MSE 를 통해 알아볼 수 있다.
이는 (x-xi)^2 로 표현할 수 있다.
y = 0.4*x + 0 일떄 50을 넣으면 예측값으로 20억으로 나온다. 근데 실제 가격은 18억 정도이다. 그러면 이를 MSE로 차이를 확인하면 (18-20)**2 = 4 라는 오차가 나온다.
제곱을 하는 이유가 무엇일까?
데이터와 예측값의 차이가 양/음이 나오므로 이에 대한 값을 절대적으로 평가하기 위함이다.
오차가 더 클수록 더 큰 패널티를 주기 위해 제곱을 한다.
여러 선들을 정해 각 선의 MSE를 통해 확인해보면 최적의 선이 빨간색 선임을 확인할 수 있다.
평균 제곱 오차 일반화
평균 제곱 오차를 각각의 데이터에 대해 일반화시키면 아래와 같다.
이는 모든 데이터에 대한 예측값들을 합산 후 데이터 개수만큼 나눈 것이다. 이는 모든 데이터에 대한 MSE값 오차들의 평균값을 구하는 것으로 확인할 수 있다.
→ 이를 통해 모든 데이터의 평균적인 MSE를 구할 수 있다.
Loss function 손실함수
선형회귀라는 머신러닝의 한 분야를 공부할때 최적선을 찾기 위해 가설함수에 대한 평가기준이 필요하다.
이를 위해 각 데이터마다 각 가설함수에 대한 평가를 하기 위해 MSE를 위해 사용한다.
이를 일반화하기 위해 평균 제곱 오차를 통해 최적선이 모든 데이터에 어떤지를 평가할 수 있다.
이때 MSE같은 것을 가설 함수의 성능을 평가하는 함수라고 표현할 수 있고,
이는 Loss Function 이라고 한다. 이 Loss Function가 작을 수록 최적선에 가까워지고 있다는 얘기이고, 커질 수록 최적선에 가깝지 않다는 것을 의미한다.
가설함수의 손실함수는 결국 input이 가설함수의 Input Variable이 아닌 세타(가중치)이다.
왜냐하면 우리가 바꾸는 값들은 데이터(x)가 아닌 세타이기 떄문이다.
경사하강법 개념
선형회귀는 데이터에 가장 잘 맞는 가설 함수를 찾는 것인데.
이때 가설함수의 세타(가중치)를 조절해서 최적선을 찾는다.
이를 위해 손실 함수를 최소화시킨다.
이떄 손실 함수를 그래프로 그리면 아래와 같다.
그러면 손실 함수를 최소로 가져야 가설함수가 최적선에 근접하다는 것이므로 극소점인 가장 아래의 지점을 최적선으로 할 것이다.
따라서 손실함수(J(세타))의 기울기의 방향과 크기를 이용해서 손실 함수가 최소값이 되게 만드는 것이 ‘경사하강법’이다.
J함수가 저렇게 생겼다고 할 때 기울기를 구하기 위해선 편미분을 이용해 기울기를 구할 수 있다.
손실함수를 편미분을 한 값을 통해 손실함수가 얼마나 기울었는지와 국소점으로 가기 위한 방향(+,-)을 알 수 있다.
따라서 손실함수의 반대방향으로 보내 J의 극소점에 가까워져 최적의 가설 함수를 구할 수 있을 것이다.
경사하강법 테크닉
경사하강법을 직접 풀어보자.
경사하강법 및 손실함수 MSE 코드
import numpy as np
def prediction(x, theta_0, theta_1):
return theta_0 + theta_1 * x
def prediction_diff(theta_0, theta_1, x, y):
return prediction(x, theta_0, theta_1) - y
def gradient_desent(theta_0, theta_1, x, y, iterations, lr, epochs):
for _ in range(epochs):
error = prediction_diff(theta_0, theta_1, x, y)
theta_0 = theta_0 - lr * np.mean(error) # 반대방향으로 보내기 위해 - 사용
theta_1 = theta_1 - lr * np.mean(error * x)
return theta_0, theta_1
경사하강법 Learning Rate를 조절해서 모델이 어떻게 학습하는 지 알아보기
import numpy as np
import matplotlib.pyplot as plt
def pred(thr0, thr1, x):
return thr0 + thr1 * x
def pred_diff(thr0, thr1, x ,y):
return pred(thr0, thr1, x) - y
def gradient_descent(thr0, thr1, x, y, epochs, lr):
m = len(x)
cost_li = []
for _ in range(epochs):
error = pred_diff(thr0, thr1, x, y)
cost = (error @ error) / (2 * m)
cost_li.append(cost)
if _ % 50 == 0:
plt.scatter(x, y)
plt.plot(x, pred(thr0, thr1, x), color = 'red')
plt.show()
thr0 = thr0 - lr * error.mean()
thr1 = thr1 - lr * (error * x).mean()
return thr0, thr1, cost_li
x = np.array([.9, 1.4, 2, 2.1, 2.6, 3.3, 3.35, 3.9, 4.4, 4.7, 5.2, 5.75, 6.7, 6.9])
y = np.array([0.3, .75, .45, 1.1, 1.45, .9, 1.8, .9, 1.5, 2.2, 1.75, 2.3, 2.49, 2.6])
#init weights
thr_0 = 2.5
thr_1 = 0.
thr_0, thr_1, cost_li = gradient_descent(thr_0, thr_1, x, y, epochs = 200, lr = 0.1)
thr_0, thr_1, cost_li = gradient_descent(thr_0, thr_1, x, y, epochs = 200, lr = 1.0)
thr_0, thr_1, cost_li = gradient_descent(thr_0, thr_1, x, y, epochs = 200, lr = 0.0001)
모델 평가 노트
모델 평가시 최적선을 찾기 위해 어떻게 평가 할 수 있을까?
주로 평가하기 위해 많이 쓰는게 RMSE(Reast Mean Squeare Error)이다. 이는 기존 손실함수에서 쓰이는 MSE는 제곱의 형태를 띄고 있기에 이를 루트로 해서 실제의 오차처럼 단위를 동일하게 만들어주는 것
<aside> 💡 MSE는 제곱을 통해 오차가 크면 더 큰 페널티를 주는 것에 반해 MAE는 절대값을 취해서 예측값과 실제값 사이의 오차를 절대적인 크기로만 비교함.
</aside>
정규방정식 : 경사하강법과 동일하게 손실함수비용을 최소화하는 방법
정규방정식을 맨날 풀기 귀찮으니까 아래의 식에 대입하면 된다.
손실함수 최소방법 : 경사하강법 ↔ 정규 방정식