DL 1 深度学习简介 张量tensor操作

1.深度学习简介

学习视频:https://www.bilibili.com/video/BV1c5yrBcEEX/?spm_id_from=333.337.search-card.all.click&vd_source=0a4fe9884700974ee1043a65993f87fb

1.1 概念

  • 深度学习是机器学习的一类算法, 以人工神经网络为结构, 可以实现自动提取特征
  • 深度学习核心思想是人工神经网络为结构, 自动提取特征

1.2 特点

  • 自动提取特征
  • 可解释性差
  • 大量数据和高性能计算能力
  • 非线性转换(引入非线性因素)

1.3 深度学习模型

  • ANN 人工神经网络 感知机

  • CNN 卷积神经网络 图像/视频

  • RNN 循环神经网络 NLP

  • transformer RNN衍生出来的

  • 自编学习器

  • ...

1.4 深度学习应用场景

  • 自然语言处理NLP
    • 生成式AI AIGC 大模型
    • 机器翻译
    • 语音识别
    • ...
  • 计算机视觉CV
    • 图像识别
    • 面部解锁
    • 视频合成
    • ...
  • 推荐系统
    • 电影
    • 音乐
    • 文章
    • 视频
    • 商品
  • 多模态大模型

2. PyTorch框架简介

  • pytorch是深度学习的框架, python的第三方包, 数据是以张量类型存在
  • pytorch特点
    • 数据类型是张量类型
    • 自动微分模块, 自动求导/梯度
    • 可以在GPU/TPU/NPU上运行, 加速运行
    • 兼容各种平台 系统/硬件(显卡)

3. 张量tensor

3.1 什么是张量

  • 张量是矩阵, 可以是多维
    • 0维->标量
    • 1维->[1 2 3 4 5]
    • 2维->[[1 2 3],[4 5 6]]
    • 3维...
  • 张量是通过类创建出来的对象, 提供各种方法和属性

3.2 张量的创建

  • 方法一:torch.tensor(data=, dtype=):指定数据(常用)
点击查看代码
    t1 = torch.tensor(10) #
    print(f't1:{t1}, type:{type(t1)}')
    data = [[1, 2, 3], [4, 5, 6]]
    t2 = torch.tensor(data, dtype=torch.float)
    print(f't2:{t2}, type:{type(t2)}')
    data = np.random.randint(0, 10, size = (2, 3))
    t3 = torch.tensor(data)
    print(f't3:{t3}, type:{type(t3)}')
    # 错误示例
    # t4 = torch.tensor(2, 3)
结果
t1:10, type:<class 'torch.Tensor'>
t2:tensor([[1., 2., 3.],[4., 5., 6.]]), type:<class 'torch.Tensor'>
t3:tensor([[7, 9, 2],[5, 4, 1]], dtype=torch.int32), type:<class 'torch.Tensor'>
  • 方法二:torch.Tensor(data=, size=):指定数据或形状
点击查看代码
    t1 = torch.Tensor(10)
    print(f't1:{t1}, type:{type(t1)}')
    data = [[1, 2, 3], [4, 5, 6]]
    t2 = torch.Tensor(data)
    print(f't2:{t2}, type:{type(t2)}')
    data = np.random.randint(0, 10, size = (2, 3))
    t3 = torch.Tensor(data)
    print(f't3:{t3}, type:{type(t3)}')
    t5 = torch.Tensor(2, 3)
    print(f't5:{t5}, type:{type(t5)}')
结果
t1:tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]), type:<class 'torch.Tensor'>
t2:tensor([[1., 2., 3.],[4., 5., 6.]]), type:<class 'torch.Tensor'>
t3:tensor([[8., 2., 9.],[0., 1., 6.]]), type:<class 'torch.Tensor'>
t5:tensor([[0., 0., 0.],[0., 0., 0.]]), type:<class 'torch.Tensor'>
  • 方法三:torch.IntTensor(data=,)/FloatTensor()/...:指定数据
