머신러닝 모델 평가: 선형 회귀와 다항 회귀 실습
머신러닝 모델 평가 및 실습: 선형 회귀와 다항 회귀를 사용한 농어 데이터 분석
오늘은 선형 회귀(Linear Regression)에 대해 공부했습니다. 데이터를 준비하고, 머신러닝 모델을 사용해 예측하며, 선형 회귀와 다항 회귀를 비교하는 과정을 배웠습니다. 아래는 학습한 주요 내용입니다.
1. 데이터 준비하기
머신러닝 모델을 학습하기 위해 필요한 첫 번째 단계는 데이터를 준비하는 것입니다. 오늘 학습에서는 농어의 길이와 무게 데이터를 사용했습니다. 이 데이터는 농어의 길이(perch_length)와 무게(perch_weight)를 각각 넘파이 배열(numpy.ndarray
)로 정의했습니다.
데이터의 구성
- 농어의 길이 (perch_length): 농어의 길이는 8.4cm에서 44cm 사이로 다양합니다. 이 데이터는 단일 특성(feature)으로 사용되며, 모델이 입력 값으로 처리합니다.
- 농어의 무게 (perch_weight): 농어의 무게는 5.9g에서 1100g 사이로 다양합니다. 이는 모델이 예측해야 할 대상(target) 값입니다.
코드로 데이터 정의
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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])
왜 데이터를 준비해야 하나요?
머신러닝 모델은 데이터를 기반으로 학습하므로, 모델이 데이터의 특성을 최대한 잘 이해할 수 있도록 데이터를 적절히 전처리해야 합니다. 예를 들어, 데이터를 정규화하거나(특성이 많을 경우), 결측값을 처리하거나, 데이터를 훈련 세트와 테스트 세트로 나누는 과정이 필요합니다.
데이터에 대한 기본 통계
우리가 사용하는 데이터의 분포를 이해하면 모델의 학습 방향을 더 잘 조정할 수 있습니다. 데이터를 탐색해보면 다음과 같은 통계를 얻을 수 있습니다.
1
2
3
4
5
6
print(f"농어 길이의 최소값: {perch_length.min()}cm")
print(f"농어 길이의 최대값: {perch_length.max()}cm")
print(f"농어 무게의 최소값: {perch_weight.min()}g")
print(f"농어 무게의 최대값: {perch_weight.max()}g")
print(f"농어 길이의 평균값: {perch_length.mean():.2f}cm")
print(f"농어 무게의 평균값: {perch_weight.mean():.2f}g")
출력:
1
2
3
4
5
6
농어 길이의 최소값: 8.4cm
농어 길이의 최대값: 44.0cm
농어 무게의 최소값: 5.9g
농어 무게의 최대값: 1100.0g
농어 길이의 평균값: 27.17cm
농어 무게의 평균값: 267.94g
데이터 분포 시각화
데이터가 어떤 분포를 가지고 있는지 시각화하면 이해하기 쉽습니다. 산점도를 그려보았습니다.
1
2
3
4
5
6
7
import matplotlib.pyplot as plt
plt.scatter(perch_length, perch_weight)
plt.xlabel('Length (cm)')
plt.ylabel('Weight (g)')
plt.title('Perch Data Distribution')
plt.show()
핵심 팁: 데이터의 패턴 이해
- 농어의 길이가 증가할수록 무게도 증가하는 경향이 보입니다.
- 이 경향은 단순 선형적인 관계가 아닐 가능성이 큽니다. 따라서 단순 선형 회귀 모델을 사용하면 데이터의 경향을 제대로 학습하지 못할 수 있습니다.
데이터의 패턴을 미리 이해하면 모델 선택 및 전처리에 더 나은 결정을 내릴 수 있습니다.
2. 훈련 세트와 테스트 세트 분리 및 2차원 배열 변환
머신러닝 모델을 학습시키기 위해서는 데이터를 훈련 세트와 테스트 세트로 나누는 것이 중요합니다.
훈련 세트는 모델을 학습시키는 데 사용되며, 테스트 세트는 학습된 모델의 성능을 평가하는 데 사용됩니다.
1. 훈련 세트와 테스트 세트 분리하기
사이킷런의 train_test_split
함수를 사용하면 데이터를 쉽게 분리할 수 있습니다.
1
2
3
4
5
6
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
)
파라미터 설명
perch_length
와perch_weight
: 입력 데이터(특성)와 출력 데이터(타깃)입니다.random_state=42
: 데이터를 무작위로 나누되, 매번 동일하게 나누기 위해 사용됩니다. 같은 랜덤 시드를 사용하면 결과를 재현할 수 있습니다.
데이터 분리 후 크기 확인
분리된 데이터의 크기를 확인해보면 다음과 같습니다.
1
print(train_input.shape, test_input.shape) # 출력: (42,) (14,)
- 훈련 세트에는 42개의 샘플이 포함되어 있습니다.
- 테스트 세트에는 14개의 샘플이 포함되어 있습니다.
- 이 비율은 기본적으로 75%:25%로 나뉘며,
train_test_split
함수의test_size
매개변수를 조정하여 비율을 변경할 수 있습니다.
2. 2차원 배열로 변환하기
scikit-learn
의 대부분의 머신러닝 알고리즘은 입력 데이터를 2차원 배열로 처리합니다. 그러나 현재 perch_length
와 같이 1차원 배열인 경우, 이를 2차원 배열로 변환해야 합니다.
1차원 배열:
1
print(train_input[:5]) # 예: [8.4, 22.0, 19.0, 21.0, 27.5]
2차원 배열 변환:
1
2
3
4
5
6
7
8
train_input = train_input.reshape(-1, 1)
test_input = test_input.reshape(-1, 1)
print(train_input[:5]) # 출력: [[ 8.4]
# [22. ]
# [19. ]
# [21. ]
# [27.5]]
reshape(-1, 1)
설명
-1
: 행(row)의 개수를 자동으로 계산합니다.1
: 열(column)의 개수를 1로 설정합니다.- 결과적으로, 데이터를
(n_samples, 1)
형태로 변환하여 모델에 적합한 입력 형식으로 만듭니다.
3. 데이터 확인
훈련 세트와 테스트 세트의 크기를 확인하고, 몇 개의 데이터를 출력해보면 아래와 같습니다.
1
2
3
4
5
print("훈련 세트 크기:", train_input.shape) # 출력: (42, 1)
print("테스트 세트 크기:", test_input.shape) # 출력: (14, 1)
# 첫 번째 5개의 샘플 확인
print("훈련 세트 일부:\n", train_input[:5])
출력:
1
2
3
4
5
6
7
8
훈련 세트 크기: (42, 1)
테스트 세트 크기: (14, 1)
훈련 세트 일부:
[[ 8.4]
[22. ]
[19. ]
[21. ]
[27.5]]
왜 2차원 배열이 필요할까?
머신러닝 알고리즘은 입력 데이터가 여러 개의 특성을 가질 수 있는 상황을 가정합니다. 따라서, 입력 데이터는 (n_samples, n_features)
형태의 2차원 배열이어야 합니다.
예시:
- 1차원 배열: [8.4, 22.0, 19.0]
→ 이는 “샘플 3개”로 해석되지 않고, “특성 3개”로 잘못 인식될 수 있습니다. - 2차원 배열:
1 2 3
[[8.4], [22.0], [19.0]]
→ 각 행이 하나의 샘플을 나타내며, 열은 특성을 나타냅니다.
데이터 분리 시 주의할 점
- 랜덤 시드 설정:
random_state
를 지정하지 않으면 매번 데이터를 나누는 방식이 달라질 수 있습니다. 이렇게 되면 결과를 재현하기 어렵습니다. - 데이터 비율 조정: 훈련 세트와 테스트 세트의 비율은 문제에 따라 다르게 설정할 수 있습니다. 기본 값은 75%:25%이지만, 데이터 양이 적을 경우 80%:20% 또는 90%:10%로 설정하기도 합니다.
추가 팁: 데이터 시각화
훈련 세트와 테스트 세트를 시각적으로 확인하면 데이터가 적절히 분리되었는지 알 수 있습니다.
1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
plt.scatter(train_input, train_target, label='Train Set', color='blue')
plt.scatter(test_input, test_target, label='Test Set', color='red')
plt.xlabel('Length (cm)')
plt.ylabel('Weight (g)')
plt.title('Train and Test Data Distribution')
plt.legend()
plt.show()
결과:
- 파란 점은 훈련 데이터, 빨간 점은 테스트 데이터입니다.
- 데이터가 적절히 섞여 있음을 확인할 수 있습니다.
3. K-최근접 이웃(K-Nearest Neighbors) 회귀
K-최근접 이웃(K-Nearest Neighbors, KNN) 회귀는 머신러닝에서 간단하면서도 직관적으로 동작하는 알고리즘입니다. KNN 회귀는 새로운 데이터 포인트의 타깃 값을 예측할 때, 가장 가까운 K개의 샘플의 타깃 값의 평균을 사용하는 방식으로 작동합니다.
1. KNN 회귀 모델 생성 및 훈련
사이킷런의 KNeighborsRegressor
클래스를 사용하여 KNN 회귀 모델을 생성하고 훈련할 수 있습니다. 아래는 길이와 무게 데이터로 모델을 학습시키는 코드입니다.
1
2
3
4
5
6
7
from sklearn.neighbors import KNeighborsRegressor
# K-최근접 이웃 모델 생성
knr = KNeighborsRegressor(n_neighbors=3) # 이웃 수(K)를 3으로 설정
# 모델 훈련
knr.fit(train_input, train_target)
주요 매개변수
n_neighbors
: 예측 시 고려할 이웃 샘플의 개수를 지정합니다. 기본 값은 5입니다. 값을 너무 작게 설정하면 모델이 훈련 데이터에 과적합(overfitting)될 수 있으며, 너무 크게 설정하면 데이터의 패턴을 제대로 반영하지 못할 수 있습니다.
2. 새로운 데이터에 대한 예측
훈련된 KNN 회귀 모델을 사용해 길이가 50cm인 농어의 무게를 예측합니다.
1
2
print(knr.predict([[50]])) # 길이가 50cm인 농어 예측
# 출력: [1033.33333333]
이 결과는 모델이 50cm 농어의 무게를 약 1,033g으로 예측했음을 나타냅니다.
3. 예측의 작동 원리
KNN 회귀는 다음과 같은 방식으로 예측 값을 계산합니다:
- 새로운 데이터 포인트와 훈련 데이터 포인트 사이의 거리를 계산합니다.
- 가장 가까운 K개의 데이터 포인트(이웃)를 선택합니다.
- 선택된 K개의 데이터 포인트의 타깃 값의 평균을 계산하여 결과를 예측합니다.
4. 예측 결과 분석: 시각화
50cm 농어를 예측하는 과정에서 모델이 선택한 이웃 데이터를 시각화해보면, 모델의 동작 방식을 더 잘 이해할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt
# 50cm 농어에 가장 가까운 이웃 샘플 찾기
distances, indexes = knr.kneighbors([[50]])
# 훈련 데이터 산점도
plt.scatter(train_input, train_target, label='Train Data')
# 이웃 데이터 표시
plt.scatter(train_input[indexes], train_target[indexes], marker='D', label='Neighbors', color='orange')
# 예측 데이터 표시
plt.scatter(50, 1033, marker='^', label='Prediction', color='red')
plt.xlabel('Length (cm)')
plt.ylabel('Weight (g)')
plt.title('KNN Regression: 50cm Perch')
plt.legend()
plt.show()
결과 분석
- 훈련 데이터 전체가 파란 점으로 표시됩니다.
- 모델이 선택한 3개의 이웃 샘플이 주황색 다이아몬드로 표시됩니다.
- 50cm 농어의 예측 값은 빨간색 삼각형으로 표시됩니다.
5. 이웃 샘플의 타깃 값 확인
선택된 이웃 샘플의 무게(타깃 값)를 확인하면, 예측 값이 이들의 평균임을 확인할 수 있습니다.
1
2
3
4
5
# 이웃 샘플의 타깃 값
print(train_target[indexes]) # 출력: [1015. 900. 1185.]
# 이웃 타깃 값의 평균 계산
print(np.mean(train_target[indexes])) # 출력: 1033.3333333333333
결과
- 선택된 이웃 샘플의 타깃 값은
[1015, 900, 1185]
입니다. - 이들의 평균은
1033.33
으로, 모델의 예측 값과 정확히 일치합니다.
6. KNN 회귀의 한계
KNN 회귀는 단순하고 직관적이지만, 몇 가지 한계가 있습니다.
- 데이터의 범위를 벗어나는 예측:
KNN은 훈련 데이터의 범위를 벗어난 값을 잘 예측하지 못합니다. 예를 들어, 길이가 100cm인 농어를 예측하면 훈련 데이터의 범위를 벗어나므로 적절한 값을 예측하지 못합니다.1
print(knr.predict([[100]])) # 출력: [1033.33333333]
- 길이가 100cm인 농어도 1,033g으로 예측했습니다. 이는 잘못된 예측입니다.
대규모 데이터셋 처리 어려움:
KNN은 새로운 데이터가 들어올 때마다 모든 훈련 샘플과의 거리를 계산해야 하므로, 데이터셋이 커질수록 예측 속도가 느려질 수 있습니다.- 데이터의 정규화 필요성:
거리 기반 알고리즘이기 때문에 데이터의 스케일에 영향을 받을 수 있습니다. 특성의 크기가 큰 경우, 정규화를 적용해야 합니다.
7. K 값을 변경해보기
K의 값을 변경하면 모델의 예측 결과가 달라질 수 있습니다. 예를 들어, K를 5로 설정하면 더 많은 이웃을 고려하게 됩니다.
1
2
3
4
knr = KNeighborsRegressor(n_neighbors=5)
knr.fit(train_input, train_target)
print(knr.predict([[50]])) # 출력: [980.6]
결과 분석
- K를 증가시키면 더 많은 이웃 샘플을 고려하므로, 예측 값이 부드럽게 변할 수 있습니다.
- 그러나 K가 너무 크면 모델이 훈련 데이터의 세부적인 패턴을 놓칠 수 있습니다.
핵심 요약
- KNN 회귀는 가장 가까운 K개의 샘플의 타깃 값을 평균하여 예측합니다.
- 훈련 데이터의 범위 내에서는 좋은 성능을 보이지만, 범위를 벗어나면 예측이 부정확할 수 있습니다.
- K 값은 모델의 성능에 중요한 영향을 미칩니다. 적절한 K를 찾기 위해 실험과 교차 검증이 필요합니다.
- 거리 기반 알고리즘이므로 스케일 정규화(예: MinMaxScaler, StandardScaler)가 필요할 수 있습니다.
4. 시각화 및 예측 분석
K-최근접 이웃(KNN) 회귀 모델은 예측할 때 가장 가까운 이웃 샘플의 타깃 값을 평균하여 결과를 계산합니다. 이 과정과 결과를 시각화하면 모델의 동작 방식을 더 명확히 이해할 수 있습니다. 여기에서는 길이가 50cm인 농어의 예측 과정과 모델의 한계를 분석합니다.
1. 50cm 농어의 예측 결과
먼저, 길이가 50cm인 농어의 무게를 예측합니다. 모델이 반환하는 값은 이웃 샘플의 타깃 값의 평균입니다.
1
print(knr.predict([[50]])) # 출력: [1033.33333333]
결과: 모델은 50cm 농어의 무게를 약 1,033g으로 예측했습니다.
2. 이웃 샘플 확인
모델은 50cm 농어와 가장 가까운 이웃 샘플 3개를 기준으로 예측 값을 계산합니다. 이 이웃 샘플의 인덱스와 타깃 값을 확인해봅니다.
1
2
3
4
5
6
7
8
# 50cm 농어와 가장 가까운 이웃 샘플의 인덱스와 거리
distances, indexes = knr.kneighbors([[50]])
print("이웃 샘플의 인덱스:", indexes)
print("이웃 샘플의 거리:", distances)
# 이웃 샘플의 타깃 값
print("이웃 샘플의 무게:", train_target[indexes])
print("예측 값 (이웃 타깃 값 평균):", np.mean(train_target[indexes]))
출력:
1
2
3
4
이웃 샘플의 인덱스: [[20 34 10]]
이웃 샘플의 거리: [[2.5 4.5 5. ]]
이웃 샘플의 무게: [[1015. 900. 1185.]]
예측 값 (이웃 타깃 값 평균): 1033.3333333333333
결과:
- 가장 가까운 3개의 이웃 샘플의 타깃 값은
[1015, 900, 1185]
입니다. - 이들의 평균은
1033.33
으로 모델의 예측 값과 동일합니다.
3. 시각화: 이웃 샘플과 예측 값
모델이 선택한 이웃 샘플과 예측 결과를 산점도로 시각화합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt
# 훈련 데이터 산점도
plt.scatter(train_input, train_target, label='Train Data', color='blue')
# 이웃 샘플 표시
plt.scatter(train_input[indexes], train_target[indexes], marker='D', label='Neighbors', color='orange')
# 예측 값 표시
plt.scatter(50, 1033, marker='^', label='Prediction', color='red')
plt.xlabel('Length (cm)')
plt.ylabel('Weight (g)')
plt.title('KNN Regression: 50cm Perch')
plt.legend()
plt.show()
결과 분석:
- 파란 점: 훈련 데이터.
- 주황색 다이아몬드: 모델이 선택한 가장 가까운 이웃 샘플.
- 빨간색 삼각형: 모델이 예측한 50cm 농어의 무게.
이 그래프를 통해 모델이 예측 값을 어떻게 계산했는지 직관적으로 이해할 수 있습니다.
4. 모델의 한계: 데이터 범위를 벗어난 샘플
KNN 회귀는 훈련 데이터의 범위를 벗어난 데이터를 잘 처리하지 못합니다. 예를 들어, 길이가 100cm인 농어를 예측할 때 모델은 여전히 가장 가까운 이웃 샘플의 평균을 반환합니다.
1
print(knr.predict([[100]])) # 출력: [1033.33333333]
결과: 100cm 농어의 무게도 1,033g으로 예측합니다. 이는 훈련 데이터 범위를 벗어난 경우 모델이 적절한 예측을 하지 못함을 보여줍니다.
5. 시각화: 100cm 농어의 예측 결과
100cm 농어에 대한 예측 결과를 시각화하여, 훈련 데이터 범위를 벗어난 예측이 얼마나 부정확한지 확인합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 100cm 농어의 이웃 샘플 찾기
distances, indexes = knr.kneighbors([[100]])
# 훈련 데이터 산점도
plt.scatter(train_input, train_target, label='Train Data', color='blue')
# 이웃 샘플 표시
plt.scatter(train_input[indexes], train_target[indexes], marker='D', label='Neighbors', color='orange')
# 예측 값 표시
plt.scatter(100, 1033, marker='^', label='Prediction', color='red')
plt.xlabel('Length (cm)')
plt.ylabel('Weight (g)')
plt.title('KNN Regression: 100cm Perch')
plt.legend()
plt.show()
결과 분석:
- 파란 점: 훈련 데이터.
- 주황색 다이아몬드: 모델이 선택한 가장 가까운 이웃 샘플.
- 빨간색 삼각형: 100cm 농어의 예측 값.
결과적으로, 모델은 훈련 데이터의 범위를 벗어난 샘플에 대해 적절한 예측을 하지 못하며, 훈련 데이터에서 가장 가까운 이웃 샘플의 평균 값만 반환합니다.
6. 요약: 시각화를 통한 모델 동작 이해
KNN 회귀의 동작 원리:
모델은 새로운 데이터 포인트와 훈련 데이터 간의 거리를 계산하여 가장 가까운 K개의 이웃 샘플을 선택하고, 이들의 타깃 값의 평균을 예측 값으로 반환합니다.시각화의 중요성:
데이터를 시각화하면 모델이 예측을 수행하는 방식을 더 명확히 이해할 수 있습니다. 또한, 모델의 한계를 쉽게 파악할 수 있습니다.모델의 한계:
- KNN 회귀는 훈련 데이터 범위 외부의 샘플을 정확히 예측하지 못합니다.
- 이 한계를 극복하기 위해 선형 회귀나 다항 회귀와 같은 다른 알고리즘을 사용할 수 있습니다.
특히 데이터의 경향이 훈련 범위를 벗어날 경우, 선형 회귀와 같은 모델 기반 알고리즘이 더 적합합니다.
5. 선형 회귀 모델
선형 회귀(Linear Regression)는 머신러닝에서 가장 기본적이고 널리 사용되는 회귀 알고리즘입니다.
데이터의 특성과 타깃 값 사이의 선형 관계를 학습하여, 입력 데이터에 대해 타깃 값을 예측하는 모델입니다.
1. 선형 회귀 모델 생성 및 훈련
사이킷런의 LinearRegression
클래스를 사용하여 선형 회귀 모델을 생성하고, 훈련 데이터에 대해 학습시킬 수 있습니다.
1
2
3
4
5
6
7
from sklearn.linear_model import LinearRegression
# 선형 회귀 모델 생성
lr = LinearRegression()
# 모델 훈련
lr.fit(train_input, train_target)
2. 길이가 50cm인 농어의 무게 예측
훈련된 선형 회귀 모델을 사용해 길이가 50cm인 농어의 무게를 예측합니다.
1
2
# 길이가 50cm인 농어의 무게 예측
print(lr.predict([[50]])) # 출력: [1241.83860323]
결과: 선형 회귀 모델은 50cm 농어의 무게를 약 1241.84g으로 예측했습니다.
이는 이전의 K-최근접 이웃 모델이 예측한 값(1033.33g)보다 높은 값입니다.
3. 모델의 선형 방정식 확인
선형 회귀 모델은 다음과 같은 선형 방정식을 학습합니다:
\[y = a \cdot x + b\]- \(a\): 기울기 (coef_)
- \(b\): 절편 (intercept_)
모델이 학습한 기울기와 절편을 확인합니다.
1
2
3
4
5
6
7
# 선형 회귀 모델의 기울기와 절편
print("기울기(coef_):", lr.coef_)
print("절편(intercept_):", lr.intercept_)
# 출력:
# 기울기(coef_): [39.01714496]
# 절편(intercept_): -709.0186449535477
결과:
- 기울기(\(a\)) = 39.02
- 절편(\(b\)) = -709.02
따라서, 모델이 학습한 방정식은 다음과 같습니다:
\[y = 39.02 \cdot x - 709.02\]4. 선형 회귀 직선 시각화
훈련 데이터와 함께 학습된 선형 방정식을 시각화하여 모델의 예측 결과를 확인합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt
# 훈련 데이터 산점도
plt.scatter(train_input, train_target, label='Train Data', color='blue')
# 선형 회귀 직선
plt.plot([15, 50], [15 * lr.coef_ + lr.intercept_, 50 * lr.coef_ + lr.intercept_], color='red', label='Linear Regression')
# 길이가 50cm인 농어의 예측 값
plt.scatter(50, 1241.84, marker='^', label='Prediction (50cm)', color='green')
plt.xlabel('Length (cm)')
plt.ylabel('Weight (g)')
plt.title('Linear Regression Model')
plt.legend()
plt.show()
결과 분석:
- 파란 점: 훈련 데이터.
- 빨간 직선: 선형 회귀 모델이 학습한 선형 방정식.
- 초록색 삼각형: 길이가 50cm인 농어에 대한 예측 값.
5. 모델 평가
선형 회귀 모델의 성능을 훈련 세트와 테스트 세트에서 평가합니다.
모델 성능은 \(R^2\) 점수를 사용하여 측정합니다. \(R^2\) 점수는 회귀 모델의 예측력이 얼마나 좋은지 나타내며, 1에 가까울수록 좋습니다.
1
2
3
4
5
6
7
# 훈련 세트와 테스트 세트의 R^2 점수
print("훈련 세트 점수:", lr.score(train_input, train_target))
print("테스트 세트 점수:", lr.score(test_input, test_target))
# 출력:
# 훈련 세트 점수: 0.939846333997604
# 테스트 세트 점수: 0.8247503123313558
결과:
- 훈련 세트 점수: 0.94
- 테스트 세트 점수: 0.82
모델은 훈련 데이터와 테스트 데이터에서 높은 점수를 기록했지만,
훈련 세트와 테스트 세트 점수 간의 차이로 인해 모델이 약간 과소적합(underfitting)되었음을 알 수 있습니다.
6. 선형 회귀 모델의 한계
데이터의 범위 밖 예측 문제:
선형 회귀 모델은 학습한 선형 방정식을 기반으로 예측합니다.
따라서, 데이터의 범위를 벗어난 경우에도 직선을 따라 예측하며, 현실과 맞지 않는 결과를 낼 수 있습니다.
예를 들어, 길이가 100cm인 농어를 예측하면 다음과 같은 결과가 나옵니다:
1
print(lr.predict([[100]])) # 출력: [3192.695851]
결과: 100cm 농어의 무게를 약 3192.7g으로 예측했습니다.
이는 농어의 무게가 비현실적으로 증가할 수 있음을 보여줍니다.
문제점:
- 데이터의 범위 밖에서는 예측이 부정확할 수 있습니다.
- 현실적으로 농어의 무게는 선형적으로 증가하지 않으며, 데이터에 따라 비선형적인 관계를 가질 가능성이 높습니다.
7. 선형 회귀 모델의 장점과 단점
장점:
- 간단하고 직관적: 선형 방정식을 기반으로 하므로 이해하기 쉽고 구현이 간단합니다.
- 빠른 계산 속도: 모델 학습 및 예측 속도가 빠릅니다.
- 넓은 응용 분야: 데이터가 선형 관계를 가질 때 매우 효과적입니다.
단점:
- 비선형 관계를 처리하지 못함: 데이터가 비선형 관계를 가질 경우 적합하지 않습니다.
- 이상치(outliers)에 민감: 이상치가 있는 데이터에서는 모델이 크게 영향을 받을 수 있습니다.
8. 개선 방법: 다항 회귀로 확장
- 선형 회귀 모델의 한계를 극복하기 위해 다항 회귀(Polynomial Regression)를 사용해 데이터의 비선형 관계를 모델링할 수 있습니다.
- 이는 다음 단계에서 다룰 예정입니다.
6. 다항 회귀 (Polynomial Regression)
다항 회귀(Polynomial Regression)는 선형 회귀를 확장하여 데이터의 비선형 관계를 모델링하는 방법입니다.
선형 회귀는 데이터를 직선으로 표현하지만, 다항 회귀는 곡선으로 데이터를 더 잘 나타낼 수 있습니다.
1. 다항 회귀를 위한 데이터 변환
다항 회귀를 수행하기 위해 데이터를 다항식의 형태로 변환해야 합니다.
길이를 입력 특성으로 사용하는 대신, 길이의 제곱 값을 추가하여 입력 데이터에 2차원 특성을 생성합니다.
1
2
3
4
5
6
7
8
import numpy as np
# 다항식 특성 생성 (길이와 길이의 제곱)
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.shape) # 출력: (42, 2) (14, 2)
결과:
- \(\text{train_poly}\): (42, 2)
→ 훈련 데이터는 42개의 샘플과 2개의 특성(길이와 길이의 제곱)으로 구성됨. - \(\text{test_poly}\): (14, 2)
→ 테스트 데이터는 14개의 샘플과 2개의 특성으로 구성됨.
데이터 변환 예시:
원래 데이터:
\[\text{train_input} = [8.4, 13.7, 15.0]\]변환된 데이터:
\[\text{train_poly} = [[8.4^2, 8.4], [13.7^2, 13.7], [15.0^2, 15.0]]\]2. 다항 회귀 모델 훈련
변환된 데이터(\(\text{train_poly}\))를 사용하여 선형 회귀 모델을 학습합니다.
다항 회귀는 선형 회귀 알고리즘을 사용하지만, 입력 데이터를 다항식으로 변환했기 때문에 비선형 관계를 모델링할 수 있습니다.
1
2
3
4
5
6
7
8
from sklearn.linear_model import LinearRegression
# 선형 회귀 모델 생성 및 훈련
lr = LinearRegression()
lr.fit(train_poly, train_target)
# 50cm 농어의 무게 예측
print(lr.predict([[50**2, 50]])) # 출력: [1573.98423528]
결과:
- 길이가 50cm인 농어의 무게를 약 1574g으로 예측했습니다.
- 이전 선형 회귀 모델(1241.84g)과 비교하여, 더 현실적인 값을 반환했습니다.
3. 다항식의 계수와 절편 확인
다항 회귀 모델이 학습한 2차 방정식의 계수와 절편을 확인합니다.
이 값들을 사용해 학습된 다항식 방정식을 도출할 수 있습니다.
1
2
3
4
5
6
print("계수(coef_):", lr.coef_)
print("절편(intercept_):", lr.intercept_)
# 출력:
# 계수(coef_): [ 1.01433211 -21.55792498]
# 절편(intercept_): 116.0502107827827
결과:
- \(a = 1.0143\) (길이의 제곱에 대한 계수)
- \(b = -21.5579\) (길이에 대한 계수)
- \(c = 116.05\) (절편)
학습된 다항식 방정식:
\[\text{무게} = 1.014 \cdot \text{길이}^2 - 21.558 \cdot \text{길이} + 116.05\]4. 다항 회귀 모델 시각화
다항 회귀 모델이 학습한 2차 방정식을 곡선으로 시각화하여, 훈련 데이터와 비교합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt
# 곡선을 그리기 위한 범위 생성
point = np.arange(15, 50)
# 훈련 데이터 산점도
plt.scatter(train_input, train_target, label='Train Data', color='blue')
# 다항 회귀 곡선
plt.plot(point, 1.014*point**2 - 21.558*point + 116.05, color='red', label='Polynomial Regression')
# 50cm 농어의 예측 값
plt.scatter(50, 1574, marker='^', color='green', label='Prediction (50cm)')
plt.xlabel('Length (cm)')
plt.ylabel('Weight (g)')
plt.title('Polynomial Regression Model')
plt.legend()
plt.show()
결과 분석:
- 파란 점: 훈련 데이터.
- 빨간 곡선: 다항 회귀 모델이 학습한 곡선.
- 초록색 삼각형: 길이가 50cm인 농어에 대한 예측 값.
5. 다항 회귀 모델 평가
훈련 세트와 테스트 세트에서 다항 회귀 모델의 \(R^2\) 점수를 평가합니다.
1
2
3
4
5
6
7
# 훈련 세트와 테스트 세트의 R^2 점수
print("훈련 세트 점수:", lr.score(train_poly, train_target))
print("테스트 세트 점수:", lr.score(test_poly, test_target))
# 출력:
# 훈련 세트 점수: 0.9706807451768623
# 테스트 세트 점수: 0.9775935108325122
결과:
- 훈련 세트 점수: 0.97
- 테스트 세트 점수: 0.98
분석:
- 다항 회귀 모델은 선형 회귀 모델보다 \(R^2\) 점수가 높습니다.
이는 다항 회귀가 데이터의 비선형 관계를 더 잘 모델링했음을 나타냅니다. - 훈련 세트와 테스트 세트 점수 차이가 적어 과적합(overfitting) 문제가 발생하지 않았습니다.
6. 선형 회귀와 다항 회귀 비교
모델 | 50cm 농어 예측 값 | 훈련 세트 점수 | 테스트 세트 점수 |
---|---|---|---|
선형 회귀 | 1241.84g | 0.94 | 0.82 |
다항 회귀 | 1574.00g | 0.97 | 0.98 |
7. 다항 회귀의 장점과 한계
장점:
- 비선형 관계 모델링:
데이터의 비선형 관계를 표현할 수 있어, 선형 회귀의 한계를 극복합니다. - 확장성:
고차 다항식을 사용하면 더 복잡한 관계도 모델링할 수 있습니다.
한계:
- 복잡도 증가:
차수가 높아질수록 모델이 복잡해져 과적합 위험이 증가할 수 있습니다. - 고차 다항식의 해석 어려움:
차수가 높은 다항식의 계수는 해석하기 어렵습니다.
핵심 요약
- 다항 회귀는 선형 회귀의 한계를 극복하여 데이터의 비선형 관계를 모델링합니다.
- 입력 데이터를 다항식 특성으로 변환한 뒤, 선형 회귀 알고리즘을 사용하여 모델을 학습합니다.
- \(R^2\) 점수와 예측 성능 면에서, 다항 회귀가 선형 회귀보다 우수한 결과를 보였습니다.
- 차수 설정 및 데이터 분포에 따라 모델 성능이 크게 달라질 수 있으므로, 적절한 특성 변환과 차수 선택이 중요합니다.
7. 모델 평가
모델 평가(Model Evaluation)는 학습한 머신러닝 모델의 성능을 확인하고, 적합성을 판단하는 과정입니다.
여기서는 다항 회귀 모델의 성능을 훈련 세트와 테스트 세트에서 평가하고, \(R^2\) 점수를 통해 모델의 예측 능력을 분석합니다.
1. 평가 지표: \(R^2\) 점수
\(R^2\) 점수(결정 계수, Coefficient of Determination)는 회귀 모델의 성능을 측정하는 데 사용됩니다.
\[R^2 = 1 - \frac{\text{SSE}}{\text{SST}}\]- SSE: 잔차 제곱합 (Sum of Squares for Error) → 모델 예측이 실제 값을 얼마나 잘 설명하는지 측정.
- SST: 총 제곱합 (Total Sum of Squares) → 타깃 값의 분산을 측정.
\(R^2\) 점수의 특징:
- \(R^2 = 1\): 완벽한 모델 (모든 데이터를 정확히 예측).
- \(R^2 = 0\): 모델이 타깃 값을 평균으로만 예측.
- \(R^2 < 0\): 모델이 타깃 값을 평균보다 못하게 예측.
2. 훈련 세트와 테스트 세트 평가
다항 회귀 모델의 \(R^2\) 점수를 훈련 세트와 테스트 세트에서 각각 계산합니다.
1
2
3
4
5
6
# 훈련 세트와 테스트 세트의 R^2 점수
train_score = lr.score(train_poly, train_target)
test_score = lr.score(test_poly, test_target)
print("훈련 세트 점수:", train_score)
print("테스트 세트 점수:", test_score)
결과:
1
2
훈련 세트 점수: 0.9706807451768623
테스트 세트 점수: 0.9775935108325122
3. 결과 분석
훈련 세트 평가:
- 훈련 세트 \(R^2 = 0.97\):
모델이 훈련 데이터를 매우 잘 학습하여, 높은 점수를 기록했습니다.
이는 다항 회귀 모델이 훈련 데이터의 비선형 관계를 잘 학습했음을 의미합니다.
테스트 세트 평가:
- 테스트 세트 \(R^2 = 0.98\):
모델이 새로운 데이터(테스트 데이터)에 대해서도 높은 성능을 보였습니다.
훈련 데이터에 과도하게 의존하지 않으면서 일반화 성능도 뛰어납니다.
훈련 세트와 테스트 세트 점수 비교:
- 훈련 세트와 테스트 세트 점수 차이가 작습니다 (\(0.97\) vs \(0.98\)).
이는 모델이 과적합(overfitting)되지 않았음을 의미합니다.
반대로 점수 차이가 크다면, 모델이 훈련 데이터에 지나치게 맞춰져 새로운 데이터에서 성능이 낮아질 수 있습니다.
4. 모델 성능을 시각화하여 확인
훈련 세트와 테스트 세트를 함께 시각화하여 모델이 데이터를 얼마나 잘 설명하는지 확인합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt
# 곡선을 그리기 위한 범위 생성
point = np.arange(15, 50)
# 훈련 데이터 산점도
plt.scatter(train_input, train_target, label='Train Data', color='blue')
# 테스트 데이터 산점도
plt.scatter(test_input, test_target, label='Test Data', color='green')
# 다항 회귀 곡선
plt.plot(point, 1.014 * point**2 - 21.558 * point + 116.05, color='red', label='Polynomial Regression')
plt.xlabel('Length (cm)')
plt.ylabel('Weight (g)')
plt.title('Model Evaluation: Polynomial Regression')
plt.legend()
plt.show()
결과 분석:
- 파란 점: 훈련 데이터
- 초록 점: 테스트 데이터
- 빨간 곡선: 다항 회귀 모델이 학습한 곡선
이 그래프는 모델이 훈련 데이터와 테스트 데이터의 분포를 모두 잘 설명하는 것을 보여줍니다.
5. 추가 평가: 범위를 벗어난 데이터
모델이 훈련 데이터의 범위를 벗어난 데이터를 어떻게 예측하는지 확인합니다.
예를 들어, 길이가 100cm인 농어를 예측해봅니다.
1
2
# 100cm 농어 예측
print(lr.predict([[100**2, 100]])) # 출력: [8803.85032891]
결과:
- 모델은 길이가 100cm인 농어의 무게를 8803.85g으로 예측했습니다.
이는 다항 회귀 모델이 훈련 데이터의 범위를 벗어난 경우에도 곡선의 연장선으로 예측을 수행함을 보여줍니다.
그러나 이러한 예측이 실제와 얼마나 일치하는지는 데이터 분포와 도메인 지식에 따라 다릅니다.
6. 모델 평가 요약
\(R^2\) 점수 평가:
데이터 세트 | 점수 | 해석 |
---|---|---|
훈련 세트 | 0.97 | 훈련 데이터를 잘 학습함. |
테스트 세트 | 0.98 | 새로운 데이터에서도 높은 성능을 보임. |
시각화:
- 모델이 훈련 데이터와 테스트 데이터의 비선형 패턴을 잘 학습했음을 확인했습니다.
추가 분석:
- 다항 회귀 모델은 훈련 데이터의 범위를 벗어난 경우에도 예측을 수행할 수 있지만, 예측 결과의 신뢰도는 보장되지 않습니다.
7. 다항 회귀의 한계와 개선 방법
한계:
- 과적합 가능성:
다항식의 차수를 너무 높게 설정하면, 훈련 데이터에 과도하게 맞춰져 테스트 데이터에서 성능이 저하될 수 있습니다. - 외삽 문제:
훈련 데이터의 범위를 벗어난 샘플에 대해 신뢰할 수 없는 예측을 수행할 수 있습니다.
개선 방법:
- 교차 검증(Cross-Validation):
모델의 일반화 성능을 확인하기 위해 교차 검증을 수행합니다. - 적절한 차수 선택:
과적합을 방지하기 위해 적절한 차수를 선택해야 합니다. 일반적으로 2차 또는 3차 다항식이 적합합니다. - 정규화(Regularization):
과적합을 방지하기 위해 정규화 기법(예: Ridge Regression, Lasso Regression)을 도입할 수 있습니다.
결론
- 다항 회귀는 선형 회귀보다 데이터의 비선형 관계를 잘 모델링합니다.
- \(R^2\) 점수를 통해 모델이 훈련 데이터와 테스트 데이터에서 우수한 성능을 보였음을 확인했습니다.
- 훈련 데이터의 범위를 벗어난 데이터 예측은 주의가 필요하며, 도메인 지식을 활용한 추가 검증이 필요합니다.
- 다항 회귀 모델을 활용할 때, 과적합과 외삽 문제를 방지하기 위한 추가적인 기법이 필요할 수 있습니다.
학습 요약
이번 학습에서는 선형 회귀(Linear Regression)와 다항 회귀(Polynomial Regression)를 중심으로 머신러닝 모델의 작동 원리, 구현 방법, 그리고 성능 평가에 대해 다뤘습니다. 아래는 학습한 내용을 요약한 부분입니다.
1. 데이터 준비
- 길이와 무게 데이터를 활용하여 농어의 무게를 예측하는 문제를 해결했습니다.
- 데이터를 훈련 세트와 테스트 세트로 나누고, 머신러닝 모델이 요구하는 2차원 배열 형태로 변환했습니다.
2. K-최근접 이웃 회귀(KNN Regression)
- 가장 가까운 K개의 샘플을 기준으로 타깃 값을 평균하여 예측하는 방식으로 작동했습니다.
- 훈련 데이터의 범위 내에서는 좋은 성능을 보였지만, 범위를 벗어난 경우 정확도가 크게 떨어졌습니다.
- K값을 조정하여 모델의 유연성과 복잡도를 조절할 수 있습니다.
3. 선형 회귀 모델
- 데이터를 선형 방정식으로 표현하여, 특성과 타깃 사이의 관계를 학습했습니다.
- \(y = a \cdot x + b\) 형태의 직선을 학습하며, \(a\)와 \(b\)는 각각 기울기와 절편으로, 모델이 학습한 모델 파라미터입니다.
- 데이터의 비선형 관계를 학습하지 못함으로 인해, 테스트 데이터에서 약간의 과소적합 문제가 나타났습니다.
4. 다항 회귀 모델
- 선형 회귀를 확장하여, 특성을 다항식 형태로 변환해 데이터를 학습했습니다.
- 비선형 관계를 잘 표현하는 2차 방정식 곡선을 학습하며, 훈련 데이터와 테스트 데이터에서 더 높은 \(R^2\) 점수를 기록했습니다.
- \(R^2\) 점수:
- 훈련 세트: 0.97
- 테스트 세트: 0.98
- 다항 회귀는 외삽 문제(범위를 벗어난 데이터 예측)와 과적합 가능성이 있으므로, 적절한 차수와 정규화 기법이 필요합니다.
5. 모델 평가
- 모델의 성능을 훈련 세트와 테스트 세트에서 각각 평가하며, 일반화 능력을 확인했습니다.
- \(R^2\) 점수를 사용하여 모델의 예측 성능을 수치적으로 평가했습니다.
- 훈련 데이터와 테스트 데이터의 점수 차이가 크지 않아, 적절한 학습이 이루어졌음을 확인했습니다.
6. 비교: 선형 회귀 vs. 다항 회귀
모델 | 50cm 농어 예측 값 | 훈련 세트 점수 | 테스트 세트 점수 |
---|---|---|---|
선형 회귀 | 1241.84g | 0.94 | 0.82 |
다항 회귀 | 1574.00g | 0.97 | 0.98 |
- 선형 회귀는 데이터를 직선으로 표현하여 단순한 모델을 제공하지만, 비선형 관계를 학습하지 못함.
- 다항 회귀는 비선형 관계를 학습하여 더 높은 정확도를 제공했으며, 훈련 세트와 테스트 세트 모두에서 뛰어난 성능을 보임.
7. 핵심 포인트
- 선형 회귀:
- 데이터를 선형 방정식으로 표현.
- 단순하지만 데이터가 선형 관계를 가지는 경우에 효과적.
- 비선형 데이터를 학습할 경우, 성능 저하 가능성.
- 다항 회귀:
- 비선형 관계를 모델링할 수 있어, 데이터의 복잡한 패턴을 학습 가능.
- 다항식의 차수가 증가할수록 과적합 위험 증가.
- 모델 평가:
- \(R^2\) 점수를 통해 모델의 예측력을 측정.
- 훈련 세트와 테스트 세트 점수의 차이가 크면 과적합(또는 과소적합) 문제를 의심.
- 모델 선택:
- 데이터의 특성과 목표에 따라 적절한 모델을 선택해야 함.
- 단순한 데이터에는 선형 회귀를, 복잡한 비선형 데이터에는 다항 회귀나 더 복잡한 모델을 사용할 수 있음.
8. 추가적인 학습 방향
- 정규화 기법:
- Ridge Regression, Lasso Regression 등을 활용해 과적합 방지.
- 교차 검증(Cross-Validation):
- 데이터 분할 방식에 따른 편향(bias) 줄이기.
- 비선형 회귀 알고리즘:
- 다항 회귀 외에 비선형 관계를 학습할 수 있는 알고리즘(예: Decision Tree, Random Forest, Neural Network) 탐구.
이번 학습을 통해 머신러닝에서 데이터의 관계를 이해하고, 적절한 모델을 선택하여 예측 성능을 향상시키는 과정을 배웠습니다.