深度学习-数据操作

本文介绍了深度学习中张量的基本概念及多种操作方法,包括张量的创建、形状变换、算术运算、逻辑运算、广播机制等内容,并通过实例展示了如何利用PyTorch进行张量操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


张量

张量表示一个数值组成的数组,这个数组可能有多个维度

import torch
x = torch.arange(12)
print(x)

结果:在这里插入图片描述




通过shape属性访问张量的形状

import torch
x = torch.arange(12)
print(x.shape)

结果:在这里插入图片描述



根据shape属性来访问张量的形状和张量中元素的总数。




通过shape属性访问张量中元素的总数

import torch
x = torch.arange(12)
print(x.numel())

结果:在这里插入图片描述




reshape改变张量的形状(不改变元素数量和元素值)

import torch
x = torch.arange(12)
print(x.reshape(3, 4))

结果:
在这里插入图片描述

这里的维度由reshape参数多少来决定的。
例如:一维(本身就是一维的)
例如:三维

import torch
x = torch.arange(12)
print(x.reshape(2, 2, 3))

结果:
在这里插入图片描述




⭐reshape的一个关注点

import torch
a = torch.arange(12)
b = a.reshape((3, 4))
b[:] = 2
print(a)

过程:
第一步之后的a在这里插入图片描述
第二步之后的b
在这里插入图片描述
第三步之后的a
在这里插入图片描述
原因:把一个数组reshape后地址并没有改,b并没有复制a,而是创建了a的一个view。




# 使用全0、全1、其他常量或者从特定分布中随机采样的数字
import torch
print(torch.zeros(2, 3, 4))
import torch
print(torch.zeros((2, 3, 4)))

两者的区别在于:直接传递多个整数参数时,torch.zeros(2, 3, 4)是更简洁的写法。而传递一个元组torch.zeros((2, 3, 4))则提供了更多的灵活性,特别是动态地构建形状时。




import torch
print(torch.ones(2, 3, 4))

结果:
在这里插入图片描述




通过提供包含数值的Python列表为所需张量中的每个元素赋予确定值。

import torch
print(torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]]))

结果:

在这里插入图片描述




张量的算数运算符升级为按元素运算

import torch
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
print(x + y)
print(x - y)
print(x * y)
print(x / y)
print(x ** y)

结果:

在这里插入图片描述
若发现数据报错无法相加时,可以使数据类型一致。如下:

y = torch.tensor([2, 2, 2, 2], dtype=torch.float32) 



张量按元素方式的指数运算

import torch
x = torch.tensor([1.0, 2, 4, 8])
print(torch.exp(x))

结果:
在这里插入图片描述




张量的连结cat函数

import torch
x = torch.arange(12, dtype=torch.float32).reshape((3, 4))
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(torch.cat((x, y), dim=0)) //dim=0的意思是按行连结
print(torch.cat((x, y), dim=1)) //dim=1的意思是按列连结

结果:在这里插入图片描述
在这里插入图片描述

注意:
1、arange()函数是左闭右开,从0开始生成。
2、x = torch.arange(12, dtype=torch.float32).reshape((3, 4))也可以是x = torch.arange(12, dtype=torch.float32).reshape(3, 4)区别在于用的那个代码是传递的元组,会更加灵活。




逻辑运算符构建二元张量

import torch
x = torch.arange(12, dtype=torch.float32).reshape((3, 4))
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(x == y)

结果:
在这里插入图片描述




sum()函数-----张量中所有元素进行求和会产生一个只有一个元素的张量

import torch
x = torch.arange(12, dtype=torch.float32).reshape((3, 4))
print(x.sum())

结果:
在这里插入图片描述




广播机制–即使形状不同也可以执行按元素操作

import torch
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
print(a)
print(b)

结果:
在这里插入图片描述

import torch
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
print(a+b)

过程:
a+b时对a的操作
[0]      [0,0]
[1]→  [1,1]
[2]      [2,2]
a+b时对b的操作
[0,1]
   ↓
[0,1]
[0,1]
[0,1]


结果:
在这里插入图片描述
分析:
两个张量形状不一样但可以变成一样(因为维数一样)
对于a中的reshape((3,2))它的行维度为3、列维度为1
对于b中的reshape((1,2))它的行维度为1、列维度为2

相加的条件:
            需要维度两同
两个变量分别有一个是一维的,否则也不能相加。




选择张量的最后一个元素

import torch
x = torch.arange(12).reshape((3, 4))
print(x[-1])

结果:
在这里插入图片描述

import torch
x = torch.arange(12).reshape((3, 4))
print(x[1:3])

结果:
在这里插入图片描述

x[1:3]是取第一行和第二行,左闭右开
但python中下标是从0开始。所以从全局来数就是第二行和第三行。




通过指定索引来将元素写入矩阵

import torch
x = torch.arange(12).reshape((3, 4))
x[1, 2] = 9
print(x)

结果:
在这里插入图片描述




通过索引所有元素为多个元素赋值相同的值

import torch
x = torch.arange(12).reshape((3, 4))
x[0:2, :] = 12
print(x)

结果:
在这里插入图片描述




内存分配的问题

运行的操作导致新结果分配内存

import torch
x = torch.arange(12).reshape((3, 4))
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
before = id(y) 	//类似指针、存放y的id
y = y + x 		//新的y的id
print(id(y) == before)

此时的y已经被析构了。
内存析构:即销毁原来的变量释放内存。

结果:在这里插入图片描述

执行原地操作

import torch
x = torch.arange(12).reshape((3, 4))
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
before = id(y)
y += x
print(id(y) == before)

结果:在这里插入图片描述

import torch
x = torch.arange(12).reshape((3, 4))
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
z = torch.zeros_like(y)
print(id(z))
z[:] = x + y
print(id(z))

结果:在这里插入图片描述
首先,z设置成和y一样的shape和数据类型但是元素都是0,然后,对z的元素进行一次改写。




转换为NumPy张量

import torch
x = torch.arange(12).reshape((3, 4))
A = x.numpy()
B = torch.tensor(A)
print(type(A), type(B))

结果:在这里插入图片描述




将大小为1的张量转换为Python标量

import torch
a = torch.tensor([3.5])
print(a)
print(a.item())
print(float(a))
print(int(a))

结果:
在这里插入图片描述




练习

1. 运行本节中的代码。将本节中的条件语句X == Y更改为X < Y或X > Y,然后看看你可以得到什么样的张量。

import torch
x = torch.arange(12, dtype=torch.float32).reshape((3, 4))
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(x < y)

结果:
在这里插入图片描述

import torch
x = torch.arange(12, dtype=torch.float32).reshape((3, 4))
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(x > y)

结果:
在这里插入图片描述



2. 用其他形状(例如三维张量)替换广播机制中按元素操作的两个张量。结果否与预期相同?

解:当张量分向量不同时,不同的分量中必须有一个为1,才可以进行广播机制。

示例:假设有两个三维张量A和B,执行元素加法
      A的形状是(m,n,p)
      B的形状是(1,n,1)

首先,B的第一个维度(大小为1)会广播到与A的第一个维度(大小为m)相同大小。

其次,B的第二个维度(大小为n)已经与A的第2个维度相同。

最后,B的第三个维度(大小为1)会广播到与A的第三个维度(大小为p)相同的大小,

相加结果是一个形状为(m,n,p)的三维张量。

例1:

import torch

a = torch.arange(6).reshape(3, 1, 2)
b = torch.arange(4).reshape(1, 2, 2)
print(a)
print(b)

结果:
在这里插入图片描述
reshape这里总共三个参数,第一个参数(这里是3),每一块均是1个二维张量。

步骤:

①首先b广播到与a相同的第一维度(3,2,2)也就是变成三块。

在这里插入图片描述
②将a中的第二维度广播到与b相同的第二维度(3,1,2)➡(3,2,2)

在这里插入图片描述

③a+b结果为:
在这里插入图片描述

图解:

在这里插入图片描述


在这里插入图片描述



在这里插入图片描述




广播机制的条件:

从后往前比较每个维度:
  从张量的最后一个维度开始,比较两个张量对应维度的大小。

维度大小为1 或者 相等
  对于每一对比的维度,如果它们的大小相等,或者其中一个的大小为1,则这两个维度是兼容的,可以参与广播。

大小为1的维度可以扩展
  如果一个张量在某个维度上的大小为1,那么在这个维度上,它可以被看作是"无限"的(即:它可以被扩展,以匹配另一个张量在该维度的大小。)

④前面的维度必须严格相等其中一个为1
  对于前面的维度(即:除了从后往前的第一个维度外)如果它们的大小不相等且都不为1,则这两个张量不能广播。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值