动手学深度学习 第三章 线性神经网络 练习(Pytorch版)

本文概述了从线性回归到softmax回归的机器学习模型,介绍了从基础实现到高级API的简洁实现,涉及数据处理、损失函数和优化算法。实践练习涵盖了模型训练、噪声模型、数据集和模型改进策略。
部署运行你感兴趣的模型镜像

线性神经网络

线性回归

小结

  • 机器学习模型中的关键要素是训练数据、损失函数、优化算法,还有模型本身。
  • 矢量化使数学表达上更简洁,同时运行的更快。
  • 最小化目标函数和执行极大似然估计等价。
  • 线性回归模型也是一个简单的神经网络。

练习

  1. 假设我们有一些数据 x 1 , … , x n ∈ R x_1, \ldots, x_n \in \mathbb{R} x1,,xnR。我们的目标是找到一个常数 b b b,使得最小化 ∑ i ( x i − b ) 2 \sum_i (x_i - b)^2 i(xib)2
    1. 找到最优值 b b b的解析解。
    2. 这个问题及其解与正态分布有什么关系?
  2. 推导出使用平方误差的线性回归优化问题的解析解。为了简化问题,可以忽略偏置 b b b(我们可以通过向 X \mathbf X X添加所有值为1的一列来做到这一点)。
    1. 用矩阵和向量表示法写出优化问题(将所有数据视为单个矩阵,将所有目标值视为单个向量)。
    2. 计算损失对 w w w的梯度。
    3. 通过将梯度设为0、求解矩阵方程来找到解析解。
    4. 什么时候可能比使用随机梯度下降更好?这种方法何时会失效?
  3. 假定控制附加噪声 ϵ \epsilon ϵ的噪声模型是指数分布。也就是说, p ( ϵ ) = 1 2 exp ⁡ ( − ∣ ϵ ∣ ) p(\epsilon) = \frac{1}{2} \exp(-|\epsilon|) p(ϵ)=21exp(ϵ)
    1. 写出模型 − log ⁡ P ( y ∣ X ) -\log P(\mathbf y \mid \mathbf X) logP(yX)下数据的负对数似然。
    2. 你能写出解析解吗?
    3. 提出一种随机梯度下降算法来解决这个问题。哪里可能出错?(提示:当我们不断更新参数时,在驻点附近会发生什么情况)你能解决这个问题吗?

在这里插入图片描述
可以使用SmoothL1Loss

线性回归的从零开始实现

小结

  • 我们学习了深度网络是如何实现和优化的。在这一过程中只使用张量和自动微分,不需要定义层或复杂的优化器。
  • 这一节只触及到了表面知识。在下面的部分中,我们将基于刚刚介绍的概念描述其他模型,并学习如何更简洁地实现其他模型。

练习

  1. 如果我们将权重初始化为零,会发生什么。算法仍然有效吗?
  2. 假设你是乔治·西蒙·欧姆,试图为电压和电流的关系建立一个模型。你能使用自动微分来学习模型的参数吗?
  3. 您能基于普朗克定律使用光谱能量密度来确定物体的温度吗?
  4. 如果你想计算二阶导数可能会遇到什么问题?你会如何解决这些问题?
  5. 为什么在squared_loss函数中需要使用reshape函数?
  6. 尝试使用不同的学习率,观察损失函数值下降的快慢。
  7. 如果样本个数不能被批量大小整除,data_iter函数的行为会有什么变化?

1 . 将权重初始化为零,算法依然有效。但网络层数加深后,在全连接的情况下,反向传播时,由于权重的对称性会导致出现隐藏神经元的对称性,是的多个隐藏神经元的作用就如同一个神经元,影响算法效果。
2.

import torch
import random
from d2l import torch as d2l
#生成数据集
def synthetic_data(r, b, num_examples):
    I = torch.normal(0, 1, (num_examples, len(r)))
    u = torch.matmul(I, r) + b
    u += torch.normal(0, 0.01, u.shape) # 噪声
    return I, u.reshape((-1, 1)) # 标量转换为向量

true_r = torch.tensor([20.0])
true_b = 0.01
features, labels = synthetic_data(true_r, true_b, 1000)

