Python绘制3D SVM决策面触发索引错误,求排查原因
错误原因与修复方案
核心错误原因
- 变量名冲突覆盖:
plot_3D_surface函数中,传入的标签参数y被后续np.meshgrid生成的网格变量y覆盖。后续代码X[y == 0, ...]中的y已不是原始标签数组,而是形状为(30,30)的网格数组,用它作为布尔索引匹配X的行维度(4000行)时,维度不匹配引发索引错误。 - 函数参数拼写错误:函数定义的第一个参数为
mode,但内部却调用model.fit(X, y),依赖全局变量而非传入的模型参数,破坏了函数的封装性。
修复后的代码
from sklearn.datasets import make_classification import numpy as np from sklearn.svm import LinearSVC import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D def plot_3D_surface(model,X,y): model.fit(X, y) # 重命名网格变量避免冲突,同步修正lambda参数 z = lambda x_val, y_val: (-model.intercept_[0] - model.coef_[0][0] * x_val - model.coef_[0][1] * y_val) / model.coef_[0][2] tmp = np.linspace(-5, 5, 30) x_val, y_val = np.meshgrid(tmp, tmp) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot3D(X[y == 0, 0], X[y == 0, 1], X[y == 0, 2], 'ob') ax.plot3D(X[y == 1, 0], X[y== 1, 1], X[y == 1, 2], 'sr') ax.plot_surface(x_val, y_val, z(x_val, y_val)) ax.view_init(30, 60) plt.show() def plot_2D_surface(model,X,y,h=0.2,**params): X0, X1 = X[:, 0], X[:, 1] x_min, x_max = X0.min() - 1, X0.max() + 1 y_min, y_max = X1.min() - 1, X1.max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) fig, ax = plt.subplots() Z = model.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) out = ax.contourf(xx, yy, Z, **params) ax.scatter(X0, X1, c=y, cmap=plt.cm.coolwarm, s=20, edgecolors='k') ax.set_ylabel('y label here') ax.set_xlabel('x label here') ax.set_xticks(()) ax.set_yticks(()) ax.set_title('Decision surface of linear SVC ') ax.legend() plt.show() # 调用代码 X, y= make_classification(n_samples=4000,n_features=3,n_informative=3,n_redundant=0,random_state=1) print(X[y==0,2]) model = LinearSVC() model.fit(X, y) #plot_2D_surface(model ,X, y, cmap=plt.cm.coolwarm, alpha=0.8) plot_3D_surface(model,X,y)
修复说明
- 将网格生成的变量名从
x, y改为x_val, y_val,彻底避免与标签参数y的命名冲突。 - 修正
plot_3D_surface的参数名,将mode改为model,确保使用传入的模型参数而非全局变量。 - 同步修改lambda表达式中的参数名,与网格变量名保持一致。
内容的提问来源于stack exchange,提问作者neural science
相关产品推荐
相关产品推荐

