Pytorch之知识点汇总

1. 简介

汇总Pytorch的一些知识点

2. 查看网络参数

  • 方法1

    1
    2
    for param in network.parameters():
    print(param.shape)
  • 方法2
    可以查看参数的名称

    1
    2
    for name, param in network.named_parameters():
    print(name, '\t\t', param.shape)

3. 分类问题

例如Fashion-MNIST分类任务中,一共有10类。假设batch_size=16,每个batch的feature维度为(16,1,28,28),label的维度(16,),经过模型最终输出的预测结果维度(16,10),然后我们使用argmax()来得出最终的预测类别。然后可以和真实label比较,看预测结果的正确性,计算预测正确的个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
> preds.argmax(dim=1)
tensor([5, 5, 5, 5, 5, 5, 4, 5, 5, 4])

> labels
tensor([9, 0, 0, 3, 0, 2, 7, 2, 5, 5])

> preds.argmax(dim=1).eq(labels)
tensor([False, False, False, False, False, False, False, False, True, False], dtype=torch.bool)

> preds.argmax(dim=1).eq(labels).sum()
tensor(1)

> preds.argmax(dim=1).eq(labels).sum().item()
1

#得到每个batch预测正确的样本
def get_num_correct(preds, labels):
return preds.argmax(dim=1).eq(labels).sum().item()

4. CrossEntropyLoss()和NLLLoss() 区别

CrossEntropyLoss()=log_softmax() + NLLLoss()

Pytorch nn.CrossEntropyLoss()和nn.NLLLoss() 区别

Pytorch里的CrossEntropyLoss详解

PyTorch 中,nn 与 nn.functional 有什么区别

5. 模型训练示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
network = Network()

train_loader = torch.utils.data.DataLoader(train_set, batch_size=100)
optimizer = optim.Adam(network.parameters(), lr=0.01)

for epoch in range(10):

total_loss = 0
total_correct = 0

for batch in train_loader: # Get Batch
images, labels = batch

preds = network(images) # Pass Batch
loss = F.cross_entropy(preds, labels) # Calculate Loss

optimizer.zero_grad()
loss.backward() # Calculate Gradients
optimizer.step() # Update Weights

total_loss += loss.item()
total_correct += get_num_correct(preds, labels)

print(
"epoch", epoch,
"total_correct:", total_correct,
"loss:", total_loss
)

6. 关闭梯度

关闭梯度有2种方法

  • 方法1:在模型训练的时候,需要计算梯度,但是在测试的时候不需要计算梯度,那我们就可以使用@torch.no_grad()。下面代码示例求所有的预测结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @torch.no_grad()
    def get_all_preds(model, loader):
    all_preds = torch.tensor([])
    for batch in loader:
    images, labels = batch
    preds = model(images)
    all_preds = torch.cat(
    (all_preds, preds),dim=0)
    return all_preds

使用@torch.no_grad()就不用再记录梯度的轨迹(不用再保存动态图的计算轨迹),省内存。

  • 方法2:
    使用with torch.no_grad()在函数内部

    1
    2
    3
    with torch.no_grad():
    prediction_loader = torch.utils.data.DataLoader(train_set, batch_size=10000)
    train_preds = get_all_preds(network, prediction_loader)

7. GPU

在这里原先一直有个误区,误认为device = torch.device("cuda")获取所有的GPU,device = torch.device("cuda:0")获取第一个GPU。下面是正解:

1
2
3
4
5
6
7
8
9
10
11
12
13
#程序只能看到1,2,3序号的GPU,然后重新给它们编号为:0,1,2
> os.environ["CUDA_VISIBLE_DEVICES"] = '1,2,3'

> device = torch.device("cuda:0")#获取下标为0的GPU
device(type='cuda', index=0)

#如果不指定cuda编号,其实有一个默认编号,
#默认为torch.cuda.current_device(),该值默认为0
> device = torch.device("cuda")
device(type='cuda')

> torch.cuda.current_device()
0

也就是说device = torch.device("cuda")还是1个GPU,等价于device = torch.device("cuda:X"),其中X = torch.cuda.current_device()

参考资料

torch.device

CUDA SEMANTICS

8. 多GPU运行程序

Pytorch之GPU程序

运行GPU程序

9. Tensor

Pytorch之Tensor学习

10. BN和Dropout在训练和测试的不同