点击查看代码
    t1 = torch.IntTensor(10)
    print(f't1:{t1}, type:{type(t1)}')
    data = [[1, 2, 3], [4, 5, 6]]
    t2 = torch.IntTensor(data)
    print(f't2:{t2}, type:{type(t2)}')
    data = np.random.randint(0, 10, size = (2, 3))
    t3 = torch.IntTensor(data)
    print(f't3:{t3}, type:{type(t3)}')
    data = np.random.randint(0, 10, size = (2, 3))
    t4 = torch.FloatTensor(data)
    print(f't4:{t4}, type:{type(t4)}')
结果
t1:tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=torch.int32), type:<class 'torch.Tensor'>
t2:tensor([[1, 2, 3],[4, 5, 6]], dtype=torch.int32), type:<class 'torch.Tensor'>
t3:tensor([[6, 9, 4],[5, 7, 4]], dtype=torch.int32), type:<class 'torch.Tensor'>
t4:tensor([[9., 2., 3.],[0., 6., 3.]]), type:<class 'torch.Tensor'>

3.3 线性和随机张量

3.3.1 线性张量
  • 方法一:torch.arrange(start=, end=, step=):创建指定步长的线性张量 左闭右开
    • step: 步长, 默认1
  • 方法二:torch.linspace(start=, end=, steps=):创建指定元素个数的线性张量 左闭右闭
    • steps: 元素个数
点击查看代码
  t1 = torch.arange(0, 10, 2)
  print(f't1:{t1}, type:{type(t1)}')
  t2 = torch.linspace(1, 10, 5)
  print(f't2:{t2}, type:{type(t2)}')
结果
t1:tensor([0, 2, 4, 6, 8]), type:<class 'torch.Tensor'>
t2:tensor([ 1.0000,  3.2500,  5.5000,  7.7500, 10.0000]), type:<class 'torch.Tensor'>
3.3.2 随机张量
  • 方法1:torch.rand(size=)/randn(size=):创建指定形状的随机浮点类型张量
  • 方法2:torch.randint(low=, high=, size=):创建指定形状指定范围随机整数类型张量 左闭右开
  • torch.initial_seed(): 查看随机种子数
    torch.manual_seed(seed=): 设置随机种子数
点击查看代码
  # torch.initial_seed()
  torch.manual_seed(3)
  t1 = torch.rand(size=(2,3))
  print(f't1:{t1}, type:{type(t1)}')
  t2 = torch.randn(size=(2, 3))
  print(f't2:{t2}, type:{type(t2)}')
  t3 = torch.randint(0, 10, size=(2, 3))
  print(f't3:{t3}, type:{type(t3)}')
结果
t1:tensor([[0.0043, 0.1056, 0.2858],[0.0270, 0.4716, 0.0601]]), type:<class 'torch.Tensor'>
t1:tensor([[ 0.4220,  0.2569, -2.3869],[-0.5047,  1.0230,  1.0523]]), type:<class 'torch.Tensor'>
t1:tensor([[6, 5, 4],[1, 6, 3]]), type:<class 'torch.Tensor'>

3.4 0/1/指定值张量

  • 全1
    • torch.ones(size=): 根据形状创建全1张量
    • torch.ones_like(input=): 根据指定张量的形状创建全1张量
  • 全0
    • torch.zeros(size=): 根据形状创建全0张量
    • torch.zeros_like(input=): 根据指定张量的形状创建全0张量
  • 指定值
    • torch.full(size=, fill_value=): 根据形状和指定值创建指定值的张量
    • torch.full_like(input=, fill_value=): 根据指定张量形状和指定值创建指定值的张量
点击查看代码
    t1 = torch.ones(2, 3)
    print(f't1:{t1}, type:{type(t1)}')
    t2 = torch.tensor([[1, 2], [3, 4], [5, 6]])
    t3 = torch.ones_like(t2)
    print(f't3:{t3}, type:{type(t3)}')
    t4 = torch.full(size=(2, 3), fill_value=255)
    print(f't4:{t4}, type:{type(t4)}')
    t5 = torch.full_like(t2, fill_value=255)
    print(f't5:{t5}, type:{type(t5)}')
