news 2026/6/10 15:32:22

误差反向传播法(误差反向传播法的实现)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
误差反向传播法(误差反向传播法的实现)

误差反向传播法的实现

通过像组装乐高积木一样组装上一节中实现的层,可以构建神经网络。
本节我们将通过组装已经实现的层来构建神经网络。

神经网络学习的全貌图

在进行具体的实现之前,我们再来确认一下神经网络学习的全貌图。神
经网络学习的步骤如下所示。

前提

神经网络中有合适的权重和偏置,调整权重和偏置以便拟合训练数据的
过程称为学习。神经网络的学习分为下面4 个步骤。

步骤1(mini-batch)

从训练数据中随机选择一部分数据。

步骤2(计算梯度)

计算损失函数关于各个权重参数的梯度。

步骤3(更新参数)

将权重参数沿梯度方向进行微小的更新。

之前介绍的误差反向传播法会在步骤2 中出现。上一章中,我们利用数
值微分求得了这个梯度。数值微分虽然实现简单,但是计算要耗费较多的时
间。和需要花费较多时间的数值微分不同,误差反向传播法可以快速高效地
计算梯度。

现在来进行神经网络的实现。这里我们要把2层神经网络实现为TwoLayerNet。
首先,将这个类的实例变量和方法整理成表5-1 和表5-2。

这个类的实现稍微有一点长,但是内容和4.5 节的学习算法的实现有很
多共通的部分,不同点主要在于这里使用了层。通过使用层,获得识别结果
的处理(predict())和计算梯度的处理(gradient())只需通过层之间的传递就能完成。下面是TwoLayerNet的代码实现。

import sys, os sys.path.append(os.pardir) import numpy as np from common.layers import * from common.gradient import numerical_gradient from collections import OrderedDict 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) # 生成层 self.layers = OrderedDict() self.layers['Affine1'] = \ Affine(self.params['W1'], self.params['b1']) self.layers['Relu1'] = Relu() self.layers['Affine2'] = \ Affine(self.params['W2'], self.params['b2']) self.lastLayer = SoftmaxWithLoss() def predict(self, x): for layer in self.layers.values(): x = layer.forward(x) return x # x:输入数据, t:监督数据 def loss(self, x, t): y = self.predict(x) return self.lastLayer.forward(y, t) def accuracy(self, x, t): y = self.predict(x) y = np.argmax(y, axis=1) if t.ndim != 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): # forward self.loss(x, t) # backward dout = 1 dout = self.lastLayer.backward(dout) layers = list(self.layers.values()) layers.reverse() for layer in layers: dout = layer.backward(dout) # 设定 grads = {} grads['W1'] = self.layers['Affine1'].dW grads['b1'] = self.layers['Affine1'].db grads['W2'] = self.layers['Affine2'].dW grads['b2'] = self.layers['Affine2'].db return grads

请注意这个实现中的粗体字代码部分,尤其是将神经网络的层保存为
OrderedDict这一点非常重要。OrderedDict是有序字典,“有序”是指它可以
记住向字典里添加元素的顺序。因此,神经网络的正向传播只需按照添加元
素的顺序调用各层的forward()方法就可以完成处理,而反向传播只需要按
照相反的顺序调用各层即可。因为Affine层和ReLU层的内部会正确处理正
向传播和反向传播,所以这里要做的事情仅仅是以正确的顺序连接各层,再
按顺序(或者逆序)调用各层。

像这样通过将神经网络的组成元素以层的方式实现,可以轻松地构建神
经网络。这个用层进行模块化的实现具有很大优点。因为想另外构建一个神
经网络(比如5 层、10 层、20 层……的大的神经网络)时,只需像组装乐高
积木那样添加必要的层就可以了。之后,通过各个层内部实现的正向传播和
反向传播,就可以正确计算进行识别处理或学习所需的梯度。

误差反向传播法的梯度确认

到目前为止,我们介绍了两种求梯度的方法。一种是基于数值微分的方
法,另一种是解析性地求解数学式的方法。后一种方法通过使用误差反向传
播法,即使存在大量的参数,也可以高效地计算梯度。因此,后文将不再使
用耗费时间的数值微分,而是使用误差反向传播法求梯度。

数值微分的计算很耗费时间,而且如果有误差反向传播法的(正确的)
实现的话,就没有必要使用数值微分的实现了。那么数值微分有什么用呢?
实际上,在确认误差反向传播法的实现是否正确时,是需要用到数值微分的。

数值微分的优点是实现简单,因此,一般情况下不太容易出错。而误差
反向传播法的实现很复杂,容易出错。所以,经常会比较数值微分的结果和
误差反向传播法的结果,以确认误差反向传播法的实现是否正确。确认数值
微分求出的梯度结果和误差反向传播法求出的结果是否一致(严格地讲,是
非常相近)的操作称为梯度确认(gradient check)。梯度确认的代码实现如下
所示(源代码在ch05/gradient_check.py中)。

importsys,os sys.path.append(os.pardir)importnumpyasnpfromdataset.mnistimportload_mnistfromtwo_layer_netimportTwoLayerNet# 读入数据(x_train,t_train),(x_test,t_test)=\ load_mnist(normalize=True,one_ hot_label=True)network=TwoLayerNet(input_size=784,hidden_size=50,output_size=10)x_batch=x_train[:3]t_batch=t_train[:3]grad_numerical=network.numerical_gradient(x_batch,t_batch)grad_backprop=network.gradient(x_batch,t_batch)# 求各个权重的绝对误差的平均值forkeyingrad_numerical.keys():diff=np.average(np.abs(grad_backprop[key]-grad_numerical[key]))print(key+":"+str(diff))

