如何可视化聚类边界?基于KNN分类器的绘图需求求助
如何为KNN分类器绘制聚类决策边界
我已经生成了多个数据集,用KNeighborsClassifier完成了分类预测,现在需要在图表中绘制聚类间的边界(线条或填充区域都可以),求实现方法。
附上我的代码:
import numpy as np import matplotlib.pyplot as plt from sklearn.neighbors import KNeighborsClassifier from sklearn.datasets import make_moons, make_circles from sklearn.model_selection import train_test_split n_sample = 2000 def make_square(n_sample): data=np.array([0,[]]) data[0] = np.random.sample((n_sample,2)) for i in range(n_sample): if data[0][i][0] > 0.5 and data[0][i][1] > 0.5 or data[0][i][0] < 0.5 and data[0][i][1] < 0.5: data[1].append(1) else: data[1].append(0) return data datasets = [ make_circles(n_samples=n_sample, noise=0.09, factor=0.5), make_square(n_sample), make_moons(n_samples=n_sample, noise=0.12), ] ks=[] for data in datasets: X,y = data[0],data[1] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=33) classifier = KNeighborsClassifier(n_neighbors=1) classifier.fit(X_train, y_train) y_pred = classifier.predict(X_test) acc = classifier.score(X_test, y_test) accs = [] for i in range(1, 8): knn = KNeighborsClassifier(n_neighbors=i) knn.fit(X_train, y_train) pred_i = knn.predict(X_test) acc0 = knn.score(X_test, y_test) accs.append(acc0) plt.figure(figsize=(12, 6)) plt.plot(range(1, 8), accs, color='red', linestyle='dashed', marker='o', markerfacecolor='blue', markersize=10) plt.title('accs Score K Value') plt.xlabel('K Value') plt.ylabel('accs Score') print("Max Score:", max(accs), "k=",accs.index(max(accs))+1) ks.append(accs.index(max(accs))+1) for i in range(3): data = datasets[i] k = ks[i] X,y = data[0],data[1] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=33) classifier = KNeighborsClassifier(n_neighbors=k) classifier.fit(X_train, y_train) y_pred = classifier.predict(X_test) plt.figure(figsize=(9,9)) plt.title("Test") plt.scatter(X_test[:,0], X_test[:,1], c=y_test) plt.figure(figsize=(9,9)) plt.title("Predict") plt.scatter(X_test[:,0], X_test[:,1], c=y_pred)
实现方法:绘制KNN决策边界
核心思路是生成覆盖整个数据范围的密集网格点,用训练好的KNN模型预测每个网格点的类别,再通过matplotlib的contourf(填充区域)或contour(线条)绘制分类边界。
修改后的完整代码如下:
import numpy as np import matplotlib.pyplot as plt from sklearn.neighbors import KNeighborsClassifier from sklearn.datasets import make_moons, make_circles from sklearn.model_selection import train_test_split n_sample = 2000 def make_square(n_sample): # 修正原函数的数组初始化错误,适配sklearn接口 data = np.array([np.random.sample((n_sample,2)), []]) for i in range(n_sample): if (data[0][i][0] > 0.5 and data[0][i][1] > 0.5) or (data[0][i][0] < 0.5 and data[0][i][1] < 0.5): data[1].append(1) else: data[1].append(0) data[1] = np.array(data[1]) return data datasets = [ make_circles(n_samples=n_sample, noise=0.09, factor=0.5), make_square(n_sample), make_moons(n_samples=n_sample, noise=0.12), ] ks=[] for data in datasets: X,y = data[0],data[1] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=33) accs = [] for i in range(1, 8): knn = KNeighborsClassifier(n_neighbors=i) knn.fit(X_train, y_train) acc0 = knn.score(X_test, y_test) accs.append(acc0) plt.figure(figsize=(12, 6)) plt.plot(range(1, 8), accs, color='red', linestyle='dashed', marker='o', markerfacecolor='blue', markersize=10) plt.title('准确率与K值关系') plt.xlabel('K值') plt.ylabel('准确率') best_k = accs.index(max(accs))+1 print("最高准确率:", max(accs), "对应K=", best_k) ks.append(best_k) # 定义绘制决策边界的工具函数 def plot_decision_boundary(classifier, X, y, title): # 生成覆盖数据范围的密集网格 h = 0.02 # 网格步长,越小边界越平滑 x_min, x_max = X[:, 0].min() - 0.1, X[:, 0].max() + 0.1 y_min, y_max = X[:, 1].min() - 0.1, X[:, 1].max() + 0.1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) # 预测所有网格点的类别 Z = classifier.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) # 绘制填充式边界与样本点 plt.figure(figsize=(9,9)) plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.Paired) plt.scatter(X[:,0], X[:,1], c=y, edgecolors='k', cmap=plt.cm.Paired) plt.title(title) plt.show() # 为每个数据集绘制决策边界 for i in range(3): data = datasets[i] k = ks[i] X,y = data[0],data[1] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=33) classifier = KNeighborsClassifier(n_neighbors=k) classifier.fit(X_train, y_train) # 绘制训练集的决策边界 plot_decision_boundary(classifier, X_train, y_train, f"数据集{i+1} - 训练集决策边界(K={k})") # 绘制测试集的预测结果与边界 plot_decision_boundary(classifier, X_test, y_test, f"数据集{i+1} - 测试集预测与边界(K={k})")
关键步骤说明
- 修正原函数问题:调整
make_square的数组初始化逻辑,将标签转换为numpy数组,适配sklearn的输入要求。 - 生成网格点:通过
meshgrid生成覆盖数据范围的密集网格,步长h控制边界平滑度,数值越小边界越精细。 - 预测网格类别:将网格点展平后输入KNN模型预测类别,再重塑为网格形状。
- 绘制边界:用
contourf填充不同类别的区域(带透明度),叠加样本点,清晰展示分类边界与样本的对应关系。
内容的提问来源于stack exchange,提问作者VladislavOkatev
相关产品推荐
相关产品推荐

