【深度学习笔记】03 微积分与自动微分

news2025/4/8 15:02:59

03 微积分与自动微分

    • 导数和微分
    • 导数解释的可视化
    • 偏导数
    • 梯度
    • 链式法则
    • 自动微分
    • 非标量变量的反向传播
    • 分离计算

导数和微分

假设我们有一个函数 f : R → R f: \mathbb{R} \rightarrow \mathbb{R} f:RR,其输入和输出都是标量。
如果 f f f导数存在,这个极限被定义为

f ′ ( x ) = lim ⁡ h → 0 f ( x + h ) − f ( x ) h . f'(x) = \lim_{h \rightarrow 0} \frac{f(x+h) - f(x)}{h}. f(x)=h0limhf(x+h)f(x).

如果 f ′ ( a ) f'(a) f(a)存在,则称 f f f a a a处是可微(differentiable)的。
如果 f f f在一个区间内的每个数上都是可微的,则此函数在此区间中是可微的。
我们可以将导数 f ′ ( x ) f'(x) f(x)解释为 f ( x ) f(x) f(x)相对于 x x x瞬时(instantaneous)变化率。
所谓的瞬时变化率是基于 x x x中的变化 h h h,且 h h h接近 0 0 0

给定 y = f ( x ) y=f(x) y=f(x),其中 x x x y y y分别是函数 f f f的自变量和因变量。以下表达式是等价的:

f ′ ( x ) = y ′ = d y d x = d f d x = d d x f ( x ) = D f ( x ) = D x f ( x ) , f'(x) = y' = \frac{dy}{dx} = \frac{df}{dx} = \frac{d}{dx} f(x) = Df(x) = D_x f(x), f(x)=y=dxdy=dxdf=dxdf(x)=Df(x)=Dxf(x),

其中符号 d d x \frac{d}{dx} dxd D D D是微分运算符,表示微分操作。
可以使用以下规则来对常见函数求微分:

  • D C = 0 DC = 0 DC=0 C C C是一个常数)
  • D x n = n x n − 1 Dx^n = nx^{n-1} Dxn=nxn1(幂律(power rule), n n n是任意实数)
  • D e x = e x De^x = e^x Dex=ex
  • D ln ⁡ ( x ) = 1 / x D\ln(x) = 1/x Dln(x)=1/x

假设函数 f f f g g g都是可微的, C C C是一个常数,则:

常数相乘法则
d d x [ C f ( x ) ] = C d d x f ( x ) , \frac{d}{dx} [Cf(x)] = C \frac{d}{dx} f(x), dxd[Cf(x)]=Cdxdf(x),

加法法则

d d x [ f ( x ) + g ( x ) ] = d d x f ( x ) + d d x g ( x ) , \frac{d}{dx} [f(x) + g(x)] = \frac{d}{dx} f(x) + \frac{d}{dx} g(x), dxd[f(x)+g(x)]=dxdf(x)+dxdg(x),

乘法法则

d d x [ f ( x ) g ( x ) ] = f ( x ) d d x [ g ( x ) ] + g ( x ) d d x [ f ( x ) ] , \frac{d}{dx} [f(x)g(x)] = f(x) \frac{d}{dx} [g(x)] + g(x) \frac{d}{dx} [f(x)], dxd[f(x)g(x)]=f(x)dxd[g(x)]+g(x)dxd[f(x)],

除法法则

d d x [ f ( x ) g ( x ) ] = g ( x ) d d x [ f ( x ) ] − f ( x ) d d x [ g ( x ) ] [ g ( x ) ] 2 . \frac{d}{dx} \left[\frac{f(x)}{g(x)}\right] = \frac{g(x) \frac{d}{dx} [f(x)] - f(x) \frac{d}{dx} [g(x)]}{[g(x)]^2}. dxd[g(x)f(x)]=[g(x)]2g(x)dxd[f(x)]f(x)dxd[g(x)].

导数解释的可视化

import numpy as np
from matplotlib_inline import backend_inline
from d2l import torch as d2l

def f(x):
    return 3 * x ** 2 - 4 * x

def use_svg_display():  #@save
    """使用svg格式在Jupyter中显示绘图"""
    backend_inline.set_matplotlib_formats('svg')

定义set_figsize函数来设置图表大小

def set_figsize(figsize=(3.5, 2.5)):  #@save
    """设置matplotlib的图表大小"""
    use_svg_display()
    d2l.plt.rcParams['figure.figsize'] = figsize

