当前位置: 首页 > news >正文

【Pytorch】2025 Pytorch基础入门教程(完整详细版)

在这里插入图片描述
想搞定 PyTorch 核心操作?这份张量指南超实用!从创建、运算到梯度计算、模型保存全拆解,帮你快速夯实深度学习基础~📌点赞关注小编哦~

一、张量创建

1.1 基本创建方式

1)torch.tensor 根据指定数据创建张量 (最常用)
2)torch.Tensor 根据形状创建张量,其也可用来创建指定数据的张量
3)torch.IntTensor、torch.FloatTensor、torch.DoubleTensor 创建指定类型的张量

Tensor是PyTorch中最基础的数据结构,简单说就是多维矩阵,能借助GPU加速运算,是承载数据和运算的核心,其基本数据类型如下

数据类型CPU 张量(类型别名)GPU 张量(类型别名)备注(dtype 对应)
8位无符号整型(uint8)torch.ByteTensortorch.cuda.ByteTensor范围 0~255,对应 dtype=torch.uint8
8位有符号整型(int8)torch.CharTensortorch.cuda.CharTensor范围 -128~127,对应 dtype=torch.int8
16位有符号整型(int16)torch.ShortTensortorch.cuda.ShortTensor对应 dtype=torch.int16
32位有符号整型(int32)torch.IntTensortorch.cuda.IntTensor对应 dtype=torch.int32
64位有符号整型(int64)torch.LongTensortorch.cuda.LongTensor修正拼写错误,对应 dtype=torch.int64
16位浮点型(半精度,float16)torch.HalfTensortorch.cuda.HalfTensorGPU 加速常用,对应 dtype=torch.float16
32位浮点型(float32)torch.FloatTensortorch.cuda.FloatTensor对应 dtype=torch.float32(默认类型)
64位浮点型(float64)torch.DoubleTensortorch.cuda.DoubleTensor对应 dtype=torch.float64
布尔类型(bool)torch.BoolTensortorch.cuda.BoolTensor对应 dtype=torch.bool(Python 布尔映射)
import numpy as np
import torch# 1. 根据已有数据创建张量
def test01():# 1. 创建张量标量data = torch.tensor(10)print(data)# 2. numpy 数组,由于 data 为 float64,下面代码也使用该类型data = np.random.randn(2, 3)data = torch.tensor(data)print(data)# 3. 列表,下面代码使用默认元素类型 float32data = [[10., 20., 30.], [40., 50., 60.]]data = torch.tensor(data)print(data)print('-' * 50)# 2. 创建指定形状的张量
def test02():# 1. 创建2行3列的张量,默认dtype为float32data = torch.Tensor(2, 3)print(data)# 2. 注意:如果传递列表,则创建包含指定元素的张量data = torch.Tensor([10])print(data)data = torch.Tensor([10, 20])print(data)print('-' * 50)# 3. 使用具体类型的张量
def test03():# 1. 创建2行3列,dtype为int32的张量data = torch.IntTensor(2, 3)print(data)# 2. 注意:如果传递的元素类型不正确,则会进行类型转换data = torch.IntTensor([-2.5, -3.3])print(data)# 3. 其他的类型# data = torch.ShortTensor([2, 3])  # int16# data = torch.LongTensor([2, 3])    # int64# data = torch.FloatTensor([2.5, 3.3])  # float32# print(data)print('-' * 50)if __name__ == '__main__':test01()test02()test03()
# 运行结果
tensor(10)
tensor([[ 0.7219,  0.7726, -1.1605],[ 0.1611,  0.4240, -0.0588]], dtype=torch.float64)
tensor([[10., 20., 30.],[40., 50., 60.]])
--------------------------------------------------
tensor([[1.7608e+13, 1.2752e-42, 3.0000e+01],[4.0000e+01, 5.0000e+01, 6.0000e+01]])
tensor([10.])
tensor([10., 20.])
--------------------------------------------------
tensor([[1434459200,        910, 1056259574],[1075273419, 1062076309, 1059627882]], dtype=torch.int32)
tensor([-2, -3], dtype=torch.int32)

1.2 创建线性和随机张量

1)torch.arange 和 torch.linspace 创建线性张量
2)torch.random.init_seed 和 torch.random.manual_seed 随机种子设置

  • torch.random.initial_seed() 用于获取当前随机数生成器的初始种子值
    在没有手动设置随机种子的情况下,PyTorch 的随机数生成器会根据系统时钟等因素自动生成一个初始种子,调用这个函数就可以查看这个自动生成的种子值

  • torch.random.manual_seed(seed) 用于手动设置随机数生成器的种子
    当你设置了一个固定的种子值后,后续的随机数生成操作就会变得可复现,即每次运行代码,只要设置相同的随机种子,就会得到相同的随机数序列

3)torch.randn 创建随机张量

import torch# 1. 创建线性空间的张量
def test01():# 1. 在指定区间按照步长生成元素 [start, end, step)data = torch.arange(0, 10, 2)print(data)# 2. 在指定区间按照元素个数生成data = torch.linspace(0, 11, 10)print(data)# 2. 创建随机张量
def test02():# 1. 创建随机张量data = torch.randn(2, 3)  # 创建2行3列张量print(data)# 2. 随机数种子设置print('随机数种子:', torch.random.initial_seed())torch.random.manual_seed(100)print('随机数种子:', torch.random.initial_seed())# 3. 随机种子的复现作用测试
def test03():# 设置随机种子torch.random.manual_seed(100)# 创建一个随机初始化的张量tensor1 = torch.randn(3, 3)print("Tensor 1:\n", tensor1)# 再次设置相同的随机种子torch.random.manual_seed(100)# 再次创建一个随机初始化的张量tensor2 = torch.randn(3, 3)print("Tensor 2:\n", tensor2)if __name__ == '__main__':test01()#test02()#test03()

