1. 简介
汇总Pytorch的一些知识点
- 1. 简介
- 2. 查看网络参数
- 3. 分类问题
- 4. CrossEntropyLoss()和NLLLoss() 区别
- 5. 模型训练示例
- 6. 关闭梯度
- 7. GPU
- 8. 多GPU运行程序
- 9. Tensor
- 10. BN和Dropout在训练和测试的不同
- 11. Linear
- 12. Embedding
- 13. Linear参数维度
2. 查看网络参数
方法1
1
2for param in network.parameters():
print(param.shape)方法2
可以查看参数的名称1
2for 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 | > preds.argmax(dim=1) |
4. CrossEntropyLoss()和NLLLoss() 区别
CrossEntropyLoss()=log_softmax() + NLLLoss()
Pytorch nn.CrossEntropyLoss()和nn.NLLLoss() 区别
PyTorch 中,nn 与 nn.functional 有什么区别
5. 模型训练示例
1 | network = Network() |
6. 关闭梯度
关闭梯度有2种方法
方法1:在模型训练的时候,需要计算梯度,但是在测试的时候不需要计算梯度,那我们就可以使用
@torch.no_grad()
。下面代码示例求所有的预测结果1
2
3
4
5
6
7
8
9
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
3with 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 | #程序只能看到1,2,3序号的GPU,然后重新给它们编号为:0,1,2 |
也就是说device = torch.device("cuda")
还是1个GPU,等价于device = torch.device("cuda:X")
,其中X = torch.cuda.current_device()
【参考资料】
8. 多GPU运行程序
9. Tensor
10. BN和Dropout在训练和测试的不同
model.train()
:启用 BatchNormalization 和 Dropoutmodel.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$始终是大写