set_axes函数用于设置由matplotlib生成图表的轴的属性

#@save
def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):
    """设置matplotlib的轴"""
    axes.set_xlabel(xlabel)
    axes.set_ylabel(ylabel)
    axes.set_xscale(xscale)
    axes.set_yscale(yscale)
    axes.set_xlim(xlim)
    axes.set_ylim(ylim)
    if legend:
        axes.legend(legend)
    axes.grid()

通过这三个用于图形配置的函数,定义一个plot函数来简洁地绘制多条曲线。

#@save
def plot(X, Y=None, xlabel=None, ylabel=None, legend=None, xlim=None,
         ylim=None, xscale='linear', yscale='linear',
         fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5), axes=None):
    """绘制数据点"""
    if legend is None:
        legend = []

    set_figsize(figsize)
    axes = axes if axes else d2l.plt.gca()

    # 如果X有一个轴,输出True
    def has_one_axis(X):
        return (hasattr(X, "ndim") and X.ndim == 1 or isinstance(X, list)
                and not hasattr(X[0], "__len__"))

    if has_one_axis(X):
        X = [X]
    if Y is None:
        X, Y = [[]] * len(X), X
    elif has_one_axis(Y):
        Y = [Y]
    if len(X) != len(Y):
        X = X * len(Y)
    axes.cla()
    for x, y, fmt in zip(X, Y, fmts):
        if len(x):
            axes.plot(x, y, fmt)
        else:
            axes.plot(y, fmt)
    set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)

绘制函数 u = f ( x ) u=f(x) u=f(x)及其在 x = 1 x=1 x=1处的切线 y = 2 x − 3 y=2x-3 y=2x3,其中系数 2 2 2是切线的斜率

x = np.arange(0, 3, 0.1)
plot(x, [f(x), 2 * x - 3], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])


在这里插入图片描述

偏导数

y = f ( x 1 , x 2 , … , x n ) y = f(x_1, x_2, \ldots, x_n) y=f(x1,x2,,xn)是一个具有 n n n个变量的函数。
y y y关于第 i i i个参数 x i x_i xi偏导数(partial derivative)为:

∂ y ∂ x i = lim ⁡ h → 0 f ( x 1 , … , x i − 1 , x i + h , x i + 1 , … , x n ) − f ( x 1 , … , x i , … , x n ) h . \frac{\partial y}{\partial x_i} = \lim_{h \rightarrow 0} \frac{f(x_1, \ldots, x_{i-1}, x_i+h, x_{i+1}, \ldots, x_n) - f(x_1, \ldots, x_i, \ldots, x_n)}{h}. xiy=h0limhf(x1,,xi1,xi+h,xi+1,,xn)f(x1,,xi,,xn).

为了计算 ∂ y ∂ x i \frac{\partial y}{\partial x_i} xiy
可以将 x 1 , … , x i − 1 , x i + 1 , … , x n x_1, \ldots, x_{i-1}, x_{i+1}, \ldots, x_n x1,,xi1,xi+1,,xn看作常数,
并计算 y y y关于 x i x_i xi的导数。
对于偏导数的表示,以下是等价的:

∂ y ∂ x i = ∂ f ∂ x i = f x i = f i = D i f = D x i f . \frac{\partial y}{\partial x_i} = \frac{\partial f}{\partial x_i} = f_{x_i} = f_i = D_i f = D_{x_i} f. xiy=xif=fxi=fi=Dif=Dxif.

梯度

可以连结一个多元函数对其所有变量的偏导数,以得到该函数的梯度(gradient)向量。
设函数 f : R n → R f:\mathbb{R}^n\rightarrow\mathbb{R} f:RnR的输入是
一个 n n n维向量 x = [ x 1 , x 2 , … , x n ] ⊤ \mathbf{x}=[x_1,x_2,\ldots,x_n]^\top x=[x1,x2,,xn],并且输出是一个标量。
函数 f ( x ) f(\mathbf{x}) f(x)相对于 x \mathbf{x} x的梯度是一个包含 n n n个偏导数的向量:

∇ x f ( x ) = [ ∂ f ( x ) ∂ x 1 , ∂ f ( x ) ∂ x 2 , … , ∂ f ( x ) ∂ x n ] ⊤ , \nabla_{\mathbf{x}} f(\mathbf{x}) = \bigg[\frac{\partial f(\mathbf{x})}{\partial x_1}, \frac{\partial f(\mathbf{x})}{\partial x_2}, \ldots, \frac{\partial f(\mathbf{x})}{\partial x_n}\bigg]^\top, xf(x)=[x1f(x),x2f(x),,xnf(x)],

