【d2l】2.4.微积分

【d2l】2.4.微积分

本节主要讲解了微分、偏导、梯度和链式法则

其中梯度需要着重强调

梯度

对于一个多元函数,我们可以对所有变量做偏导数,从而得到该函数的梯度向量

函数\(f:\mathbb{R}^n \rightarrow \mathbb{R}\)输入了一个\(n\)维向量\(x = [x_1, x_2,..., x_n]^\top\),输出一个标量。

\(f(x)\)的梯度为

\[\nabla_xf(x) = [\frac{\partial f(x_1)}{x_1}, \frac{\partial f(x_2)}{x_2}, ..., \frac{\partial f(x_n)}{x_n}] \]

梯度有以下常用性质

  • \(\nabla_x Ax = A^\top\)
  • \(\nabla_x x^\top A = A\)
  • \(\nabla_x x^\top Ax = (A + A^\top)x\)
  • \(\nabla_x ||x||^2 = \nabla_x x^\top x = 2x\)

以上的性质事实上是在说明一件事情:向量对向量的导数是一个矩阵,拿第一个性质举例

\[Ax = \left [ \begin{matrix} a_1^\top x\\ a_2^\top x\\ \vdots \\ a_n^\top x \end{matrix} \right ] \]

于是对于每一行都能求偏导

\[\frac{\partial(a_i^\top x)}{\partial x} = a_i \]

堆叠起来正好是矩阵的转置

在这样的基础上考虑第三个性质,可以知道是类似的,只不过是对一个二次型求偏导【考虑第\(k\)维】

\[\frac{\partial}{\partial x_k}\sum_{i, j}A_{ij}x_ix_j = \sum_{j}A_{kj}x_j + \sum_{i}A_{ik}x_i \]

左右分别是\(A\)\(A^\top\)

最后一个性质就是第三个性质的特例了,几何意义就是距离原点越远,梯度越大

曲线绘制

本节还有一个相对重要的内容,即曲线的绘制

由于我的pytorch版本较高,d2l可能不太有效,因此我考虑一步步自己构造一个d2l_local自带库

首先在项目的根目录设置一个d2l_local,要在notebook导入的话需要在系统路径加入一点东西

import sys
sys.path.appened("..") # 这样就会从项目根目录找自带库了
from d2l_local import torch as d2l

然后就是关于曲线的绘制了,首先要实现使用svg格式绘图、设置图标大小、设置轴的函数

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

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

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函数封装,这样就能简洁地绘制不同曲线了

ef 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 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)
posted @ 2025-12-19 10:22  R4y  阅读(2)  评论(0)    收藏  举报