结果
t1:tensor([[1., 1., 1.],[1., 1., 1.]]), type:<class 'torch.Tensor'>
t3:tensor([[1, 1],[1, 1],[1, 1]]), type:<class 'torch.Tensor'>
t4:tensor([[255, 255, 255],[255, 255, 255]]), type:<class 'torch.Tensor'>
t5:tensor([[255, 255],[255, 255],[255, 255]]), type:<class 'torch.Tensor'>

3.5 指定元素类型张量

  • 方法1:torch.tensor(data=, dtype=)
  • 方法2:tensor.type(dtype=): 修改张量元素类型(常用)
    • dtype=torch.float32/torch.FloatTensor/torch.cuda.FloatTensor/...
  • 方法3:tensor.half()/float()/double()/short()/int()/long()
点击查看代码
  t1 = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float)
  print(f't1:{t1}, (元素)type:{t1.dtype},(张量)type:{type(t1)}')
  t2 = t1.type(torch.int16)
  print(f't2:{t2}, (元素)type:{t2.dtype},(张量)type:{type(t2)}')
结果
t1:tensor([1., 2., 3., 4., 5.]), (元素)type:torch.float32,(张量)type:<class 'torch.Tensor'>
t2:tensor([1, 2, 3, 4, 5], dtype=torch.int16), (元素)type:torch.int16,(张量)type:<class 'torch.Tensor'>

3.6 张量类型转换

  • 张量转换为NumPy数组
    • tensor.numpy(): 共享内存, 修改一个另外一个也跟着变, 可以通过copy()函数不共享内存
点击查看代码
	t1 = torch.tensor([[1, 2, 3], [4, 5, 6]])
	print('t1->', t1)
	# 转换成numpy数组
	# n1 = t1.numpy()
	n1 = t1.numpy().copy()
	print('n1->', n1)
	print('n1的类型->', type(n1))
	# 修改n1的第一个值
	# [0][0]->第一行第一列的元素
	n1[0][0] = 100
	print('n1修改后->', n1)
	print('t1->', t1)
  • NumPy数组转换为张量
    • torch.from_numpy(ndarray): 共享内存, 对ndarray数组进行copy()
    • torch.tensor(data=ndarray): 不共享内存
点击查看代码
	n1 = np.array([[1, 2, 3], [4, 5, 6]])
	# 转换成张量
	# 共享内存
	t1 = torch.from_numpy(n1)
	# 不共享内存
	# t1 = torch.from_numpy(n1.copy())
	# t1 = torch.tensor(data=n1)
	print('t1->', t1)
	print('t1类型->', type(t1))
	# 修改张量元素
	t1[0][0] = 8888
	print('t1修改后->', t1)
	print('n1->', n1)
  • 提取标量张量的数值
    • tensor.item(): 提取单个元素张量的数值, 张量可以是标量张量/一维张量/二维张量...只要是单个元素即可
点击查看代码
	# 数值转换成张量
	# 标量
	t1 = torch.tensor(data=10)
	# 一维
	# t1 = torch.tensor(data=[10])
	# 二维
	# t1 = torch.tensor(data=[[10]])
	print('t1->', t1)
	print('t1形状->', t1.shape)
	# 单个元素张量转换成数值, 提取数值
	print('t1.item()->', t1.item())

3.7 张量数值计算

3.7.1 基本运算

  • 运算: 张量和数值之间运算, 张量和张量之间运算
  • +-*/-
  • add(other=) sub() mul() div() neg() 不修改原张量
  • add_() sub_() mul_() div_() neg_() 修改原张量
