7 个有用的 PyTorch 技巧
原文:https://www.reddit.com/r/MachineLearning/comments/n9fti7/d_a_few_helpful_pytorch_tips_examples_included/
原文標(biāo)題:a_few_helpful_pytorch_tips_examples_included
譯文作者:kbsc13
聯(lián)系方式:
Github:https://github.com/ccc013/AI_algorithm_notes
知乎專(zhuān)欄:機(jī)器學(xué)習(xí)與計(jì)算機(jī)視覺(jué),AI 論文筆記
微信公眾號(hào):AI 算法筆記
前言
這是在國(guó)外的論壇 reddit 的機(jī)器學(xué)習(xí)版塊,有人總結(jié)了大概 7 個(gè)有用的 PyTorch 技巧,并且還附帶了 colab 的代碼例子和視頻,代碼和視頻鏈接分別如下:
代碼:https://colab.research.google.com/drive/15vGzXs_ueoKL0jYpC4gr9BCTfWt935DC?usp=sharing
視頻:https://youtu.be/BoC8SGaT3GE
視頻也同步上傳到我的 b 站上,鏈接如下:
https://www.bilibili.com/video/BV1YK4y1A7KM/
另外代碼和視頻可以在我的公眾號(hào)后臺(tái)回復(fù)"12"獲取。
1. 直接在目標(biāo)設(shè)備上創(chuàng)建 Tensors
第一個(gè)技巧就是使用 device 參數(shù)直接在目標(biāo)設(shè)備上創(chuàng)建張量,這里分別演示了兩種做法的運(yùn)行時(shí)間,
第一種是先在 cpu 上創(chuàng)建 tensors,然后用.cuda() 移動(dòng)到 GPU 上,代碼如下所示:
start_time = time.time()for _ in range(100):# Creating on the CPU, then transfering to the GPUcpu_tensor = torch.ones((1000, 64, 64))gpu_tensor = cpu_tensor.cuda()print('Total time: {:.3f}s'.format(time.time() - start_time))第二種則是直接在目標(biāo)設(shè)備上創(chuàng)建張量,代碼如下所示:
start_time = time.time()for _ in range(100):# Creating on GPU directlycpu_tensor = torch.ones((1000, 64, 64), device='cuda')print('Total time: {:.3f}s'.format(time.time() - start_time))兩種方法的運(yùn)行時(shí)間如下所示:
可以看到直接在目標(biāo)設(shè)備創(chuàng)建 Tensors 的速度是非常快速的;
2. 盡可能使用 Sequential 層
第二個(gè)技巧就是采用Sequential 層來(lái)讓代碼看起來(lái)更加簡(jiǎn)潔。
第一種搭建網(wǎng)絡(luò)模型的代碼如下:
class ExampleModel(nn.Module):def __init__(self):super().__init__()input_size = 2output_size = 3hidden_size = 16self.input_layer = nn.Linear(input_size, hidden_size)self.input_activation = nn.ReLU()self.mid_layer = nn.Linear(hidden_size, hidden_size)self.mid_activation = nn.ReLU()self.output_layer = nn.Linear(hidden_size, output_size)def forward(self, x):z = self.input_layer(x)z = self.input_activation(z)z = self.mid_layer(z)z = self.mid_activation(z)out = self.output_layer(z)return out其運(yùn)行效果如下:
而采用 Sequential 來(lái)搭建網(wǎng)絡(luò)模型的寫(xiě)法如下所示:
class ExampleSequentialModel(nn.Module):def __init__(self):super().__init__()input_size = 2output_size = 3hidden_size = 16self.layers = nn.Sequential(nn.Linear(input_size, hidden_size),nn.ReLU(),nn.Linear(hidden_size, hidden_size),nn.ReLU(),nn.Linear(hidden_size, output_size))def forward(self, x):out = self.layers(x)return out其運(yùn)行效果如下:
可以看到用 nn.Sequential 來(lái)搭建網(wǎng)絡(luò)模型的代碼是更加的簡(jiǎn)潔。
3. 不要使用列表來(lái)存放網(wǎng)絡(luò)層
第三個(gè)技巧是不建議使用列表來(lái)存放創(chuàng)建的網(wǎng)絡(luò)層,因?yàn)?nn.Module 類(lèi)不能成功注冊(cè)他們。相反,應(yīng)該把列表傳入到nn.Sequential 中。
首先是展示一個(gè)錯(cuò)誤的例子:
class BadListModel(nn.Module):def __init__(self):super().__init__()input_size = 2output_size = 3hidden_size = 16self.input_layer = nn.Linear(input_size, hidden_size)self.input_activation = nn.ReLU()# Fairly common when using residual layersself.mid_layers = []for _ in range(5):self.mid_layers.append(nn.Linear(hidden_size, hidden_size))self.mid_layers.append(nn.ReLU())self.output_layer = nn.Linear(hidden_size, output_size)def forward(self, x):z = self.input_layer(x)z = self.input_activation(z)for layer in self.mid_layers:z = layer(z)out = self.output_layer(z)return outbad_list_model = BadListModel() print('Output shape:', bad_list_model(torch.ones([100, 2])).shape) gpu_input = torch.ones([100, 2], device='cuda') gpu_bad_list_model = bad_list_model.cuda() print('Output shape:', bad_list_model(gpu_input).shape)上述寫(xiě)法在打印第二句的時(shí)候,會(huì)報(bào)錯(cuò):
正確的寫(xiě)法:
class CorrectListModel(nn.Module):def __init__(self):super().__init__()input_size = 2output_size = 3hidden_size = 16self.input_layer = nn.Linear(input_size, hidden_size)self.input_activation = nn.ReLU()# Fairly common when using residual layersself.mid_layers = []for _ in range(5):self.mid_layers.append(nn.Linear(hidden_size, hidden_size))self.mid_layers.append(nn.ReLU())self.mid_layers = nn.Sequential(*self.mid_layers)self.output_layer = nn.Linear(hidden_size, output_size)def forward(self, x):z = self.input_layer(x)z = self.input_activation(z)z = self.mid_layers(z)out = self.output_layer(z)return outcorrect_list_model = CorrectListModel() gpu_input = torch.ones([100, 2], device='cuda') gpu_correct_list_model = correct_list_model.cuda() print('Output shape:', correct_list_model(gpu_input).shape)其打印結(jié)果:
4. 好好使用 distributions
第四個(gè)技巧是PyTorch 的 torch.distributions 庫(kù)中有一些很棒的對(duì)象和方法來(lái)實(shí)現(xiàn)分布式,但是并沒(méi)有得到很好地使用,官方文檔鏈接:
https://pytorch.org/docs/stable/distributions.html
下面是一個(gè)使用的例子:
5. 在長(zhǎng)期指標(biāo)上使用 detach
第 5 個(gè)技巧是在每個(gè) epoch 之間如果需要存儲(chǔ)張量指標(biāo),采用 .detach() 來(lái)防止內(nèi)存泄露。
下面用一個(gè)代碼例子來(lái)說(shuō)說(shuō)明,首先是初始配置:
# Setup example_model = ExampleModel() data_batches = [torch.rand((10, 2)) for _ in range(5)] criterion = nn.MSELoss(reduce='mean')錯(cuò)誤的代碼例子:
losses = []# Training loop for batch in data_batches:output = example_model(batch)target = torch.rand((10, 3))loss = criterion(output, target)losses.append(loss)# Optimization happens hereprint(losses)打印結(jié)果如下:
正確的寫(xiě)法
losses = []# Training loop for batch in data_batches:output = example_model(batch)target = torch.rand((10, 3))loss = criterion(output, target)losses.append(loss.item()) # Or `loss.item()`# Optimization happens hereprint(losses)打印結(jié)果如下:
這里應(yīng)該調(diào)用 loss.item() 方法來(lái)保存每個(gè) epoch 中的 loss 數(shù)值。
6. 刪除 GPU上模型的技巧
第六個(gè)技巧是可以采用 torch.cuda.empty_cache() 來(lái)清理 GPU 緩存,這個(gè)方法在使用 notebook 的時(shí)候很有幫助,特別是你想要?jiǎng)h除和重新創(chuàng)建一個(gè)很大的模型的時(shí)候。
使用例子如下所示:
import gcexample_model = ExampleModel().cuda()del example_modelgc.collect() # The model will normally stay on the cache until something takes it's place torch.cuda.empty_cache()7. 測(cè)試前調(diào)用 eval()
最后一個(gè)是開(kāi)始測(cè)試前別忘了調(diào)用 model.eval() ,這個(gè)很簡(jiǎn)單但很容易忘記。這個(gè)操作會(huì)讓一些在訓(xùn)練和驗(yàn)證階段設(shè)置不一樣的網(wǎng)絡(luò)層有必要的改變,會(huì)有影響的模塊包括:
- Dropout
- Batch Normalization
- RNNs
- Lazy Variants
這個(gè)可以參考:https://stackoverflow.com/questions/66534762/which-pytorch-modules-are-affected-by-model-eval-and-model-train
使用例子如下:
example_model = ExampleModel()# Do trainingexample_model.eval()# Do testingexample_model.train()# Do training again總結(jié)
以上是生活随笔為你收集整理的7 个有用的 PyTorch 技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 搞清这些陷阱,NULL和三值逻辑再也不会
- 下一篇: MATLAB中saveas函数使用