API笔记

网页搜索(ctrl+f)
.xx()表示方法,@xx表示类
-xx表示某些内容的关键字

pytorch


.register_buffer()
-参数
注册参数,跟self.xx差不多,注册完的参数可以通过self的方式调用。buffer会调用_apply方法,model.cuda时跟model一起执行cuda()等方法,self.xx不会;而且在stat_dict中不会被注册。

class TT(nn.Module):
    def __init__(self, i):
        super(TT, self).__init__()
        self.x = torch.zeros(i)
        self.register_buffer("y", torch.zeros(i))

model = TT((2,3)).cuda()
print(model.x)
print(model.y)
print(model.state_dict())
>>tensor([[0., 0., 0.],
        [0., 0., 0.]])
tensor([[0., 0., 0.],
        [0., 0., 0.]], device='cuda:0')
OrderedDict([('y', tensor([[0., 0., 0.],
        [0., 0., 0.]], device='cuda:0'))])

@LayerNorm
-层标准化-公式-细节
在这里插入图片描述
需要注意这里用到的Var。计算的时候根据论文中公式分母是n
而tensor.var()用的分母是n-1
初始化时需要给出需要norm的shape
input为 B × d 1 × d 2 × d 3 × d 4 B\times d_1\times d_2\times d_3\times d_4 B×d1×d2×d3×d4,则初始化的shape需要是 d 3 × d 4 d_3\times d_4 d3×d4 d 4 d_4 d4这样后面几个连续的维度,所进行的操作就是对后几个维度拉平后求均值和方差

x = torch.randn(4,3,5,6,7)
model = nn.LayerNorm((6,7))
mx = model(x)

b = x.view(4,3,5,-1) # 拉平
a = (b-b.mean(dim=-1, keepdim=True))/torch.sqrt(b.var(dim=-1, keepdim=True, unbiased=False)+1e-5)
a = a.view_as(mx)
print(torch.sum(a-mx))
>>tensor(3.8086e-06, grad_fn=<SumBackward0>)

如果是中间层的高维特征,比如B x 129 x H x W,这个时候考虑到位置因素,往往只在一个像素点上的129个channels上做标准化,由于LayerNorm是对最后的几个维度做标准化,所以需要把中间的输入做permute,把一个像素点上的所有channel全放到最后,然后设置normalization_shape为channel个数


.var()
-方差-细节-公式
unbiased参数控制分母是n还是n-1

a = torch.randn(3,)
v1 = (a-a.mean()).pow(2).mean()
v2 = (a-a.mean()).pow(2).sum()/2
print(v1, a.var(unbiased=False), v2, a.var(unbiased=True))
>>tensor(0.0338) tensor(0.0338) tensor(0.0507) tensor(0.0507)

.cross_entropy()
-高维-损失函数-输入-交叉熵-高维交叉熵
需要注意输入是logits,在函数内包含了softmax的操作,target是long类型的索引;高维时需要注意输入输出的shape需要对应以及channel所在的维度,参考文档
在这里插入图片描述


.contiguous()
-连续-内存-性能-解释-view-permute-flatten-stride
出于性能考虑,tensor的数值以行优先顺序存储在内存中,使用permute\transpose方法会得到一个不连续的tensor,这时只是得到一个stride改变了的指针(共享数值和梯度)。而view只能在连续的tensor上操作(并且得到的也是同一个指针,同一内存段两个view后求导,也会加在同一内存上)所以需要contiguous方法从原来的内存中拷贝一份到新内存并且按permute完的shape组合成连续的tensor从而进行view操作。contiguous就是看flatten后和连续内存上的顺序是不是一样的

  1. 创建一段连续内存view为2 x 3
  2. permute后仍未那段连续内存,但是stride改变了,所以flatten后顺序改变,不是连续的了
  3. contiguous后按新的flatten生成一段新的连续内存
  4. 如果只是view的话,内存仍为原来的内存,数值和梯度共享
a = nn.Parameter(torch.arange(6).view(2,3).float(), requires_grad=True) # No.1
print(a.data_ptr())
print(a)
print(a.flatten(),a.is_contiguous())
b = a.permute(1,0) # No.2
print(b.data_ptr())
print(b)
print(b.flatten(),b.is_contiguous())
b = b.contiguous() # No.3
print(b.data_ptr())
print(b)
print(b.flatten(),b.is_contiguous())
c = a.view(3,2) #No.4
print(c.data_ptr())
print(c)
print(c.flatten(),c.is_contiguous())
>>2625976178048
Parameter containing:
tensor([[0., 1., 2.],
        [3., 4., 5.]], requires_grad=True)
tensor([0., 1., 2., 3., 4., 5.], grad_fn=<ViewBackward>) True
2625976178048
tensor([[0., 3.],
        [1., 4.],
        [2., 5.]], grad_fn=<PermuteBackward>)
tensor([0., 3., 1., 4., 2., 5.], grad_fn=<UnsafeViewBackward>) False
2625976177024
tensor([[0., 3.],
        [1., 4.],
        [2., 5.]], grad_fn=<CopyBackwards>)
tensor([0., 3., 1., 4., 2., 5.], grad_fn=<ViewBackward>) True
2625976178048
tensor([[0., 1.],
        [2., 3.],
        [4., 5.]], grad_fn=<ViewBackward>)
