회귀(Regression)
- 지도 학습(supervised learning)은 크게 분류와 회귀로 나뉜다. 회귀는 클래스 중 하나로 분류하는 것이 아니라 임의의 어떤 숫자를 예측하는 문제이다. 즉, 회귀는 두 변수 사이의 상관관계를 분석한다.
K-최근접 이웃 회귀
- K-최근접이웃 분류 알고리즘에서는 예측하려는 샘플에서 거리가 가장 가까운 k개를 선택해 다수를 차지하는 클래스를 새로운 샘플의 클래스로 예측한다. k-최근접이웃 회귀도 비슷하다. 단, 분류가 아니라 회귀이기 때문에 이웃한 샘플의 타깃은 어떤 클래스가 아니라 임의의 수치이다. 예를 들어 이웃한 3개의 샘플값이 100, 80, 60이라면 이를 평균을 내어 80이라는 타깃값을 생성한다.
데이터 준비
# 농어의 길이, 무게 데이터 준비하기
import numpy as np
perch_length = np.array([8.4, 13.7, 15.0, 16.2, 17.4, 18.0, 18.7, 19.0, 19.6, 20.0, 21.0,
21.0, 21.0, 21.3, 22.0, 22.0, 22.0, 22.0, 22.0, 22.5, 22.5, 22.7,
23.0, 23.5, 24.0, 24.0, 24.6, 25.0, 25.6, 26.5, 27.3, 27.5, 27.5,
27.5, 28.0, 28.7, 30.0, 32.8, 34.5, 35.0, 36.5, 36.0, 37.0, 37.0,
39.0, 39.0, 39.0, 40.0, 40.0, 40.0, 40.0, 42.0, 43.0, 43.0, 43.5,
44.0])
perch_weight = np.array([5.9, 32.0, 40.0, 51.5, 70.0, 100.0, 78.0, 80.0, 85.0, 85.0, 110.0,
115.0, 125.0, 130.0, 120.0, 120.0, 130.0, 135.0, 110.0, 130.0,
150.0, 145.0, 150.0, 170.0, 225.0, 145.0, 188.0, 180.0, 197.0,
218.0, 300.0, 260.0, 265.0, 250.0, 250.0, 300.0, 320.0, 514.0,
556.0, 840.0, 685.0, 700.0, 700.0, 690.0, 900.0, 650.0, 820.0,
850.0, 900.0, 1015.0, 820.0, 1100.0, 1000.0, 1100.0, 1000.0,
1000.0])
# 농어의 길이와 무게 산점도로 표현해보기
import matplotlib.pyplot as plt
plt.scatter(perch_length, perch_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show() # 길이가 증가하면 무게도 증가한다
데이터 분리와 배열 맞추기
# 사이킷런으로 데이터 분리하기
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight, random_state=42)
# 하지만 사이킷런에 사용할 훈련 세트는 2차원 배열이어야 하므로, 2차원 배열로 바꿔준다
# reshape() 함수 이용
train_input = train_input.reshape(-1,1)
test_input = test_input.reshape(-1,1)
# 2차원 배열로 만들기 위해 열을 한 줄로 만들어줌. 그리고 나머지는 알아서 맞추어줌
# -1 을 이용할 수 있음
결정 계수와 평균 절댓값 오차(MAE)
# 모델 훈련시키기
from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor()
knr.fit(train_input, train_target)
knr.score(test_input, test_target)
# 결정계수 0.9928094061010639 (매우 높음)
# 사이킷런에 있는 절댓값 오차 함수
from sklearn.metrics import mean_absolute_error
# 테스트 세트에 대한 예측을 만든다
test_prediction = knr.predict(test_input)
# 평균 절댓값 오차를 계산한다
mae = mean_absolute_error(test_target, test_prediction)
#19.xxx, 결과에서 예측이 평균적으로 19g 정도 타깃값과 다르다는 것을 알 수 있음
과대적합과 과소적합
knr.score(test_input, test_target)
# 결정계수 0.9928094061010639 (매우 높음)
# 이번에는 훈련 데이터로 평가해본다
knr.score(train_input, train_target)
# 0.96988... (정확도가 낮아진다) [과소적합]
# 이웃의 개수를 더 작게 설정한다. 3으로 설정
knr.n_neighbors = 3
# 모델 재훈련 후 훈련 세트로 평가
knr.fit(train_input, train_target)
knr.score(train_input, train_target)
# 0.98...
# 테스트 세트로 평가
knr.score(test_input, test_target)
# 0.97... (과소적합 문제 해결)
# k-최근접 이웃 회귀 객체를 만든다
knr = KNeighborsRegressor()
# 5에서 45까지 x 좌표를 만든다
x = np.arange(5,45).reshape(-1,1)
# n=1,5,10일 때 예측 결과를 그래프로 나타낸다
for n in [1,5,10]:
# 모델 훈련
knr.n_neighbors = n
knr.fit(train_input, train_target)
# 지정한 범위 x에 대한 예측을 구한다
prediction = knr.predict(x)
# 훈련 세트와 예측 결과를 그래프로 나타낸다
plt.scatter(train_input, train_target)
plt.plot(x, prediction)
plt.title('n_neighbors = {}'.format(n))
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
선형 회귀( Linear Regression)
- **선형 회귀(linear regression)**는 널리 사용되는 회귀 알고리즘으로, 비교적 간단하고 성능이 뛰어나다. 특성이 하나인 경우 어떤 직선을 학습하는 알고리즘이며, 그 특성을 가장 잘 나타낼 수 있는 직선을 학습한다. sklearn.linear_model에 존재하는 LinearRegression 클래스를 사용한다.