其中 ∇ x f ( x ) \nabla_{\mathbf{x}} f(\mathbf{x}) xf(x)通常在没有歧义时被 ∇ f ( x ) \nabla f(\mathbf{x}) f(x)取代。

假设 x \mathbf{x} x n n n维向量,在微分多元函数时经常使用以下规则:

  • 对于所有 A ∈ R m × n \mathbf{A} \in \mathbb{R}^{m \times n} ARm×n,都有 ∇ x A x = A ⊤ \nabla_{\mathbf{x}} \mathbf{A} \mathbf{x} = \mathbf{A}^\top xAx=A
  • 对于所有 A ∈ R n × m \mathbf{A} \in \mathbb{R}^{n \times m} ARn×m,都有 ∇ x x ⊤ A = A \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} = \mathbf{A} xxA=A
  • 对于所有 A ∈ R n × n \mathbf{A} \in \mathbb{R}^{n \times n} ARn×n,都有 ∇ x x ⊤ A x = ( A + A ⊤ ) x \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{A} \mathbf{x} = (\mathbf{A} + \mathbf{A}^\top)\mathbf{x} xxAx=(A+A)x
  • ∇ x ∥ x ∥ 2 = ∇ x x ⊤ x = 2 x \nabla_{\mathbf{x}} \|\mathbf{x} \|^2 = \nabla_{\mathbf{x}} \mathbf{x}^\top \mathbf{x} = 2\mathbf{x} xx2=xxx=2x

    同样,对于任何矩阵 X \mathbf{X} X,都有 ∇ X ∥ X ∥ F 2 = 2 X \nabla_{\mathbf{X}} \|\mathbf{X} \|_F^2 = 2\mathbf{X} XXF2=2X

链式法则

链式法则可以被用来微分复合函数。

假设函数 y = f ( u ) y=f(u) y=f(u) u = g ( x ) u=g(x) u=g(x)都是可微的,根据链式法则:

d y d x = d y d u d u d x . \frac{dy}{dx} = \frac{dy}{du} \frac{du}{dx}. dxdy=dudydxdu.

现在考虑一个更一般的场景,即函数具有任意数量的变量的情况。
假设可微分函数 y y y有变量 u 1 , u 2 , … , u m u_1, u_2, \ldots, u_m u1,u2,,um,其中每个可微分函数 u i u_i ui都有变量 x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1,x2,,xn
注意, y y y x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1,x2,xn的函数。
对于任意 i = 1 , 2 , … , n i = 1, 2, \ldots, n i=1,2,,n,链式法则给出:

∂ y ∂ x i = ∂ y ∂ u 1 ∂ u 1 ∂ x i + ∂ y ∂ u 2 ∂ u 2 ∂ x i + ⋯ + ∂ y ∂ u m ∂ u m ∂ x i \frac{\partial y}{\partial x_i} = \frac{\partial y}{\partial u_1} \frac{\partial u_1}{\partial x_i} + \frac{\partial y}{\partial u_2} \frac{\partial u_2}{\partial x_i} + \cdots + \frac{\partial y}{\partial u_m} \frac{\partial u_m}{\partial x_i} xiy=u1yxiu1+u2yxiu2++umyxium

自动微分

深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。
实际中,根据设计好的模型,系统会构建一个计算图(computational graph),
来跟踪计算是哪些数据通过哪些操作组合起来产生输出。
自动微分使系统能够随后反向传播梯度。
这里,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。

例如对函数 y = 2 x T x y=2x^{T}x y=2xTx关于列向量 x x x求导

首先创建变量 x x x并为其分配一个初始值

import torch

x = torch.arange(4.0)
x
tensor([0., 1., 2., 3.])
x.requires_grad_(True)  # 等价于x=torch.arange(4.0,requires_grad=True)
x.grad  # 默认值是None

# 计算y
y = 2 * torch.dot(x, x)
y
tensor(28., grad_fn=<MulBackward0>)

通过调用反向传播函数来自动计算 y y y关于 x x x每个分量的梯度

y.backward()
x.grad
tensor([ 0.,  4.,  8., 12.])

验证梯度计算是否正确

x.grad == 4 * x
tensor([True, True, True, True])

计算 x x x的另一个函数

# 在默认情况下,PyTorch会累计梯度,需要清除之前的值
x.grad.zero_()
y = x.sum()
y.backward()
x.grad
tensor([1., 1., 1., 1.])