tensor([0., 1., 2., 3., 4., 5.], grad_fn=<ViewBackward>) True

在这里插入图片描述

# 这个实验可以看出,view的不同结果,梯度是共享的
a = nn.Parameter(torch.arange(6).view(2,3).float(), requires_grad=True)
b = a.view(6,1)
c = a.view(3,2)
d = torch.sum(2*b)+torch.sum(3*c)
d.backward()
print(a.grad)
>>tensor([[0., 1., 2.],
        [3., 4., 5.]], requires_grad=True)
tensor([[5., 5., 5.],
        [5., 5., 5.]])

.mulitinominal()
-采样-概率-分布
按照给出的离散分布进行采样,给出的probs必须是softmax后的。
如果允许重复采样(replacement=True),概率大的值采样到的次数就多。
如果不允许重复采样,概率大的先采到。(一共2种情况采样5次肯定有重复的)
以上两个都不是绝对的,下图采5次的第3行0的概率比1大却采到的少

probs = torch.randn(4, 2).softmax(dim=1)
print(probs)
sample = torch.multinomial(probs, 2)
print(sample)
sample = torch.multinomial(probs, 5, replacement=True)
print(sample)
>>tensor([[0.5902, 0.4098],
        [0.1258, 0.8742],
        [0.5257, 0.4743],
        [0.1107, 0.8893]])
tensor([[1, 0],
        [0, 1],
        [0, 1],
        [1, 0]])
tensor([[0, 0, 0, 1, 0],
        [1, 1, 1, 1, 1],
        [1, 0, 0, 1, 1],
        [0, 1, 1, 0, 1]])

.expand()
-扩展-区别-内存
对tensor进行扩展,只能对某个维度为1的维度上进行扩展,跟广播基本一个意思,不开辟新内存,只是将stride改变,如果原数据的发生改变,则expand后的数据同时改变。
.repeat()
-重复-内存
同样是对tensor进行扩展,可以以原tensor作为一个元进行高维扩展,2 x 3的tensor扩展为3 x 3则扩展后的tensor为6 x 9。开辟新内存(但是梯度会落回原tensor)

a = nn.Parameter(torch.arange(3).view(3,1).float(), requires_grad=True)
b = a.expand(3,4)
c = a.repeat(2,4) # 3 x 1的扩展2 x 4后为6 x 4
print(a.data_ptr(),b.data_ptr(),c.data_ptr())
print(b)
print(c)
with torch.no_grad():
    a[0,0] = 3
print(b)
print(c)
>>2224894900800 2224894900800 2224868503680
tensor([[0., 0., 0., 0.],
        [1., 1., 1., 1.],
        [2., 2., 2., 2.]], grad_fn=<ExpandBackward>)
tensor([[0., 0., 0., 0.],
        [1., 1., 1., 1.],
        [2., 2., 2., 2.],
        [0., 0., 0., 0.],
        [1., 1., 1., 1.],
        [2., 2., 2., 2.]], grad_fn=<RepeatBackward>)
tensor([[3., 3., 3., 3.],
        [1., 1., 1., 1.],
        [2., 2., 2., 2.]], grad_fn=<AsStridedBackward>)
tensor([[0., 0., 0., 0.],
        [1., 1., 1., 1.],
        [2., 2., 2., 2.],
        [0., 0., 0., 0.],
        [1., 1., 1., 1.],
        [2., 2., 2., 2.]], grad_fn=<RepeatBackward>)

.data_ptr()
-调试-指针-内存
得到tensor的内存地址,便于调试时看函数是否开辟新的内存还是对原tensor进行浅拷贝。


@summary
-模型结构-参数-输入输出大小-结构可视化
将模型的参数信息打印出来,第二个参数为一个样本的shape(不带B的维度)

from torchsummary import summary
summary(model.net, (1,20,20))
>>----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
          MaskConv-1           [-1, 64, 18, 18]           3,200
         LayerNorm-2           [-1, 64, 18, 18]             128
...
...
        LeakyReLU-40           [-1, 64, 18, 18]               0
         MaskConv-41           [-1, 15, 18, 18]             975
================================================================
Total params: 226,447
Trainable params: 226,447
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 5.10
Params size (MB): 0.86
Estimated Total Size (MB): 5.96
----------------------------------------------------------------

python

@enumerate
-迭代
包装一个可迭代的对象,得到同时得到索引和内容

a = ['a', 'b', 'c', 'd']
for i,j in enumerate(a):
    print(i, j)
>>0 a
1 b
2 c
3 d

numpy

matplotlib

argparse

模板
parser = argparse.ArgumentParser()
parser.add_argument(’–dataset’, default=‘FLO’, help=‘FLO’)

一系列参数

opt = parser.parse_args()
参数详情
在这里插入图片描述

需求

pytorch指定使用哪块GPU

os.environ['CUDA_VISIBLE_DEVICES']= '0' # 指定0号GPU默认情况

将参数列表连接起来

from itertools import chain
chain(a.parameters(), b.parameters(), c.parameters())

便于多个模型统一设置optimizer


动态变化学习率

for g in optimizer.param_groups:    
	g['lr'] = f(g['lr'], epoch) # 根据epoch动态得到学习率

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值