-
[혼공머] 3-2. 선형 회귀Data Science/딥러닝 & 머신러닝 2025. 1. 10. 23:40
1. K-최근접 이웃의 한계
1. 농어의 무게 예측 오류
- 1절의 내용인 length & weight를 이용해 길이가 50cm인 농어의 무게를 예측해보자.
# 1절의 내용을 돌아보기 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]) 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) train_input = train_input.reshape(-1, 1) test_input = test_input.reshape(-1, 1) from sklearn.neighbors import KNeighborsRegressor knr = KNeighborsRegressor(n_neighbors=3) knr.fit(train_input, train_target)
knr.predict([[50]]) # array([1033.33333333])
예측 결과 : 1.033g, 실제로 농어 50cm는 1g보다 훨씬 많다.
2. 최근접 이웃 산점도로 표시
import matplotlib.pyplot as plt distances, indexes = knr.kneighbors([[50]]) # 50cm 농어와의 이웃 찾기, 3개로 정해놓음 plt.scatter(train_input, train_target) # 훈련 세트의 산점도 plt.scatter(train_input[indexes], train_target[indexes], marker='D') # 50cm 농어와의 이웃만 다시 표시 plt.scatter(50, 1033, marker = '^') # 50cm 농어 표시 plt.xlabel('length') plt.ylabel('weight') print(np.mean(train_target[indexes])) # 1033.3333333333333
3. 100cm의 농어 무게 예측
print(knr.predict([[100]]) distances, indexes = knr.kneighbors([[100]]) # 100cm 농어의 이웃 plt.scatter(train_input, train_target) # 훈련 세트의 산점도 plt.scatter(train_input[indexes], train_target[indexes], marker='D') # 100cm 농어와의 이웃만 다시 표시 plt.scatter(100, 1033, marker = '^') # 100cm 농어 표시 plt.xlabel('length') plt.ylabel('weight')
4. K-최근접 이웃의 문제점 *
- 새로운 샘플이 훈련 세트의 범위를 벗어나면 엉뚱한 값을 예측할 수 있음
2. 선형 회귀
1. 선형 회귀 클래스
from sklearn.linear_model import LinearRegression
- 목적 : 특성을 가장 잘 나타낼 수 있는 ‘직선’을 학습한다.
- LinearRegression에도 fit, score, predict 메서드가 있다.
2. 선형 회귀 모델 훈련과 예측
from sklearn.linear_model import LinearRegression lr = LinearRegression() lr.fit(train_input, train_target) print(lr.predict([[50]]) # array([1241.83860323])
이전의 1g보다는 합리적인 결과가 나왔다.
3. 선형 회귀 모델의 모델파라미터
- 모델 파라미터 : 머신러닝 알고리즘이 찾은 값
- 기울기와 절편을 찾을 수 있다.
- coef_ 와 intercept_
print(lr.coef_, lr.intercept_) # [39.01714496] -709.0186449535477
4. 선형 회귀 직선 산점도 위에 그려보기
- 시작점의 x,y 점과 끝점의 x,y 점 잇기
# 훈련 세트의 산점도 plt.scatter(train_input, train_target) # 15 ~ 50까지 방정식 그래프 그리기 = (15, -) 과 (50, -)의 두 점 잇기 plt.plot([15, 50], [15*lr.coef_ + lr.intercept_, 50*lr.coef_ + lr.intercept_]) # 50cm 농어 데이터 plt.scatter(train_input, train_target) plt.scatter(50, 1241.88, marker='^')
이제 훈련 세트 범위를 벗어난 무게도 예측 가능하다.
5. 정확도 확인하기
print(lr.score(train_input, train_target)) # 0.93 print(lr.score(test_input, test_target)) # 0.82
- 훈련 세트 > 테스트 세트 인데, 훈련 세트도 낮은 정확도에 속하는 편
- 그래프 시작 부분을 잘 얘기해줄 수 없는 그래프
3. 다항 회귀
1. 다항 회귀의 목적
- 선형 회귀가 데이터를 잘 나타내지 못할 때
- 특히 그래프에서 무게가 0g 이하로 내려갈 수는 없다.
2. 다항 회귀
- 다항식을 사용한 선형 회귀
- 곡선의 형태
- 제곱항이 필요하다 → 길이를 제곱한 항을 추가한다.
3. 다항회귀를 위한 제곱항 추가
- 배열을 나란히 붙이기 위해 np.column_stack 사용
train_poly = np.column_stack((train_input **2, train_input)) test_poly = np.column_stack((test_input **2, test_input))
4. 다항회귀 모델 훈련 & 예측
lr = LinearRegression() lr.fit(train_poly, train_target)
- 50cm 농어의 무게 예측 → 제곱항도 함께 넣어준다
print(lr.predict([[50**2, 50]])) # array([1573.98423528])
- 모델 파라미터 확인
print(lr.coef_, lr.intercept_) # [ 1.01433211 -21.55792498] 116.0502107827827
제곱항을 치환하면 선형 회귀로 볼 수도 있다.
5. 다항회귀 모델의 산점도
# 15 ~ 49까지 정수 배열 point = np.arange(15, 50) plt.scatter(train_input, train_target) # 짧은 직선을 이어 그리면 곡선처럼 표시 가능 plt.plot(point, 1.01*point**2 - 21.6*point + 116.05) # 50cm 농어 plt.scatter(50, 1574, marker='^') plt.show()
6. 다항회귀 모델의 정확도
print(lr.score(train_poly, train_target)) # 0.970 print(lr.score(test_poly, test_target)) # 0.977
- 훈련 < 테스트 == 과소적합 → 더 복잡한 모델 필요3. 다항 회귀
- 선형 회귀가 데이터를 잘 나타내지 못할 때
- 특히 그래프에서 무게가 0g 이하로 내려갈 수는 없다.
4. 선형 회귀로 훈련 범위 밖의 샘플 예측 전체 소스 코드
# 데이터 준비 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]) # 훈련 세트와 테스트 세트 구분, 2차원 배열로 변환 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) train_input = train_input.reshape(-1, 1) test_input = test_input.reshape(-1, 1) # k-최근접 이웃 회귀 모델 훈련 from sklearn.neighbors import KNeighborsRegressor knr = KNeighborsRegressor(n_neighbors=3) knr.fit(train_input, train_target) knr.score(test_input, test_target) # 50cm 농어 무게 예측 knr.predict([[50]]) # 50cm의 k-최근접 이웃 회귀 모델 산점도 distances, indexes = knr.kneighbors([[50]]) plt.scatter(train_input, train_target) plt.scatter(train_input[indexes], train_target[indexes], marker = 'D') plt.scatter(50, 1033, marker = '^') plt.xlabel('length') plt.ylabel('weight') plt.show() # 100cm 농어 무게 예측 knr.predict([[100]]) # 100cm의 k-최근접 이웃 회귀 모델 산점도 distances, indexes = knr.kneighbors([[100]]) plt.scatter(train_input, train_target) plt.scatter(train_input[indexes], train_target[indexes], marker='D') plt.scatter(100, 1033, marker='^') plt.xlabel('length') plt.ylabel('weight') plt.show() # sol 1. 선형회귀 from sklearn.linear_model import LinearRegression lr = LinearRegression() lr.fit(train_input, train_target) # 학습한 직선의 파라미터 print(lr.coef_, lr.intercept_) # 50cm 도미 예측 lr.predict([[50]]) # 직선과 데이터의 산점도 그리기 plt.plot([15, 50], [15*lr.coef_ + lr.intercept_, 50*lr.coef_ + lr.intercept_]) plt.scatter(train_input, train_target) plt.scatter(50, 1241.88, marker='^') # 결정계수값 print(lr.score(train_input, train_target)) print(lr.score(test_input, test_target)) # sol 2. 다항회귀 - 선형회귀에서는 무게가 0 이하도 잡힘 # 길이의 제곱 추가 train_poly = np.column_stack((train_input**2, train_input)) test_poly = np.column_stack((test_input**2, test_input)) # 모델 생성, 훈련 lr = LinearRegression() lr.fit(train_poly, train_target) # 학습한 직선의 파라미터 print(lr.coef_, lr.intercept_) # 50cm 도미 예측 : 2차식이라 길이의 제곱, 길이 입력 lr.predict([[50**2, 50]]) # 그래프와 데이터의 산점도 그리기 # 15 ~ 49까지 정수 배열 point = np.arange(15, 50) plt.scatter(train_input, train_target) plt.plot(point, 1.01*point**2 - 21.6*point + 116.05) # 50cm 농어 plt.scatter(50, 1574, marker='^') plt.show() # 결정계수값 print(lr.score(train_poly, train_target)) print(lr.score(test_poly, test_target))
'Data Science > 딥러닝 & 머신러닝' 카테고리의 다른 글
[혼공머] 4-1. 로지스틱 회귀 (0) 2025.01.10 [혼공머] 3-3. 특성 공학과 규제 (0) 2025.01.10 [혼공머] 3-1. K-최근접 이웃 회귀 (0) 2025.01.10 [혼공머] 2-2. 데이터 전처리 (0) 2025.01.10 [혼공머] 2-1. 훈련 세트와 테스트 세트 (0) 2025.01.10