You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何可视化聚类边界?基于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})")

关键步骤说明

  1. 修正原函数问题:调整make_square的数组初始化逻辑,将标签转换为numpy数组,适配sklearn的输入要求。
  2. 生成网格点:通过meshgrid生成覆盖数据范围的密集网格,步长h控制边界平滑度,数值越小边界越精细。
  3. 预测网格类别:将网格点展平后输入KNN模型预测类别,再重塑为网格形状。
  4. 绘制边界:用contourf填充不同类别的区域(带透明度),叠加样本点,清晰展示分类边界与样本的对应关系。

内容的提问来源于stack exchange,提问作者VladislavOkatev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 13:50:24