点击查看代码
  	# 创建张量
  	t1 = torch.tensor(data=[1, 2, 3, 4])
  	# 张量和数值运算
  	t2 = t1 + 10
  	print('t2->', t2)
  	# 张量之间运算, 对应位置的元素进行计算
  	t3 = t1 + t2
  	print('t3->', t3)
  
  	# add() 不修改原张量
  	t1.add(other=100)
  	t4 = torch.add(input=t1, other=100)
  	print('t4->', t4)
  
  	# neg_() 修改原张量, 负号
  	t5 = t1.neg_()
  	print('t1->', t1)
  	print('t5->', t5)

3.7.2 点乘运算

  • 点乘: 又称为阿达玛积, 张量元素级乘法, 对应位置的元素进行点乘, 一般要求两个张量形状相同 * mul()
点击查看代码
  	# t1 = torch.tensor(data=[[1, 2], [3, 4]])
  	# (2, )
  	t1 = torch.tensor(data=[1, 2])
  	# (2, 2)
  	t2 = torch.tensor(data=[[5, 6], [7, 8]])
  	t3 = t1 * t2
  	print('t3->', t3)
  	t4 = torch.mul(input=t1, other=t2)
  	print('t4->', t4)

3.7.3 矩阵乘法运算

  • 矩阵乘法: (n, m) * (m, p) = (n, p) 第一个矩阵的行和第二个矩阵的列相乘 @ torch.matmul(input=, ohter=)
点击查看代码
  	# (2, 2)
  	t1 = torch.tensor(data=[[1, 2],
  							[3, 4]])
  	# (2, 3)
  	t2 = torch.tensor(data=[[5, 6, 7],
  							[8, 9, 10]])
  
  	# @
  	t3 = t1 @ t2
  	print('t3->', t3)
  	# torch.matmul(): 不同形状, 只要后边维度符合矩阵乘法规则即可
  	t4 = torch.matmul(input=t1, other=t2)
  	print('t4->', t4)

3.7.4 张量运算函数

  • mean() # 注意:tensor 必须为 Float 或者 Double 类型
  • sum()
  • min()/max()
  • 以上可以指定dim, dim: 按不同维度计算
  • exp(): 指数
  • sqrt(): 平方根
  • pow(): 幂次方
  • log()/log2()/log10(): 对数
点击查看代码
  	# 创建张量
  	t1 = torch.tensor(data=[[1., 2, 3, 4],
  							[5, 6, 7, 8]])
  
  	# dim=0 按列
  	# dim=1 按行
  	# 平均值
  	print('所有值平均值->', t1.mean())
  	print('按列平均值->', t1.mean(dim=0))
  	print('按行平均值->', t1.mean(dim=1))
  	# 求和
  	print('所有值求和->', t1.sum())
  	print('按列求和->', t1.sum(dim=0))
  	print('按行求和->', t1.sum(dim=1))
  	# sqrt: 开方 平方根
  	print('所有值开方->', t1.sqrt())
  	# pow: 幂次方  x^n
  	# exponent:几次方
  	print('幂次方->',torch.pow(input=t1, exponent=2))
  	# exp: 指数 e^x  张量的元素值就是x
  	print('指数->', torch.exp(input=t1))
  	# log: 对数  log(x)->以e为底  log2()  log10()
  	print('以e为底对数->', torch.log(input=t1))
  	print('以2为底对数->', t1.log2())
  	print('以10为底对数->', t1.log10())

3.8 张量的索引操作

