도찐개찐
[Python] 선형회귀 본문
선형회귀 기본 개념
- 함수란 두 집합 사이의 관계를 설명하는 수학 개념입니다.
- 변수 x와 y가 있을 때, x가 변하면 이에 따라 y는 어떤 규칙으로 변하는지 나타냅니다.
- 일차 함수는 y가 x에 관한 일차식으로 표현된 경우를 의미
- 일차 함수식 y = ax + b에서 a는 기울기, b는 절편이라고 합니다.
- 기울기는 기울어진 정도를 의미하는데, x 값이 증가할 때 y 값이 어느 정도 증가하는지에 따라 정해짐
- 절편은 그래프가 축과 만나는 지점을 의미
- x가 주어지고 원하는 y 값이 있을 때 적절한 a와 b를 찾는 것 - 머신러닝 핵심
- 이차 함수란 y가 x에 관한 이차식으로 표현되는 경우를 의미 - 𝑦=𝑎𝑥2y=ax2
- y = ax2의 그래프를 x축 방향으로 p만큼, y축 방향으로 q만큼 평행 이동시키면 점 p와 q를 꼭짓점으로 하는 포물선이 되겠지요
- 포물선의 맨 아래에 위치한 지점이 최솟값이 되는데, 딥러닝을 실행할 때는 이 최솟값을 찾아내는 과정이 매우 중요
- 이 최솟값은 4장에 소개할 ‘최소 제곱법’ 공식으로 쉽게 알아낼 수 있습니다
- 러닝을 실제로 실행할 때 만나는 문제에서는 대부분 최소 제곱법을 활용할 수가 없습
- 따라서 미분과 기울기를 이용
- 미분, 순간 변화율과 미분계수, 기울기
- 편미분 - 여러 가지 변수가 식 안에 있을 때, 모든 변수를 미분하는 것이 아니라 우리가 원하는 한 가지 변수만 미분하고 그 외에는 모두 상수로 취급하는 것
- 지수와 지수 함수, 시그모이드 함수, 로그와 로그 함수
가장 훌륭한 예측선 - 선형회귀
- 독립적으로 변할 수 있는 값 x를 독립 변수(feature)라고 합니다.
- 이 독립 변수에 따라 종속적으로 변하는 y를 종속 변수(label)라고 합니다.
- 선형 회귀란 독립 변수 x를 사용해 종속 변수 y의 움직임을 예측하고 설명하는 작업
- 하나의 x 값만으로도 y 값을 설명할 수 있다면 단순 선형 회귀(simple linear regression)라고 합니다.
- 또한, x 값이 여러 개 필요하다면 다중 선형 회귀(multiple linear regression)라고 합니다.
import numpy as np
# 공부한 시간과 중간고사 성적 데이터
# 공부한 시간 2시간 4시간 6시간 8시간
# 성적 81점 93점 91점 97점
x = np.array([2, 4, 6, 8])
y = np.array([81, 93, 91, 97])
# x, y의 평균값을 구합니다.
mx = np.mean(x)
my = np.mean(y)
# 기울기 공식의 분모 부분입니다.
divisor = sum([(i - mx)**2 for i in x])
# 기울기 공식의 분자 부분입니다.
def top(x, mx, y, my):
d = 0
for i in range(len(x)):
d += (x[i] - mx) * (y[i] - my)
return d
dividend = top(x, mx, y, my)
# 기울기 a를 구하는 공식입니다.
a = dividend / divisor
# y 절편 b를 구하는 공식입니다.
b = my - (mx*a)
a, b
# 결과 : 2.3, 79.0
평균 제곱 오차(Mean Square Error, MSE)
- 오차 = 실제 값 - 예측 값
- 그래프의 기울기가 잘못되었을수록 빨간색 선의 거리의 합, 즉 오차의 합도 커집니다
- 만일 기울기가 무한대로 커지면 오차도 무한대로 커지는 상관관계가 있는 것을 알 수 있
- 선형 회귀란 임의의 직선을 그어 이에 대한 평균 제곱 오차를 구하고, 이 값을 가장 작게 만들어 주는 a 값과 b 값을 찾아가는 작업
# 가상의 기울기 a와 y 절편 b를 정합니다.
fake_a = 3
fake_b = 76
# 공부 시간 x와 성적 y의 넘파이 배열을 만듭니다.
x = np.array([2, 4, 6, 8])
y = np.array([81, 93, 91, 97])
# y = ax + b에 가상의 a 값과 b 값을 대입한 결과를 출력하는 함수입니다.
def predict(x):
return fake_a * x + fake_b
# 예측 값이 들어갈 빈 리스트를 만듭니다.
predict_result = []
# 모든 x 값을 한 번씩 대입해 predict_result 리스트를 완성합니다.
for i in range(len(x)):
predict_result.append(predict(x[i]))
print("공부시간=%.f, 실제점수=%.f, 예측점수=%.f" % (x[i], y[i], predict(x[i])))
# 평균 제곱 오차 함수를 각 y 값에 대입해 최종 값을 구하는 함수입니다.
n = len(x)
def mse(y, y_pred):
return (1/n) * sum((y - y_pred)**2)
# 평균 제곱 오차 값을 출력합니다.
print("평균 제곱 오차: " + str(mse(y, predict_result)))
# 결과
# 공부시간=2, 실제점수=81, 예측점수=82
# 공부시간=4, 실제점수=93, 예측점수=88
# 공부시간=6, 실제점수=91, 예측점수=94
# 공부시간=8, 실제점수=97, 예측점수=100
평균 제곱 오차: 11.0
그래프 시각화
fake_a = 3
fake_b = 76
# 기울기를 3, 절편을 76으로 놓고 예측값 계산
z = [(fake_a * v + fake_b) for v in x]
z # 예측값
import matplotlib.pyplot as plt
plt.plot(x, y, 'ro')
plt.plot(x, z, 'b') # 예측선 : 기울기 : 3, 절편 : 76
plt.show()
fake_a2, fake_b2 = 2, 76
z = [(fake_a2 * v + fake_b2) for v in x]
z # 예측값
plt.plot(x, y, 'ro')
plt.plot(x, z, 'b') # 예측선 : 기울기 : 2, 절편 : 76
plt.show()
# 평균 제곱 오차 값을 출력합니다.
print("평균 제곱 오차: " + str(mse(y, z)))
# 결과 :
# 평균 제곱 오차: 29.0
기울기와 오차
- 기울기 a를 너무 크게 잡으면 오차가 커지는 것을 확인했습니다.
- 기울기를 너무 작게 잡아도 오차가 커집니다.
- 기울기 a와 오차 사이에는 이렇게 상관관계가 있습
- 기울기가 무한대로 커지거나 무한대로 작아지면 그래프는 y축과 나란한 직선이 됩니다
- 기울기 a와 오차 사이에는 이차 함수의 관계가 있다는 의미
- 오차가 가장 작을 때는 언제일까요? 그래프의 가장 아래쪽 볼록한 부분에 이르렀을 때입니다.
- 바로 미분 기울기를 이용하는 경사 하강법(gradient decent)
- 우리가 찾는 최솟값 m에서의 순간 기울기
- 그래프가 이차 함수 포물선이므로 꼭짓점의 기울기는 x축과 평행한 선이 됩니다.
- 즉, 기울기가 0입니다. 따라서 우리가 할 일은 ‘미분 값이 0인 지점’을 찾는 것이 됩니다.
- 학습률(learning rate)
- 어느 만큼 이동시킬지 신중히 결정해야 하는데, 이때 이동 거리를 정해 주는 것이 바로 학습률입니다.
- 딥러닝에서 학습률의 값을 적절히 바꾸면서 최적의 학습률을 찾는 것은 중요한 최적화 과정 중 하나
기울기와 오차간의 관계 시각화
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
weights = [] # 기울기
loss = [] # 오차
b = 0 # 절편은 0으로 편의상 설정
for w in range(-20, 50) : # 기울기를 -20 ~ 50까지 설정
xtrain = np.array([2,4,6,8])
ytrain = np.array([91,93,91,97]) # 실제값
ytrain_hat = w * xtrain + b # 예측값
weights.append(w)
loss.append(mean_squared_error(ytrain, ytrain_hat))
# 결과 출력 및 그래프 그리기
# print(weights, '\n', loss)
plt.plot(weights, loss)
# plt.axis([-15,45, 0, 30000])
plt.show()
import matplotlib.pyplot as plt
# 기울기 a의 값과 절편 b의 값을 초기화합니다.
a = 0
b = 0
# 학습률을 정합니다.
lr = 0.03
# 전체데이터를 대상으로 학습을 몇 번 반복될지 설정합니다.
epochs = 2001
# x 값이 총 몇 개인지 셉니다.
n = len(x)
# 경사 하강법을 시작합니다.
for i in range(epochs): # 에포크 수만큼 반복합니다.
y_pred = a * x + b # 예측 값을 구하는 식입니다.
error = y - y_pred # 실제 값과 비교한 오차를 error로 놓습니다.
a_diff = (2/n) * sum(-x * (error)) # 오차 함수를 a로 편미분한 값입니다.
b_diff = (2/n) * sum(-(error)) # 오차 함수를 b로 편미분한 값입니다.
a = a - lr * a_diff # 학습률을 곱해 기존의 a 값을 업데이트합니다.
b = b - lr * b_diff # 학습률을 곱해 기존의 b 값을 업데이트합니다.
#if i % 100 == 0: # 100번 반복될 때마다 현재의 a 값, b 값을 출력합니다.
# print("epoch=%.f, 기울기=%.04f, 절편=%.04f, 오차=%.04f" % (i, a, b, mse(y, y_pred)))
# 앞서 구한 최종 a 값을 기울기, b 값을 y 절편에 대입해 그래프를 그립니다.
y_pred = a * x + b
# 공부 시간 X와 성 y의 넘파이 배열을 만듭니다.
x = np.array([2, 4, 6, 8])
y = np.array([81, 93, 91, 97])
# 데이터의 분포를 그래프로 나타냅니다.
plt.scatter(x, y)
plt.plot(x, y_pred,'r')
plt.show()
728x90
'PYTHON > 데이터분석' 카테고리의 다른 글
[데이터분석] 02. 통계와 데이터 (0) | 2023.01.02 |
---|---|
[데이터 분석] 01. 통계와 데이터 (0) | 2023.01.02 |
인공지능 개념 (0) | 2022.12.26 |
[Python] folium(지도시각화) (0) | 2022.12.26 |
[Python] plot 한글 사용 (0) | 2022.12.26 |
Comments