📌关于计算机中的随机数的原理?

  • 本质: 计算机中没有真随机数,全都是 伪随机数!!!
  • 伪随机数: 都是一个起始值,按照一系列确定的公式计算出来的值!!!
    • 为什么要给一个初始化种子(100)?就是给这个确定的起始值

1.3 创建 01张量

1)torch.ones 和 torch.ones_like 创建全1张量
2)torch.zeros 和 torch.zeros_like 创建全0张量
3)torch.full 和 torch.full_like 创建全为指定值张量

import torch# 1. 创建全0张量
def test01():# 1. 创建指定形状全0张量data = torch.zeros(2, 3)print(data)# 2. 根据张量形状创建全0张量data = torch.zeros_like(data)print(data)print('-' * 50)# 2. 创建全1张量
def test02():# 1. 创建指定形状全1张量data = torch.ones(2, 3)print(data)# 2. 根据张量形状创建全1张量data = torch.ones_like(data)print(data)print('-' * 50)# 3. 创建全为指定值的张量
def test03():# 1. 创建指定形状指定值的张量data = torch.full([2, 3], 10)print(data)# 2. 根据张量形状创建指定值的张量data = torch.full_like(data, 20)print(data)if __name__ == '__main__':test01()test02()test03()
# 运行结果
tensor([[0., 0., 0.],[0., 0., 0.]])
tensor([[0., 0., 0.],[0., 0., 0.]])
--------------------------------------------------
tensor([[1., 1., 1.],[1., 1., 1.]])
tensor([[1., 1., 1.],[1., 1., 1.]])
--------------------------------------------------
tensor([[10, 10, 10],[10, 10, 10]])
tensor([[20, 20, 20],[20, 20, 20]])

1.4 张量类型的转换

1)tensor.type(torch.DoubleTensor)
2)torch.double

import torchdef test():data = torch.full([2, 3], 10)print(data.dtype)# 将 data 元素类型转换为 float64 类型# 1. 第一种方法data = data.type(torch.DoubleTensor)print(data.dtype)# 转换为其他类型(示例,可按需取消注释使用)# data = data.type(torch.ShortTensor)# data = data.type(torch.IntTensor)# data = data.type(torch.LongTensor)# data = data.type(torch.FloatTensor)# 2. 第二种方法data = data.double()print(data.dtype)# 转换为其他类型(示例,可按需取消注释使用)data = data.short()print(data.dtype)data = data.int()print(data.dtype)data = data.long()print(data.dtype)data = data.float()print(data.dtype)if __name__ == "__main__":test()
# 运行结果
torch.int64
torch.float64
torch.float64
torch.int16
torch.int32
torch.int64
torch.float32

📌关于模型参数的精度?

  • np.random.randn() — 默认精度为 float64
  • torch.randn() — PyTorch中的浮点值默认精度为 float32
  • 混合精度训练: float32float16bfloat16 混合训练(节省显存)
  • DeepSeek-V3: float8 + float16 + float32 混合训练

二、张量数值运算

2.1 张量基本运算

基本运算中,包括 add、sub、mul、div、neg 等函数, 以及这些函数的带下划线的版本 add_、sub_、mul_、div_、neg_, 其中带下划线的版本为修改原数据

import numpy as np
import torchdef test():data = torch.randint(0, 10, [2, 3])print(data)print('-' * 50)# 1. 不修改原数据new_data = data.add(10)  # 等价 new_data = data + 10print(new_data)print(data)print('-' * 50)# 2. 直接修改原数据# 注意: 带下划线的函数为修改原数据本身data.add_(10)  # 等价 data += 10print(data)# 3. 其他函数print(data.sub(100))  #对张量 data 中的每个元素都减去 100print(data.mul(100))print(data.div(100))print(data.neg())print(data.abs())if __name__ == '__main__':test()
# 运行结果
tensor([[8, 7, 4],[6, 0, 1]])
--------------------------------------------------
tensor([[18, 17, 14],[16, 10, 11]])
tensor([[8, 7, 4],[6, 0, 1]])
--------------------------------------------------
tensor([[18, 17, 14],[16, 10, 11]])
tensor([[-82, -83, -86],[-84, -90, -89]])
tensor([[1800, 1700, 1400],[1600, 1000, 1100]])
tensor([[0.1800, 0.1700, 0.1400],[0.1600, 0.1000, 0.1100]])
tensor([[-18, -17, -14],[-16, -10, -11]])
tensor([[18, 17, 14],[16, 10, 11]])

2.2 阿达玛积

阿达玛积指的是矩阵对应位置的元素相乘

import numpy as np
import torchdef test():data1 = torch.tensor([[1, 2], [3, 4]])data2 = torch.tensor([[5, 6], [7, 8]])# 第一种方式data = torch.mul(data1, data2)print(data)print('-' * 50)# 第二种方式data = data1 * data2print(data)if __name__ == '__main__':test()
# 运行结果
tensor([[ 5, 12],[21, 32]])
--------------------------------------------------
tensor([[ 5, 12],[21, 32]])

2.3 点积运算

点积运算要求第一个矩阵 shape: (n, m),第二个矩阵 shape: (m, p), 两个矩阵点积运算 shape 为: (n, p)
运算符 @ 用于进行两个矩阵的点乘运算
torch.mm 用于进行两个矩阵点乘运算,要求输入的矩阵为 2 维
torch.bmm 用于批量进行矩阵点乘运算,要求输入的矩阵为 3 维

📌torch.matmul 对进行点乘运算的两矩阵形状没有限定.
a. 对于输入都是二维的张量相当于 mm 运算.
b. 对于输入都是三维的张量相当于 bmm 运算
c. 对数输入的 shape 不同的张量,对应的最后几个维度必须符合矩阵运算规则