非标量变量的反向传播

# 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。
# 本例只想求偏导数的和,所以传递一个1的梯度是合适的
x.grad.zero_()
y = x * x
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad
tensor([0., 2., 4., 6.])

分离计算

有时希望将某些计算移动到记录的计算图之外。例如,加入 y y y是作为 x x x的函数计算的,而 z z z则是作为 y y y x x x的函数计算的。此时想计算 z z z关于 x x x的梯度,但由于某种原因,希望将 y y y视为一个常熟,并且只考虑到 x x x y y y被计算之后发挥的作用。

这里可以分离 y y y来返回一个新变量 u u u,该变量与 y y y具有相同的值,但丢弃计算图中如何计算 y y y的任何信息,即梯度不会向后流经 u u u x x x

因此,反向传播函数计算 z = u ∗ x z=u*x z=ux关于 x x x的偏导数,同时将 u u u作为常数处理,而不是 z = x ∗ x ∗ x z=x*x*x z=xxx关于 x x x的偏导数。

x.grad.zero_()
y = x * x
u = y.detach()
z = u * x

z.sum().backward()
x.grad == u
tensor([True, True, True, True])

由于记录了 y y y的计算结果,我们随后可以在 y y y上调用反向传播,得到 y = x ∗ x y=x*x y=xx关于 x x x的导数,即 2 ∗ x 2*x 2x

x.grad.zero_()
y.sum().backward()
x.grad == 2 * x
tensor([True, True, True, True])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1253853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

按需引入 ElMessage,没有样式且类型检查失败

文章目录 ElMessage 弹框没有样式问题描述解决方案 ts 类型检查失败问题描述解决办法 eslint 检查失败问题描述解决办法 ElMessage 弹框没有样式 问题描述 Element-plus 在使用 ElMessage 消息弹框的时候没有样式&#xff0c;按照官方的按需加载的方式引入的 import { ElMes…

Kafka系列 - Kafka一篇入门

Kafka是一个分布式流式处理平台。很多分布式处理系统&#xff0c;例如Spark&#xff0c;Flink等都支持与Kafka集成。 Kafka使用场景 消息系统&#xff1a;Kafka实现了消息顺序性保证和回溯消费。存储系统&#xff1a;Kafka把消息持久化到磁盘&#xff0c;相比于其他基于内存的…

PropertyTokenizer属性解析器实现,So Easy

PropertyTokenizer是Mybatis中的属性解析器&#xff0c;其主要实现原理如下&#xff1a; public PropertyTokenizer(String fullname) {// 判断是否以“.”分隔int delim fullname.indexOf(.);if (delim > -1) {name fullname.substring(0, delim);children fullname.su…

1 时间序列模型入门: LSTM

0 前言 循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一种用于处理序列数据的神经网络。相比一般的神经网络来说&#xff0c;他能够处理序列变化的数据。比如某个单词的意思会因为上文提到的内容不同而有不同的含义&#xff0c;RNN就能够很好…

抖音小店开店指南:流程、准备和营销策略一站解析

抖音小店已成为一个热门的社交电商平台&#xff0c;为商家提供了一个快速、方便、低成本的开店通道。下面四川不若与众将介绍抖音小店开店的流程和需要准备的工作&#xff0c;帮助商家顺利开启自己的电商之路。 一、开店准备工作&#xff1a; 1. 产品准备&#xff1a;确定出售…

系列十五、BeanDefinition

一、BeanDefinition 1.1、概述 BeanDefinition是一个接口&#xff0c;主要负责存储bean的定义信息&#xff0c;决定bean的生产方式&#xff0c;是一个定义态的bean&#xff0c;类似于说明书。后续BeanFactory就可以根据这些信息生产bean了。比如实例化&#xff1a;可以通过反射…

浅析基于物联网的远程抄表系统的设计及应用

安科瑞 华楠 摘 要&#xff1a;本文基于物联网的概念&#xff0c;使用 ZigBee、通用分组无线服务技术两种无线通信技术相结合的方式实现远程抄表并对数据进行存储和管理。此系统设计主要分为硬件方面的设计和软件方面的设计&#xff0c;硬件方面的设计需要完成三个部分的硬件制…

快速认识Linux的几个指令

我们先简单认识几个指令&#xff0c;为之后的指令学习打好基础 打开XShell并登录云服务器 01.pwd指令 pwd命令的作用是显示当前在Linux系统中所处的路径 02.ls指令 ls命令的作业是罗列出当前路径下的文件名&#xff08;即pwd的路径下&#xff09;&#xff0c;由于我们没有新…

