Ch.17 KNN
1. KNN (K-Nearest Neighbor)
K의 가장 가까운 사례를 Train Data Set에서 찾아 해당하는 데이터의 y값을 기반으로 결과 제시
분류와 회귀 문제를 모두 다를 수 있음
- 분류 문제(Classifier)를 풀 떄는 class 다수결로 결과 class를 예측
- 회귀 문제(Regressor)를 풀 떄는 가중평균값을 결과값으로 예측
K값이 작을수록 overfitting, K값이 클수록 underfitting의 위험이 있음
2. KNeighbors
from sklearn.neighbors import KNeighborsClassifier
from sklearn.neighbors import KNeighborsRegressor
# 분류
model_c = KNeighborsClassifier(n_neighbors = 3)
model_c.fit(X = df.iloc[:, :4], y = df["is_setosa"])
# 회귀
model_r = KNeighborsRegressor(n_neighbors = 3)
model_r.fit(X = df.iloc[:, :3], y = df["Petal.Width"])
구조는 동일하고, fit 뒤에 독립변수, 종속변수를 넣어준다. 분류는 독립변수가 범주형, 회귀는 수치형.
분류형의 경우는 accuracy_score, precision 등으로 평가, 수치형은 MSE, RMSE 등으로 평가
문제 1
당뇨 발생 여부를 예측하기 위해 임신 횟수, 혈당, 혈압을 사용할 경우 그 정확도는 얼마인가?
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.neighbors import KNeighborsRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
df = pd.read_csv('diabetes.csv')
df_train, df_test = train_test_split(df, train_size = 0.7, test_size = 0.3, random_state = 123)
model = KNeighborsClassifier(n_neighbors = 5)
model.fit(X = df_train.loc[:, ["Pregnancies", "Glucose", "BloodPressure"]], y = df_train["Outcome"])
pred = model.predict(X = df_test.loc[:, ["Pregnancies", "Glucose", "BloodPressure"]])
accuracy_score(y_true = df_test["Outcome"], y_pred = pred)
pred 값은 array 형태였다는 걸 이제야 알았다. 어쨌든 맞춰서 기분이 좋은 문제~
문제 2
종속변수를 당뇨 발병 여부로 하고, 독립변수를 임신여부, 혈당, 혈압, 인슐린, 체질량지수로 하여 정확도를 확인했을 때 그 k값과 정확도가 올바르게 연결되지 않은 것은?
df = pd.read_csv('diabetes.csv')
df["is_preg"] = (df["Pregnancies"] > 0) + 0
df_train, df_test = train_test_split(df, train_size = 0.8, test_size = 0.2, random_state = 123)
X_cols = ["is_preg", "Glucose", "BloodPressure", "Insulin", "BMI"]
neighbors = [3, 5, 10, 20]
accs = []
for n_n in neighbors:
model = KNeighborClassifier(n_neighbors = n_n)
model.fit(X = df.loc[:, X_cols], y = df_train["Outcome"])
pred = model.predict(X = df.loc[:, X_cols])
acc_sub = accuracy_score(y_true = df_test["Outcome"], y_pred = pred)
accs = accs + [acc_sub]
df_score = pd.DataFrame({"neighbors": neighbors, "accs" : accs})
df_score["accs"] = df_score["accs"].round(2)
df_score
물론 나는 그냥 일일이 neighbor 값을 바꿔가면서 풀었다.
보면 대강 따라갈 수는 있겠지만 실제로 이렇게 쓸 자신은 없다...
문제 3
종속변수를 체질량 지수로 하고, 독립변수를 임신여부, 혈당, 혈압, 인슐린으로 하여 예측값을 확인했을 때 그 k값과 RMSE가 올바르게 연결되지 않은 것은?
from sklearn.metrics import mean_squared_error
X_cols = ["is_preg", "Glucose", "BloodPressure", "Insulin"]
neighbors = [3, 5, 10, 20]
rmses = []
for n_n in neighbors:
model = KNeighborsRegressor(n_neighbors = n_n).fit(X = df_train.loc[:,X_cols], y = df_train["BMI"])
pred = model.predict(X = df_test.loc[:, X_cols])
rmse_sub = mean_squared_error(y_pred = pred, y_true = df_test["BMI"]) ** 0.5
rmses = rmse + [rmse_sub]
df_score = pd.DataFrame({"neighbors" : neighbors, "rmses" : rmses})
df_score["rmses"] = df_score["rmses"].round(3)
df_score
역시 2번과 동일한 방식. 근데 하나하나 대입했을 떄 답이 다르게 나왔는데... 나중에 다시 풀어봐야겠다.