pytorch学习笔记
Tensor
和numpy
对象共享内存torch.tensor()
或者tensor.clone()
总是会进行数据拷贝,新tensor和原来的数据不再共享内存。而torch.from_numpy()
或者tensor.detach()
可以新建一个tensor, 二者共享内存。当numpy的数据类型和Tensor的类型不一样的时候,数据会被复制,不会共享内存。- 要想使得Tensor使用autograd功能,只需要设置tensor.requries_grad=True.
- tensor有data、grad、grad_fn
- 没有参数的建议放在forward中使用nn.functional代替
rand/randn(*sizes)
均匀/标准分布torch.Tensor()
可以接受list,也可以tolist()
tensor.view
不会修改自身的数据,返回的新tensor与源tensor共享内存; 索引出来的结果也与原tensor共享内存,而高级索引操作的结果一般不和原始的Tensor共享内存。
a = t.arange(0, 6)
b = a.view(2, 3)
print(b)
b[0][0] = 3
print(a)
'''
tensor([[0, 1, 2],
[3, 4, 5]])
tensor([3, 1, 2, 3, 4, 5])
'''
# 高级索引
x = t.arange(0,27).view(3,3,3)
x[[1, 2], [1, 2], [2, 0]] # x[1,1,2]和x[2,2,0]
x[[2, 1, 0], [0], [1]] # x[2,0,1],x[1,0,1],x[0,0,1]
x[[0, 2], ...] # x[0] 和 x[2]
gather
和scatter_
相对应,为互逆操作
# gather
out[i][j] = input[index[i][j]][j] # dim=0
out[i][j] = input[i][index[i][j]] # dim=1
-
tensor数据类型
-
归并操作
-
比较操作
-
矩阵的转置会导致存储空间不连续,需调用它的
.contiguous
方法将其转为连续 -
repeat
与expand
功能类似,但是repeat会把相同数据复制多份,因此会占用额外的空间,expand不会占用额外空间,只会在需要的时候才扩充,可极大节省内存。 -
id为在内存中的地址、.storage()、.data_ptr()返回tensor首元素的内存地址
-
torch.set_printoptions(precision=10)设置打印tensor时的数值精度和格式
-
torch.manual_seed(1000) 设置随机种子
-
在反向传播过程中非叶子节点的导数计算完之后即被清空,可使用autograd.grad函数或者使用hook来保存。
torch.autograd.grad(z, y) # z对y的梯度,隐式调用backward()
# 第二种方法:使用hook
# hook是一个函数,输入是梯度,不应该有返回值
def variable_hook(grad):
print('y的梯度:',grad)
x = t.ones(3, requires_grad=True)
w = t.rand(3, requires_grad=True)
y = x * w
# 注册hook
hook_handle = y.register_hook(variable_hook)
z = y.sum()
z.backward()
# 除非你每次都要用hook,否则用完之后记得移除hook
hook_handle.remove()
- 不支持自动反向求导,就写一个Function
- torch.autograd.grad(y,x) 实现dy/dx
- t.autograd.gradcheck(Sigmoid.apply, (test_input,), eps=1e-3) 返回bool 采用数值逼近方式检验计算梯度的公式
- 赋值卷积核参数(初始化):
# 锐化卷积核
kernel = t.ones(3, 3)/-9.
kernel[1][1] = 1
conv = nn.Conv2d(1, 1, (3, 3), 1, bias=False)
conv.weight.data = kernel.view(1, 1, 3, 3)
out = conv(input)
- Sequential、ModuleList、ParameterList
# Sequential的三种写法
net1 = nn.Sequential()
net1.add_module('conv', nn.Conv2d(3, 3, 3))
net1.add_module('batchnorm', nn.BatchNorm2d(3))
net1.add_module('activation_layer', nn.ReLU())
net2 = nn.Sequential(
nn.Conv2d(3, 3, 3),
nn.BatchNorm2d(3),
nn.ReLU()
)
from collections import OrderedDict
net3= nn.Sequential(OrderedDict([
('conv1', nn.Conv2d(3, 3, 3)),
('bn1', nn.BatchNorm2d(3)),
('relu1', nn.ReLU())
]))
'''
net1: Sequential(
(conv): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
(batchnorm): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(activation_layer): ReLU()
)
net2: Sequential(
(0): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
(1): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU()
)
net3: Sequential(
(conv1): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
(bn1): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu1): ReLU()
)
'''
- 分组设置学习率
# 只为两个全连接层设置较大的学习率,其余层的学习率较小
special_layers = nn.ModuleList([net.classifier[0], net.classifier[3]])
special_layers_params = list(map(id, special_layers.parameters()))
base_params = filter(lambda p: id(p) not in special_layers_params, net.parameters())
optimizer = t.optim.SGD([
{'params': base_params},
{'params': special_layers.parameters(), 'lr': 0.01}
], lr=0.001 )
- model.train()函数,它会将当前module及其子module中的所有training属性都设为True,相应的,model.eval()函数会把training属性都设为False。
- nn.Module基类的构造函数
- 有一个预训练好的模型,需要提取模型的某一层(不是最后一层)的输出作为特征进行分类,但又不希望修改其原有的模型定义文件,这时就可以利用
钩子函数
。
model = VGG()
features = t.Tensor()
def hook(module, input, output):
'''把这层的输出拷贝到features中'''
features.copy_(output.data)
handle = model.layer8.register_forward_hook(hook)
_ = model(input)
# 用完hook后删除
handle.remove()
- result = obj.name会调用buildin函数getattr(obj, ‘name’),如果该属性找不到,会调用obj.getattr(‘name’)
- obj.name = value会调用buildin函数setattr(obj, ‘name’, value),如果obj对象实现了__setattr__方法,setattr会直接调用obj.setattr(‘name’, value’)
- nn.Module实现了自定义的__setattr__函数,当执行module.name=value时,会在__setattr__中判断value是否为Parameter或nn.Module对象,如果是则将这些对象加到_parameters和_modules两个字典中,而如果是其它类型的对象,如Variable、list、dict等,则调用默认的操作,将这个值保存在__dict__中。