#读取数据集
def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(indices[i: min(i + batch_size, num_examples)])
        yield features[batch_indices],labels[batch_indices]
        
batch_size = 10
# 初始化权重
r = torch.normal(0,0.01,size = ((1,1)), requires_grad = True)
b = torch.zeros(1, requires_grad = True)

# 定义模型
def linreg(I, r, b):
    return torch.matmul(I, r) + b
# 损失函数
def square_loss(u_hat, u):
    return (u_hat - u.reshape(u_hat.shape)) ** 2/2
# 优化算法
def sgd(params, lr, batch_size):
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad/batch_size
            param.grad.zero_()

lr = 0.03
num_epochs = 10
net = linreg
loss = square_loss

for epoch in range(num_epochs):
    for I, u in data_iter(batch_size, features, labels):
        l = loss(net(I, r, b), u)
        l.sum().backward()
        sgd([r, b], lr, batch_size)
    with torch.no_grad():
        train_l = loss(net(features, r, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
print(r)
print(b)
print(f'r的估计误差: {true_r - r.reshape(true_r.shape)}')
print(f'b的估计误差: {true_b - b}')
epoch 1, loss 0.329473
epoch 2, loss 0.000541
epoch 3, loss 0.000050
epoch 4, loss 0.000050
epoch 5, loss 0.000050
epoch 6, loss 0.000050
epoch 7, loss 0.000050
epoch 8, loss 0.000050
epoch 9, loss 0.000050
epoch 10, loss 0.000050
tensor([[19.9997]], requires_grad=True)
tensor([0.0093], requires_grad=True)
r的估计误差: tensor([0.0003], grad_fn=<SubBackward0>)
b的估计误差: tensor([0.0007], grad_fn=<RsubBackward1>)

3 . 尝试写了一下,但好像出错了,结果loss = nan
M λ b b = 2 π h c 2 λ 5 ⋅ 1 e h c λ k T − 1 = c 1 λ 5 ⋅ 1 e c 2 k T − 1 M_{\lambda b b}=\frac{2 \pi h c^{2}}{\lambda^{5}} \cdot \frac{1}{e^{\frac{h c}{\lambda k T}}-1}=\frac{c_{1}}{\lambda^{5}} \cdot \frac{1}{e^{\frac{c_{2}}{k T}}-1} Mλbb=λ52πhc2eλkThc11=λ5c1ekTc211

# 3
# 普朗克公式
# x:波长
# T:温度
import torch
import random
from d2l import torch as d2l


#生成数据集
def synthetic_data(x, num_examples):
    T = torch.normal(0, 1, (num_examples, len(x)))
    u = c1 / ((x ** 5) * ((torch.exp(c2 / (x * T))) - 1));
    u += torch.normal(0, 0.01, u.shape) # 噪声
    return T, u.reshape((-1, 1)) # 标量转换为向量


c1 = 3.7414*10**8  # c1常量
c2 = 1.43879*10**4  # c2常量
true_x = torch.tensor([500.0])

features, labels = synthetic_data(true_x, 1000)


#读取数据集
def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(indices[i: min(i + batch_size, num_examples)])
        yield features[batch_indices],labels[batch_indices]

batch_size = 10
# 初始化权重
x = torch.normal(0,0.01,size = ((1,1)), requires_grad = True)


# 定义模型
def planck_formula(T, x):
    return c1 / ((x ** 5) * ((torch.exp(c2 / (x * T))) - 1))
# 损失函数
def square_loss(u_hat, u):
    return (u_hat - u.reshape(u_hat.shape)) ** 2/2
# 优化算法
def sgd(params, lr, batch_size):
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad/batch_size
            param.grad.zero_()

lr = 0.001
num_epochs = 10
net = planck_formula
loss = square_loss

for epoch in range(num_epochs):
    for T, u in data_iter(batch_size, features, labels):
        l = loss(net(T, x), u)
        l.sum().backward()
        sgd([x], lr, batch_size)
    with torch.no_grad():
        train_l = loss(net(features, x), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

print(f'r的估计误差: {true_x - x.reshape(true_x.shape)}')
  1. 二阶导数可能不存在,或无法得到显式的一阶导数。可以在求一阶导数时使用retain_graph=True参数保存计算图,进而求二阶导。
  2. y_hat和y的维度可能不相同,分别为行向量和列向量,维度(n,1)(n, )
  3. 学习率越大,损失函数下降越快。但学习率过大可能导致无法收敛。
learning rate = 0.03
epoch 1, loss 0.039505
epoch 2, loss 0.000141
epoch 3, loss 0.000048

learning rate = 0.05
epoch 1, loss 0.000576
epoch 2, loss 0.000052
epoch 3, loss 0.000052

learning rate = 0.5
epoch 1, loss 0.000057
epoch 2, loss 0.000053
epoch 3, loss 0.000051
  1. 设置了indices[i: min(i + batch_size, num_examples)],样本个数不能被批量大小整除不会导致data_iter变化,不设置的话可能会报错。

线性回归的简洁实现

小结

  • 我们可以使用PyTorch的高级API更简洁地实现模型。
  • 在PyTorch中,data模块提供了数据处理工具,nn模块定义了大量的神经网络层和常见损失函数。
  • 我们可以通过_结尾的方法将参数替换,从而初始化参数。

练习

  1. 如果将小批量的总损失替换为小批量损失的平均值,你需要如何更改学习率?
  2. 查看深度学习框架文档,它们提供了哪些损失函数和初始化方法?用Huber损失代替原损失,即
    l ( y , y ′ ) = { ∣ y − y ′ ∣ − σ 2  if  ∣ y − y ′ ∣ > σ 1 2 σ ( y − y ′ ) 2  其它情况 l(y,y') = \begin{cases}|y-y'| -\frac{\sigma}{2} & \text{ if } |y-y'| > \sigma \\ \frac{1}{2 \sigma} (y-y')^2 & \text{ 其它情况}\end{cases} l(y,y)={yy2σ2σ1(yy)2 if yy>σ 其它情况
  3. 你如何访问线性回归的梯度?

1 . 将学习率缩小为之前的1/n

2 . 部分loss function
在这里插入图片描述
将损失函数更改为HuberLoss(仅1.9.0及以上版本的pytorch才有HuberLoss)

#%%
import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l

#%%
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)

def load_array(data_arrays, batch_size, is_train = True): #@save
    '''pytorch数据迭代器'''
    dataset = data.TensorDataset(*data_arrays) # 把输入的两类数据一一对应;*表示对list解开入参
    return data.DataLoader(dataset, batch_size, shuffle = is_train) # 重新排序

batch_size = 10
data_iter = load_array((features, labels), batch_size) # 和手动实现中data_iter使用方法相同

#%%
# 构造迭代器并验证data_iter的效果
next(iter(data_iter))  # 获得第一个batch的数据

#%% 定义模型
from torch import nn
net = nn.Sequential(nn.Linear(2, 1))  # Linear中两个参数一个表示输入形状一个表示输出形状
# sequential相当于一个存放各层数据的list,单层时也可以只用Linear

#%% 初始化模型参数
# 使用net[0]选择神经网络中的第一层
net[0].weight.data.normal_(0, 0.01) # 正态分布
net[0].bias.data.fill_(0)

#%% 定义损失函数
loss = torch.nn.HuberLoss()
#%% 定义优化算法
trainer = torch.optim.SGD(net.parameters(), lr=0.03) # optim module中的SGD
#%% 训练
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X), y)
        trainer.zero_grad()
        l.backward()
        trainer.step()
    l = loss(net(features), labels)
    print(f'epoch {epoch+1}, loss {l:f}')

#%% 查看误差
w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)

3 . 线性回归的梯度

print(net[0].weight.grad)
print(net[0].bias.grad)

softmax回归

小结

  • softmax运算获取一个向量并将其映射为概率。
  • softmax回归适用于分类问题,它使用了softmax运算中输出类别的概率分布。
  • 交叉熵是一个衡量两个概率分布之间差异的很好的度量,它测量给定模型编码数据所需的比特数。

练习

  1. 我们可以更深入地探讨指数族与softmax之间的联系。
    1. 计算softmax交叉熵损失 l ( y , y ^ ) l(\mathbf{y},\hat{\mathbf{y}}) l(y,y^)的二阶导数。
    2. 计算 s o f t m a x ( o ) \mathrm{softmax}(\mathbf{o}) softmax(o)给出的分布方差,并与上面计算的二阶导数匹配。
  2. 假设我们有三个类发生的概率相等,即概率向量是 ( 1 3 , 1 3 , 1 3 ) (\frac{1}{3}, \frac{1}{3}, \frac{1}{3}) (31,31,31)
    1. 如果我们尝试为它设计二进制代码,有什么问题?
    2. 你能设计一个更好的代码吗?提示:如果我们尝试编码两个独立的观察结果会发生什么?如果我们联合编码 n n n个观测值怎么办?
  3. softmax是对上面介绍的映射的误称(虽然深度学习领域中很多人都使用这个名字)。真正的softmax被定义为 R e a l S o f t M a x ( a , b ) = log ⁡ ( exp ⁡ ( a ) + exp ⁡ ( b ) ) \mathrm{RealSoftMax}(a, b) = \log (\exp(a) + \exp(b)) RealSoftMax(a,b)=log(exp(a)+exp(b))
    1. 证明 R e a l S o f t M a x ( a , b ) > m a x ( a , b ) \mathrm{RealSoftMax}(a, b) > \mathrm{max}(a, b) RealSoftMax(a,b)>max(a,b)
    2. 证明 λ − 1 R e a l S o f t M a x ( λ a , λ b ) > m a x ( a , b ) \lambda^{-1} \mathrm{RealSoftMax}(\lambda a, \lambda b) > \mathrm{max}(a, b) λ1RealSoftMax(λa,λb)>max(a,b)成立,前提是 λ > 0 \lambda > 0 λ>0
    3. 证明对于 λ → ∞ \lambda \to \infty λ,有 λ − 1 R e a l S o f t M a x ( λ a , λ b ) → m a x ( a , b ) \lambda^{-1} \mathrm{RealSoftMax}(\lambda a, \lambda b) \to \mathrm{max}(a, b) λ1RealSoftMax(λa,λb)max(a,b)
    4. soft-min会是什么样子?
    5. 将其扩展到两个以上的数字。

1 . 不确定答案
在这里插入图片描述

2 . 可以使用one-hot编码,需要的元素个数等于label数量

3 .
在这里插入图片描述

图像分类数据集

小结

  • Fashion-MNIST是一个服装分类数据集,由10个类别的图像组成。我们将在后续章节中使用此数据集来评估各种分类算法。
  • 我们将高度 h h h像素,宽度 w w w像素图像的形状记为 h × w h \times w h×w或( h h h, w w w)。
  • 数据迭代器是获得更高性能的关键组件。依靠实现良好的数据迭代器,利用高性能计算来避免减慢训练过程。

练习

  1. 减少batch_size(如减少到1)是否会影响读取性能?
  2. 数据迭代器的性能非常重要。你认为当前的实现足够快吗?探索各种选择来改进它。
  3. 查阅框架的在线API文档。还有哪些其他数据集可用?

  1. 会影响,batch_size越小,读取越慢
  2. 可以调节进程数
  3. torchvision可用数据集:https://pytorch.org/vision/stable/datasets.html

softmax回归的从零开始实现

小结

  • 借助softmax回归,我们可以训练多分类的模型。
  • 训练softmax回归循环模型与训练线性回归模型非常相似:先读取数据,再定义模型和损失函数,然后使用优化算法训练模型。大多数常见的深度学习模型都有类似的训练过程。

练习

  1. 在本节中,我们直接实现了基于数学定义softmax运算的softmax函数。这可能会导致什么问题?提示:尝试计算 exp ⁡ ( 50 ) \exp(50) exp(50)的大小。
  2. 本节中的函数cross_entropy是根据交叉熵损失函数的定义实现的。它可能有什么问题?提示:考虑对数的定义域。
  3. 你可以想到什么解决方案来解决上述两个问题?
  4. 返回概率最大的分类标签总是最优解吗?例如,医疗诊断场景下你会这样做吗?
  5. 假设我们使用softmax回归来预测下一个单词,可选取的单词数目过多可能会带来哪些问题?

  1. 数值稳定性问题,可能会导致上溢(overflow
    )。如果数值过大, e x p ( o ) exp(o) exp(o)可能会大于数据类型允许的最大数字,这将使分母或分子变为inf(无穷大),最后得到的是0、infnan(不是数字)的 y ^ j \hat y_j y^j

  2. 若最大的 y ^ \hat y y^的值极小,接近0,可能会导致 − l o g y ^ -log\hat y logy^的值过大,超出数据类型的范围。或出现下溢(underflow)问题,由于精度限制, y ^ \hat y y^四舍五入为0,并且使得 log ⁡ ( y ^ j ) \log(\hat y_j) log(y^j)的值为-inf
    反向传播几步后,可能会出现nan结果。

  3. 使用LogSumExp技巧。
    在继续softmax计算之前,先从所有 o k o_k ok中减去 max ⁡ ( o k ) \max(o_k) max(ok)
    可以看到每个 o k o_k ok按常数进行的移动不会改变softmax的返回值:

y ^ j = exp ⁡ ( o j − max ⁡ ( o k ) ) exp ⁡ ( max ⁡ ( o k ) ) ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) exp ⁡ ( max ⁡ ( o k ) ) = exp ⁡ ( o j − max ⁡ ( o k ) ) ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) . \begin{aligned} \hat y_j & = \frac{\exp(o_j - \max(o_k))\exp(\max(o_k))}{\sum_k \exp(o_k - \max(o_k))\exp(\max(o_k))} \\ & = \frac{\exp(o_j - \max(o_k))}{\sum_k \exp(o_k - \max(o_k))}. \end{aligned} y^j=kexp(okmax(ok))exp(max(ok))exp(ojmax(ok))exp(max(ok))=kexp(okmax(ok))exp(ojmax(ok)).

