基于Numpy/Pandas的MNIST分类神经网络gradient_descent参数报错排查
问题原因与解决方法
核心错误:实例方法缺少self参数
你定义的gradient_descent是类的实例方法,但没有在参数列表里添加第一个必选的self参数。当你用nn.gradient_descent(...)调用时,Python会自动把nn这个实例作为第一个参数传入方法,加上你手动传入的4个参数,总共就有5个参数,和方法定义的4个参数不匹配,因此触发报错。
修复方法
修改gradient_descent的定义,将self作为第一个参数:
def gradient_descent(self, x, y, alpha, iterations):
代码中其他需修复的问题
除核心错误外,代码还有多处语法和逻辑问题,修复后才能正常运行:
- 类内部方法调用未加
self:类里调用自身方法(如ReLU、softmax、forward等)必须用self.方法名()的形式,否则会被当作全局函数处理。例如a1 = ReLU(z1)要改成a1 = self.ReLU(z1)。 - 方法名不匹配:代码里存在方法名调用错误,比如定义的是
forward却写成forward_prop,backward写成backward_prop,需统一方法名。 - 参数初始化错误:
gradient_descent里的w1, b1, w2, b2 = __init__()完全错误,应直接使用实例初始化的属性:w1, b1, w2, b2 = self.w1, self.b1, self.w2, self.b2。 get_preds方法缺少self:该方法是实例方法,必须添加self参数:def get_preds(self, a2):。- ReLU导数方法拼写错误:
RelU_deriv应改为ReLU_deriv(第二个字母为e)。 softmax维度错误:原实现未考虑批量数据,需指定维度求和:return np.exp(z) / np.sum(np.exp(z), axis=0, keepdims=True)。backward中m未定义:应使用训练集样本数,可替换为1 / x.shape[1](x的列数为样本数)。return位置错误:原代码将return写在for循环内部,会导致第一次循环就返回,需移到循环外部。
修复后的核心代码示例
import numpy as np # 假设data为已加载的MNIST数据集 data = np.array(data) m, n = data.shape np.random.shuffle(data) # 拆分前打乱数据 data_dev = data[0:1000].T y_dev = data_dev[0] x_dev = data_dev[1:n] x_dev = x_dev / 255. data_train = data[1000:m].T y_train = data_train[0] x_train = data_train[1:n] x_train = x_train / 255. _, m_train = x_train.shape class NeuralNet(): def __init__(self, i_lay, h_lay, o_lay): self.i_lay = i_lay self.h_lay = h_lay self.o_lay = o_lay # 修正权重矩阵维度,确保矩阵乘法合法 self.w1 = np.random.rand(self.h_lay, self.i_lay)/np.sqrt(self.i_lay) self.b1 = np.zeros((self.h_lay, 1)) self.w2 = np.random.rand(self.o_lay, self.h_lay)/np.sqrt(self.h_lay) self.b2 = np.zeros((self.o_lay, 1)) def ReLU(self, z): return np.maximum(z, 0) def softmax(self, z): return np.exp(z) / np.sum(np.exp(z), axis=0, keepdims=True) def forward(self, x): z1 = self.w1.dot(x) + self.b1 a1 = self.ReLU(z1) z2 = self.w2.dot(a1) + self.b2 a2 = self.softmax(z2) return z1, a1, z2, a2 def ReLU_deriv(self, z): return z > 0 def one_hot(self, y): one_hot_y = np.zeros((y.size, y.max() + 1)) one_hot_y[np.arange(y.size), y] = 1 one_hot_y = one_hot_y.T return one_hot_y def backward(self, z1, a1, z2, a2, x, y): m = x.shape[1] one_hot_y = self.one_hot(y) dz2 = a2 - one_hot_y dw2 = 1 / m * dz2.dot(a1.T) db2 = 1 / m * np.sum(dz2, axis=1, keepdims=True) dz1 = self.w2.T.dot(dz2) * self.ReLU_deriv(z1) dw1 = 1 / m * dz1.dot(x.T) db1 = 1 / m * np.sum(dz1, axis=1, keepdims=True) return dw1, db1, dw2, db2 def update_parameters(self, dw1, db1, dw2, db2, alpha): self.w1 -= alpha * dw1 self.b1 -= alpha * db1 self.w2 -= alpha * dw2 self.b2 -= alpha * db2 def get_preds(self, a2): return np.argmax(a2, 0) def get_acc(self, preds, y): return np.sum(preds == y) / y.size def gradient_descent(self, x, y, alpha, iterations): for i in range(iterations): z1, a1, z2, a2 = self.forward(x) dw1, db1, dw2, db2 = self.backward(z1, a1, z2, a2, x, y) self.update_parameters(dw1, db1, dw2, db2, alpha) if i % 10 == 0: print("Iteration: ", i) predictions = self.get_preds(a2) print(f"Accuracy: {self.get_acc(predictions, y):.4f}") return self.w1, self.b1, self.w2, self.b2 nn = NeuralNet(784, 10, 10) nn.gradient_descent(x_train, y_train, 0.1, 500)
内容的提问来源于stack exchange,提问作者philomath
相关产品推荐
相关产品推荐

