2023. 8. 8. 08:22ㆍ2023-2 KHUDA/ML 기초세션
이 게시물은 한빛미디어의 <혼자 공부하는 머신러닝 + 딥러닝>를 정리한 글입니다.
혼자 공부하는 머신러닝+딥러닝
혼자 공부하는 머신러닝 딥러닝, 무료 동영상 강의, 머신러닝+딥러닝 용어집을 다운로드 하세요. 포기하지 마세요! 독학으로 충분히 하실 수 있습니다. ‘때론 혼자, 때론 같이’ 하며 힘이 되겠
hongong.hanbit.co.kr
Chapter 03-1에서 사용했던 k-최근접 이웃 회귀 모델로 새로운 농어 데이터를 예측한다.
print(knr.predict([[50]]))
# -> [1033.33333333]
knr 모델은 50cm 농어의 무게를 1,033g 정도로 예측했다. 하지만 실제로 이 농어의 무게는 훨씬 더 많이 나간다고 한다.
훈련 세트와 50cm 농어, 이 농어의 최근접 이웃을 산점도로 확인한다.

#50cm 농어의 이웃을 구합니다.
distances, indexes = knr.kneighbors([[50]])
#훈련 세트의 산점도를 그립니다.
plt.scatter(train_input, train_target)
#훈련 세트 중에서 이웃 샘플만 다시 그립니다.
plt.scatter(train_input[indexes], train_target[indexes],
marker='D')
#50cm 농어 데이터
plt.scatter(50, 1033, marker='^')
plt.show()
print(np.mean(train_target[indexes]))
# -> [1033.33333333]
이 산점도를 보면 길이가 커질수록 무게가 증가하는 경향임을 알 수 있다. 하지만 50cm 농어에서 가장 가까운 샘플은 45cm 근처이기 때문에 k-최근접 이웃 알고리즘은 이 샘플들의 무게를 평균한다.
따라서 새로운 샘플이 훈련 세트의 범위를 벗어나면 엉뚱한 값을 예측할 수 있다.
예를 들어, 길이가 100cm인 농어도 똑같이 1,033g으로 예측한다.

#100cm 농어의 이웃을 구합니다.
distances, indexes = knr.kneighbors([[100]])
#훈련 세트의 산점도를 그립니다.
plt.scatter(train_input, train_target)
#훈련 세트 중에서 이웃 샘플만 다시 그립니다.
plt.scatter(train_input[indexes], train_target[indexes], marker='D')
#100cm 농어 데이터
plt.scatter(100, 1033, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
k-최근접 이웃을 사용해 이 문제를 해결하려면 가장 큰 농어가 포함되도록 훈련 세트를 다시 만들어야 한다.
하지만 새로운 알고리즘을 찾아 문제를 해결해보겠다.
선형 회귀
선형 회귀(linear regression)은 대표적인 회귀 알고리즘이며 비교적 간단하고 성능이 뛰어나다. 특성이 하나인 경우, 특성을 가장 잘 나타낼 수 있는 직선을 학습하는 알고리즘이다.
LinearRegression 모델 객체를 생성해 회귀 모델을 훈련하고 정확도를 측정한다.
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
#선형 회귀 모델 훈련
lr.fit(train_input, train_target)
#50cm 농어에 대한 예측
print(lr.predict([[50]]))
# -> [1241.83860323]
k-최근접 이웃 회귀를 사용했을 때와 다르게 선형 회귀는 50cm 농어의 무게를 아주 높게 예측하였다.
하나의 직선을 나타내려면 y = ax + b와 같은 식이 있어야 한다. 여기서 x가 농어의 길이, y가 농어의 무게이다.
LinearRegression 클래스가 찾은 a와 b는 lr 객체의 coef_와 intercept_에 각각 저장되어 있다.
print(lr.coef_, lr.intercept_)
# -> [39.01714496] -709.0186449535477
앞서 구한 기울기와 절편을 이용해 농어의 길이 15에서 50까지의 직선과 훈련 세트의 산점도를 그려준다.

#훈련 세트의 산점도를 그립니다.
plt.scatter(train_input, train_target)
#15에서 50까지 1차 방정식 그래프를 그립니다.
plt.plot([15, 50], [15*lr.coef_+lr.intercept_, 50*lr.coef_+lr.intercept_])
#50cm 농어 데이터
plt.scatter(50, 1241.8, marker='^')
plt.show()
print(lr.score(train_input, train_target))
# -> 0.939846333997604
print(lr.score(test_input, test_target))
# -> 0.8247503123313558
이 모델은 과대적합되었다기에는 훈련 세트의 점수도 높지 않아 오히려 전체적으로 과소적합되었다고 볼 수 있다.
다항 회귀
선형 회귀로 만들어낸 직선으로 예측하면 농어의 무게가 0g 이하로 내려갈 것이다.
훈련 세트의 산점도를 보면 일직선이라기보다는 곡선에 가깝다.
그렇다면 최적의 곡선을 찾아보자!
2차 방정식의 그래프를 찾으려면 길이를 제곱한 항이 훈련 세트에 추가되어야 한다.
train_poly = np.column_stack((train_input ** 2, train_input))
test_poly = np.column_stack((test_input ** 2, test_input))
print(train_poly.shape, test_poly.reshape)
# -> (42, 2) (14, 2)
train_poly를 이용해 선형 회귀 모델을 다시 훈련시킨다.
lr = LinearRegression()
lr.fit(train_poly, train_target)
print(lr.predict([[50**2, 50]]))
# -> [1573.98423528]
print(lr.coef_, lr.intercept_)
# -> [ 1.01433211 -21.55792498] 116.0502107827827
이 모델은 다음과 같은 그래프를 학습하였다.

이런 다항식을 사용한 선형 회귀를 다항 회귀(polynomial regression)라 한다.
그래프와 훈련 세트의 산점도를 그려준다.
짧은 직선을 이어서 그리면 곡선처럼 표현할 수 있다. 여기서는 1씩 끊어서 그린다.

#구간별 직선을 그리기 위해 15에서 49까지 정수 배열을 만듭니다.
point = np.arange(15, 50)
#훈련 세트의 산점도를 그립니다.
plt.scatter(train_input, train_target)
#15에서 49까지 2차 방정식 그래프를 그립니다.
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))
# -> 0.9706807451768623
print(lr.score(test_poly, test_target))
# -> 0.9775935108325122
훈련 세트와 테스트 세트에 대한 점수가 크게 높아졌다. 하지만 테스트 세트의 점수가 더 높아 과소적합이다.
더 복잡한 모델을 사용해야 한다.
'2023-2 KHUDA > ML 기초세션' 카테고리의 다른 글
| [혼자 공부하는 머신러닝 + 딥러닝] Chapter 04-1 로지스틱 회귀 (0) | 2023.08.15 |
|---|---|
| [혼자 공부하는 머신러닝 + 딥러닝] Chapter 03-3 특성 공학과 규제 (0) | 2023.08.08 |
| [혼자 공부하는 머신러닝 + 딥러닝] Chapter 03-1 k-최근접 이웃 회귀 (0) | 2023.08.08 |
| [혼자 공부하는 머신러닝 + 딥러닝] Chapter 02 데이터 다루기 (0) | 2023.08.08 |
| [혼자 공부하는 머신러닝 + 딥러닝] Chapter 01 나의 첫 머신러닝 (0) | 2023.08.08 |