我想知道k近邻算法中最佳的k值。我使用LeaveOneOut方法将数据分为训练集和测试集。在下面的代码中,我有150个数据条目,因此我得到了150个不同的训练集和测试集。k的值应该在1到40之间。
我想绘制交叉验证的平均分类错误率作为k的函数,以查看哪个k值对KNN最佳。
这是我的代码:
import scipy.io as sioimport seaborn as snimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.metrics import confusion_matrixfrom sklearn.model_selection import LeaveOneOut error = []array = np.array(range(1,41))dataset = pd.read_excel('Data/iris.xls')X = dataset.iloc[:, :-1].values y = dataset.iloc[:, 4].valuesloo = LeaveOneOut()loo.get_n_splits(X)for train_index, test_index in loo.split(X): #print("TRAIN:", train_index, "TEST:", test_index) X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] #print(X_train, X_test, y_train, y_test) for i in range(1, 41): classifier = KNeighborsClassifier(n_neighbors=i) classifier.fit(X_train, y_train) y_pred = classifier.predict(X_test) error.append(np.mean(y_pred != y_test))plt.figure(figsize=(12, 6)) plt.plot(range(1, 41), error, color='red', linestyle='dashed', marker='o', markerfacecolor='blue', markersize=10)plt.title('Error Rate K Value') plt.xlabel('K Value') plt.ylabel('Mean Error')
回答:
您在每次预测时都计算错误,这就是为什么您的error
数组中有6000个点。您需要为给定的'n_neighbors'
收集折叠中所有点的预测,然后计算该值的错误。
您可以这样做:
# 遍历可能的"n_neighbors"值for i in range(1, 41): # 为单个"n_neighbors"收集所有拆分的实际和预测值 actual = [] predicted = [] for train_index, test_index in loo.split(X): #print("TRAIN:", train_index, "TEST:", test_index) X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] classifier = KNeighborsClassifier(n_neighbors=i) classifier.fit(X_train, y_train) y_pred = classifier.predict(X_test) # 在这里添加单个预测和实际值。 actual.append(y_test[0]) predicted.append(y_pred[0]) # 在循环外计算错误。 error.append(np.mean(np.array(predicted) != np.array(actual)))
您的代码的其他部分是正确的。
如果使用cross_val_predict
,有一种更紧凑的方法来做这件事
from sklearn.model_selection import cross_val_predictfor i in range(1, 41): classifier = KNeighborsClassifier(n_neighbors=i) y_pred = cross_val_predict(classifier, X, y, cv=loo) error.append(np.mean(y_pred != y))