1. 회귀 분석

  • 독립변수 x에 대응하는 종속변수 y와 가장 유사한 값을 갖는 함수 f(x)를 찾는 과정
    → f(x)를 통해 미래 사건 예측
    ^y = f(x) ≈ y


  • 회귀 분석을 통해 구한 함수 f(x)가 선형 함수일 때 f(x) = 회귀 직선
  • 선형 회귀 분석
    • 특성과 타겟 사이의 관계를 잘 나타내는 선형 회귀 모형을 찾고, 이들의 상관관계는 가중치/계수(m), 편향(b)에 저장됨
      => ^y = w * x + b


2. 비용 함수 = 손실 함수

  • 선형 모델의 예측훈련 데이터 사이의 거리를 재는 함수
  • 비용 함수의 결과값이 작을수록 선형 모델의 예측이 정확함


  • 선형 회귀는 선형 모델이라는 가설을 세우는 방식이므로, 실제 데이터(훈련 데이터)와 선형 모델의 예측 사이에 차이 존재
  • 실제 데이터와 선형 모델의 예측 사이의 차이를 평가하는 함수 → 비용 함수를 사용하여 정확도 계산
  • MSE 가장 많이 사용 [실제값과 예측값의 차이인 오차들의 제곱의 평균]


3. 선형 회귀 구현


1) 선형 회귀 모델 구현


# 훈련 세트, 테스트 세트 생성
from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight, random_stae = 42)
train_input = train_input.reshape(-1, 1)
test_input = test_input.reshape(-1, 1)

# 50cm 농어 평균 무게 예측
from sklearn.linear_model import LinearRegression

lr = LinearRegression()
lr.fit(train_input, train_target)
print(lr.predict([50]))

# 1241.83860323


2) 회귀 확인


# 회귀 직선 ^y = W * x + b 구하기
print(lr.coef_, lr.intercept_)

# [39.01714496], -709.0186449535477
# => y = lr.coef_ * x + lr.intercept_

plt.plot([15, 50], [15*lr.coef_+lr.intercept_, 50*lr.coef_+lr.intercept_])


regression


3) 훈련 세트 산점도 그리기


plt.plot([15, 50], [15*lr.coef_ + lr.intercept_, 50*lr.coef_ + lr.intercept_])

plt.scatter(train_input, train_target)