点击查看代码
# 下标从左到右从0开始(0->第一个值), 从右到左从-1开始
# data[行下标, 列下标]
# data[0轴下标, 1轴下标, 2轴下标]
	# 创建张量
	torch.manual_seed(0)
	data = torch.randint(low=0, high=10, size=(4, 5))
	print('data->', data)
	# 根据下标值获取对应位置的元素
	# 行数据 第一行
	print('data[0] ->', data[0])
	# 列数据 第一列
	print('data[:, 0]->', data[:, 0])
	# 根据下标列表取值
	# 第二行第三列的值和第四行第五列值
	print('data[[1, 3], [2, 4]]->', data[[1, 3], [2, 4]])
	# [[1], [3]: 第二行第三列 第二行第五列值   第四行第三列 第四行第五列值
	print('data[[[1], [3]], [2, 4]]->', data[[[1], [3]], [2, 4]])
	# 根据布尔值取值
	# 第二列大于6的所有行数据
	print(data[:, 1] > 6)
	print('data[data[:, 1] > 6]->', data[data[:, 1] > 6])
	# 第三行大于6的所有列数据
	print('data[:, data[2]>6]->', data[:, data[2] > 6])
	# 根据范围取值  切片  [起始下标:结束下标:步长]
	# 第一行第三行以及第二列第四列张量
	print('data[::2, 1::2]->', data[::2, 1::2])

	# 创建三维张量
	data2 = torch.randint(0, 10, (3, 4, 5))
	print("data2->", data2)
	# 0轴第一个值
	print(data2[0, :, :])
	# 1轴第一个值
	print(data2[:, 0, :])
	# 2轴第一个值
	print(data2[:, :, 0])
结果
data-> tensor([[4, 9, 3, 0, 3],
        [9, 7, 3, 7, 3],
        [1, 6, 6, 9, 8],
        [6, 6, 8, 4, 3]])
data[0] -> tensor([4, 9, 3, 0, 3])
data[:, 0]-> tensor([4, 9, 1, 6])
data[[1, 3], [2, 4]]-> tensor([3, 3])
data[[[1], [3]], [2, 4]]-> tensor([[3, 3],
        [8, 3]])
tensor([ True,  True, False, False])
data[data[:, 1] > 6]-> tensor([[4, 9, 3, 0, 3],
        [9, 7, 3, 7, 3]])
data[:, data[2]>6]-> tensor([[0, 3],
        [7, 3],
        [9, 8],
        [4, 3]])
data[::2, 1::2]-> tensor([[9, 0],
        [6, 9]])
data2-> tensor([[[6, 9, 1, 4, 4],
         [1, 9, 9, 9, 0],
         [1, 2, 3, 0, 5],
         [5, 2, 9, 1, 8]],

        [[8, 3, 6, 9, 1],
         [7, 3, 5, 2, 1],
         [0, 9, 3, 1, 1],
         [0, 3, 6, 6, 7]],

        [[9, 6, 3, 4, 5],
         [0, 8, 2, 8, 2],
         [7, 5, 0, 0, 8],
         [1, 9, 6, 1, 0]]])
tensor([[6, 9, 1, 4, 4],
        [1, 9, 9, 9, 0],
        [1, 2, 3, 0, 5],
        [5, 2, 9, 1, 8]])
tensor([[6, 9, 1, 4, 4],
        [8, 3, 6, 9, 1],
        [9, 6, 3, 4, 5]])
tensor([[6, 1, 1, 5],
        [8, 7, 0, 0],
        [9, 0, 7, 1]])

3.9 张量的形状操作

  • reshape(shape=(行,列)):在不改变张量内容的前提下, 对其形状做改变.
    • ‌自动处理连续性问题。若张量不连续,reshape会先调用contiguous()生成连续副本,再进行形状变换。
    • reshape参数为-1表示自动计算,有多少转多少,如reshape((-1, 2)),行数自动计算
点击查看代码
    torch.manual_seed(0)
    # 1. 定义2行3列的张量.
    t1 = torch.randint(1, 10, size=(2, 3))
    print(f't1: {t1}, shape: {t1.shape}, row: {t1.shape[0]}, columns: {t1.shape[1]}, {t1.shape[-1]}')

    # 2. 通过reshape()函数, 把t1 -> 3行2列, 1行6列, 6行1列.
    t2 = t1.reshape(3, 2)
    # t2 = t1.reshape(1, 6)
    # t2 = t1.reshape(6, 1)
    print(f't2: {t2}, shape: {t2.shape}, row: {t2.shape[0]}, columns: {t2.shape[1]}, {t2.shape[-1]}')

    # 3. 尝试通过reshape()函数, 把t1 -> 2行5列的结果.
    # t3 = t1.reshape(2, 5)       # 报错, 转之前共计 2*3=6个元素, 转之后共计 2*5=10个元素, 不一致.
    # t3 = t1.reshape(1, 5)       # 报错,内容不一致
    # print(f't3: {t3}')
结果
t1: tensor([[9, 1, 3],
        [7, 8, 7]]), shape: torch.Size([2, 3]), row: 2, columns: 3, 3
t2: tensor([[9, 1],
        [3, 7],
        [8, 7]]), shape: torch.Size([3, 2]), row: 3, columns: 2, 2
  • unsqueeze(dim=): 在指定维度上增加值为1的维度 dim=-1:最后维度
  • squeeze(dim=): 删除值为1的维度, dim->指定维度, 维度值不为1不生效 不设置dim,删除所有值为1的维度
    • 例如: (3,1,2,1) -> squeeze()->(3,2) squeeze(dim=1)->(3,2,1)
点击查看代码
	torch.manual_seed(0)
	# 四维
	t1 = torch.randint(0, 10, (3, 1, 2, 1))
	print('t1->', t1)
	print('t1的形状->', t1.shape)
	# squeeze: 降维
	t2 = torch.squeeze(t1)
	print('t2->', t2)
	print('t2的形状->', t2.shape)
	# dim: 指定维度
	t3 = torch.squeeze(t1, dim=1)
	print('t3->', t3)
	print('t3的形状->', t3.shape)
	# unsqueeze: 升维
	# (3, 2)->(1, 3, 2)
	# t4 = t2.unsqueeze(dim=0)
	# 最后维度 (3, 2)->(3, 2, 1)
	t4 = t2.unsqueeze(dim=-1) # 或者 t4 = t2.unsqueeze(dim=2)
	print('t4->', t4)
	print('t4的形状->', t4.shape)
结果
t1-> tensor([[[[4],
          [9]]],


        [[[3],
          [0]]],


        [[[3],
          [9]]]])
t1的形状-> torch.Size([3, 1, 2, 1])
t2-> tensor([[4, 9],
        [3, 0],
        [3, 9]])
t2的形状-> torch.Size([3, 2])
t3-> tensor([[[4],
         [9]],

        [[3],
         [0]],

        [[3],
         [9]]])
t3的形状-> torch.Size([3, 2, 1])
t4-> tensor([[[4],
         [9]],

        [[3],
         [0]],

        [[3],
         [9]]])
t4的形状-> torch.Size([3, 2, 1])
  • transpose(input=,dim0=,dim1=):一次只能交换2个维度.
    • dims: 改变后的维度顺序, 传入轴下标值 (1,2,3)->(3,1,2)
  • permute(input=,dims=):一次可以同时交换多个维度.
点击查看代码
    # 1. 定义张量.
    torch.manual_seed(0)
    t1 = torch.randint(1, 10, size=(2, 3, 4))
    print(f't1: {t1}, shape: {t1.shape}')

    # 2. 改变维度从 (2, 3, 4) -> (4, 3, 2)
    # t2 = t1.transpose(0, 2)
    t2 = t1.transpose(0, -1)        # 效果同上.
    print(f't2: {t2}, shape: {t2.shape}')

    # 3. 改变维度从 (2, 3, 4) -> (4, 2, 3)
    t3 = t1.permute(2, 0, 1)
    print(f't3: {t3}, shape: {t3.shape}')
结果
t1: tensor([[[9, 1, 3, 7],
         [8, 7, 8, 2],
         [2, 1, 9, 3]],

        [[7, 4, 2, 3],
         [1, 1, 6, 4],
         [9, 3, 9, 3]]]), shape: torch.Size([2, 3, 4])
t2: tensor([[[9, 7],
         [8, 1],
         [2, 9]],

        [[1, 4],
         [7, 1],
         [1, 3]],

        [[3, 2],
         [8, 6],
         [9, 9]],

        [[7, 3],
         [2, 4],
         [3, 3]]]), shape: torch.Size([4, 3, 2])
