<jupyter_start><jupyter_text>自动求导假设我们想对函数 $y = 2\mathbf{x}^{\top}\mathbf{x}$关于列向量 $\mathbf{x}$求导<jupyter_code>import torch

x = torch.arange(4.0)
x<jupyter_output><empty_output><jupyter_text>等价于：↓<jupyter_code>x2 = torch.arange(4.0, requires_grad=True)
x2<jupyter_output><empty_output><jupyter_text>在我们计算$y$关于$\mathbf{x}$的梯度之前，我们需要一个地方来存储梯度<jupyter_code># 等价于 x = torch.arange(4.0, requires_grad=True)
x.requires_grad_(True)
# x.grad 存储了x的梯度
x.grad<jupyter_output><empty_output><jupyter_text>现在让我们计算 $y$<jupyter_code># 此处，y是标量
y = 2 * torch.dot(x, x)
y<jupyter_output><empty_output><jupyter_text>通过调用反向传播函数来自动计算`y`关于`x` 每个分量的梯度- Notice: 标量对向量求导，结果为向量！！！<jupyter_code>y.backward()
x.grad
x.grad == 4 * x<jupyter_output><empty_output><jupyter_text>现在让我们计算 `x` 的另一个函数- 在默认情况下，PyTorch会累积梯度，我们需要清除之前的值。- Notice: PyTorch中，带下划线的函数（例如 `zero_()`）表示重写内容<jupyter_code>x.sum()
x.grad.zero_()

y = x.sum()

y.backward()
x.grad<jupyter_output><empty_output><jupyter_text>深度学习中，我们的目的不是计算微分矩阵，而是批量中每个样本单独计算的偏导数之和，所以先做一个sum操作，将y转换为标量，之后再求导，得到标量关于向量的导数，结果为向量，而不是矩阵。<jupyter_code>x.grad.zero_()

# 此处，y是向量
y = x * x

# 等价于 y.backward(torch.ones(len(x)))
y.sum().backward()

# 向量对向量求导的结果是矩阵
x.grad<jupyter_output><empty_output><jupyter_text>将某些计算移动到记录的计算图之外 .detach()返回一个新的tensor，从当前计算图中分离下来的，但是仍指向原变量的存放位置，不同之处只是requires_grad为false，得到的这个tensor永远不需要计算其梯度，不具有grad。即使之后重新将它的requires_grad置为true，它也不会具有梯度grad这样就会继续使用这个新的tensor进行计算，后面进行反向传播时，调用detach()的tensor就会停止，不能再继续向前进行传播。注意：使用detach返回的tensor和原始的tensor共同一个内存，即一个修改另一个也会跟着改变---参考：https://blog.csdn.net/qq_27825451/article/details/95498211<jupyter_code>x.grad.zero_()
y = x * x

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

z.sum().backward()
x.grad == u
x.grad.zero_()

y.sum().backward()

x.grad == 2 * x<jupyter_output><empty_output><jupyter_text>即使构建函数的计算图需要通过 Python控制流（例如，条件、循环或任意函数调用），我们仍然可以计算得到的变量的梯度<jupyter_code>def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c

# 不指定size，则表示标量
a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()

a.grad == d / a<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1581196581196581, 'fraction_numerical': 0.018043684710351376, 'mean_word_length': 7.166666666666667, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 38, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '377295', 'license': 'MIT', 'n_tokens_mistral': 1284, 'n_tokens_neox': 1351, 'n_words': 102, 'path': '.ipynb_checkpoints/autograd-Copy1-checkpoint.ipynb', 'repo_name': 'datamonday/Dive-into-DL-Notes', 'size': '2106'}