import numpy as np
import torch# 1. 点积运算
def test01():data1 = torch.tensor([[1, 2], [3, 4], [5, 6]])data2 = torch.tensor([[5, 6], [7, 8]])# 第一种方式data = data1 @ data2print(data)print('-' * 50)# 第二种方式data = torch.mm(data1, data2)print(data)print('-' * 50)# 第三种方式data = torch.matmul(data1, data2)print(data)print('-' * 50)# 2. torch.mm 和 torch.matmul 的区别
def test02():# matmul 可以两个维度可以不同# 第一个张量: (3, 4, 5)# 第二个张量: (5, 4)# torch.mm 不可以相乘,而 matmul 则可以相乘print(torch.matmul(torch.randn(2, 3, 4, 5), torch.randn(1, 5, 4)).shape)# print(torch.matmul(torch.randn(5, 4), torch.randn(3, 4, 5)).shape)# print(torch.mm(torch.randn(3, 4, 5), torch.randn(5, 4)).shape)# print(torch.mm(torch.randn(5, 4), torch.randn(3, 4, 5)).shape)# 3. torch.mm 函数的用法(注:实际用的是 torch.bmm,这里注释可能笔误)
def test03():# 批量点积运算# 第一个维度为 batch_size# 矩阵的二三维要满足矩阵乘法规则data1 = torch.randn(3, 4, 5)data2 = torch.randn(3, 5, 8)data = torch.bmm(data1, data2)print(data.shape)if __name__ == '__main__':test01()  test02()  test03()
# 运行结果
tensor([[19, 22],[43, 50],[67, 78]])
--------------------------------------------------
tensor([[19, 22],[43, 50],[67, 78]])
--------------------------------------------------
tensor([[19, 22],[43, 50],[67, 78]])
--------------------------------------------------
torch.Size([2, 3, 4, 4])
torch.Size([3, 4, 8])

2.4 指定运行设备

PyTorch 默认会将张量创建在 CPU 控制的内存中, 即: 默认的运算设备为 CPU。我们也可以将张量创建在 GPU 上, 能够利用对于矩阵计算的优势加快模型训练。 将张量移动到 GPU 上有三种方法:

  1. 使用 cuda 方法 2. 直接在 GPU 上创建张量 3. 使用 to 方法指定设备
import torch# 1. 使用 cuda 方法
def test01():data = torch.tensor([10, 20, 30])print('存储设备:', data.device)# 如果安装的不是 gpu 版本的 PyTorch# 或电脑本身没有 NVIDIA 卡的计算环境# 下面代码可能会报错data = data.cuda()print('存储设备:', data.device)# 使用 cpu 函数将张量移动到 cpu 上data = data.cpu()print('存储设备:', data.device)# 输出结果:# 存储设备: cpu# 存储设备: cuda:0# 存储设备: cpu# 2. 直接将张量创建在 GPU 上
def test02():data = torch.tensor([10, 20, 30], device='cuda:0')print('存储设备:', data.device)# 使用 cpu 函数将张量移动到 cpu 上data = data.cpu()print('存储设备:', data.device)# 输出结果:# 存储设备: cuda:0# 存储设备: cpu# 3. 使用 to 方法
def test03():data = torch.tensor([10, 20, 30])print('存储设备:', data.device)data = data.to('cuda:0')print('存储设备:', data.device)# 输出结果:# 存储设备: cpu# 存储设备: cuda:0# 4. 存储在不同设备的张量不能运算
def test04():data1 = torch.tensor([10, 20, 30], device='cuda:0')data2 = torch.tensor([10, 20, 30])print(data1.device, data2.device)# RuntimeError: Expected all tensors to be on the same device,# but found at least two devices, cuda:0 and cpu!data = data1 + data2print(data)if __name__ == '__main__':test01()test02()test03()test04()

三、张量类型转换

3.1 张量转换为 numpy 数组

使用 Tensor.numpy 函数可以将张量转换为 ndarray 数组,但是共享内存,可以使用 copy 函数避免共享

# 1. 将张量转换为 numpy 数组
def test01():data_tensor = torch.tensor([2, 3, 4])# 使用张量对象中的 numpy 函数进行转换data_numpy = data_tensor.numpy()print(type(data_tensor))print(type(data_numpy))# 注意: data_tensor 和 data_numpy 共享内存# 修改其中的一个, 另外一个也会发生改变# data_tensor[0] = 100data_numpy[0] = 100print(data_tensor)print(data_numpy)# 2. 使用 torch.tensor 函数
def test02():data_numpy = np.array([2, 3, 4])data_tensor = torch.tensor(data_numpy)# numpy 和 tensor 不共享内存# data_numpy[0] = 100data_tensor[0] = 100print(data_tensor)print(data_numpy)# 3. 标量张量和数字的转换
def test03():# 当张量只包含一个元素时,可以通过 item 函数提取出该值data = torch.tensor([30, ])print(data.item())data = torch.tensor(30)print(data.item())# data1 = torch.tensor([1.55, 2.55])data1 = torch.tensor([1.55])print(data1.item())if __name__ == '__main__':test01()test02()test03()
<class 'torch.Tensor'>
<class 'numpy.ndarray'>
tensor([100,   3,   4])
[100   3   4]
tensor([100,   3,   4], dtype=torch.int32)
[2 3 4]
30
30
1.5499999523162842

📌Python代码中如何比较两个数的大小?

方法1: 直接比较(适用于整数/精确值)

if x == y:  print('hello world')  
else:  print('bad!')  

方法2: 浮点数差值比较(避免精度误差)

if (x - y) < 1e-6:  # 设定极小区间(如1e-6)  print('hello world')  
else:  print('bad!')  

四、张量拼接操作