t3: tensor([[[9, 8, 2],
         [7, 1, 9]],

        [[1, 7, 1],
         [4, 1, 3]],

        [[3, 8, 9],
         [2, 6, 9]],

        [[7, 2, 3],
         [3, 4, 3]]]), shape: torch.Size([4, 2, 3])

       view 函数也可以用于修改张量的形状,只能用于修改连续的张量。在 PVTorch 中,有些张量的底层数据在内存中的存储顺序与其在张量中的逻辑顺序不一致,view 函数无法对这样的张量进行变形处理,例如:一个张量经过了 transpose或者 permute 函数的处理之后,就无法使用 view 函数进行形状操作。

  • view():只能修改连续的张量的形状, 连续张量 = 内存中存储顺序 和 在张量中显示的顺序相同.
  • contiguous():把不连续的张量 -> 连续的张量, 即: 基于张量中显示的顺序, 修改内存中的存储顺序.
  • is_contiguous():判断张量是否是连续的.
点击查看代码
    torch.manual_seed(0)
    # 1. 定义张量.
    t1 = torch.randint(1, 10, size=(2, 3))
    print(f't1: {t1}, shape: {t1.shape}')

    # 2. 判断张量是否连续. 即: 张量中的顺序 和 内存中存储顺序是否一致.
    # print(t1.is_contiguous())       # True

    # 3. 通过 view()函数, 修改上述张量的形状. 从(2, 3) -> (3, 2)
    t2 = t1.view(3, 2)
    print(f't2: {t2}, shape: {t2.shape}')
    print(t2.is_contiguous())        # True

    # 4. 通过 transpose()交换维度 -> 交换之后, 不连续了.
    t3 = t1.transpose(0, 1)
    print(f't3: {t3}, shape: {t3.shape}')
    print(t3.is_contiguous())        # False

    # 5. 尝试把 t3张量 从(3, 2), 通过 view() 转成 (2, 3).
    # t4 = t3.view(2, 3)      # t3不连续, 所以view()无法改变形状. 报错.
    # print(f't4: {t4}, shape: {t4.shape}')

    # 6. 可以通过 contiguous()函数, 把 t3张量 -> 连续张量 -> 然后就能通过view修改形状了.
    t5 = t3.contiguous().view(2, 3)
    print(f't5: {t5}, shape: {t5.shape}')

    # 7. 通过reshape修改形状后,是连续的,可以使用view
    # ‌reshape‌:自动处理连续性问题。若张量不连续,reshape会先调用contiguous()生成连续副本,再进行形状变换。
    t6 = t1.reshape((3,2)) 
    print(f't6: {t6}, shape: {t6.shape}')
    print(t6.is_contiguous()) # True
    t7 = t6.view(3, 2)
    print(f't7: {t7}, shape: {t7.shape}')
结果
t1: tensor([[9, 1, 3],
        [7, 8, 7]]), shape: torch.Size([2, 3])
t2: tensor([[9, 1],
        [3, 7],
        [8, 7]]), shape: torch.Size([3, 2])
True
t3: tensor([[9, 7],
        [1, 8],
        [3, 7]]), shape: torch.Size([3, 2])
False
t5: tensor([[9, 7, 1],
        [8, 3, 7]]), shape: torch.Size([2, 3])
t6: tensor([[9, 1],
        [3, 7],
        [8, 7]]), shape: torch.Size([3, 2])
True
t7: tensor([[9, 1],
        [3, 7],
        [8, 7]]), shape: torch.Size([3, 2])

3.10 张量拼接操作

  • torch.cat()/concat(tensors=, dim=): 在指定维度上进行拼接, 其他维度值必须相同, 不改变新张量的维度, 指定维度值相加
    • tensors: 多个张量列表
    • dim: 拼接维度
