文章目录
- 前言
- 一. 初始化tensor
- 1. 创建tensor
- 2. 快速创建tensor
- 3. 改变tensor分布
- 4. 变量类型与数据类型转换
- 二. 张量的数学计算与比较
- 1. 张量的加减
- 2. 张量的除法
- 3. inplace操作
- 4. 求幂
- 5. 简单的比较
- 6. 张量乘法
- 7. 矩阵求幂
- 8. batch 级矩阵乘法
- 9. 其余有用的操作,像求和,最大值
- 三. 张量索引
- 1. 基础索引
- 2. 稍微高级
- 3. 高级点的索引操作
- 4. 其余有用的操作, 例如, .unique
- 5. 广播机制
- 四. reshape操作
- 1. `view()` & `reshape`
- 2. `()`
- 3. 二维与多维矩阵的转置
- 五. `squeeze()` 操作
- 六. ``
- 1.沿X轴复制
前言
主要介绍一系列对tensor的操作,可以作为工具查找
一. 初始化tensor
1. 创建tensor
import torch
my_tensor = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32, device='cuda')
- 如果有cuda当然就能用,不能则是cpu,所有有更好的写法
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# 两者均可
my_tensor = torch.tensor([[1, 2, 3], [4, 5, 6]], dtype=torch.float32, device=device, requires_grad=True)
# 可选参数还有requires_grad, 这是能否自动求梯度的关键,单独写的时候是关的
# dtype也很重要,因为cuda一般只支持float32
- 还可以用.的方法调用
my_tensor.dtype
my_tensor.device
my_tensor.requires.grad
2. 快速创建tensor
x = torch.empty(size=(3, 3))
x = torch.zeros((3, 3))
x = torch.rand((3, 3))
x = torch.ones((3, 3))
x = torch.eye(5, 5)
- 首先在后面没有参数的情况下,()与(())没有区别, 然后
()
是0~1的均匀分布, 而()
是0~1的正态分布 -
()
啊,多好的拟声词编程, 和 I I I含义一样
x = torch.arange(start=0, end=5, step=1)
x = torch.linspace(start=0, end=1, steps=10)
- 这两个常用来比较, 当然可以不用写参数名, 其中第一个是按步长取数, 第二个是按个数, 一般这种都是左包右不包
- 两者的输出
tensor([0, 1, 2, 3, 4])
tensor([0.0000, 0.1111, 0.2222, 0.3333, 0.4444, 0.5556, 0.6667, 0.7778, 0.8889, 1.0000])
3. 改变tensor分布
x = torch.empty(size=(1, 5)).normal_(mean=0, std=1)
- 更改分布为均值为0, 标准差为1的正态分布
x = torch.empty(1, 5).uniform_(0, 1)
x = torch.ones(1, 5).uniform_(0, 1)
- 更改分布为均匀分布,
.方法
是强制转换, 并不关心原来有什么
x = torch.ones(5)
x = torch.diag(x)
- 保留对角线的元素, 上面处理之后等同于(5)
4. 变量类型与数据类型转换
x = torch.arange(5)
print(x.bool())
>>
tensor([False, True, True, True, True])
print(x[x.bool()]
>>
tensor([1, 2, 3, 4])
- bool类型在true的时候保留
x = torch.arange(4)
print(x.short()) # int16
print(x.long()) # int64 (important)
print(x.half()) # float16
print(x.float()) # float32 (important)
print(x.double()) # float64
- 一些快速变化的方法
x = numpy.zeros(5)
x = torch.from_numpy(x) # 从numpy变为tensor
a = x.numpy() # 从tensor变回numpy
二. 张量的数学计算与比较
1. 张量的加减
a = torch.tensor([1, 2, 3])
b = torch.tensor([1, 2, 3])
z = a + b
z = a - b
- 虽然
(a, b)
也是可以的, 但是还是简洁一点好
2. 张量的除法
a = torch.tensor([1, 2, 3])
b = torch.tensor([1, 2, 3])
c = torch.tensor([2])
print(torch.true_divide(a, b))
-
torch.true_divide()
是元素级的除法,如果维度一致就是一对一除法, 如果除数是单个tensor就统统除以它
3. inplace操作
-
inplace操作
是pytorch计算的一种技巧, 它使得pytorch不会创建变量的副本, 而是就地操作,增加了计算效率
a = torch.ones(1, 3)
b = torch.zeros(1, 3)
b.add_(a)
b += a
-
inplace
有两种方式, 一种是这样加下划线, 一种是类似b += a
的操作, 有些令人疑惑, 因为b = b+a
就会创建副本
4. 求幂
x = torch.tensor([1, 2, 3])
print(x.pow(2))
print(x ** 2)
- 一样的结果
5. 简单的比较
x = torch.tensor([0, 1, 2, 3])
print(x > 0)
print(x < 0)
- 这样会返回一个bool类型的tensor
6. 张量乘法
a = torch.rand(2, 5)
b = torch.rand(5, 3)
print(torch.mm(a, b)) # 2*3
print(a.mm(b))
-
()
与()
都是正常的矩阵乘法
a = torch.rand(2, 5)
b = torch.rand(2, 5)
print(a * b)
- 这是执行的元素级的乘法
a = torch.tensor([1, 2, 3])
b = torch.tensor([1, 2, 3])
print(a.dot(b))
(b)
是先元素级相乘再求和
7. 矩阵求幂
- 这里是对方针进行操作, 因为实际是对自己执行矩阵运算
a = torch.rand(2, 2)
print(a.matrix_power(3))
8. batch 级矩阵乘法
- 两个维度当然可以直接矩阵乘法, 但是带有batch就需要batch的乘法
a = torch.rand(3, 2, 5)
b = torch.rand(3, 5, 4)
print(torch.bmm(a, b)) # 3, 2, 4
- batch不变, 而后对每片执行矩阵乘法
9. 其余有用的操作,像求和,最大值
x = torch.tensor([1, 2, 3])
y = torch.tensor([2, 3, 4])
sum_x = torch.sum(x, dim=0)
values, index = torch.max(x, dim=0) # 返回的是tensor的数,比如index是tensor(2)
values, index = torch.min(x, dim=0)
abs_x = torch.abs(x) # 计算绝对值
z = torch.argmax(x, dim=0) # 感觉有些像max的特例, 因为它只返回索引值
z = torch.argmin(x, dim=0)
mean_x = torch.mean(x.float(), dim=0) # 注意mean需要float的格式
z = torch.eq(x, y) # 这里输出的是元素等级判别的bool值
sorted_value, index = torch.sort(y, dim=0, descending=False) # descending参数为True则为降序, 反之为升序
z = torch.clamp(x, min=2, max=10) # min与max可以缺省, 这里是小于2的被设为2, 大于10的被限制为10
三. 张量索引
1. 基础索引
batch_size = 10
features = 25
print(x[0])
print(x[:, 0]) # 这是取所有行第一列
print(x[2, 0:10]) # 第三行, 0到9列, 左包右不包
2. 稍微高级
x = torch.arange(10)
index = [2, 4, 5]
print(x[index]) # 索引可以是列表
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
rows = torch.tensor([1, 0])
cols = torch.tensor([1, 0])
print(x[rows, cols])
>>
tensor([5, 1])
- 先选第二行第二个数, 然后是第一行第一个数
x = torch.ones((4, 4))
y = x[::2, ::2]
- 隔着两个元素确定行和列
3. 高级点的索引操作
x = torch.tensor([2, 3, 5])
print(x[(x<2) | (x > 3)]) # 输出x小于2或者x大于3的数
print(x[(x>2) & (x < 5)]) # 输出x大于2或者x小于5的数
x = torch.arange(10)
print(x[x.remainder(2) == 0]) # 这是输出x除2余数为0
4. 其余有用的操作, 例如, .unique
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(torch.where(x>5, x, 10))
- 这个
有些像
if else
这种, 上面如果满足x>5
的地方就维持x不变, 如果不满足也就是小于等于5就变为10
x = torch.tensor([0, 0, 1, 2])
print(x.unique())
- 这个是集合那种保留单个的操作
x = torch.rand(3, 4)
print(x.ndimension())
>>
2
- 这是输出的有几维
x = torch.rand(3, 4)
print(x.numel())
>>
12
- 输出一个矩阵的总元素个数
5. 广播机制
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
print(a+b)
>>
tensor([[0, 1],
[1, 2],
[2, 3]])
- 相当于是a的列复制了一下,b的行复制了一下
四. reshape操作
1. view()
& reshape
-
reshape
有两种方法, 一是view()
, 另一个是reshape()
x = torch.arange(9)
x = x.reshape(3, 3)
x = x.view(3, 3)
-
这两者有些不同,
view
用于储存在连续内存的张量,reshape
则不受限制\ -
下面用一个例子来说明:
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(x.t())
x = x.t()
x = x.view(6)
这样就会报错, 因为转置使得其不再连续空间了, 所以此时需要用reshape
2. ()
x = torch.rand(2, 3)
y = torch.rand(2, 3)
z = torch.cat(x, y, dim=0) # (4, 3)
z = torch.cat(x, y, dim=1) # (2, 6)
3. 二维与多维矩阵的转置
- 对于二维有两种方法
x = torch.rand(2, 3)
print(x.t()) # 3, 2
print(x.T)
-
这两个是一样的
-
对于多维
x = torch.rand(5, 3, 8)
z = x.permute(0, 2, 1)
print(z.shape)
>>
torch.Size([5, 8, 3])
-
()
是变换轴, 上面程序0轴不变, 而1与2轴交换位置
五. squeeze()
操作
-
squeeze()
与unsqueeze
是个比较重要的函数, 主要是对数据的维度进行压缩或者解压.
x = torch.arange(10)
print(x.unsqueeze(0).shape)
print(x.unsqueeze(1).shape)
>>
torch.Size([1, 10])
torch.Size([10, 1])
x = torch.arange(10)
print(x.unsqueeze(0).unsqueeze(2).shape)
y = x.unsqueeze(0).unsqueeze(2)
print(y.squeeze(2).shape)
>>
torch.Size([1, 10, 1])
torch.Size([1, 10])
六.
1.沿X轴复制
- 在numpy中,(a,(2))函数的作用就是将函数将函数沿着X轴扩大两倍。如果扩大倍数只有一个,默认为X轴