张量的拼接操作在神经网络搭建过程中是非常常用的方法,例如:在后面将要学习到的残差网络、注意力机制中都使用到了张量拼接

4.1 torch.cat 函数的使用

import torchdef test01():data1 = torch.randint(0, 10, [3, 5, 4])data2 = torch.randint(0, 10, [3, 5, 4])print(data1)print(data2)print('-' * 50)# 1. 按0维度拼接new_data = torch.cat([data1, data2], dim=0)print(new_data.shape)print(new_data)print('-' * 50)# 2. 按1维度拼接new_data = torch.cat([data1, data2], dim=1)print(new_data.shape)print(new_data)print('-' * 50)# 3. 按2维度拼接new_data = torch.cat([data1, data2], dim=2)print(new_data.shape)print(new_data)print('-' * 50)'''new_data = torch.cat([data1, data2], dim=-1)print(new_data.shape)new_data = torch.cat([data1, data2], dim=-3)print(new_data.shape)'''def test02():data1 = torch.randint(0, 10, [2, 3])data2 = torch.randint(0, 10, [2, 3])# data2= torch.randint(0, 10, [2, 3, 4])print(data1)print(data2)new_data1 = torch.cat([data1, data2], dim=0)print('-----------------------------')new_data2 = torch.stack([data1, data2], dim=0)print(new_data1.shape)print(new_data2.shape)print(new_data1)print(new_data2)#print('-' * 50)# x = torch.Tensor([1])# y = torch.Tensor([2])# z = torch.stack([x, y],dim=0)# print(z)'''new_data = torch.stack([data1, data2], dim=1)print(new_data.shape)print(new_data)print('---------------------')new_data = torch.stack([data1, data2], dim=2)print(new_data.shape)print(new_data)'''if __name__ == '__main__':test01()  test02()
tensor([[[4, 9, 8, 2],[2, 7, 5, 0],[5, 0, 5, 0],[1, 7, 2, 4],[5, 6, 1, 3]],[[6, 3, 2, 9],[3, 5, 6, 8],[3, 8, 8, 6],[2, 2, 0, 8],[2, 1, 7, 4]],[[8, 0, 3, 6],[4, 6, 1, 6],[6, 3, 6, 6],[3, 1, 2, 6],[5, 5, 8, 1]]])
tensor([[[5, 9, 2, 6],[5, 3, 4, 5],[4, 3, 2, 6],[2, 9, 5, 0],[7, 9, 5, 0]],[[3, 7, 9, 0],[4, 2, 1, 5],[0, 4, 6, 1],[3, 3, 9, 4],[1, 1, 3, 0]],[[4, 5, 4, 6],[7, 6, 2, 0],[8, 4, 9, 5],[3, 9, 7, 1],[5, 8, 0, 2]]])
--------------------------------------------------
torch.Size([6, 5, 4])
tensor([[[4, 9, 8, 2],[2, 7, 5, 0],[5, 0, 5, 0],[1, 7, 2, 4],[5, 6, 1, 3]],[[6, 3, 2, 9],[3, 5, 6, 8],[3, 8, 8, 6],[2, 2, 0, 8],[2, 1, 7, 4]],[[8, 0, 3, 6],[4, 6, 1, 6],[6, 3, 6, 6],[3, 1, 2, 6],[5, 5, 8, 1]],[[5, 9, 2, 6],[5, 3, 4, 5],[4, 3, 2, 6],[2, 9, 5, 0],[7, 9, 5, 0]],[[3, 7, 9, 0],[4, 2, 1, 5],[0, 4, 6, 1],[3, 3, 9, 4],[1, 1, 3, 0]],[[4, 5, 4, 6],[7, 6, 2, 0],[8, 4, 9, 5],[3, 9, 7, 1],[5, 8, 0, 2]]])
--------------------------------------------------
torch.Size([3, 10, 4])
tensor([[[4, 9, 8, 2],[2, 7, 5, 0],[5, 0, 5, 0],[1, 7, 2, 4],[5, 6, 1, 3],[5, 9, 2, 6],[5, 3, 4, 5],[4, 3, 2, 6],[2, 9, 5, 0],[7, 9, 5, 0]],[[6, 3, 2, 9],[3, 5, 6, 8],[3, 8, 8, 6],[2, 2, 0, 8],[2, 1, 7, 4],[3, 7, 9, 0],[4, 2, 1, 5],[0, 4, 6, 1],[3, 3, 9, 4],[1, 1, 3, 0]],[[8, 0, 3, 6],[4, 6, 1, 6],[6, 3, 6, 6],[3, 1, 2, 6],[5, 5, 8, 1],[4, 5, 4, 6],[7, 6, 2, 0],[8, 4, 9, 5],[3, 9, 7, 1],[5, 8, 0, 2]]])
--------------------------------------------------
torch.Size([3, 5, 8])
tensor([[[4, 9, 8, 2, 5, 9, 2, 6],[2, 7, 5, 0, 5, 3, 4, 5],[5, 0, 5, 0, 4, 3, 2, 6],[1, 7, 2, 4, 2, 9, 5, 0],[5, 6, 1, 3, 7, 9, 5, 0]],[[6, 3, 2, 9, 3, 7, 9, 0],[3, 5, 6, 8, 4, 2, 1, 5],[3, 8, 8, 6, 0, 4, 6, 1],[2, 2, 0, 8, 3, 3, 9, 4],[2, 1, 7, 4, 1, 1, 3, 0]],[[8, 0, 3, 6, 4, 5, 4, 6],[4, 6, 1, 6, 7, 6, 2, 0],[6, 3, 6, 6, 8, 4, 9, 5],[3, 1, 2, 6, 3, 9, 7, 1],[5, 5, 8, 1, 5, 8, 0, 2]]])