点击查看代码
    t1 = torch.randint(1, 10, (2, 3))
    print(f't1: {t1}, shape: {t1.shape}')

    t2 = torch.randint(1, 10, (2, 3))
    print(f't2: {t2}, shape: {t2.shape}')

    t3 = torch.cat([t1, t2], dim=0)     # (2, 3) + (2, 3) = (4, 3)
    print(f't3: {t3}, shape: {t3.shape}')

    t4 = torch.cat([t1, t2], dim=1)     # (2, 3) + (2, 3) = (2, 6)
    print(f't4: {t4}, shape: {t4.shape}')

    t5 = torch.cat([t1, t2], dim=-1)    # 效果同上
    print(f't5: {t5}, shape: {t5.shape}')

    # t6 = torch.cat([t1, t2], dim=2) # 报错.
    # print(f't6: {t6}, shape: {t6.shape}')
结果
t1: tensor([[6, 4, 9],
        [3, 9, 3]]), shape: torch.Size([2, 3])
t2: tensor([[9, 6, 8],
        [9, 7, 1]]), shape: torch.Size([2, 3])
t3: tensor([[6, 4, 9],
        [3, 9, 3],
        [9, 6, 8],
        [9, 7, 1]]), shape: torch.Size([4, 3])
t4: tensor([[6, 4, 9, 9, 6, 8],
        [3, 9, 3, 9, 7, 1]]), shape: torch.Size([2, 6])
t5: tensor([[6, 4, 9, 9, 6, 8],
        [3, 9, 3, 9, 7, 1]]), shape: torch.Size([2, 6])
  • torch.stack(tensors=, dim=): 根据指定维度进行堆叠, 在指定维度上新增一个维度(维度值张量个数), 新张量维度发生改变
    • tensors: 多个张量列表
    • dim: 拼接维度
点击查看代码
    torch.manual_seed(24)
    t1 = torch.randint(1, 10, (2, 3))
    print(f't1: {t1}, shape: {t1.shape}')
    t2 = torch.randint(1, 10, (2, 3))
    print(f't2: {t2}, shape: {t2.shape}')
    # dim=0, 2插在第一个位置,所以(2, 2, 3);dim=1, 2插在第二个位置,所以(2, 2, 3);dim=2, 2插在第三个位置,所以(2, 3, 2);
    # 注意谁和谁拼
    t7 = torch.stack([t1, t2], dim=0)   # (2, 3) + (2, 3) = (2, 2, 3)
    print(f't7: {t7}, shape: {t7.shape}')

    t8 = torch.stack([t1, t2], dim=1)   # (2, 3) + (2, 3) = (2, 2, 3)
    print(f't8: {t8}, shape: {t8.shape}')

    t9 = torch.stack([t1, t2], dim=2)   # (2, 3) + (2, 3) = (2, 3, 2)
    print(f't9: {t9}, shape: {t9.shape}')

    # 报错.
    # t10 = torch.stack([t1, t2], dim=3)   # (2, 3) + (2, 3) = (2, 3, ?, 2)
    # print(f't10: {t10}, shape: {t10.shape}')
结果
t1: tensor([[6, 9, 9],
        [2, 8, 7]]), shape: torch.Size([2, 3])
t2: tensor([[8, 5, 8],
        [4, 7, 4]]), shape: torch.Size([2, 3])
t7: tensor([[[6, 9, 9],
         [2, 8, 7]],

        [[8, 5, 8],
         [4, 7, 4]]]), shape: torch.Size([2, 2, 3])
t8: tensor([[[6, 9, 9],
         [8, 5, 8]],

        [[2, 8, 7],
         [4, 7, 4]]]), shape: torch.Size([2, 2, 3])
t9: tensor([[[6, 8],
         [9, 5],
         [9, 8]],

        [[2, 4],
         [8, 7],
         [7, 4]]]), shape: torch.Size([2, 3, 2])
posted @ 2025-11-16 15:42  __zjy0  阅读(8)  评论(0)    收藏  举报