데이터의 출처와 학습 내용은 [박혜선 혼자 공부하는 머신러닝 + 딥러닝 ],한빛미디어 를 인용했습니다.
K최근접이웃 회귀 (K-Nearest Neighbors Regression)는 K-NN 알고리즘 을 회귀 문제에 적용한 것입니다. KNN은 기본적으로 분류(classification) 문제에 많이 사용되지만, 회귀 문제에도 적용할 수 있습니다. KNN 회귀는 주어진 데이터 포인트와 가장 가까운 K개의 이웃을 기준으로 예측값을 계산하는 방식입니다.
지도 학습 알고리즘은 크게 분류와 회귀로 분류할 수 있습니다. 이전 게시글에서는 분류(classification)를 다루었습니다.
물고기의 크기에 따라 종류를 예측하는 모델을 만들었었죠, 하지만 수치형 데이터 즉 임의의 어떤 숫자를 예측해야 할 경우에는 어떻게 해야 할까요. 바로 이 때 K-NN Regression이 가장 기초가 되는 회귀 방법입니다.
회귀는 두 변수 간의 관계를 모델링하고, 그 관계를 통해 연속적인 값을 예측하는 통계학적 기법입니다. 회귀 분석은 입력 변수와 출력 변수 간의 관계를 파악하고, 이를 기반으로 새로운 데이터에 대해 예측값을 도출하는 데 사용됩니다. 특히, 회귀 분석은 연속적인 값이나 수치형 데이터를 예측하는 데 유용합니다.
따른 모델을 사용하는 것이 아닌 KNN을 사용해서 해보겠습니다.
KNN은 분류문제에 적합하다고 소개했지만, 사실 회귀문제에도 적용할 수 있습니다. 하지만 근접 점을 인용하는 방식이 수치형 데이터를 어떻게 표시할까요? knn regression도 사실 간단합니다.
이전 KNN 마찬가지로 근접점을 설정하여 인용합니다. 이후 근접점의 distance들의 평균으로 예측하게 됩니다.
이제 이를 sklearn을 통해서 표현해봤습니다.
이번에 사용할 데이터는 농어의 무게 측정입니다. 상황을 부여하자면, 어촌에서 농어의 무게를 측정하는 머신이 오류가 나 더 이상 농어의 무게를 측정하지 못하여 판매 하는데에 어렴움을 겪고 있습니다. 따라서 저희는 이를 해결하기 위해 농어의 무게를 예측하는 것 입니다.
데이터 출처: http://bit.ly/perch_data
농어의 길이와 무게 데이터
농어의 길이와 무게 데이터. GitHub Gist: instantly share code, notes, and snippets.
gist.github.com
데이터를 로드했으니, 먼저 데이터의 분포를 파악해보겠습니다. 이런 KNN과 두 변수의 관계를 파악할 때는 산점도가 적합합니다.
농어의 길이가 커짐에 따라서 무게 또한 늘어남을 알 수 있습니다. 하지만 새로운 데이터가 왔음에도 이런 패턴을 고려해서 예측할 수 있는지는 의문입니다. 따라서 모델링 해보겠습니다. 먼저 테스트 데이터와 트레인 데이터를 나누겠습니다. 이는 이전 게시글에서 언급했으니 설명은 생략하겠습니다.
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)
이제 모델을 바로 학습시켜보겠습니다. 하지만 sklearn에서 모델을 학습할 때 받는 인풋 데이터는 2차원 데이터입니다.
따라서 현재 1차원인 데이터를 2차원 데이터로 변화해주겠습니다.
train_input = train_input.reshape(-1,1)
test_input = test_input.reshape(-1,1)
target 데이터는 1차원 데이터가 올바른 차원이니 건들지 않았습니다. input데이터만 2차원으로 변환해주시면 됩니다.
따라서 이제 학습할 준비가 다 되었습니다.
KNN-regression은 아래와 같이 모듈명으로 불러오고 선언해야 합니다. 이전 KNN과 다른 방식입니다.
from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor()
knr.fit(train_input,train_target)
print(knr.score(test_input,test_target))
knr로 학습하고 score를 측정했습니다. 정확도는 약 99%가 나왔습니다. 이는 잘 학습 됐다고 판단 해야 할 까요?
이 사실 전에 고민해야 할게 있습니다. 분류(classification)에서는 정확도를 전체 데이터 중에 맞힌 분류객체로 판단했습니다.
하지만 수치형(숫자) 데이터에서는 이를 소수점 까지 완벽하게 맞출 수 있을까요? 아마 테스트 데이터가 클수록 0%에 수렴하지 않을까 생각합니다. 따라서 만약 .score을 호출 하는 객체가 KNR일 경우에는 이를 이전 방식이 아닌 R2(R**2)(R square)로 판단합니다. 이 점수를 결정계수라고 합니다. 이는 다음과 같이 계산됩니다.
이 값은 라벨의 평균 정도를 예측하는 수준이면 0에 가까워지고 예측이 라벨에 아주 가까워지면 1에 가까운 값이 됩니다.
하지만 정확도 처럼 확 와닿지는 않죠. 이를 위해 sklearn.metrics에서 mean_absoulte_error 기능이 있습니다.
from sklearn.metrics import mean_absolute_error
test_prediction = knr.predict(test_input)
mae = mean_absolute_error(test_target,test_prediction)
print(mae)
약 19g정도 라벨과 다르다는 것을 알 수 있습니다. 이 처럼 mean_abosolue_error, 평균제곱오차를 사용하면 모델을 평가하는 기준이 명확해집니다. 다시 원래 언급으로 넘어가 이번에 오버피팅과 언더피팅을 실제 정확도에 비교해보며 성능을 올려보겠습니다.
오버피팅은 훈련데이터에 너무 과적합 즉 훈련데이터에 너무 최적화 되어 모델이 새로운 데이터에 들어올 때 올바르지 않은 값을 기대할 수 있는 뜻입니다. 보통 트레인 데이터가 테스트 데이터에 비해 정확도가 많이 높은 상황일 때 오버핏팅이 일어납니다.
언더피팅은 훈련데이터의 양이 너무 적거나 다른 여러가지 이유로 훈련 세트보다 테스트의 세트의 점수가 높거나 두 점수가 모두 너무 낮은 경우입니다.
그렇다면 트레인 데이터의 score를 확인해보고 오버피팅이 일어났는지 언더피팅이 일어났는지 혹은 제대로 잘 학습했는지 확인해보겠습니다.
트레인의 성능은 약 0.96입니다. 테스트 데이터 보다 훈련 데이터보다 점수가 높으니 언더피팅 현상이 발생했습니다.
이 때는 데이터의 수를 증강해서 올려주는 방법도 있지만, 알고리즘 모델을 더 복잡하게 만드는 방법이 있습니다.
KNN에서는 이웃의 개수를 줄이는 것 입니다. 현재 deafult 값 5로 설정되어 있는데 3으로 낮춰보겠습니다.
knr.n_neighbors = 3
knr.fit(train_input,train_target)
print(knr.score(train_input,train_target))
n_neighbors는 처음에 설정하시거나 이 처럼 knr.n_neighbors = ? 로 변경 할 수 있습니다.
정확도가 올라간 것을 확인할 수 있습니다. 이제 테스트 데이터도 확인해보겠습니다.
print(knr.fit([test_input,test_target]))
둘의 정확도가 크게 차이나지 않아 오버피팅도 언더피팅도 되지 않았다고 판단 했습니다. 이 처럼 n의 파라메터 값도 중요함을 알 수 있습니다. 단순하게 파라메터만 수정해도 모델이 언더피팅을 벗어납니다. 사실 이러한 역할을 데이터 모델러 분들이 하시는 역할입니다. 이후 게시글에서 이 최적의 n값을 찾아보겠습니다.
'Machine-Learning' 카테고리의 다른 글
Linear Regression _ 선형 회귀 (1) | 2025.03.26 |
---|---|
Scaling ? Z-score (1) | 2025.03.19 |
데이터 전처리, 데이터셋 나누기 (0) | 2025.03.19 |
K-Nearest Neighbors, KNN (0) | 2025.03.13 |