ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PyTorch Tensor教程:从创建、属性到实战操作的深度学习入门

PyTorch Tensor教程:从创建、属性到实战操作的深度学习入门 1. 为什么要从 Tensor 开始认识 PyTorch1.1 Tensor 是什么如果你接触过深度学习大概率听过这样一句话PyTorch 的一切操作都是围绕 Tensor张量展开的。Tensor 的中文翻译是“张量”。用一句话概括Tensor 是 PyTorch 中最基础的数据结构它用来存放数据既可以是标量、向量、矩阵也可以是更高维度的数组。你可以把 Tensor 简单理解为一个“支持 GPU 加速、能自动记录梯度、专门为深度学习设计的 NumPy 数组”。举个例子单个数字是 0 维张量标量一列数字是 1 维张量向量一个二维表格是 2 维张量矩阵一张彩色图片通常用 3 维张量表示比如(通道数, 高度, 宽度)一批彩色图片则是 4 维张量比如(批量大小, 通道数, 高度, 宽度)。在 PyTorch 中输入数据、网络权重、中间特征、梯度信息全部以 Tensor 的形式存储和流转。所以不管以后你是做 CV、NLP、推荐系统还是强化学习Tensor 都是绕不开的第一课。1.2 Tensor 与 NumPy 数组、Python 列表的区别很多刚入门的读者会问Python 有 listNumPy 有 ndarray为什么 PyTorch 还要设计一个 Tensor区别主要体现在三个层面设备支持NumPy 数组只能跑在 CPU 上Tensor 可以轻松地在 CPU 和 GPU 之间迁移。深度学习训练时数据量巨大GPU 并行计算能带来几十倍的加速这是 NumPy 无法直接提供的。自动求导Tensor 有一个关键属性requires_grad打开后 PyTorch 会自动记录张量上的所有运算并在反向传播时自动计算梯度。NumPy 没有这个能力。深度集成PyTorch 的神经网络层如nn.Linear、nn.Conv2d输入输出都要求是 Tensor整个生态都以 Tensor 为统一接口。当然Tensor 也保留了 NumPy 的很多优点比如支持向量化运算、广播机制、切片索引等。掌握 Tensor 之后你会发现在处理数据时比直接用 Python 列表高效得多。1.3 本文你能学到什么本文是 PyTorch 系列教程的第 1 课内容保持“概念 代码 经验”的结构读完你应该掌握Tensor 是什么适合什么场景如何在自己的电脑上搭建 PyTorch 运行环境创建 Tensor 的 6 种常用方式Tensor 的属性如何查看和使用Tensor 的索引、切片、形状变换、数学运算等基本操作一个包含数据生成、预处理、特征构建的完整小案例新手最容易踩的坑和工程实践建议。接下来我们先把环境准备好然后用大量可以直接复制的代码带你一步步认识 Tensor。2. 环境准备搭建 PyTorch 运行环境2.1 安装方式选择PyTorch 的安装方式很灵活你可以根据习惯选择使用 conda / miniforge 创建虚拟环境推荐直接使用 pip 安装使用 Docker 镜像。对于初学者我最推荐用虚拟环境来隔离项目依赖。因为深度学习项目往往需要不同的 PyTorch 版本和 Python 版本如果全部装在系统 Python 里很容易出现依赖冲突。如果你使用的是 Anaconda 或 Miniforge可以用下面的命令创建环境conda create -n pytorch_env python3.10 -y conda activate pytorch_env这里以 Python 3.10 为例具体版本可以根据你的项目需求调整。PyTorch 对 Python 版本的兼容性比较好3.8 到 3.12 都能覆盖大部分稳定版本。2.2 安装 PyTorch安装 PyTorch 最核心的一点是一定要到 PyTorch 官网的安装页生成你的专属命令因为官网会根据你的操作系统、包管理器、CUDA 版本实时给出推荐命令。需要注意PyTorch 安装命令中的 CUDA 版本和你电脑实际安装的显卡驱动不是一回事。简单理解如果你有 NVIDIA 显卡并希望用 GPU 训练需要安装对应 CUDA 版本的 PyTorch如果你没有 NVIDIA 显卡或者暂时只做 CPU 学习选择 CPU 版本即可AMD 显卡和 Apple Silicon 芯片也有对应的支持方式同样以官网获取的安装命令为准。下面给出的是一个没有 CUDA 的 CPU 版安装示例pip install torch torchvision torchaudio如果你需要用 GPU推荐到官网安装页选择自己的环境后复制命令这样可以避免版本不匹配。比如选择 Linux pip CUDA 12.1 时命令会类似于pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121由于 PyTorch 版本更新较快且不同版本对应的 wheel 链接可能变化不建议硬记命令每次安装都以官网生成的结果为准。2.3 验证安装是否成功在终端激活环境并启动 Python 交互界面输入以下代码import torch print(torch.__version__) print(torch.cuda.is_available())如果输出类似下面的内容说明 PyTorch 已经安装成功2.3.1 Falsetorch.__version__输出版本号torch.cuda.is_available()返回True表示当前环境可以使用 GPU返回False表示当前是 CPU 环境或 CUDA 配置不对。注意就算输出False也不要着急CPU 环境完全够用来学习本文的 Tensor 操作。真正需要 GPU 的时候再回头检查驱动和 CUDA 配置即可。3. 创建 Tensor 的六种核心方式创建 Tensor 是 PyTorch 中最频繁的操作之一。下面我按使用频率从高到低把常用的创建方法完整梳理一遍。3.1 从 Python 列表或 NumPy 数组创建最直接的方式是用torch.tensor()把已有的 Python 列表转换成一个 Tensorimport torch # 从列表创建 a torch.tensor([1, 2, 3]) print(a) # 从嵌套列表创建矩阵 b torch.tensor([[1, 2], [3, 4]]) print(b) # 指定数据类型 c torch.tensor([1.2, 3.4], dtypetorch.float32) print(c, c.dtype)输出结果tensor([1, 2, 3]) tensor([[1, 2], [3, 4]]) tensor([1.2000, 3.4000]) torch.float32需要注意torch.tensor()会复制数据生成的新 Tensor 和原始数据不再共享内存。如果你希望 Tensor 和 NumPy 数组共享内存可以用torch.from_numpy()import numpy as np arr np.array([1, 2, 3]) t torch.from_numpy(arr) t[0] 100 print(arr) # 输出 [100 2 3]arr 被同步修改了这个特性在数据处理时很有用可以避免不必要的内存拷贝但也容易引起“数据被偷偷改了”的困惑需要留心。3.2 全 0、全 1 与单位矩阵在深度学习中初始化权重、创建掩码、填充数据时经常需要全 0 或全 1 的矩阵。# 全 0 矩阵 zeros torch.zeros(2, 3) print(zeros) # 全 1 矩阵 ones torch.ones(3, 2) print(ones) # 单位矩阵 eye torch.eye(3) print(eye)输出结果tensor([[0., 0., 0.], [0., 0., 0.]]) tensor([[1., 1.], [1., 1.], [1., 1.]]) tensor([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])torch.zeros和torch.ones的第一个参数是形状shape可以传一个元组也可以传多个整数作为维度的尺寸。torch.eye只接受一个参数 n生成 n 行 n 列的单位矩阵。3.3 随机张量均匀分布与正态分布随机初始化是神经网络训练的基础操作PyTorch 提供了多种随机张量生成函数。# 均匀分布 [0, 1) uniform torch.rand(2, 3) print(uniform) # 标准正态分布 normal torch.randn(2, 3) print(normal) # 指定上下限的均匀分布 rand_int torch.randint(0, 10, (3, 3)) print(rand_int)输出结果每次运行会略有不同tensor([[0.2338, 0.6932, 0.9821], [0.7621, 0.1348, 0.8755]]) tensor([[ 0.3904, -0.1280, 1.0035], [ 0.0231, -0.8912, 0.5761]]) tensor([[3, 7, 0], [9, 2, 5], [4, 8, 1]])几个函数的记忆方法torch.randrandom 的缩写生成 0 到 1 之间的均匀随机数torch.randnnormal 的缩写生成均值为 0、方差为 1 的标准正态分布随机数torch.randint生成指定范围内的随机整数。随机种子在机器学习实验中非常重要后面第 8 节我会专门说如何设置随机种子保证结果可复现。3.4 等差数列与等间隔序列生成序列数据时torch.arange和torch.linspace非常常用。# 类似 range生成等差数列 a torch.arange(0, 10, 2) print(a) # 在 [0, 1] 区间生成 5 个等间隔数 b torch.linspace(0, 1, 5) print(b)输出结果tensor([0, 2, 4, 6, 8]) tensor([0.0000, 0.2500, 0.5000, 0.7500, 1.0000])torch.arange(start, end, step)生成从start开始到end结束不包含的等差数列步长为step。torch.linspace(start, end, steps)则在start和end之间均匀生成steps个数注意这里包含end本身。两者最直观的区别是arange关注步长linspace关注数量。3.5 指定形状与填充值有时候需要把一个固定值填充到指定形状的张量中比如初始化偏置为 0 或者常数。# 填充 7 full torch.full((2, 3), 7) print(full) # 生成一个未初始化的张量内容为内存中的随机值 empty torch.empty(2, 2) print(empty)输出结果tensor([[7, 7, 7], [7, 7, 7]]) tensor([[6.5738e-33, 4.5746e-41], [0.0000e00, 0.0000e00]])torch.full的用法很直观第一个参数是形状第二个参数是填充值。torch.empty不会对内存做初始化所以它的默认内容是什么都不确定。在实际项目中empty往往用于后续马上被覆盖赋值的情景避免多余的初始化开销。初学者不建议频繁使用容易产生莫名其妙的数值问题。3.6 创建张量时的设备与梯度设置上面创建的 Tensor 默认都在 CPU 上且关闭了梯度记录。但为了后续训练模型我们需要掌握两个额外参数。# 指定设备为 GPU如果可用 device torch.device(cuda if torch.cuda.is_available() else cpu) a torch.tensor([1, 2, 3], devicedevice) print(a.device) # 开启梯度记录 b torch.tensor([1.0, 2.0], requires_gradTrue) print(b.requires_grad)输出结果cuda:0 Truedevice决定数据在哪个设备上存储和计算requires_grad决定是否在后续运算中自动构建计算图。这两者会在训练神经网络时频繁出现现在先建立概念即可。4. Tensor 的核心属性详解创建好 Tensor 之后我们需要学会查看它的各种属性否则后续处理数据时会一头雾水。4.1 shape形状shape是 Tensor 最常用的属性表示每个维度的大小。x torch.rand(2, 3, 4) print(x.shape)输出结果torch.Size([2, 3, 4])这里的torch.Size([2, 3, 4])本质是一个元组表示这个 Tensor 是 3 维的第一维有 2 个元素第二维有 3 个元素第三维有 4 个元素。在深度学习框架中我们经常会看到一个叫“维度”的概念。比如全连接层的输入通常是 2 维张量(batch_size, feature_dim)卷积层的输入通常是 4 维张量(batch_size, channel, height, width)Transformer 的输入通常是 3 维张量(batch_size, seq_len, hidden_dim)。理解shape是理解一切张量操作的基础。4.2 ndim、size()、numel()除了shape还有几个高频属性需要掌握。x torch.rand(2, 3, 4) print(x.ndim) # 维度数量输出 3 print(x.size()) # 等价于 x.shape print(x.size(0)) # 第 0 维大小输出 2 print(x.numel()) # 元素总数 2*3*4 24输出结果3 torch.Size([2, 3, 4]) 2 24ndim返回维度数你可以把它理解为“这个张量有几层方括号”size()和shape等价numel()返回所有元素的数量常用于统计参数量或计算损失时进行归一化。4.3 dtype数据类型dtype表示 Tensor 中元素的类型。常见的类型包括torch.float32默认浮点类型深度学习中最常用torch.float64双精度浮点精度高但更慢、更占内存torch.int32、torch.int64整数类型torch.bool布尔类型a torch.tensor([1, 2, 3]) b torch.tensor([1.0, 2.0, 3.0]) print(a.dtype) # torch.int64 print(b.dtype) # torch.float32PyTorch 的默认整数类型是int64默认浮点类型是float32。这也是深度学习中最常见的配置。GPU 对float32的优化最好内存占用也更小。新手经常犯的一个错误是把整型 Tensor 和浮点型 Tensor 混在一起计算导致类型不匹配报错。建议在创建 Tensor 时就显式指定dtype或者通过.float()、.int()、.long()等方法转换。4.4 device设备device表示 Tensor 存储在 CPU 还是 GPU 上。cpu_tensor torch.rand(2, 2) gpu_tensor cpu_tensor.to(cuda) # 如果 GPU 可用 print(cpu_tensor.device) # cpu print(gpu_tensor.device) # cuda:0在训练过程中最常见的报错之一就是“device mismatch”一个 Tensor 在 CPU 上另一个在 GPU 上直接运算就会报错。后面排错章节会更详细展开。4.5 requires_grad自动梯度开关requires_grad是 PyTorch 自动求导的开关。当它为True时PyTorch 会记录这个张量上的所有操作并构建一个计算图之后可以通过反向传播计算梯度。x torch.tensor([2.0], requires_gradTrue) y x ** 2 y.backward() print(x.grad) # tensor([4.])上面代码中y x^2对x求导结果是2x 4PyTorch 正确计算出了梯度。这里我们只需要记住训练神经网络时网络权重.weight和.bias默认requires_gradTrue普通数据默认是False不需要手动修改除非你要实现自定义梯度逻辑。4.6 stride 与内存布局进阶stride是 Tensor 内存布局的重要概念它表示在每个维度上移动到下一个元素需要跨越的内存步长。x torch.rand(3, 4) print(x.stride()) # (4, 1)对于这样连续的二维张量第 0 维的步长是 4即跳过一行 4 个元素第 1 维的步长是 1。stride对张量性能影响很大因为非连续张量在运算时可能触发额外的拷贝。不过对初学者来说更重要的是知道transpose、permute等操作会改变内存布局导致张量变成“非连续”状态如果后面要强制改变形状需要用contiguous()先转回连续内存布局。5. Tensor 的基本操作入门5.1 索引与切片Tensor 的索引和切片与 NumPy 非常像甚至和 Python 列表也有相似之处。x torch.arange(12).reshape(3, 4) print(x)输出结果tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])接下来看几个常用操作print(x[0]) # 第 0 行 print(x[:, 1]) # 所有行的第 1 列 print(x[1:, :2]) # 从第 1 行开始前 2 列 print(x[-1]) # 最后一行输出结果tensor([0, 1, 2, 3]) tensor([1, 5, 9]) tensor([[4, 5], [8, 9]]) tensor([ 8, 9, 10, 11])切片返回的是原始 Tensor 的视图不是拷贝。也就是说修改切片结果会同步影响原始数据。如果需要独立副本要调用.clone()。5.2 形状变换view、reshape、transpose形状变换在实际开发中非常高频因为数据和网络层之间的形状常常需要对齐。x torch.arange(12) # view 改变形状 y x.view(3, 4) print(y) # reshape 改变形状 z x.reshape(2, 6) print(z)输出结果tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) tensor([[ 0, 1, 2, 3, 4, 5], [ 6, 7, 8, 9, 10, 11]])view只适用于内存连续的张量reshape更通用。如果view遇到不连续的张量会直接报错此时可以先调用.contiguous()再view。在新手阶段可以优先用reshape减少踩坑。再看一个转置操作x torch.rand(2, 3) print(x.shape) # torch.Size([2, 3]) y x.transpose(0, 1) print(y.shape) # torch.Size([3, 2])transpose(0, 1)交换第 0 维和第 1 维。需要注意transpose得到的是视图内存布局会变成非连续状态。如果之后要view改形状需要先.contiguous()。5.3 数学运算与广播机制Tensor 支持所有常见数学运算比如加减乘除、幂运算、指数和对数等。a torch.tensor([1, 2, 3], dtypetorch.float32) b torch.tensor([4, 5, 6], dtypetorch.float32) print(a b) # tensor([5., 7., 9.]) print(a - b) # tensor([-3., -3., -3.]) print(a * b) # tensor([ 4., 10., 18.]) print(a / b) # tensor([0.2500, 0.4000, 0.5000]) print(torch.pow(a, 2)) # tensor([1., 4., 9.]) print(torch.sqrt(a)) # tensor([1.0000, 1.4142, 1.7321])还有一个非常重要的机制叫“广播”Broadcasting。当两个张量形状不一致时PyTorch 会尝试自动扩展维度使它们可以运算。a torch.tensor([1, 2, 3]) b torch.tensor(10) print(a b) # tensor([11, 12, 13])标量10被广播到和[1, 2, 3]相同形状后再相加。再举个矩阵和向量的例子m torch.rand(2, 3) v torch.tensor([1, 2, 3]) # m 的形状是 (2, 3)v 的形状是 (3,)可以广播 print(m v)广播机制让代码更简洁但也容易让新手误判形状。如果两个张量形状完全不兼容PyTorch 会抛出 RuntimeError此时优先去检查维度是否对齐。5.4 拼接与拆分在处理批量数据或合并特征时拼接操作非常常见。a torch.tensor([[1, 2], [3, 4]]) b torch.tensor([[5, 6], [7, 8]]) # 按第 0 维拼接相当于上下拼接 c torch.cat([a, b], dim0) print(c.shape) # torch.Size([4, 2]) # 按第 1 维拼接相当于左右拼接 d torch.cat([a, b], dim1) print(d.shape) # torch.Size([2, 4])torch.stack和cat不同它会创建一个新的维度e torch.stack([a, b], dim0) print(e.shape) # torch.Size([2, 2, 2])cat拼接时不会增加维度stack会在指定位置新增一个维度。在实际项目里cat用于合并特征stack用于把多个样本堆叠成批次。拆分操作可以使用torch.chunk或torch.splitx torch.rand(4, 6) # 平均分成 2 块 chunks torch.chunk(x, chunks2, dim0) print(len(chunks)) # 2 # 按指定大小切分 splits torch.split(x, split_size_or_sections2, dim1) print(len(splits)) # 35.5 与 NumPy 互转及深浅拷贝PyTorch 和 NumPy 的互转非常方便。import numpy as np # Tensor 转 NumPy t torch.tensor([1, 2, 3]) arr t.numpy() print(arr, arr.dtype) # NumPy 转 Tensor arr2 np.array([4, 5, 6]) t2 torch.from_numpy(arr2) print(t2)输出结果[1 2 3] int64 tensor([4, 5, 6])需要特别注意的是t.numpy()和torch.from_numpy()生成的转换结果默认与原始对象共享内存。如果修改其中一个另一个也会变化。如果希望完全独立需要用.clone()或.copy()。t torch.tensor([1, 2, 3]) arr t.numpy() arr[0] 100 print(t) # tensor([100, 2, 3])6. 实战从数据到特征的完整 Tensor 流程6.1 场景描述学完基本操作后我们通过一个小案例把它们串起来。假设我们有一个身高和体重的数据列表需要计算 BMI 指数然后把数据归一化到 0 到 1 之间最后从张量中筛选出 BMI 正常范围18.5 到 24.9的样本并转换成 NumPy 数组用于后续存储。这个场景覆盖了创建 Tensor、类型转换、数学运算、索引筛选、NumPy 互转等高频操作。6.2 完整代码import torch # 1. 原始数据身高(m)体重(kg) heights [1.65, 1.75, 1.80, 1.60, 1.70] weights [55.0, 70.0, 82.0, 50.0, 68.0] # 2. 创建浮点 Tensor h torch.tensor(heights, dtypetorch.float32) w torch.tensor(weights, dtypetorch.float32) # 3. 计算 BMI 体重 / 身高^2 bmi w / (h ** 2) print(BMI:, bmi) # 4. 手动归一化 (x - min) / (max - min) bmi_min bmi.min() bmi_max bmi.max() bmi_norm (bmi - bmi_min) / (bmi_max - bmi_min) print(归一化 BMI:, bmi_norm) # 5. 筛选 BMI 正常范围样本 mask (bmi 18.5) (bmi 24.9) print(正常掩码:, mask) normal_bmi bmi[mask] print(正常 BMI 值:, normal_bmi) # 6. 转成 NumPy 数组 normal_bmi_np normal_bmi.numpy() print(NumPy 结果:, normal_bmi_np)6.3 运行结果与说明输出结果BMI: tensor([20.2020, 22.8571, 25.3086, 19.5312, 23.5294]) 归一化 BMI: tensor([0.1315, 0.6151, 1.0000, 0.0000, 0.7387]) 正常掩码: tensor([ True, True, False, True, True]) 正常 BMI 值: tensor([20.2020, 22.8571, 19.5312, 23.5294]) NumPy 结果: [20.20202 22.857143 19.53125 23.52941 ]这个例子虽然简单但你已经用上了 Tensor 的创建、计算、统计、掩码索引和 NumPy 转换。在真实项目中类似的数据预处理流程还会配合torch.utils.data.Dataset来完成那是后续教程要讲的内容。7. 常见问题与排查思路刚接触 PyTorch遇到报错是很正常的。把下面这些高频问题收藏起来能帮你减少很多排查时间。问题现象常见原因解决思路RuntimeError: Expected object of scalar type Long but got scalar type Float数据类型不匹配比如索引需要整数类型你传了浮点类型用.long()、.int()、.float()显式转换RuntimeError: Expected all tensors to be on the same device一个 Tensor 在 CPU另一个在 GPU直接参与运算将所有张量统一移动到同一设备使用.to(device)RuntimeError: view size is not compatible with input tensors size and stride对非连续张量使用view且新形状与内存布局冲突先调用.contiguous()再view或直接改用reshapeTensor在训练过程中梯度不断累积每个 batch 未清空梯度在每轮反向传播前调用optimizer.zero_grad().numpy()报错Tensor 的requires_gradTrue或当前在 GPU 上先.detach().cpu()再转 NumPy改了切片结果后原始 Tensor 也变了切片返回的是视图不是副本如果需要独立数据使用.clone()CUDA out of memoryGPU 显存不足减小 batch size、降低输入尺寸、清理不需要的中间变量、使用torch.no_grad()推理下面重点说两个最常见的问题。7.1 设备不一致报错在 GPU 环境下最常见的错误就是设备不一致# 模拟错误一个张量在 CPU一个在 GPU cpu_tensor torch.rand(3, 3) gpu_tensor torch.rand(3, 3, devicecuda) # 下面这行会报错 # result cpu_tensor gpu_tensor正确的做法是统一设备device torch.device(cuda if torch.cuda.is_available() else cpu) cpu_tensor cpu_tensor.to(device) result cpu_tensor gpu_tensor7.2 非连续张量的 view 报错# 创建一个连续张量 x torch.arange(12).reshape(3, 4) # 转置后变成非连续 y x.transpose(0, 1) # 下面这行可能报错 # y.view(12) # 正确做法 y y.contiguous() print(y.view(12))在编写模型时transpose、permute、squeeze、unsqueeze都可能改变内存布局遇到view报错时优先用.contiguous()修复。8. 最佳实践与工程建议8.1 明确 dtype 和 device在创建 Tensor 时尽量显式指定dtype和device。特别是在处理来自不同来源的数据时类型和设备的隐式转换可能带来性能损耗或直接报错。推荐统一使用浮点类型torch.float32这是 PyTorch 在深度学习中默认且优化最好的类型。整数做索引时用torch.int64即可。实际项目里建议封装一个设备工具函数import torch device torch.device(cuda if torch.cuda.is_available() else cpu) def to_device(data): if isinstance(data, torch.Tensor): return data.to(device) return data8.2 正确处理梯度和原地操作训练神经网络时有几个习惯可以尽早养成每轮反向传播前调用optimizer.zero_grad()否则梯度会累加推理阶段用torch.no_grad()包裹既省内存又提高速度对不需要梯度的数据可以设置requires_gradFalse或者用.detach()把张量从计算图中分离。另外在开启requires_grad的 Tensor 上尽量避免使用原地操作比如t 1或t.add_(1)。因为原地操作会修改变量的值而计算图记录的是操作历史这可能导致梯度计算错误。用非原地写法t t 1更安全。8.3 可复现性设置深度学习实验非常依赖随机初始化。为了结果可复现最好在脚本开头统一设置随机种子import random import numpy as np import torch def set_seed(seed42): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed)注意即使设置了随机种子由于 GPU 并行计算本身存在不确定性完全复现仍然有难度但设置种子能大幅降低实验之间的随机差异。8.4 内存管理与性能优化对于大张量有几个实用建议用.clone()或tensor.copy_()时要注意是否真的需要副本不必要的拷贝会浪费内存大批量数据不要一次性全部加载到内存推荐配合torch.utils.data.DataLoader分批读取中间变量如果不再使用Python 的垃圾回收会处理但在循环中显式删除大变量也能帮助释放显存如果显存不够优先减小 batch size而不是降低模型复杂度。8.5 编写可读代码Tensor 操作很容易写出一长串难以阅读的链式调用。推荐把复杂操作拆成小函数并加上类型注释。比如def normalize_tensor(x: torch.Tensor) - torch.Tensor: 将张量归一化到 [0, 1] 区间。 return (x - x.min()) / (x.max() - x.min())这样既方便复用也方便测试。9. 下一步学习路线到这里第 1 课的内容就算完整结束了。回顾一下你已经掌握了 PyTorch 中最核心的数据结构 Tensor如何创建、如何查看属性、如何做基本操作以及常见的坑和工程建议。但 Tensor 只是 PyTorch 的起点。要真正开始训练神经网络还有几个关键知识需要继续学习自动求导机制autograd是如何工作的计算图是什么梯度如何流动torch.nn模块如何搭建全连接网络、卷积网络、循环网络数据集与数据加载Dataset、DataLoader、数据增强训练循环损失函数、优化器、评估指标、模型保存与加载GPU 训练与分布式训练多卡训练常用技巧。如果你有自己的数据建议先拿一批小数据把“数据预处理 → 模型搭建 → 训练 → 评估”的完整流程跑通再逐步加深理论。亲手敲代码比只看教程有效得多遇到报错也可以去官方文档和社区搜索结合本文第 7 节的排错思路大部分问题都能很快定位。后续我会继续更新这个 PyTorch 系列教程下一课计划讲自动求导与线性回归实战帮助你完全理解梯度下降是如何在 PyTorch 中自动完成的。如果你在跟着实操时遇到问题欢迎在评论区留言我会根据大家反馈调整后续内容的侧重点。
返回列表