手写数字识别的神经网络2层神经网络的类代码详解
- 创业
- 2025-09-01 11:57:02

源代码和图解来自鱼书
目录
2层神经网络的类
源代码:
详解:
1. 类的初始化 (__init__)
2. 前向传播 (predict)
3. 损失函数 (loss)
4. 准确率计算 (accuracy)
5. 数值梯度计算 (numerical_gradient)
6. 反向传播计算梯度 (gradient)
总结:
2层神经网络的类 源代码: # coding: utf-8 import sys, os sys.path.append(os.pardir) # 为了导入父目录的文件而进行的设定 from common.functions import * from common.gradient import numerical_gradient class TwoLayerNet: def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01): # 初始化权重 self.params = {} self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size) self.params['b1'] = np.zeros(hidden_size) self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) self.params['b2'] = np.zeros(output_size) def predict(self, x): W1, W2 = self.params['W1'], self.params['W2'] b1, b2 = self.params['b1'], self.params['b2'] a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, W2) + b2 y = softmax(a2) return y # x:输入数据, t:监督数据 def loss(self, x, t): y = self.predict(x) return cross_entropy_error(y, t) def accuracy(self, x, t): y = self.predict(x) y = np.argmax(y, axis=1) t = np.argmax(t, axis=1) accuracy = np.sum(y == t) / float(x.shape[0]) return accuracy # x:输入数据, t:监督数据 def numerical_gradient(self, x, t): loss_W = lambda W: self.loss(x, t) grads = {} grads['W1'] = numerical_gradient(loss_W, self.params['W1']) grads['b1'] = numerical_gradient(loss_W, self.params['b1']) grads['W2'] = numerical_gradient(loss_W, self.params['W2']) grads['b2'] = numerical_gradient(loss_W, self.params['b2']) return grads def gradient(self, x, t): W1, W2 = self.params['W1'], self.params['W2'] b1, b2 = self.params['b1'], self.params['b2'] grads = {} batch_num = x.shape[0] # forward a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, W2) + b2 y = softmax(a2) # backward dy = (y - t) / batch_num grads['W2'] = np.dot(z1.T, dy) grads['b2'] = np.sum(dy, axis=0) da1 = np.dot(dy, W2.T) dz1 = sigmoid_grad(a1) * da1 grads['W1'] = np.dot(x.T, dz1) grads['b1'] = np.sum(dz1, axis=0) return grads 详解:
这段代码实现了一个两层神经网络 TwoLayerNet,并包含了前向传播、损失计算、准确率计算、梯度计算等功能。我们逐步解释每个部分:
1. 类的初始化 (__init__) class TwoLayerNet: def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01): self.params = {} self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size) self.params['b1'] = np.zeros(hidden_size) self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size) self.params['b2'] = np.zeros(output_size) input_size、hidden_size 和 output_size 分别是输入层、隐藏层和输出层的神经元数目。权重 W1 和 W2 是从正态分布中随机初始化的(通过 np.random.randn),偏置 b1 和 b2 被初始化为零。weight_init_std 是一个可选的参数,用于控制权重的初始化标准差。 2. 前向传播 (predict) def predict(self, x): W1, W2 = self.params['W1'], self.params['W2'] b1, b2 = self.params['b1'], self.params['b2'] a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, W2) + b2 y = softmax(a2) return y 通过 x(输入数据),计算网络的输出: a1 = np.dot(x, W1) + b1:将输入数据与第一个权重矩阵相乘并加上偏置。z1 = sigmoid(a1):对 a1 进行 Sigmoid 激活。a2 = np.dot(z1, W2) + b2:将隐藏层的输出 z1 乘以第二层的权重矩阵并加上偏置。y = softmax(a2):对第二层的结果应用 Softmax 激活,得到最终的输出概率分布。 3. 损失函数 (loss) def loss(self, x, t): y = self.predict(x) return cross_entropy_error(y, t) 使用 predict 方法计算网络的输出 y,然后计算输出与真实标签 t 之间的交叉熵损失。交叉熵损失用于评估模型预测的概率分布与实际标签之间的差异。 4. 准确率计算 (accuracy) def accuracy(self, x, t): y = self.predict(x) y = np.argmax(y, axis=1) t = np.argmax(t, axis=1) accuracy = np.sum(y == t) / float(x.shape[0]) return accuracy y = np.argmax(y, axis=1):将每个样本的输出概率向量转化为类别标签(选择概率最大的位置作为预测类别)。t = np.argmax(t, axis=1):将真实标签 t 也转化为类别标签。计算预测正确的样本比例,即准确率。 5. 数值梯度计算 (numerical_gradient) def numerical_gradient(self, x, t): loss_W = lambda W: self.loss(x, t) grads = {} grads['W1'] = numerical_gradient(loss_W, self.params['W1']) grads['b1'] = numerical_gradient(loss_W, self.params['b1']) grads['W2'] = numerical_gradient(loss_W, self.params['W2']) grads['b2'] = numerical_gradient(loss_W, self.params['b2']) return grads 通过数值梯度法(numerical_gradient)计算各个参数(权重和偏置)的梯度。loss_W 是由lambda定义的一个匿名函数,计算在给定输入 x 和标签 t 下,损失函数的值。numerical_gradient 用于计算每个参数的梯度,返回一个字典 grads,包含了所有权重和偏置的梯度。在反向传播过程中,numerical_gradient(loss_W, self.params['W1']) 会通过数值方法(有限差分法)计算出 loss(W) 对 W1 的梯度。 6. 反向传播计算梯度 (gradient) def gradient(self, x, t): W1, W2 = self.params['W1'], self.params['W2'] b1, b2 = self.params['b1'], self.params['b2'] grads = {} batch_num = x.shape[0] # forward a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, W2) + b2 y = softmax(a2) # backward dy = (y - t) / batch_num grads['W2'] = np.dot(z1.T, dy) grads['b2'] = np.sum(dy, axis=0) da1 = np.dot(dy, W2.T) dz1 = sigmoid_grad(a1) * da1 grads['W1'] = np.dot(x.T, dz1) grads['b1'] = np.sum(dz1, axis=0) return grads 前向传播: predict 函数中计算出神经网络的输出 y的步骤。反向传播: 计算损失对输出层的梯度:dy = (y - t) / batch_num,这是 Softmax 层和交叉熵损失的导数。更新 W2 和 b2:通过矩阵乘法 np.dot(z1.T, dy) 计算梯度。计算隐藏层的梯度:da1 = np.dot(dy, W2.T),然后通过 sigmoid_grad 对 a1 的梯度进行修正。更新 W1 和 b1:使用反向传播的链式法则进行计算。 总结: 前向传播 计算神经网络的输出。损失函数 计算网络预测与实际标签之间的误差。准确率 计算模型的预测准确性。数值梯度 通过数值方法估算参数的梯度。反向传播 计算每一层的梯度,利用链式法则更新权重和偏置。手写数字识别的神经网络2层神经网络的类代码详解由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“手写数字识别的神经网络2层神经网络的类代码详解”
下一篇
7-1打印沙漏