📌torch.cat() 和 torch.stack() 的区别?

  • torch.cat():连接两个张量,指定维度(如dim=0),结果维度不变!!!
  • torch.stack():拼接两个张量,指定维度(如dim=0),结果维度+1(在指定dim上新增一个维度!!!)

五、张量索引操作

我们在操作张量时,经常需要去进行获取或者修改操作,掌握张量的花式索引操作是必须的一项能力

import torch# 1. 简单行、列索引
def test01(data):print("简单行、列索引:")print("第0行数据:", data[0])          # 获取第0行数据print("所有行的第0列数据:", data[:, 0])  # 获取所有行的第0列数据print('-' * 50)# 2. 列表索引
def test02(data):print("列表索引:")# 返回 (0, 1)、(1, 2) 两个位置的元素print("(0,1)和(1,2)位置元素:", data[[0, 1], [1, 2]])# 返回 0、1 行的 1、2 列共4个元素(二维索引)print("0-1行的1-2列元素:\n", data[[[0], [1]], [1, 2]])print('-' * 50)# 3. 范围索引
def test03(data):print("范围索引:")# 前3行的前2列数据(行:0-2,列:0-1)print("前3行前2列:\n", data[:3, :2])# 第2行到最后一行的前2列数据(行:2-末尾,列:0-1)print("第2行及以后的前2列:\n", data[2:, :2])print('-' * 50)# 4. 布尔索引
def test04(data):print("布尔索引:")# 第2列大于5的行数据print("第2列>5的行:\n", data[data[:, 2] > 5])# 第1行大于5的列数据print("第1行>5的列:", data[:, data[1] > 5])print('-' * 50)# 5. 多维索引(三维张量)
def test05():print("多维索引(三维张量):")# 创建3×4×5的三维随机整数张量(0-9)data = torch.randint(0, 10, [3, 4, 5])print("原始三维张量:\n", data)print("=" * 50)print("第0层的4×5矩阵:\n", data[0, :, :])  # 第0个维度全取print("每一层的第0行:\n", data[:, 0, :])    # 第1个维度取第0行print("每一层每一行的第0列:\n", data[:, :, 0])  # 第2个维度取第0列print("张量形状:", data.shape)print('-' * 50)if __name__ == '__main__':# 定义一个5行6列的二维张量(0-9随机整数),供test01-test04使用data_2d = torch.randint(0, 10, [5, 6])print("基础二维张量:\n", data_2d)print("=" * 50)# 依次调用索引测试函数(传入二维张量)test01(data_2d)test02(data_2d)test03(data_2d)test04(data_2d)# 测试三维张量索引(内部独立定义数据)test05()
# 运行结果
基础二维张量:tensor([[1, 1, 7, 9, 6, 3],[4, 7, 2, 1, 3, 4],[6, 6, 0, 9, 9, 6],[0, 2, 9, 6, 3, 1],[7, 4, 2, 6, 7, 4]])
==================================================
简单行、列索引:
第0行数据: tensor([1, 1, 7, 9, 6, 3])
所有行的第0列数据: tensor([1, 4, 6, 0, 7])
--------------------------------------------------
列表索引:
(0,1)(1,2)位置元素: tensor([1, 2])
0-1行的1-2列元素:tensor([[1, 7],[7, 2]])
--------------------------------------------------
范围索引:
前3行前2列:tensor([[1, 1],[4, 7],[6, 6]])2行及以后的前2列:tensor([[6, 6],[0, 2],[7, 4]])
--------------------------------------------------
布尔索引:
第2>5的行:tensor([[1, 1, 7, 9, 6, 3],[0, 2, 9, 6, 3, 1]])1>5的列: tensor([[1],[7],[6],[2],[4]])
--------------------------------------------------
多维索引(三维张量):
原始三维张量:tensor([[[4, 1, 8, 9, 7],[5, 4, 3, 3, 4],[2, 0, 8, 6, 3],[8, 7, 2, 7, 4]],[[8, 9, 1, 9, 7],[9, 6, 1, 1, 2],[2, 9, 7, 5, 8],[7, 7, 0, 9, 4]],[[6, 6, 3, 3, 1],[7, 6, 7, 1, 6],[3, 4, 2, 5, 2],[3, 5, 3, 0, 1]]])
==================================================0层的4×5矩阵:tensor([[4, 1, 8, 9, 7],[5, 4, 3, 3, 4],[2, 0, 8, 6, 3],[8, 7, 2, 7, 4]])
每一层的第0行:tensor([[4, 1, 8, 9, 7],[8, 9, 1, 9, 7],[6, 6, 3, 3, 1]])
每一层每一行的第0列:tensor([[4, 5, 2, 8],[8, 9, 2, 7],[6, 7, 3, 3]])
张量形状: torch.Size([3, 4, 5])

张量操作是 PyTorch 的基石,吃透这些能为深度学习项目铺路。趁热打铁,用这些知识开启你的 AI 开发实战吧!

六、张量形状操作

  • 学习目标

  • 掌握reshape, transpose, permute, view, contiguous, squeeze, unsqueeze等函数使用

  • 在我们后面搭建网络模型时,数据都是基于张量形式的表示,网络层与层之间很多都是以不同的 shape 的方式进行表现和运算,我们需要掌握对张量形状的操作,以便能够更好处理网络各层之间的数据连接

6.1 reshape 函数的用法

  • reshape 函数可以在保证张量数据不变的前提下改变数据的维度,将其转换成指定的形状,在后面的神经网络学习时,会经常使用该函数来调节数据的形状,以适配不同网络层之间的数据传递。
import torch
import numpy as npdef test():data = torch.tensor([[10, 20, 30], [40, 50, 60]])# 1、使用 shape 属性或者 size 方法都可以获得张量的形状print(data.shape, data.shape[0], data.shape[1])print(data.size(), data.size(0), data.size(1))# 2、使用 reshape 函数修改张量形状new_data = data.reshape(1, 6)print(new_data.shape)if __name__ == '__main__':test()
# 运行结果
torch.Size([2, 3]) 2 3
torch.Size([2, 3]) 2 3
torch.Size([1, 6])