model.train():启用 BatchNormalization 和 Dropout
model.eval():不启用 BatchNormalization 和 Dropout
训练完train样本后,生成的模型model要用来测试样本。在model(test)之前,需要加上model.eval(),否则的话,有输入数据,即使不训练,它也会改变权值。这是model中含有batch normalization层所带来的的性质。

参考资料
Pytorch model.train 与 model.eval
‘model.eval()’ vs ‘with torch.no_grad()’
https://github.com/pytorch/examples/word_language_model

11. Linear

原先误以为Pytorch中的Linear的输入只能接受二维数据,实际上Linear的输入数据可以是三维、四维等更多维。但是输入数据的最后一维一定要和in_dim一致,输出数据维度就是把in_dim换成了out_dim,前面所有的维度都不变
例如定义一个全连接nn.Linear(10,5),输入数据维度为(3,6,10),输出维度为(3,6,5)。即输入数据最后一个维度一定要和in_dim一致,也不用纠结到底3是batch_size,还是6是batch_size,因为最终输出的数据只有最后一个维度变化,前面维度都不变。

1
dense = nn.Linear(in_dim,out_dim)

2020.3.7更新

12. Embedding

Embedding层常用在词嵌入中,目的是将高维数据变成稠密的低维数据。例如:字典共9个字:[我,你,看,吃,吧,吗,饭,了,的],例句:吃饭了吗,对这句话用向量表示有2种方式:

  • one-hot表示
    [0,0,0,1,0,0,0,0,0],
    [0,0,0,0,0,0,1,0,0],
    [0,0,0,0,0,0,0,1,0],
    [0,0,0,0,0,1,0,0,0]
    one-hot表示过于稀疏,如果字典中的层变大,维度会非常高
  • 使用Embedding,字典中共有9个字,下标从0~8,例句被表示为[3,6,7,5],但是只用数字并不能表示字的含义和相似度,下面使用Embedding对其嵌入。

    1
    2
    3
    4
    5
    6
    7
    8
    # example with padding_idx
    embedding = nn.Embedding(9, 3)
    input = torch.LongTensor([[3,6,7,5]])
    embedding(input)
    tensor([[[ 0.0000, 0.0000, 0.0000],
    [ 0.1535, -2.0309, 0.9315],
    [ 0.0000, 0.0000, 0.0000],
    [-0.1655, 0.9897, 0.0635]]])

    CLASS torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None, max_norm=None, norm_type=2.0, scale_grad_by_freq=False, sparse=False, _weight=None)

    num_embeddings:原始数据维度,例如字典中有9个字,该值为9
    embedding_dim:嵌入维度,每个字用3维向量表示,该值为3
    输入维度:()任意维度
    输出维度:(\
    ,embedding_dim),*表示输入维度
    例如输入维度(16,100),输出为(16,100,3),表示有16个句子,每个句子100个字,经过Embedding层后,有16个句子,每个句子100个字,每个字用3维特征表示。

    在时空领域中,经常需要考虑外部因素,例如时间,天气,holiday等,需要对外部因素进行Embedding,例如https://github.com/UrbComp/DeepTTE


2020.7.8更新

13. Linear参数维度

做全连接时,我们平时看到的公式有以下形式:
$Y=XW+b$(实际方便使用)
$Y=XW^T+b$(Pytorch封装)
$Y=W^TX+b$

因为不同的公式,此时的$W$形状也不同,假设$X\in\mathbb{R}^{100\times2}$表示100个样本,每个样本有2维,假设输出维度5
$y=XW+b$,$W\in\mathbb{R}^{2\times5}$
$y=XW^T+b$,$W\in\mathbb{R}^{5\times2}$
$y=W^TX+b$,对于这种情况,默认$X$中每个样本是列向量,即$X\in\mathbb{R}^{2\times100}$,$W\in\mathbb{R}^{2\times5}$

在Pytorch中的Linear中采用的是公式2,参数形状$W\in\mathbb{R}^{输出维度\times输入维度}$

但在实际使用中,为了方便,一般用公式1,此时$W\in\mathbb{R}^{输入维度\times输出维度}$

在写公式时,需要注意公式的大写还是小写

$Y=XW+b$这里的$X,Y$表示所有样本
$y=xW+b$这里的$x,y$表示一个样本
但这两种情况中,$W$始终是大写

打赏
0%