人工智能-注意力机制之Transformer

Transformer 比较了卷积神经网络&#xff08;CNN&#xff09;、循环神经网络&#xff08;RNN&#xff09;和自注意力&#xff08;self-attention&#xff09;。值得注意的是&#xff0c;自注意力同时具有并行计算和最短的最大路径长度这两个优势。因此&#xff0c;使用自注意力…

【H5 Canvas】一篇通

文章目录 Canvas的创建(HTMLCanvasElement)图形绘制&#xff1a;H5为Canvas对应的2D上下文Context提供了一系列的画图接口保存save、恢复restore、变换Transformations Canvas的创建(HTMLCanvasElement) 定义canvas HTML元素&#xff0c;默认长宽300x150 <canvas width&qu…

利用chart.js来完成动态网页显示拆线图的效果

<% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%><%! String list"[一月份, 二月份, 三月份,四月份, 五月份, 六月份, 七月]"; String label"我的一个折线图"; String data &qu…

RocketMq架构和源码解析

NameServer&#xff1a;作为注册中心&#xff0c;提供路由注册、路由踢出、路由发现功能&#xff0c;舍弃强一致&#xff0c;保证高可用&#xff0c;集群中各个节点不会实时通讯&#xff0c;其中一个节点下线之后&#xff0c;会提供另外一个节点保证路由功能。 Broker&#xf…

为什么网上大量程序员卡35岁年龄招聘,而从来不报道测试、技术支持、售前售后工程师呢?

其实&#xff0c;网上只报道程序员卡35岁&#xff0c;这个说法并不成立。 而是普遍卡35岁&#xff0c;但并没有明确的一个职业类别。 随便搜一下&#xff0c;一眼望过去&#xff0c;其实已经波及很多行业了。 但如果你把IT从业人员合并报道&#xff0c;确实容易给人一种“程序…

Docker Swarm总结+service创建和部署、overlay网络以及Raft算法(2/4)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

【Go实现】实践GoF的23种设计模式:备忘录模式

上一篇&#xff1a;【Go实现】实践GoF的23种设计模式&#xff1a;命令模式 简单的分布式应用系统&#xff08;示例代码工程&#xff09;&#xff1a;https://github.com/ruanrunxue/Practice-Design-Pattern–Go-Implementation 简介 相对于代理模式、工厂模式等设计模式&…

红队攻防实战系列一之metasploit

百目无她&#xff0c;百书质华&#xff0c;君当醒悟&#xff0c;建我中华 本文首发于先知社区&#xff0c;原创作者即是本人 前言 在红队攻防中&#xff0c;我们主要在外网进行信息收集&#xff0c;通过cms或者其他漏洞拿到shell&#xff0c;之后通过免杀木马将windows或lin…

【通讯协议】gRPC和Webhook

RPC&#xff08;Remote procedure Call&#xff09;之所以被称为“远程”&#xff0c;是因为在微服务架构下&#xff0c;当服务部署到不同的服务器上时&#xff0c;它可以实现远程服务之间的通信。从用户的角度来看&#xff0c;它的作用就像本地函数调用。 下图说明了gRPC的整…

java io 流,输入流和输出流;节点流和处理流;字节流和字符流

文章目录 java 中 IO 流分为几种?按照流的流向分&#xff0c;可以分为输入流和输出流&#xff1b;按照流的角色划分为节点流和处理流。IO流主要的分类方式有以下3种&#xff1a; java中的IO流也是工作中使用到比较频繁的一个内容&#xff0c;今天以这篇文章来了解它的概念和整…

第十七章 解读PyTorch断点训练(工具)

主要有以下几方面的内容&#xff1a; 对于多步长训练需要保存lr_schedule初始化随机数种子保存每一代最好的结果 简单详细介绍 最近在尝试用CIFAR10训练分类问题的时候&#xff0c;由于数据集体量比较大&#xff0c;训练的过程中时间比较长&#xff0c;有时候想给停下来&…

下一代图片压缩格式 AVIF

长期以来我们都在为了在网络上使用什么样的图片格式而进行纠结。我们所熟知的或者运用到 Web 应用中的图片格式无非就是 PNG、JPG、GIF、SVG 或者 WebP。 HEIC是一种图像格式&#xff0c;上线时间还比较短&#xff0c;只有4年左右。 自iOS 11和 macOS High Sierra&#xff08…