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

封装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'。未封装类时代码正常运行,调整参数类型后仍无法解决问题。


核心错误原因

  1. predict函数未作为类方法定义:你的predict函数缩进错误,不在Perceptron类内部,导致它无法访问实例的self.vv属性,且调用逻辑完全错误。
  2. 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拼写错误,应为alpha
  • scatter函数中参数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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 12:35:59