Как исправить алгоритм ML k-ближайших соседей (kNN)?
Есть код k-ближайших соседей (kNN) и набор данных, разбитый на два набора (для обучения (X, Y) и проверки (x_test, y_test)). А также условие y_knn_filt = np.max(knn.predict_proba(x_test), axis=1) == 1, для прогнозирования меток классов только для тех выборок из x_test, у которых два ближайших соседа n_neighbors=2 имеют одинаковые метки.
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import cross_val_score
knn = KNeighborsClassifier(n_neighbors=2, n_jobs=-1, weights='distance').fit(X, Y)
y_knn = knn.predict(x_test)
print('все предсказания', y_knn)
y_knn_filt = np.max(knn.predict_proba(x_test), axis=1) == 1
print('фильтр уверенных предсказаний', y_knn_filt)
print('только уверенные предсказания', np.array(y_knn)[y_knn_filt])
AA = accuracy_score(a[y_test], y_knn)
print('score по всем предсказаниям', AA)
AA_filt = accuracy_score(np.array(y_test)[y_knn_filt], np.array(y_knn)[y_knn_filt])
print('score по уверенным предсказаниям', AA_filt)
Либо добавлял вот такое условие для определения одинаковости меток у ближайших соседей:
from sklearn.neighbors import NearestNeighbors
neigh = NearestNeighbors(n_neighbors=2).fit(X)
AA = neigh.kneighbors(x_test)
print(AA)
for i in AA[1]:
if np.unique(Y[i]).size == 1:
print('da', Y[i])
else:
print('net')
Проблема, не могу эти условия (условия по прогнозированию меток только для тех выборок, у которых ближайшие соседи имею одинаковые метки) переписать для kNN с перекрестной проверкой "Все кроме одного" - from sklearn.model_selection import LeaveOneOut
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import LeaveOneOut
knn = KNeighborsClassifier(n_neighbors=2, n_jobs=-1, weights='distance').fit(X, Y)
scores = cross_val_score(knn, X, Y, cv=LeaveOneOut())
print(scores.mean())
Кто-нибудь знает как это можно реализовать?
Ответы (1 шт):
LeaveOneOut просто предоставляет вам последовательность train/test наборов, вы можете итерироваться по ним, делать fit, predict и вычислять score внутри цикла по этим наборам:
from sklearn.model_selection import LeaveOneOut
score_list = []
loo = LeaveOneOut()
skipped = 0
for train_index, test_index in loo.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
knn.fit(X_train, y_train)
y_knn = knn.predict(X_test)
y_knn_filt = np.max(knn.predict_proba(X_test), axis=1) == 1
if not any(y_knn_filt):
skipped += 1
continue
score = accuracy_score(np.array(y_test)[y_knn_filt], np.array(y_knn)[y_knn_filt])
score_list.append(score)
print(np.mean(score_list))
print('пропущено', skipped, 'неуверенных сэмплов из', X.shape[0])
Постарайтесь на будущее использовать в коде X большое, потому что это матрица, и y маленькое, потому что это вектор. Так принято. :)
UPDATE: Добавил в ответ проверку, что нашлось хотя бы одно "уверенное" предсказание. С учётом того, что LeaveOneOut выдаёт по всему одному тестовому сэмплу, вероятность того, что этот сэмпл окажется неуверенным предсказанием и score придётся считать от пустого множества, очень велико и такие случаи надо пропускать.