NarcissusInMirror / DailyWorkLog

0 stars 0 forks source link

Pytorch学习笔记 #7

Open NarcissusInMirror opened 4 years ago

NarcissusInMirror commented 4 years ago

torch.nn.Parameter

Parameter类是Tensor的子类,是一个模型内可以进行梯度更新的参数,可通过model.parameters()进行迭代,

for param in model.parameters():
    print(type(param.data), param.size(), param.names)

在优化器中会指定这些参数

optimizer = optim.SGD(model.parameters(), lr=0.0001, momentum=0.9)

因此,如果只是定义了tensor,没有加到模型的parameter里面,这些tensor是无法被训练的,即使requires_grad设置为了True,因此需要用Parametertensor进行包装。以下的代码写在模块的__init__函数下,会自动认为加入到当前模块中

class ResnetAttention(nn.Module):
    def __init__(self, model, num_classes):
        super(ResnetAttention, self).__init__()
        ...
        self.w1 = nn.Parameter(torch.tensor([1.]), requires_grad=True)
        self.w2 = nn.Parameter(torch.tensor([1.]), requires_grad=True)
        self.w3 = nn.Parameter(torch.tensor([1.]), requires_grad=True)
       ...
#注意!这里后面不能加上.cuda(),否则会从parameter退回tensor,模块会默认把所有参数放到gpu上

下面的代码是在模块中加入parameter的另一种方法,name参数传入字符串,可以通过这个名字来访问该parameterparam参数则是需要加入模块的parmameter,注意,必须是parametertensor不行,这里可能是用来加入到其他模块中?

self.register_parameter(param=self.w1, name='aaa')
self.register_parameter(name='bbb', param=self.w2)
self.register_parameter(name='ccc', param=self.w3)
NarcissusInMirror commented 4 years ago

Pytorch的自定义拓展

image 每个tensor可以记录梯度;这个自定义的过程比nn.Module要多定义一个backward函数,也就是需要自定义梯度怎么回传;backward最后返回的是一个和输入形状一样的tensor,每个位置对应着

NarcissusInMirror commented 4 years ago

2019.6.21工作日志

Pytorch 实战总结

输入数据维度:(sample_size, 25) 标签:(sample_size)

CrossEntropyLoss

image 可以看到,要求的输入维度形状,即output = model.forward(input_data)output的形状为(批大小,分类个数 ),维度为2;输入的标签维度应为(批大小,),维度为1,且以0~N-1代表N个类别,不接受二维的one-hot编码,这些需要在进行数据处理时注意。

BatchNorm1d

image image

1d的batchnorm输入的向量是2维或者3维的,即(批大小,特征维数)(批大小,通道数,特征维数)。当输入为2维时features参数为特征维数;当输入为3维时,features参数为通道数。但实际上都是沿着channel的维度进行的batchnorm。

BatchNorm2d

image image

顺带学习一下2d的batchnorm。batchnorm2d的输入必须是4维的,(批大小,通道数,图像高度,图像宽度),num_features为通道数。

batch1d又称为temporal batchnorm, batch2d又称为spatial batchnormal

image image

numpy axis选择

以np.mean(nparray, axis)为例

>>> a = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9], [10, 11, 12])
>>> a
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12]])
>>> a.shape
(4, 3)
>>> np.mean(a, axis=0)
array([5.5, 6.5, 7.5])
>>> np.mean(a, axis=1)
array([ 2.,  5.,  8., 11.])

以axis=0为例,a.shape=[4, 3]四行三列,当选择axis=0时,即选中4,求平均时则求的是4个元素的平均,即按列平均。同理,axis=1时,选中3,求平均时则求的是三个元素的平均,即按行平均。

torch.max 返回值和索引

torch.max(input, dim, keepdim=False, out=None) -> (Tensor, LongTensor)

>>> a = torch.randn(3,3)
>>> a
-0.7845 -1.7758 -1.5602
 1.9941 -1.2037 -0.2332
 0.1480 -0.0921  0.4939
[torch.FloatTensor of size 3x3]

>>> torch.max(a)
1.9940658807754517

>>> torch.max(a,0)
(
 1.9941
-0.0921
 0.4939
[torch.FloatTensor of size 3]
,
 1
 2
 2
[torch.LongTensor of size 3]
)

pytorch Variable的detach和detach_

先占个坑,本次实验中,需要把forward后的向量转成numpy数组进行一些操作,而输入的tensor经过了如下操作,大概是改为gpu向量,具体还需了解,回头补上。

data, label = data.cuda(), label.cuda()
data, label = Variable(data), Variable(label)
optimizer.zero_grad()
output = model.forward(data)

因此进行操作前需要先detach出来并且放到cpu中output = output.detach().cpu()

scipy的softmax

image

from scipy.special import softmax
output = softmax(output, axis=1)

存储和加载模型

image

存储:

  torch.save(model, PATH),model为定义过的nn.Module的子类模块

加载:

  model = torch.load(PATH)
  model.eval()
  # 保存和加载整个模型
  torch.save(model_object, 'model.pkl')
  model = torch.load('model.pkl')
  # 仅保存和加载模型参数(推荐使用)
  torch.save(model_object.state_dict(), 'params.pkl')
  model_object.load_state_dict(torch.load('params.pkl'))

Adaptive AvgPool2d

image

NarcissusInMirror commented 4 years ago

batchnorm对训练和验证的影响

警惕!损失Loss为Nan或者超级大的原因

NarcissusInMirror commented 4 years ago

*layer

layers = []
layers.append(...) # 在layers中添加相应的层
return nn.Sequential(*layers) # 把layers中的层添加到sequential中

权重初始化 官方文档1.3.0

self.lateral_conv_1 = nn.Conv2d(64, 512, 1, bias=False) # 定义层
# 使用nn.init提供的初始化方法,参数传入相关层的需要初始化的参数
nn.init.kaiming_normal_(self.lateral_conv_1.weight, mode='fan_out', nonlinearity='relu') 

# 对于Sequential来说,可以通过index来访问其中包含的层
self.fc1_1 = nn.Sequential(
    nn.Linear(512 * 1 * 1, self.L),
    nn.ReLU(),
)

nn.init.normal_(self.fc1_1[0].weight)

pytorch如何初始化全连接层

image