2022.03.14 월
: K-NN (K-Nearest Neighbors) 가장 가까운 훈련 데이터 포인트 하나를 최근접 이웃으로 찾기
mglearn.plots.plot_knn_classification(n_neighbors=1)
새로운 데이터 포인트 ⭐ 3개 - 가장 가까운 이웃 1개 선택
mglearn.plots.plot_knn_classification(n_neighbors=3)
가까운 이웃 3개 선택 - 어떤 클래스에 속한 이웃이 더 많은지 판단 - 해당 클래스를 레이블로 지정
적용
# 알고리즘 적용
from sklearn.model_selection import train_test_split
X,y = mglearn.datasets.make_forge()
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=0)
'''
random_state 는
재현가능(for reproducibility)하도록 난수의 초기값을 설정해주는 것이며,
아무 숫자나 넣어주면 됨
'''
# KNeighborsClassifier 객체 만들기
from sklearn.neighbors import KNeighborsClassifier
clf = KNeighborsClassifier(n_neighbors=3)
# training
clf.fit(X_train,y_train)
# test
print("테스트 세트 예측:",clf.predict(X_test))
print("테스트 세트 정확도: {:.2f}".format(clf.score(X_test,y_test)))
# decision boundary
fig, axes = plt.subplots(1,3,figsize=(10,3))
# 1*3개의 축을 가진 figure 생성
# figsize : figure 크기
# 이웃이 1, 3, 9명 일 때
for n_neighbors, ax in zip([1,3,9], axes):
# fit 메소드 self 오브젝트 리턴 -> 객체 생성과 fit 메소드 한줄에 사용 가능
clf = KNeighborsClassifier(n_neighbors=n_neighbors).fit(X,y)
mglearn.plots.plot_2d_separator(clf, X, fill=True, eps=0.5, ax=ax, alpha=.4)
# 산점도
mglearn.discrete_scatter(X[:,0], X[:,1], y, ax=ax)
ax.set_title("{} 이웃".format(n_neighbors))
ax.set_xlabel("특성 0")
ax.set_ylabel("특성 1")
axes[0].legend(loc=3)
# 첫번째 축에 설명 넣기 (3=lower left)
이웃 하나 선택 했을 때 → 경계가 점점 부드러워짐 → 이웃을 9개 선택 했을 때
⇒ 이웃 ⬇️ → 복잡도 ⬆️
⇒ 이웃 ⬆️ → 복잡도 ⬇️
If) 이웃의 수 == 훈련 데이터 수
→ 모든 테스트 포인트 모든 훈련 데이터를 이웃으로 가짐
→ 그냥 가장 많은 데이터 포인트 가진 클래스가 예측값이 되어버림
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
cancer.data, cancer.target, stratify=cancer.target, random_state=66)
# stratify : 계층화 무작위 추출을 하겠다!
training_accuracy = []
test_accuracy = []
# 1 ~ 10 n_neighbors 적용
neighbors_settings = range(1,11)
for n_neighbors in neighbors_settings:
# 모델 생성
clf = KNeighborsClassifier(n_neighbors=n_neighbors).fit(X_train,y_train)
# 훈련 세트 정확도 저장
training_accuracy.append(clf.score(X_train,y_train))
# 일반화 정확도 저장
test_accuracy.append(clf.score(X_test,y_test))
plt.plot(neighbors_settings, training_accuracy, label="훈련 정확도")
plt.plot(neighbors_settings, test_accuracy, label="테스트 정확도")
plt.xlabel("n_neighbors")
plt.ylabel("정확도")
plt.legend()
⇒ 이웃 ⬇️ → 복잡도 ⬆️
⇒ 그래서 두 그래프가 뒤집힌 형태
⇒ 이웃 1개 일 때, 모델 너무 복잡해서 정확도 나쁨 → 과대적합
⇒ 이웃 10개 일 때, 모델 너무 단순해서 정확도 더 나빠짐 → 과소적합
K-최근접 이웃 회귀 회귀 분석에서 쓰이는 형태 - plot_knn_regression
# 이웃을 하나만 사용했을 경우
mglearn.plots.plot_knn_regression(n_neighbors=1)
# 이웃을 둘 이상
mglearn.plots.plot_knn_regression(n_neighbors=3)
회귀를 위한 k-최근접 이웃 알고리즘
from sklearn.neighbors import KNeighborRegressor
X,y = mglearn.datasets.make_wave(n_samples=40)
# wave 데이터셋을 훈련 세트와 테스트 세트로 나누기
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=0)
# 이웃의 수를 3으로 하여 모델의 객체 만들기
reg = KNeighborsRegressor(n_neighbors=3)
# 훈련데이터와 타깃을 사용하여 모델 학습
reg.fit(X_train, y_train)
# 테스트 세트 예측
print("테스트 세트 예측:\\n", reg.predict(X_test))
# 정확도 평가
print("테스트 세트 R^2: {:.2f}".format(reg.score(X_test,y_test)))
KNeighborsRegressor 분석 가능한 모든 특성 값을 만들어 예측
fig, axes = plt.subplots(1, 3, figsize=(15,4))
# -3과 3 사이에 1000개의 데이터 포인트를 만듬
line = np.linspace(-3, 3, 1000).reshape(-1,1)
for n_neighbors, ax in zip([1, 3, 9], axes):
# 1,3,9 이웃을 사용한 예측하기
reg = KNeighborsRegressor(n_neighbors=n_neighbors)
reg.fit(X_train, y_train)
ax.plot(line, reg.predict(line)) # 예측값 라인으로 표시
# 모양 표시
ax.plot(X_train, y_train, '^', c=mglearn.cm2(0), markersize=8)
ax.plot(X_test, y_test, 'v', c=mglearn.cm2(1), markersize=8)
# 라벨링
ax.set_title("{} 이웃의 훈련 스코어: {:.2f} 테스트 스코어: {:.2f}".format(n_neighbors, reg.score(X_train, y_train), reg.score(X_test, y_test)))
ax.set_xlabel("특성")
ax.set_ylabel("타깃")
axes[0].legend(["모델 에측","훈련 데이터/타깃", "테스트 데이터/타깃"], loc= "best")
매개 변수 중요 매개 변수 2개 → 1) 거리를 재는 방법 2) 이웃의 수
장단점
⇒ 현업에서는 잘 쓰지 않음 → 선형모델