和以前一样,读入MNIST数据集。然后,使用训练数据的一部分,确
认数值微分求出的梯度和误差反向传播法求出的梯度的误差。这里误差的计
算方法是求各个权重参数中对应元素的差的绝对值,并计算其平均值。运行
上面的代码后,会输出如下结果。

b1:9.70418809871e-13 W2:8.41139039497e-13 b2:1.1945999745e-10 W1:2.2232446644e-13

从这个结果可以看出,通过数值微分和误差反向传播法求出的梯度的差
非常小。比如,第1 层的偏置的误差是9.7 e − 13 ( 0.00000000000097 ) 9.7e-13(0.00000000000097)9.7e130.00000000000097。这样一来,
我们就知道了通过误差反向传播法求出的梯度是正确的,误差反向传播法的
实现没有错误。

数值微分和误差反向传播法的计算结果之间的误差为0 是很少见的。
这是因为计算机的计算精度有限(比如,32 位浮点数)。受到数值精
度的限制,刚才的误差一般不会为0,但是如果实现正确的话,可
以期待这个误差是一个接近0 的很小的值。如果这个值很大,就说
明误差反向传播法的实现存在错误。

使用误差反向传播法的学习

最后,我们来看一下使用了误差反向传播法的神经网络的学习的实现。
和之前的实现相比,不同之处仅在于通过误差反向传播法求梯度这一点。这
里只列出了代码,省略了说明(源代码在ch05/train_neuralnet.py中)。

importsys,os sys.path.append(os.pardir)importnumpyasnpfromdataset.mnistimportload_mnistfromtwo_layer_netimportTwoLayerNet# 读入数据(x_train,t_train),(x_test,t_test)=\ load_mnist(normalize=True,one_hot_label=True)network=TwoLayerNet(input_size=784,hidden_size=50,output_size=10)iters_num=10000train_size=x_train.shape[0]batch_size=100learning_rate=0.1train_loss_list=[]train_acc_list=[]test_acc_list=[]iter_per_epoch=max(train_size/batch_size,1)foriinrange(iters_num):batch_mask=np.random.choice(train_size,batch_size)x_batch=x_train[batch_mask]t_batch=t_train[batch_mask]# 通过误差反向传播法求梯度grad=network.gradient(x_batch,t_batch)# 更新forkeyin('W1','b1','W2','b2'):network.params[key]-=learning_rate*grad[key]loss=network.loss(x_batch,t_batch)train_loss_list.append(loss)ifi%iter_per_epoch==0:train_acc=network.accuracy(x_train,t_train)test_acc=network.accuracy(x_test,t_test)train_acc_list.append(train_acc)test_acc_list.append(test_acc)print(train_acc,test_acc)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 13:26:15

在吴忠,遇见你的羽毛球引路人:专业教练与智能系统,助力每一步成长

在吴忠,有一处让羽毛球爱好者们心生向往的地方——吴忠码上羽毛球俱乐部。这里不仅洋溢着运动的活力,更拥有一套将专业教练智慧与现代技术支撑相结合的训练体系。在国家二级运动员韩宁波教练的引领下,配合智能化的训练管理,俱乐部…

作者头像 李华
网站建设 2026/6/10 13:24:52

强烈安利10个AI论文工具,助本科生轻松写论文!

强烈安利10个AI论文工具,助本科生轻松写论文! AI 工具,正在重塑论文写作的未来 在当今这个信息爆炸的时代,本科生们面对论文写作的压力越来越大。从选题到开题,从初稿到降重,每一个环节都可能让人感到力不从…

作者头像 李华
网站建设 2026/6/10 11:01:32

吐血推荐专科生必用9款AI论文平台测评TOP9

吐血推荐专科生必用9款AI论文平台测评TOP9 2026年专科生论文写作工具测评:为何需要这份榜单? 随着AI技术在教育领域的深入应用,越来越多的专科生开始借助智能写作工具提升论文效率。然而,面对市场上琳琅满目的AI平台&#xff0c…

作者头像 李华
网站建设 2026/6/10 10:58:27

Laravel12 + Vue3 的免费可商用 PHP 管理后台 CatchAdmin V5.1.1 发布

Laravel12 Vue3 的免费可商用 PHP 管理后台 CatchAdmin V5.1.1 发布 介绍 CatchAdmin 是一款基于 Laravel 12.x 与 Vue3 二次开发的 PHP 开源后台管理系统,采用前后端分离架构,面向企业级后台场景提供开箱即用的基础能力与可扩展的模块化框架。系统内…

作者头像 李华
网站建设 2026/6/9 18:37:44

大电流PCB布局布线:线宽计算完整示例

以下是对您提供的技术博文进行 深度润色与结构重构后的专业级技术文章 。全文严格遵循您的全部优化要求: ✅ 彻底去除AI痕迹,语言自然如资深工程师现场讲解; ✅ 摒弃所有模板化标题(“引言”“总结”“核心特性”等&#xff0…

作者头像 李华
网站建设 2026/6/10 10:54:03

Llama3与GPT-OSS对比:开源模型推理延迟实测

Llama3与GPT-OSS对比:开源模型推理延迟实测 1. 实测背景与测试目标 最近开源大模型圈里热闹得很,Llama3刚发布不久,OpenAI也悄悄放出了一个叫GPT-OSS的模型——注意,这不是官方命名,而是社区对某款开源推理实现的代称…

作者头像 李华