plt.scatter(50, 1241, 8, marker = '^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()


scatter


  • 회귀 직선이 어느 정도는 데이터를 잘 나타내고 있음
  • 그러나, 훈련 세트와 테스트 세트 모두 결정 계수가 너무 낮음 → 과소 적합
    + 산점도에서 매우 작은 길이를 가진 농어의 경우 회귀 직선이 데이터를 설명하지 못함


4. 선형 회귀 모델의 최적화 → 경사 하강법

  • 머신러닝, 딥러닝 알고리즘을 학습시킬 때 사용하는 방법
  • 비용 함수의 기울기를 계속 낮은 쪽으로 이동시켜 극값(최적값)에 이를 때까지 반복하는 것


  • 경사 하강법을 이용하여 비용 함수에서 기울기가 ‘0’일 때의 비용(오차)값을 구할 수 있음
  • 비용 함수의 최소값 을 구하면 이때 회귀 함수를 최적화 할 수 있게 됨


  • 비용 함수에서 기울기가 '0'일 때 (비용 함수가 최솟값일 때) 모델의 기울기와 y절편을 구하여 회귀 함수 최적화


descent


5. 경사 하강법 - learning rate(학습률)

  • 선형 회귀에서 가중치(w)편향(b)을 경사 하강법에서 반복 학습시킬 때, 한 번 반복 학습시킬 때마다 포인트를 얼만큼씩 이동시킬 것인지 정하는 상수
  • 학습률이 너무 작은 경우: local minimum에 빠질 수 있음
  • 학습률이 너무 큰 경우: 수렴이 일어나지 않음


=> 적당한 learning rate를 찾는 것이 중요!

  • 시작을 0.01로 시작해서 overshooting이 일어나면 값을 줄이고, 학습 속도가 매우 느리다면 값을 올리는 방향으로 진행


import numpy as np
import matplotlib.pyplot as plt

X = np.random.rand(100)
Y = 0.2 * X + 0.5       # 실제값 함수 가정

plt.figure()
plt.scatter(X, Y)
plt.show()


real


# 실제값, 예측값 산점도 그리는 함수
def plot_prediction(pred, y):
    plt.figure()
    plt.scatter(X, Y)
    plt.scatter(X, pred)
    plt.show()

# 경사 하강법 구현
W = np.random.uniform(-1, 1)
b = np.random.uniform(-1, 1)

learning_rate = 0.7    # 임의

for epoch in range(100):
    Y_pred = W * X + b    # 예측값
    
    error = np.abs(Y_pred - Y).mean()
    if error < 0.001:
        break
    
    # gradient descent 계산 (반복할 때마다 변경되는 W, b값)
    w_grad = learning_rate * ((Y_pred-Y) * X).mean()
    b_grad = learning_rate * ((Y_pred-Y)).mean()
    
    # W, b 값 갱신
    W = W - w_grad
    b = b - b_grad
    
    # 실제값과 예측값이 얼마나 근사해지는지 epoch % 5 ==0 될 때마다 그래프 그림
    if epoch % 5 == 0:
        Y_pred = W * X + b
        plot_prediction(Y_pred, Y)


learning


파랑: 실제값, 주황: 예측값


  • 반복문이 실행되면서 오차가 점차 작아짐을 알 수 있음
  • 최종적으로 오차가 줄어들며 실제값을 정확히 추정할 수 있음!


6. 다항 회귀

  • 다항식을 사용한 선형 회귀
  • y = a * x² + b * x + c 에서 x²을 z로 치환하면 y = a * z + b * x + c라는 선형식으로 쓸 수 있음

=> 다항식을 이용해서도 선형 회귀를 할 수 있음 → 최적의 곡선 찾기

  • 비선형성을 띄는 데이터도 선형 모델을 활용하여 학습시킬 수 있다는 것

  • 다항 회귀 기법: log, exp, 제곱 등을 적용해 선형식으로 변형한 뒤 학습시키는 것


poly

위의 선형회귀 모델의 문제점 해결


# 50cm 농어 평균 무게 예측

# 훈련 세트, 테스트 세트의 길이를 제곱한 값의 열 추가 - 새로운 훈련, 테스트 세트 생성
train_poly = np.column_stack((train_input**2, train_input))
test_poly = np.column_statck((test_input**2, test_input))

# 새로운 훈련 세트, 테스트 세트로 선형 회귀 모델 훈련
lr = LinearRegression()
lr.fit(train_poly, train_target)

# 무게 예측
print(lr.predict([50**2, 50]))

# [1573.98423528]


7. 다항 회귀 구현


1) 회귀 다항식 y = a * x² + b * x + c 구하기

print(lr.coef_, lr.intercept_)

# [1.01433211 -21.55792498] 116.05021078278259

회귀 다항식) 무게 = 1.01 * 길이$^2$ - 21.6 * 길이 + 116.05


2) 훈련 세트의 산점도, 회귀 다항식 그리기


# 훈련 세트 산점도
plt.scatter(train_input, train_target)

point = np.arange(15, 50)

# 15~49까지 회귀 다항식 그래프 그리기
plt.plot(point, 1.01*point**2 -21.6*point + 116.05)

# 농어 데이터 표시하기
plt.scatter(50, 1574, marker = '^')

plt.xlabel('length')
plt.ylabel('weight')
plt.show()


train


# 결정 계수
print(lr.score(train_poly, train_target))
print(lr.score(test_poly, test_target))

# 0.9706807451768623
# 0.9775935108325121

결정 계수 점수가 1에 근접하므로, 해당 모델은 위의 선형 모델보다 정확성이 높음