最近毕业论文写得差不多了,就打算把一些平时经常会用到知识记录一下,方便以后忘了可以看看。先把本文参考的资料列在前面:
创建Tensor有四种方式:
torch.Tensor(data)
:Tensor
类的构造函数;数据类型只能是float32
;不共享内存。torch.tensor(data)
:数据类型根据传入的数据而定,或通过传入dtype
来指定;不共享内存。torch.as_tensor(data)
:根据传入数据或传入dtype
来决定数据类型;共享内存。torch.from_numpy(data)
:仅接受np.array
的输入数据;根据传入数据或传入dtype
来决定数据类型;共享内存。综上,更推荐使用torch.tensor(data)
和 torch.as_tensor(data)
来创建Tensor。
> data = np.array([1,2,3])
> o1 = torch.Tensor(data)
> o2 = torch.tensor(data)
> o3 = torch.as_tensor(data)
> o4 = torch.from_numpy(data)
> print(o1)
> print(o2)
> print(o3)
> print(o4)
tensor([1., 2., 3.])
tensor([1, 2, 3], dtype=torch.int32)
tensor([1, 2, 3], dtype=torch.int32)
tensor([1, 2, 3], dtype=torch.int32)
> print(o1.dtype)
> print(o2.dtype)
> print(o3.dtype)
> print(o4.dtype)
torch.float32
torch.int32
torch.int32
torch.int32
# 是否共享内存
> print('old:', data)
old: [1 2 3]
> data[0] = 0
> print('new:', data)
new: [0 2 3]
> print(o1)
> print(o2)
> print(o3)
> print(o4)
tensor([1., 2., 3.])
tensor([1, 2, 3], dtype=torch.int32)
tensor([0, 2, 3], dtype=torch.int32)
tensor([0, 2, 3], dtype=torch.int32)
> t = torch.tensor([
[1,2,3],
[4,5,6],
[7,8,9]
], dtype=torch.float32)
> t.mean()
tensor(5.)
# Tensor → Scaler
> t.mean().item()
5.0
# Tensor → List
> t.mean(dim=0).tolist()
[4.0, 5.0, 6.0]
# Tensor → Array
> t.mean(dim=0).numpy()
array([4., 5., 6.], dtype=float32)
获取Tensor的shape有两种种方式:
t.size()
t.shape
> t = torch.tensor([
[1,1,1,1],
[2,2,2,2],
[3,3,3,3]
], dtype=torch.float32)
> t.size()
> t.shape
torch.Size([3, 4])
torch.Size([3, 4])
> t.size(0)
> t.shape[0]
3
3
torch.squeeze(input, dim=None, out=None) → Tensor
dim
:如果指定的维度的维数是1,则删除该维度;否则,不作任何操作。dim
:删除所有维数为1的维度。torch.unsqueeze(input, dim, out=None) → Tensor
dim
上增加一个维度。> t = torch.tensor([
[1,1,1,1],
[2,2,2,2],
[3,3,3,3]
], dtype=torch.float32)
> t.size()
torch.Size([3, 4])
# squeeze - 指定维度的维数不为1
> torch.squeeze(t, dim=0)
tensor([[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.]])
> t = t.reshape([1,12])
> t.size()
torch.Size([1, 12])
# squeeze - 指定维度的维数为1
> torch.squeeze(t, dim=0)
> torch.squeeze(t, dim=0).size()
tensor([1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.])
torch.Size([12])
# unsqueeze
> t = torch.unsqueeze(t, dim=2)
> t.size()
torch.Size([1, 12, 1])
# unsqueeze - 不指定维度
> t = torch.squeeze(t)
> t.size()
torch.Size([12])
torch.cat(tensors, dim=0, out=None) → Tensor
:在指定dim
上对Tensor进行拼接。
> t = torch.cat((t1,t2,t3), dim=0)
> t.size()
torch.Size([3, 12, 1])
t1,t2,t3
的维度都是(1,12,1)
,在dim=0
上进行拼接,则得到为维度是(3,12,1)
。
torch.stack(tensors, dim=0, out=None) → Tensor
:在指定dim
上增加一维,并在新增维度上对Tensor进行拼接。
> t = torch.stack((t1,t2,t3), dim=0)
> t.size()
torch.Size([3, 1, 12, 1])
t1,t2,t3
的维度都是(1,12,1)
,torch.stack()
在dim=0
上先新增一个维度,再在该维度上进行拼接,则得到为维度是(3,1,12,1)
。
torch.sum(input, dim=None) → Tensor
:求和。
# 不指定dim
> t = torch.tensor([
[0,1,0],
[2,0,2],
[0,3,0]
], dtype=torch.float32)
> t.sum()
tensor(8.)
# 指定dim
> t = torch.tensor([
[1,1,1,1],
[2,2,2,2],
[3,3,3,3]
], dtype=torch.float32)
> t.sum(dim=0)
tensor([6., 6., 6., 6.])
torch.max(input, dim=None) → Tensor
:求最大值。
torch.argmax(input, dim=None) → Tensor
:求最大值对应的下标。
> t = torch.tensor([
[1,0,0,2],
[0,3,3,0],
[4,0,0,5]
], dtype=torch.float32)
# 不指定dim,返回整个Tensor最大值的下标
> t.max()
tensor(5.)
> t.argmax()
tensor(11)
# 指定dim,返回指定轴上最大值下标
> t.max(dim=0)
(tensor([4., 3., 3., 5.]), tensor([2, 1, 1, 2]))
> t.argmax(dim=0)
tensor([2, 1, 1, 2])
逐元素运算有四种情况:
t1+t2
,t1
和t2
shape相同:两者直接按位进行运算。t1+2
,t1-2
,t1*2
,t1/2
:先对2进行了broadcasting,然后再和t1
运算。t1+t2
,rank相同,shape不同。首先判断两个Tensor的各个维度是否兼容,满足兼容的情况有两个,二者满足其一即可:t1
的shape是(1,2)
,t2
的shape是(3,1)
,从后往前对比,各维度均满足上述的第二个条件,因此二者兼容。从后往前对比,先看第二维度,取最大值作为输出维度,即2,再看第一维度也是取最大值,即3。则输出的shape是(3,2)
,分别将t1
,t2
广播成(3,2)
,然后再逐元素进行相加,得到最终的结果。t1+t2
,rank不同。同样,首先判断两个Tensor的各个维度是否兼容,例如:t1
的维度(2,4)
,t2
的维度是(4,)
,从后往前对比,最后一维相等,但是t2
只有一维,那就在缺失的维度上补1,变成(1,4)
,然后再广播成(2,4)
,再和t1
计算。t1
的维度(2,4)
,t2
的维度是(2,)
,从后往前对比,最后一维不相等,因此t1
和t2
的shape不兼容,无法进行下一步运算。# Case 1
> t1 = torch.tensor([
[1,2],
[3,4]
], dtype=torch.float32)
> t2 = torch.tensor([
[9,8],
[7,6]
], dtype=torch.float32)
> t1 + t2
tensor([[10., 10.],
[10., 10.]])
# Case 2
> t1 + 2
tensor([[3., 4.],
[5., 6.]])
> t1 - 2
tensor([[-1., 0.],
[ 1., 2.]])
> t1 * 2
tensor([[2., 4.],
[6., 8.]])
> t1 / 2
tensor([[0.5000, 1.0000],
[1.5000, 2.0000]])
除了四则运算外,以下运算也是Element-wise运算:
<
,>
,==
,!=
torch.abs()
torch.neg()
torch.sqrt()
> t = torch.tensor([
[0,5,0],
[6,0,7],
[0,8,0]
], dtype=torch.float32)
# 比较
> t == 0
tensor([[True, False, True],
[False, True, False],
[True, False, True]])
# 取绝对
> t.abs()
tensor([[0., 5., 0.],
[6., 0., 7.],
[0., 8., 0.]])
# 取反
> t.neg()
tensor([[-0., -5., -0.],
[-6., -0., -7.],
[-0., -8., -0.]])
# 开根
> t.sqrt()
tensor([[0.0000, 2.2361, 0.0000],
[2.4495, 0.0000, 2.6458],
[0.0000, 2.8284, 0.0000]])
按位相乘的实现方法有两种,二者用法相同:
*
:支持broadcast。torch.mul(input, other, *, out=None)→ Tensor
:支持broadcast。按位相乘的实现方法有两种:
torch.mm(input, mat2, *, out=None) → Tensor
:只接受二维矩阵作为输入,且两个矩阵的shape满足矩阵乘法的要求,不支持broadcast。torch.matmul(input, other, *, out=None) → Tensor
:接受高维矩阵作为输入,支持broadcast。
tensor.mm
用法相同。# 二维的矩阵乘法
>>> a = torch.ones(3,4)
>>> b = torch.ones(4,5)
>>> c = torch.matmul(a,b)
>>> c.shape
torch.Size([3, 5])
# 高维的矩阵乘法
>>> a = torch.ones(2,1,3,4)
>>> b = torch.ones(5,4,2)
>>> c = torch.matmul(a,b)
>>> c.shape
torch.Size([2, 5, 3, 2])