目录
- 张量
- 通过shape属性访问张量的形状
- 通过shape属性访问张量中元素的总数
- reshape改变张量的形状(不改变元素数量和元素值)
- 使用全0、全1、其他常量或者从特定分布中随机采样的数字
- 通过提供包含数值的Python列表为所需张量中的每个元素赋予确定值。
- 张量的算数运算符升级为按元素运算
- 张量按元素方式的指数运算
- 张量的连结cat函数
- 逻辑运算符构建二元张量
- sum()函数-----张量中所有元素进行求和会产生一个只有一个元素的张量
- 广播机制--即使形状不同也可以执行按元素操作
- 选择张量的最后一个元素
- 通过指定索引来将元素写入矩阵
- 通过索引所有元素为多个元素赋值相同的值
- 内存分配的问题
- 运行的操作导致新结果分配内存
- 执行原地操作
- 转换为NumPy张量
- 将大小为1的张量转换为Python标量
张量
张量表示一个数值组成的数组,这个数组可能有多个维度
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))
结果:
使用全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))
结果: