首页 > 技术文章 > pytorch笔记

sdu20112013 2019-10-24 13:47 原文

torch和torchvision版本匹配查询

https://github.com/pytorch/vision#installation

查看torch支持的cuda版本

>>> import torchvision
>>> torchvision.__version__
'0.10.0+cu102'
>>> import torch
>>> torch.__version__
'1.9.0'
>>> torch.version.cuda
'11.1'
>>> 

Tensor create

#创建特定shape value为random值的tensor
input = torch.rand((64,64,3))

创建bool tensor

>>> mask = torch.zeros(3,4,dtype=torch.bool)
>>> mask
tensor([[False, False, False, False],
        [False, False, False, False],
        [False, False, False, False]])

tensor copy

"""
torch里tensor的复制
"""
a=torch.tensor([1])
b=a
a[0]=2
print('a={},b={}'.format(a,b))
#a,b是同一个东西

a=torch.tensor([1])
c = a * torch.ones(3)
#做完运算后a,c是两个东西
a[0]=2
print('a={},c={}'.format(a,c))
c[0]=5
print('a={},c={}'.format(a,c))

a=torch.tensor([1])
d=a.clone()
#a,d是两个东西
a[0]=2
print('a={},d={}'.format(a,d))

Tensor slice

Tensor的indices操作

  • 以[2,3]矩阵为例,slice后可以得到任意shape的矩阵,并不是说一定会小于2行3列.
import torch

truths=torch.Tensor([[1,2,3],[4,5,6]])

#代表新生成一个[3,]的矩阵,行位置分别取原先矩阵的第1,第0,第1行.
print(truths[[1,0,1],:])
print(truths[[1,0,1]]) #等同于truths[[1,0,1],:]

#代表新生成一个[,4]的矩阵,列位置分别取原先矩阵的第2,第2,第2,第2列
print(truths[:,[2,2,2,2]])

输出

  • 用bool型的tensor去切片
import torch
x = torch.tensor([[1,2,3],[4,5,6]])
index = x>2
print(index.type())

x[index]

tensor扩展


Expanding a tensor does not allocate new memory, but only creates a new view on the existing tensor where a dimension of size one is expanded to a larger size by setting the stride to 0. Any dimension of size 1 can be expanded to an arbitrary value without allocating new memory.
并不分配新内存. 只是改变了已有tensor的view. size为1的维度被扩展为更大的size.

>>> x = torch.tensor([[1], [2], [3]])
>>> x.size()
torch.Size([3, 1])
>>> x.expand(3, 4)
tensor([[ 1,  1,  1,  1],
        [ 2,  2,  2,  2],
        [ 3,  3,  3,  3]])
>>> x.expand(-1, 4)   # -1 means not changing the size of that dimension
tensor([[ 1,  1,  1,  1],
        [ 2,  2,  2,  2],
        [ 3,  3,  3,  3]])

gather

torch.gather(input, dim, index, out=None, sparse_grad=False) → Tensor

即dim维度的下标由index替换.input是n维的,index也得是n维的,tensor在第dim维度上的size可以和input不一致. 最终的output和index的shape是一致的.

即对dim维度的数据按照index来索引.

比如

import torch
t = torch.tensor([[1,2],[3,4]])
index=torch.tensor([[0,0],[1,0]])
torch.gather(t,1,index)

输出
tensor([[1, 1],
        [4, 3]])

gather(t,1,index)替换第1维度的数据(即列方向),替换成哪些列的值呢?[[0,0],[1,0]],对第一行,分别为第0列,第0列,对第二行,分别为第1列,第0列.
从而得到tensor([[1, 1],[4, 3]])

sum


沿着第n维度,求和.keepdim表示是否保持维度数目不变.

import torch
t = torch.tensor([[1,2],[3,4]])
a=torch.sum(t,0)
b=torch.sum(t,1,keepdim=True)
print(a.shape,b.shape)
print(a)
print(b)

sort


沿着第n个维度的方向排序

import torch
t = torch.tensor([[1,9,7],[8,5,6]])
_sorted,_index = t.sort(1)
print(_sorted)
print(_index)

_sorted,_index = t.sort(0)
print(_sorted)
print(_index)

clamp

import torch
print()

t = torch.tensor([[1,2,7],[3,4,8]])
res = t.clamp(3,7)          #<3的变为3,>7的变为7  中间范围的不变
print(res)

res2 = torch.clamp(t,max=5) #所有大于5的都改为5
print(res2)


各种损失函数

https://blog.csdn.net/zhangxb35/article/details/72464152

有用link:

torch.repeat()

沿着某个维度对tensor做复制.
比如

>>> x=torch.tensor([1,2,3])
>>> x.shape
torch.Size([3])
>>> x.repeat(4,2)
tensor([[1, 2, 3, 1, 2, 3],
        [1, 2, 3, 1, 2, 3],
        [1, 2, 3, 1, 2, 3],
        [1, 2, 3, 1, 2, 3]])
>>> x.repeat(4,2,1)
tensor([[[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]]])

这个过程实际上相当于

>>> y=x.unsqueeze(0).unsqueeze(0)
>>> y.shape
torch.Size([1, 1, 3])
>>> y.repeat(4,2,1)
tensor([[[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]],

        [[1, 2, 3],
         [1, 2, 3]]])

由于x的初始维度只有一个dim,当在三个维度上想做(4,2,1)的倍数放大时,需要先把x扩展为3个维度,即[1,1,3]这个shape. 然后再做复制.

torch.min

https://pytorch.org/docs/stable/generated/torch.minimum.html#torch.minimum
当对两个tensor做比较时,如果两个tensor的shape不同,实际上要先将两个tensor repeat到相同的shape,再做element-wise的比较.
比如

>>> a=torch.tensor([[1,3,5],[2,6,4]])
>>> b=torch.tensor([[1,3],[2,4]])
>>> torch.min(a,b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: The size of tensor a (3) must match the size of tensor b (2) at non-singleton dimension 1

这样是无法比较的,因为a,b的shape不同.

而:

>>> a=torch.tensor([[1,3],[2,4]])
>>> b= torch.tensor([[1,2],[3,4],[5,6]])
>>> a=a.unsqueeze(0)
>>> b=b.unsqueeze(1)
>>> a.shape,b.shape
(torch.Size([1, 2, 2]), torch.Size([3, 1, 2]))
>>> c=torch.min(a,b)
>>> c
tensor([[[1, 2],
         [1, 2]],

        [[1, 3],
         [2, 4]],

        [[1, 3],
         [2, 4]]])

a和b的shape是不同的.但是他们都含有1维的维度.所以实际上会将其扩展为[3,2,2]后比较.

>>> a.shape,b.shape
(torch.Size([1, 2, 2]), torch.Size([3, 1, 2]))
>>> a=a.repeat(3,1,1)
>>> b=b.repeat(1,2,1)
>>> a.shape,b.shape
(torch.Size([3, 2, 2]), torch.Size([3, 2, 2]))
>>> torch.min(a,b)
tensor([[[1, 2],
         [1, 2]],

        [[1, 3],
         [2, 4]],

        [[1, 3],
         [2, 4]]])

可以看到结果是相同的

Loss函数

BCEWithLogitsLoss

a=torch.tensor([0.3,0.9,0.8])
gt=torch.tensor([0.,1.,0.])
mask=torch.tensor([0.,1.,0.],dtype=torch.uint8)
l=torch.nn.BCEWithLogitsLoss(reduction='sum')
l(a,gt)

pos=a[mask]
neg=a[~mask]
pos_gt=gt[mask]
neg_gt=gt[~mask]
l(pos,pos_gt)+l(neg,neg_gt)

输出相同.tensor(2.3666)

推荐阅读