6.2 transpose 和 permute 函数的使用

  • transpose 函数可以实现交换张量形状的指定维度,例如:一个张量的形状为 (2,3,4) 可以通过 transpose 函数把 3 和 4 进行交换,将张量的形状变为 (2,4,3)

  • 📌permute 函数可以一次交换更多的维度

import torch
import numpy as npdef test():data = torch.tensor(np.random.randint(0, 10, [3, 4, 5]))print('data shape:', data.shape)# 1、交换1和2维度new_data = torch.transpose(data, 1, 2)print('new_data shape:', new_data.shape)data[0,0,0] = 1000print("data:",data)print("new_data:", new_data)print("new_data shape:", new_data.size())print("="*50)# 2、将 data 的形状修改为 (4, 5, 3)new_data = torch.transpose(data, 0, 1)print('new_data shape:', new_data.shape)new_data = torch.transpose(new_data, 1, 2)print('new_data shape:', new_data.shape)print("="*50)# 3、使用 permute 函数将形状修改为 (4, 5, 3)new_data = torch.permute(data, [1, 2, 0])print('new_data shape:', new_data.shape)if __name__ == '__main__':test()
# 运行结果
data shape: torch.Size([3, 4, 5])
new_data shape: torch.Size([3, 5, 4])
data: tensor([[[1000,    4,    6,    0,    7],[   2,    4,    9,    6,    3],[   4,    8,    8,    9,    3],[   6,    6,    4,    6,    1]],[[   1,    4,    2,    0,    5],[   0,    0,    0,    7,    9],[   5,    0,    2,    2,    4],[   1,    2,    5,    6,    0]],[[   1,    2,    9,    1,    4],[   3,    2,    0,    7,    6],[   9,    5,    4,    2,    7],[   7,    9,    1,    1,    1]]], dtype=torch.int32)
new_data: tensor([[[1000,    2,    4,    6],[   4,    4,    8,    6],[   6,    9,    8,    4],[   0,    6,    9,    6],[   7,    3,    3,    1]],[[   1,    0,    5,    1],[   4,    0,    0,    2],[   2,    0,    2,    5],[   0,    7,    2,    6],[   5,    9,    4,    0]],[[   1,    3,    9,    7],[   2,    2,    5,    9],[   9,    0,    4,    1],[   1,    7,    2,    1],[   4,    6,    7,    1]]], dtype=torch.int32)
new_data shape: torch.Size([3, 5, 4])
==================================================
new_data shape: torch.Size([4, 3, 5])
new_data shape: torch.Size([4, 5, 3])
==================================================
new_data shape: torch.Size([4, 5, 3])

6.3 view 和 contigous 函数的用法

  • 📌 view 函数也可以用于修改张量的形状,但是其用法比较局限,只能用于存储在整块内存中的张量。在 PyTorch 中,有些张量是由不同的数块组成的,它们并没有存储在整块的内存中,view 函数无法对这样的张量进行变形处理。例如一个张量经过了 transpose 或者 permute 函数的处理之后,就无法使用 view 函数进行形状操作
import torch
import numpy as npdef test():data = torch.tensor([[10, 20, 30], [40, 50, 60]])print('data shape:', data.shape)# 1、使用 view 函数修改形状new_data = data.view(3, 2)print('new_data shape:', new_data.shape)# 2、判断张量是否使用整块内存print('data:', data.is_contiguous())  # True# 3、使用 transpose 函数修改形状new_data = torch.transpose(data, 0, 1)print('new_data:', new_data.is_contiguous())  # Falseprint("="*50)# new_data = new_data.view(2, 3)  # RuntimeErrornew_data = new_data.reshape(2,3)print('new_data.shape:',new_data.shape)print(new_data.is_contiguous())print("="*50)# 需要先使用 contiguous 函数转换为整块内存的张量,再使用 view 函数print('new_data.contiguous():', new_data.contiguous().is_contiguous())new_data = new_data.contiguous().view(2, 3)print('new_data shape:', new_data.shape)if __name__ == '__main__':test()
# 运行结果
data shape: torch.Size([2, 3])
new_data shape: torch.Size([3, 2])
data: True
new_data: False
==================================================
new_data.shape: torch.Size([2, 3])
True
==================================================
new_data.contiguous(): True
new_data shape: torch.Size([2, 3])

6.4 squeeze 和 unsqueze 函数的用法

  • squeeze 函数用于删除 shape 为 1 的维度,unsqueeze 在指定维度添加 1,以增加数据的形状。
import torch
import numpy as npdef test():data = torch.tensor(np.random.randint(0, 10, [1, 3, 1, 5]))print('data shape:', data.size())# 1、去掉值为1的维度new_data = data.squeeze()print('new_data shape:', new_data.size())  # torch.Size([3, 5])# 2、去掉指定位置为1的维度,注意:如果指定位置不是1则不删除new_data = data.squeeze(2)print('new_data shape:', new_data.size())  # torch.Size([3, 5])# 3、在2维度增加一个维度(原代码中维度索引为 -1 ,即最后一维)new_data = data.unsqueeze(-1)print('new_data shape:', new_data.size())  # torch.Size([1, 3, 1, 5, 1])if __name__ == '__main__':test()
# 运行结果
data shape: torch.Size([1, 3, 1, 5])
new_data shape: torch.Size([3, 5])
new_data shape: torch.Size([1, 3, 5])
new_data shape: torch.Size([1, 3, 1, 5, 1])

七、 张量运算函数

  • 学习目标
  • 掌握张量相关运算函数