之后,将softmax和交叉熵结合在一起,如下面的等式所示,我们避免计算 exp ⁡ ( o j − max ⁡ ( o k ) ) \exp(o_j - \max(o_k)) exp(ojmax(ok))
而可以直接使用 o j − max ⁡ ( o k ) o_j - \max(o_k) ojmax(ok),因为 log ⁡ ( exp ⁡ ( ⋅ ) ) \log(\exp(\cdot)) log(exp())被抵消了。

log ⁡ ( y ^ j ) = log ⁡ ( exp ⁡ ( o j − max ⁡ ( o k ) ) ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) = log ⁡ ( exp ⁡ ( o j − max ⁡ ( o k ) ) ) − log ⁡ ( ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) = o j − max ⁡ ( o k ) − log ⁡ ( ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) . \begin{aligned} \log{(\hat y_j)} & = \log\left( \frac{\exp(o_j - \max(o_k))}{\sum_k \exp(o_k - \max(o_k))}\right) \\ & = \log{(\exp(o_j - \max(o_k)))}-\log{\left( \sum_k \exp(o_k - \max(o_k)) \right)} \\ & = o_j - \max(o_k) -\log{\left( \sum_k \exp(o_k - \max(o_k)) \right)}. \end{aligned} log(y^j)=log(kexp(okmax(ok))exp(ojmax(ok)))=log(exp(ojmax(ok)))log(kexp(okmax(ok)))=ojmax(ok)log(kexp(okmax(ok))).

  1. 返回概率最大的分类标签不总是最优解。一些情况下可能需要输出具体的概率值来辅助判断。

  2. 可能会造成单词之间概率差距不大,或概率过于接近0的情况。在计算过程中loss也会较高。

