封装Perceptron类后触发'numpy.ndarray'无'vv'属性错误求助
问题解决:Perceptron类中
'numpy.ndarray' object has no attribute 'vv'错误 问题描述
尝试运行Sebastian Raschka《Python机器学习》中的代码,将相关函数封装到Perceptron类后,使用self.vv时触发错误:'numpy.ndarray' object has no attribute 'vv'。未封装类时代码正常运行,调整参数类型后仍无法解决问题。
核心错误原因
predict函数未作为类方法定义:你的predict函数缩进错误,不在Perceptron类内部,导致它无法访问实例的self.vv属性,且调用逻辑完全错误。fit方法中调用predict的方式错误:直接调用predict(x, self.vv),这里把self.vv作为参数传入,导致predict内部的self被当成了numpy数组(即传入的x),从而触发numpy.ndarray无vv属性的错误。
其他次要错误(必须修正才能正常运行)
X[:,0].min和X[:,0].max是numpy数组的方法,需要加括号调用:X[:,0].min()、X[:,0].max()contourf中的apha拼写错误,应为alphascatter函数中参数colors应为color,且索引错误:X[Y == cl]需指定列索引,比如X[Y == cl, 0]和X[Y == cl, 1]- 数据集读取时
header=None会把CSV表头当成数据,应去掉该参数 - 随机种子未正确初始化:
np.random.RandomState(1)需要赋值给变量才能生效
修正后的完整代码
import pandas as pd import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import ListedColormap class Perceptron(object): def fit(self, X: np.array, Y: np.array, eta: float, iter_ep: int): # 正确初始化随机种子 rng = np.random.RandomState(1) self.vv = rng.normal(loc=0.0, scale=0.01, size=X.shape[1]+1) self.Error_total = [] for i in range(iter_ep): error = 0 for x, y in zip(X, Y): # 通过self调用类内的predict方法 update = eta * (y - self.predict(x)) self.vv[1:] += update * x self.vv[0] += update error += int(update != 0.0) self.Error_total.append(error) return self # 将predict缩进,作为类的实例方法 def predict(self, x_examples): return np.where(np.dot(x_examples, self.vv[1:]) + self.vv[0] >= 0.0, 1, -1) def plot_decision_regions(X, Y, classifier, resolution=0.01): markers = ('', 's', '^', 'o', '4') colors = ('red', 'blue', 'green', 'cyan', 'grey') cmap = ListedColormap(colors[:len(np.unique(Y))]) # 修正min/max为方法调用 x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) Z = Z.reshape(xx1.shape) # 修正apha为alpha plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) # 修正scatter的参数和索引 for idx, cl in enumerate(np.unique(Y)): plt.scatter(X[Y == cl, 0], X[Y == cl, 1], alpha=0.8, color=colors[idx], marker=markers[idx], label='versicolor' if cl == 1 else 'setosa', edgecolor='black') # 读取数据集,去掉header=None,因为CSV有表头 s = 'https://gist.githubusercontent.com/curran/a08a1080b88344b0c8a7/raw/0e7a9b0a5d22642a06d3d5b9bcbad9890c8ee534/iris.csv' df = pd.read_csv(s, encoding='utf-8') # 取前100条数据(setosa和versicolor) y = np.where(df.iloc[:100, 4].values == 'setosa', -1, 1) x = df.iloc[:100, [0,2]].values x = x.astype(float) plt.scatter(x[0:50,0], x[0:50, 1], color='blue', marker='s', label='setosa') plt.scatter(x[50:100, 0], x[50:100, 1], color='red', marker='^', label='versicolor') plt.xlabel('sepal_length, cm') plt.ylabel('petal_length, cm') plt.show() # 训练模型 ppn = Perceptron() ppn.fit(x, y, 0.1, 10) plt.plot(range(1, len(ppn.Error_total)+1), ppn.Error_total, marker='o') plt.xlabel('Quantity of epoch, units') plt.ylabel('Quantity of updates, units') plt.show() # 可视化决策边界 plot_decision_regions(x, y, ppn) plt.xlabel('sepal_length, cm') plt.ylabel('petal_length, cm') plt.legend(loc='upper left') plt.show()
关键修正点说明
- 将
predict函数缩进至Perceptron类内部,使其成为实例方法,能通过self访问self.vv属性 - 在
fit方法中调用predict时,使用self.predict(x)而非全局调用 - 修正了数据读取、绘图函数中的语法错误,确保代码可正常运行
内容的提问来源于stack exchange,提问作者My_password_is_my_cat
相关产品推荐
相关产品推荐