7.1 常见运算函数

  • PyTorch 为每个张量封装很多实用的计算函数,例如计算均值、平方根、求和等等
import torchdef test():data = torch.randint(0, 10, [2, 3], dtype=torch.float64)print(data)print('-' * 50)# 1. 计算均值  print(data.mean())  print(data.mean(dim=0))  # 📌 按列计算均值  print(data.mean(dim=1))  # 📌 按行计算均值  print('-' * 50)  # 2. 计算总和  print(data.sum())  print(data.sum(dim=0))  print(data.sum(dim=1))  print('-' * 50)  # 3. 计算平方  print(data.pow(2))  print('-' * 50)  # 4. 计算平方根  print(data.sqrt())  print('-' * 50)  # 5. 指数计算,e^n 次方  print(data.exp())  print('-' * 50)  # 6. 对数计算  print(data.log())    # 以 e 为底  print(data.log10())  print(data.log2())  if __name__ == '__main__':  test()  
# 运行结果
tensor([[2., 7., 1.],[0., 1., 3.]], dtype=torch.float64)
--------------------------------------------------
tensor(2.3333, dtype=torch.float64)
tensor([1., 4., 2.], dtype=torch.float64)
tensor([3.3333, 1.3333], dtype=torch.float64)
--------------------------------------------------
tensor(14., dtype=torch.float64)
tensor([2., 8., 4.], dtype=torch.float64)
tensor([10.,  4.], dtype=torch.float64)
--------------------------------------------------
tensor([[ 4., 49.,  1.],[ 0.,  1.,  9.]], dtype=torch.float64)
--------------------------------------------------
tensor([[1.4142, 2.6458, 1.0000],[0.0000, 1.0000, 1.7321]], dtype=torch.float64)
--------------------------------------------------
tensor([[7.3891e+00, 1.0966e+03, 2.7183e+00],[1.0000e+00, 2.7183e+00, 2.0086e+01]], dtype=torch.float64)
--------------------------------------------------
tensor([[0.6931, 1.9459, 0.0000],[  -inf, 0.0000, 1.0986]], dtype=torch.float64)
tensor([[0.3010, 0.8451, 0.0000],[  -inf, 0.0000, 0.4771]], dtype=torch.float64)
tensor([[1.0000, 2.8074, 0.0000],[  -inf, 0.0000, 1.5850]], dtype=torch.float64)

八、 自动微分模块

  • 学习目标

  • 掌握梯度计算

  • 自动微分(Autograd)模块对张量做了进一步的封装,具有自动求导功能。自动微分模块是构成神经网络训练的必要模块,在神经网络的反向传播过程中,Autograd 模块基于正向计算的结果对当前的参数进行微分计算,从而实现网络权重参数的更新

8.1 梯度基本计算

我们使用 backward 方法、grad 属性来实现梯度的计算和访问。

import torch  # 1. 单标量梯度的计算  
# y = x**2 + 20  
def test01():  # 定义需要求导的张量  # 张量的类型必须是浮点类型  x = torch.tensor(10, requires_grad=True, dtype=torch.float64)  # 变量经过中间计算  f = x ** 2 + 20  # 自动微分  f.backward()  # 打印 x 变量的梯度  # backward 函数计算的梯度值会存储在张量的 grad 属性中  print(x.grad)  # 2. 单向量梯度的计算  
# y = x**2 + 20  
def test02():  # 定义需要求导张量  x = torch.tensor([10, 20, 30, 40], requires_grad=True, dtype=torch.float64)  f1 = x ** 2 + 20  # 注意:  # 由于求导的结果必须是标量  # 而 f1 的结果是: tensor([120., 420., ...])  # 所以,不能直接自动微分  # 需要将结果计算为标量才能进行计算  f2 = f1.mean()  # f2 = 1/2 * x  # 自动微分  f2.backward()  # 打印 x 变量的梯度  print(x.grad)  if __name__ == '__main__':  test01()  test02()  # 若需测试可取消注释  
# 运行结果
tensor(20., dtype=torch.float64)
tensor([5., 10., 15., 20.], dtype=torch.float64)

8.2 控制梯度计算

  • 我们可以通过一些方法使得在 requires_grad=True 的张量在某些时候计算不进行梯度计算。
##### 1. 控制不计算梯度  def test01():  x = torch.tensor(10, requires_grad=True, dtype=torch.float64)  print(x.requires_grad)  # 第一种方式:对代码进行装饰  with torch.no_grad():  y = x ** 2  print(y.requires_grad)  # 第二种方式:对函数进行装饰  @torch.no_grad()  def my_func(x):  return x ** 2  print(my_func(x).requires_grad)  # 第三种方式  torch.set_grad_enabled(False)  y = x ** 2  print(y.requires_grad)  # 2. 注意:累计梯度
def test02():  # 定义需要求导张量  x = torch.tensor([10., 20., 30., 40.], requires_grad=True, dtype=torch.float64)  for _ in range(3):  f1 = x ** 2 + 20  f2 = f1.mean()  print(f'f2=', f2)  # 默认张量的 grad 属性会累计历史梯度值  # 所以,需要我们每次手动清理上次的梯度  # 注意:一开始梯度不存在,需要做判断  if x.grad is not None:  x.grad.data.zero_()  f2.backward()  print(x.grad)  print('-' * 50)  # 3. 梯度下降优化最优解  
def test03():  # y = x**2  x = torch.tensor(10., requires_grad=True, dtype=torch.float64)  count = 0  for _ in range(50000):  # 正向计算  f = x ** 2  # 梯度清零  if x.grad is not None:  x.grad.data.zero_()  # 反向传播计算梯度  f.backward()  # 更新参数 (variable) data: Tensor | Any  x.data = x.data - 0.001 * x.grad  count += 1  if count % 500 == 0:  print(f'{count:10} {x.data}')  if __name__ == '__main__':  # test01()  # test02()  test03()  if __name__ == '__main__':  test01()  