softmax回归的简洁实现

小结

  • 使用深度学习框架的高级API,我们可以更简洁地实现softmax回归。
  • 从计算的角度来看,实现softmax回归比较复杂。在许多情况下,深度学习框架在这些著名的技巧之外采取了额外的预防措施,来确保数值的稳定性。这使我们避免了在实践中从零开始编写模型时可能遇到的陷阱。

练习

  1. 尝试调整超参数,例如批量大小、迭代周期数和学习率,并查看结果。
  2. 增加迭代周期的数量。为什么测试精度会在一段时间后降低?我们怎么解决这个问题?

  1. 可能出现过拟合现象。可以观察一下精度的变化,若精度一直下降,则在合适的位置终止计算。

您可能感兴趣的与本文相关的镜像

TensorFlow-v2.9

TensorFlow-v2.9

TensorFlow

TensorFlow 是由Google Brain 团队开发的开源机器学习框架,广泛应用于深度学习研究和生产环境。 它提供了一个灵活的平台,用于构建和训练各种机器学习模型

动手学深度学习》的第二章主要围绕深度学习的预备知识展开,为后续章节的学习打下基础。该章内容涵盖了数据操作、数据预处理、线性代数、微积分、自动微分以及概率等关键领域,旨在帮助读者熟悉深度学习所需的数学与编程基础[^3]。 ### 数据操作 在数据操作部分,介绍了张量(Tensor)的基本操作,包括创建、索引、切片、运算符以及广播机制等。张量是深度学习中的核心数据结构,用于表示输入数据、模型参数和输出结果。通过掌握张量的操作,可以更高效地进行数据处理和模型训练。此外,还提到了内存优化的技巧,例如避免不必要的数据复制,从而提高程序的运行效率[^3]。 ### 数据预处理 数据预处理是深度学习中不可或缺的一环。该部分介绍了如何读取和处理数据集,包括处理缺失值、将数据转换为张量格式等。在实际应用中,原始数据往往存在缺失、噪声或格式不一致的问题,因此需要通过预处理步骤将其转化为模型可以处理的形式。例如,缺失值可以通过插值或删除的方式处理,类别型数据则可以通过独热编码等方式进行转换[^3]。 ### 线性代数 线性代数是深度学习的数学基础之一。该部分详细介绍了向量、矩阵的基本运算,包括点积、矩阵乘法、降维等操作。这些运算在神经网络中广泛应用于特征提取、权重更新等过程。此外,还提到了范数的概念,范数用于衡量向量或矩阵的大小,在正则化等技术中有着重要作用[^3]。 ### 微积分 微积分是理解神经网络优化算法的关键。该部分介绍了导数、梯度等基本概念,并讨论了它们在深度学习中的应用。梯度是损失函数对模型参数的偏导数组成的向量,表示了损失函数在参数空间中的变化方向。通过计算梯度,可以使用梯度下降法等优化算法来更新模型参数,使模型更好地拟合训练数据。 ### 自动微分 自动微分是深度学习框架的核心功能之一,能够自动计算复杂函数的导数。该部分通过简单的例子展示了如何使用PyTorch进行自动微分,包括标量和非标量变量的反向传播。在控制流的例子中,演示了如何设计一个带有条件判断和循环的函数,并计算其梯度。需要注意的是,当变量为非标量时,必须明确指定梯度的形状,否则会引发错误[^4]。 ### 概率 概率论在深度学习中扮演着重要角色,尤其是在处理不确定性问题时。该部分介绍了概率的基本概念,包括概率分布、期望、方差等。概率模型可以帮助我们更好地理解和建模数据的不确定性,从而提高模型的鲁棒性和泛化能力[^3]。 ### 课后练习 为了巩固所学内容,第二章还提供了丰富的课后练习,涵盖了各个小节的知识点。例如,练习中探讨了为什么计算二阶导数比一阶导数的开销更大,以及在运行反向传播函数之后再次运行会发生的错误原因。此外,还设计了一些与控制流相关的梯度计算问题,帮助读者深入理解自动微分的工作原理[^4]。 ### 代码示例 以下是一个简单的PyTorch代码示例,展示了如何进行张量操作和自动微分: ```python import torch # 创建一个张量并设置 requires_grad=True 以追踪其梯度 a = torch.randn(size=(), requires_grad=True) # 定义一个简单的函数 def f(a): b = a * 2 while b.exp() < 1000: b = b * 2 if b.sum() > 0: c = b else: c = 100 * b return c # 计算函数值 d = f(a) # 计算梯度 d.backward() # 输出梯度 print(a.grad) ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值