九、模型的保存加载

  • 学习目标
  • 掌握PyTorch保存模型的方法
  • 神经网络的训练有时需要几天、几周,甚至几个月,为了在每次使用模型时避免高代价的重复训练,我们就需要将模型序列化到磁盘中,使用的时候反序列化到内存中

9.1 保存模型参数

import torch  
import torch.nn as nn  # 假设我们有一个模型  
class SimpleModel(nn.Module):  def __init__(self):  super(SimpleModel, self).__init__()  self.fc = nn.Linear(10, 1)  def forward(self, x):  return self.fc(x)  model = SimpleModel()  # 📌保存模型的参数  
torch.save(model.state_dict(), 'model_weights.pth')  

9.2 保存全部模型

import torch  
import torch.nn as nn  # 假设我们有一个模型  
class SimpleModel(nn.Module):  def __init__(self):  super(SimpleModel, self).__init__()  self.fc = nn.Linear(10, 1)  def forward(self, x):  return self.fc(x)  model = SimpleModel()  # 保存全部模型  
torch.save(model, 'model.pth')  

9.3 加载模型参数

# 创建一个与保存时相同结构的模型  
model = SimpleModel()  # 加载模型的参数  
model.load_state_dict(torch.load('model_weights.pth'))  
print(model)  # 保存模型的参数  
# torch.save(model.state_dict(), 'model_weights.pth')  
# print(model)  
# print('---------------------')  
# print(model.state_dict())  # 保存完整的模型  
# torch.save(model, 'model_weights_1.pth')  
# print(model)  

9.4 加载全部模型

model = torch.load('model.pth')  
print(model)  

9.5 注意事项

  • 模型结构:如果你只保存了模型的参数,那么在加载时需要确保你有与保存时相同的模型结构
  • 设备兼容性:如果你在一个设备上保存了模型(例如GPU),而在另一个设备上加载(例如CPU),你可能需要使用 map_location 参数来指定设备:
    device = torch.device('cpu')  
    model.load_state_dict(torch.load('model_weights.pth', map_location=device))  
    

📌吃透这些技巧,PyTorch 开发难题迎刃而解,让模型训练更顺畅,助你在 AI 实践中快速进阶!


文章转载自:

http://SHki5k46.jqswf.cn
http://fl2AQhd0.jqswf.cn
http://Enq8WvMX.jqswf.cn
http://SMNbN3nu.jqswf.cn
http://fDIfYM6t.jqswf.cn
http://PfyHAYyL.jqswf.cn
http://um4G3VxF.jqswf.cn
http://DZjX8fwG.jqswf.cn
http://BVJfIiK3.jqswf.cn
http://Sti2yHbO.jqswf.cn
http://B9rvlHbe.jqswf.cn
http://2RJHvjN3.jqswf.cn
http://f5eXYSnL.jqswf.cn
http://FrEiKFKc.jqswf.cn
http://mTusvVuk.jqswf.cn
http://UFOAJeLZ.jqswf.cn
http://QmfHb1yt.jqswf.cn
http://UKWW2w1H.jqswf.cn
http://OpaSkVQd.jqswf.cn
http://e5RQjXRe.jqswf.cn
http://TM8kDOF9.jqswf.cn
http://LpOx14H0.jqswf.cn
http://eRVXAjOP.jqswf.cn
http://z04N0M5Z.jqswf.cn
http://U53azKIm.jqswf.cn
http://J7WfPVUS.jqswf.cn
http://omWWAVup.jqswf.cn
http://iq7ugIe9.jqswf.cn
http://cB54ENfy.jqswf.cn
http://DpUrJwZf.jqswf.cn
http://www.dtcms.com/a/375917.html

相关文章:

  • Cookie 与 Session 的关系详解
  • Java微服务架构拆分:边界原则的实战破局与多场景案例解析
  • expect脚本详解
  • 交通识别摄像头以及带AI算法
  • SpringMVC通过注解实现全局异常处理
  • Linux基础知识(四)
  • 向量化与嵌入模型:RAG系统背后的隐形英雄
  • 你知道zip()和zip(*)怎么用吗?
  • 工业领域企业CRM常用的有哪些系统?
  • Git cherry-pick 与分支重置技术实现代码健全性保障下的提交记录精简
  • 【Nginx 运维实战】版本替换:强制 vs 平滑升级全解析
  • HTTPS加解密流程解析
  • Android 升级minSdkVersion 导致 包体积变大的处理
  • Linux系统 Python3.12版本连接达梦数据库dmPython和django_dmPython
  • 零知开源——ESP32驱动OV7670摄像头实现简易照相机系统
  • 前端开发工具trae的使用
  • Coze源码分析-资源库-创建插件-前端源码-核心组件
  • 数据集成平台怎么选?从ETL到CDC再到iPaaS的全景对比
  • 【Linux基础】Linux系统配置IP详解:从入门到精通
  • 2025版基于springboot的企业考勤管理系统
  • 【计算机毕业设计选题】2025-2026年计算机毕业设计选题经验与项目推荐
  • Python数据处理管道完全指南:从基础到高并发系统实战
  • VMware安装CentOS 7教程
  • SpringBoot + MinIO/S3 文件服务实现:FileService 接口与 FileServiceImpl 详解
  • 如何确定丝杆升降机的额定负载和峰值负载?
  • AI 与 Web3 技术写作大赛,瓜分 2000RMB
  • git 合并多条commit
  • 联邦学习指导、代码、实验、创新点
  • 开源 C++ QT Widget 开发(十五)多媒体--音频播放
  • 绿算技术闪耀智博会 赋能乡村振兴与产业升级