PyTorch常用代碼段

2021-01-14 CVHub


本次實驗的代碼大家可以到下面的 GitHub倉庫 連結中進行下載與學習(點擊文末閱讀原文可直達)。

https://github.com/CVHuber/Pytorch_common_code張量基本信息
tensor = torch.randn(3,4,5)
print(tensor.type())  # 數據類型
print(tensor.size())  # 張量大小
print(tensor.dim())   # 維度的數量

張量命名
NCHW = [『N』, 『C』, 『H』, 『W』] 
images = torch.randn(32, 3, 56, 56, names=NCHW) 
images.sum('C') 
images.select('C', index=0)

torch.Tensor與np.ndarray轉換
ndarray = tensor.cpu().numpy() 
tensor = torch.from_numpy(ndarray).float() 

Torch.tensor與PIL.Image轉換
# torch.Tensor -> PIL.Image 
image = torchvision.transforms.functional.to_pil_image(tensor) 
# PIL.Image -> torch.Tensor 
path = r'./figure.jpg' 
tensor =torchvision.transforms.functional.to_tensor(PIL.Image.open(path))

np.ndarray與PIL.Image的轉換
image = PIL.Image.fromarray(ndarray.astype(np.uint8))
ndarray = np.asarray(PIL.Image.open(path))

張量拼接
tensor = torch.cat(list_of_tensors, dim=0) 
tensor = torch.stack(list_of_tensors, dim=0)

將整數標籤轉為one-hot編碼

# pytorch 的標記默認從 0 開始
tensor = torch.tensor([0, 2, 1, 3])
N = tensor.size(0)
num_classes = 4 
one_hot = torch.zeros(N, num_classes).long() one_hot.scatter_(dim=1,index=torch.unsqueeze(tensor,dim=1),src=torch.ones(N,num_classes).long())

矩陣乘法
# Matrix multiplcation: (m*n) * (n*p) * -> (m*p). 
result = torch.mm(tensor1, tensor2) 
# Batch matrix multiplication: (b*m*n) * (b*n*p) -> (b*m*p) 
result = torch.bmm(tensor1, tensor2) 
# Element-wise multiplication. 
result = tensor1 * tensor2

模型定義

兩層卷積網絡的示例
class ConvNet(nn.Module): 
  def __init__(self, num_classes=10): 
    super(ConvNet, self).__init__() 
    self.layer1 = nn.Sequential( nn.Conv2d(1, 16, kernel_size=5, stride=1, padding=2), nn.BatchNorm2d(16), nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2)) 
    self.layer2 = nn.Sequential( nn.Conv2d(16, 32, kernel_size=5, stride=1, padding=2), nn.BatchNorm2d(32), nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2)) 
    self.fc = nn.Linear(7*7*32, num_classes)
     
  def forward(self, x): 
    out = self.layer1(x) 
    out = self.layer2(out) 
    out = out.reshape(out.size(0), -1) 
    out = self.fc(out) return out 
model = ConvNet(num_classes).to(device)

計算模型整體參數量
num_parameters = sum(torch.numel(parameter) for parameter in model.parameters())

模型權重初始化model.modules() :迭代地遍歷模型的所有子層model.children() :只遍歷模型下的一層

for layer in model.modules():
  if isinstance(layer, torch.nn.Conv2d):
      torch.nn.init.kaiming_normal_(layer.weight,mode='fan_out', nonlinearity='relu')
  if layer.bias is not None:
      torch.nn.init.constant_(layer.bias, val=0.0)
  elif isinstance(layer, torch.nn.BatchNorm2d):
      torch.nn.init.constant_(layer.weight, val=1.0) torch.nn.init.constant_(layer.bias, val=0.0)
  elif isinstance(layer, torch.nn.Linear):
      torch.nn.init.xavier_normal_(layer.weight)
  if layer.bias is not None:
      torch.nn.init.constant_(layer.bias, val=0.0)
      layer.weight = torch.nn.Parameter(tensor)

將在 GPU 保存的模型加載到 CPU
model.load_state_dict(torch.load('model.pth',map_location='cp'))

計算數據集的均值和標準差
import os
import cv2
import numpy as np
from torch.utils.data import Dataset
from PIL import Image
def compute_mean_and_std(dataset):
    # 輸入 PyTorch 的 dataset,輸出均值和標準差
    mean_r = 0
    mean_g = 0
    mean_b = 0
    for img, _ in dataset: 
      img = np.asarray(img) # PIL Image轉為numpy array
      mean_b += np.mean(img[:, :, 0]) 
      mean_g += np.mean(img[:, :, 1]) 
      mean_r += np.mean(img[:, :, 2])
      
    mean_b /= len(dataset)
    mean_g /= len(dataset)
    mean_r /= len(dataset)
    
    diff_r = 0
    diff_g = 0
    diff_b = 0
    N = 0
    for img, _ in dataset: 
      img = np.asarray(img) 
      
      diff_b += np.sum(np.power(img[:, :, 0] - mean_b, 2)) 
      diff_g += np.sum(np.power(img[:, :, 1] - mean_g, 2)) 
      diff_r += np.sum(np.power(img[:, :, 2] - mean_r, 2))
      
      N += np.prod(img[:, :, 0].shape)
      
    std_b = np.sqrt(diff_b / N)
    std_g = np.sqrt(diff_g / N)
    std_r = np.sqrt(diff_r / N)
    
    mean = (mean_b.item() / 255.0, mean_g.item() / 255.0, mean_r.item() / 255.0) 
    std = (std_b.item() / 255.0, std_g.item() / 255.0, std_r.item() / 255.0) return mean, std

常用訓練和驗證數據預處理其中,ToTensor 操作會將 PIL.Image 或形狀為 H×W×D,數值範圍為 [0, 255] 的 np.ndarray 轉換為形狀為 D×H×W,數值範圍為 [0.0, 1.0] 的 torch.Tensor。
train_transform = torchvision.transforms.Compose([torchvision.transforms.RandomResizedCrop(size=224, scale=(0.08, 1.0)),   torchvision.transforms.RandomHorizontalFlip(), torchvision.transforms.ToTensor(), torchvision.transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), ]) 
val_transform = torchvision.transforms.Compose([torchvision.transforms.Resize(256), torchvision.transforms.CenterCrop(224), torchvision.transforms.ToTensor(), torchvision.transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), ])

分類模型訓練代碼
# 損失函數和優化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# 訓練模型
total_step = len(train_loader) 
for epoch in range(num_epochs): 
  for i ,(images, labels) in enumerate(train_loader): 
    images = images.to(device) 
    labels = labels.to(device)
    
    # 計算損失
    outputs = model(images)
    loss = criterion(outputs, labels)
    
    # 梯度反向傳播
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if (i+1) % 100 == 0: 
    print('Epoch: [{}/{}], Step: [{}/{}], Loss: {}' 
    .format(epoch+1, num_epochs, i+1, total_step, loss.item()))

分類模型測試代碼
# 測試模型
model.eval() 
# eval mode(batch norm uses moving mean/variance 
#instead of mini-batch mean/variance) 
with torch.no_grad(): 
  correct = 0 
  total = 0 
  for images, labels in test_loader: 
    images = images.to(device) 
    labels = labels.to(device)
    outputs = model(images)
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum().item()
  print('Test accuracy of the model on the 10000 test images: {} %' .format(100 * correct / total))

自定義損失函數
class MyLoss(torch.nn.Moudle): 
  def __init__(self): 
    super(MyLoss, self).__init__() 
  def forward(self, x, y): 
    loss = torch.mean((x - y) ** 2) 
    return loss

預訓練模型修改
class Net(nn.Module):
  def __init__(self , model):
    super(Net, self).__init__()
      # 忽略模型的最後兩層
      self.resnet_layer = nn.Sequential(*list(model.children())[:-2])
      # 自定義層
      self.transion_layer = nn.ConvTranspose2d(2048, 2048, kernel_size=14, stride=3)
      self.pool_layer = nn.MaxPool2d(32)  
      self.Linear_layer = nn.Linear(2048, 8)
            
  def forward(self, x):
      x = self.resnet_layer(x)
      x = self.transion_layer(x)
      x = self.pool_layer(x)
      x = x.view(x.size(0), -1) 
      x = self.Linear_layer(x) 
      return x
      
resnet = models.resnet50(pretrained= True)
model = Net(resnet)

學習率衰減策略
# 定義優化器
optimizer_ExpLR = torch.optim.SGD(net.parameters(),lr=0.1)
# 指數衰減
ExpLR = torch.optim.lr_scheduler.ExponentialLR(optimizer_ExpLR,gamma=0.98)
# 固定步長衰減
optimizer_StepLR = torch.optim.SGD(net.parameters(), lr=0.1)
StepLR = torch.optim.lr_scheduler.StepLR(optimizer_StepLR, step_size=step_size, gamma=0.65)
# 多步長衰減
optimizer_MultiStepLR = torch.optim.SGD(net.parameters(), lr=0.1)
torch.optim.lr_scheduler.MultiStepLR(optimizer_MultiStepLR,
                    milestones=[200, 300, 320, 340, 200], gamma=0.8)
# 餘弦退火衰減
optimizer_CosineLR = torch.optim.SGD(net.parameters(), lr=0.1)
CosineLR = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer_CosineLR, T_max=150, eta_min=0)

保存與加載斷點
# 加載模型
if resume:
model_path = os.path.join('model', 'best_checkpoint.pth.tar')
assert os.path.isfile(model_path)
checkpoint = torch.load(model_path)
best_acc = checkpoint['best_acc']
start_epoch = checkpoint['epoch'] model.load_state_dict(checkpoint['model']) optimizer.load_state_dict(checkpoint['optimizer'])
print('Load checkpoint at epoch {}.'.format(start_epoch))
print('Best accuracy so far {}.'.format(best_acc))
# 訓練模型
for epoch in range(start_epoch, num_epochs):
...
# 測試模型
...
# 保存checkpoint
is_best = current_acc > best_acc
best_acc = max(current_acc, best_acc)
checkpoint = { 'best_acc': best_acc, 'epoch': epoch + 1, 'model': model.state_dict(), 'optimizer': optimizer.state_dict(), }
model_path = os.path.join('model', 'checkpoint.pth.tar') best_model_path = os.path.join('model', 'best_checkpoint.pth.tar') torch.save(checkpoint, model_path)
if is_best: shutil.copy(model_path, best_model_path)

model(x) 定義好後,用 model.train() 和 model.eval() 切換模型狀態。

使用with torch.no_grad() 包含無需計算梯度的代碼塊

model.eval()與torch.no_grad的區別:前者是將模型切換為測試態,例如BN和Dropout在訓練和測試階段使用不同的計算方法;後者是關閉張量的自動求導機制,減少存儲和加速計算。

torch.nn.CrossEntropyLoss 等價於 torch.nn.functional.log_softmax + torch.nn.NLLLoss。

ReLU可使用inplace操作減少顯存消耗。

使用半精度浮點數 half() 可以節省計算資源同時提升模型計算速度,但需要小心數值精度過低帶來的穩定性問題。


本次實驗的代碼大家可以到下面的 GitHub倉庫 連結中進行下載與學習(點擊文末閱讀原文可直達)。

https://github.com/CVHuber/Segmentation-getting-started



相關焦點

  • 華為雲應用編排,手把手教您完成pytorch代碼部署
    本文將以一個使用了pytorch的demo代碼pytorch-classify為例,通過華為雲上的容器服務一鍵式部署, 5 分鐘完成免費的雲上pytorch代碼的部署。傳統部署方式首先是準備環境。先有個伺服器,這臺伺服器需要能夠被外部訪問。
  • 一行代碼安裝,TPU也能運行PyTorch,修改少量代碼即可快速移植
    pip install pytorch-lightning該項目的開發者William Falcon說,PyTorch Lightning是他在紐約大學和FAIR做博士生時研發,專門為從事AI研究的專業研究人員和博士生創建的。
  • PyTorch最佳實踐,教你寫出一手風格優美的代碼
    這是一個開發的項目,歡迎其它讀者改進該文檔:https://github.com/IgorSusmelj/pytorch-styleguide 本文檔主要由三個部分構成:首先,本文會簡要清點 Python 中的最好裝備。接著,本文會介紹一些使用 PyTorch 的技巧和建議。
  • 一行代碼即可調用18款主流模型!PyTorch Hub輕鬆解決論文可復現性
    圖靈獎得主Yann LeCun發推表示,只需要一行代碼就可以調用所有倉庫裡的模型,通過一個pull請求來發布你自己的模型。同時,PyTorch Hub整合了Google Colab,併集成了論文代碼結合網站Papers With Code,可以直接找到論文的代碼。PyTorch Hub怎麼用?
  • 新版PyTorch 1.2 已發布:功能更多、兼容更全、操作更快!
    除了這些新功能之外,用戶對 TensorBoard(https://pytorch.org/docs/stable/tensorboard.html)的使用也更便捷,現在只需輸入代碼「from torch.utils.tensorboard import SummaryWriter」,即可開始使用。
  • 用Java實現目標檢測|PyTorch
    只需幾行代碼,用戶就可以輕鬆部署深度學習模型用作推理。那麼我們就開始上手用DJL部署一個PyTorch 模型吧。前期準備用戶可以輕鬆使用maven或者gradle等Java常用配置管理包來引用DJL。下面是一個示例:plugins {id'java'}repositories { jcenter()}dependencies { implementation "ai.djl:api:0.4.0" implementation "ai.djl:repository:0.4.0" runtimeOnly "ai.djl.pytorch
  • 華為雲pytorch代碼怎麼部署?
    華為雲pytorch代碼怎麼部署? 本文將以一個使用了pytorch的demo代碼pytorch-classify為例,通過華為雲上的容器服務一鍵式部署,5分鐘完成免費的雲上pytorch代碼的部署。 傳統部署方式 首先是準備環境。先有個伺服器,這臺伺服器需要能夠被外部訪問。
  • 分離硬體和代碼、穩定 API,PyTorch Lightning 1.0.0 版本正式發布
    William Falcon 表示自己非常期待有一天,當用戶查看 GitHub 上的複雜項目時,深度學習代碼不再那麼令人望而生畏。特斯拉 AI 負責人 Andrej Karpathy 也評論稱:「這看起來很棒,也很有前途。PyTorch Lightning 倡導對深度學習代碼進行重構,將『工程(硬體)』與『科學(代碼)』分割開,然後將前者委託給框架。」
  • 用Java實現目標檢測 | PyTorch
    只需幾行代碼,用戶就可以輕鬆部署深度學習模型用作推理。那麼我們就開始上手用DJL部署一個PyTorch 模型吧。前期準備用戶可以輕鬆使用maven或者gradle等Java常用配置管理包來引用DJL。 jcenter()}dependencies { implementation "ai.djl:api:0.4.0" implementation "ai.djl:repository:0.4.0" runtimeOnly "ai.djl.pytorch
  • 圖靈獎得主力推:PyTorch 1.3 今天發布
    本次 PyTorch1.3 更新增加了很多的新特性,包括無縫行動裝置部署、量化模型以加速推斷、前端改進(如對張量進行命名和創建更乾淨的代碼)。PyTorch 官方同時還開源了很多新工具和庫。在開發者大會上,PyTorch 官方表示甚至微軟都將其列入了支持的深度學習框架中。
  • Pytorch中的分布式神經網絡訓練|pytorch|bat|拆分|調用_網易訂閱
    跨GPU的模型拆分  跨GPU拆分模型非常簡單,不需要太多代碼更改。 在設置網絡本身時,可以將模型的某些部分移至特定的GPU。 之後,在通過網絡轉發數據時,數據也需要移動到相應的GPU。 下面是執行相同操作的PyTorch代碼段。
  • 重磅| Torch7團隊開源PyTorch:Python優先的深度學習框架
    官網:http://pytorch.orgGitHub:https://github.com/pytorch/pytorchPyTorch 是一個 Python 軟體包,其提供了兩種高層面的功能:使用強大的 GPU 加速的 Tensor 計算(類似 numpy)構建於基於 tape 的 autograd 系統的深度神經網絡如有需要,你也可以復用你最喜歡的
  • PyTorch 0.4:完全改變API,官方支持Windows
    PyTorch團隊編寫了一個遷移指南,幫助用戶將代碼轉換為新的API和style。如果您想要遷移以前版本的PyTorch中的代碼。遷移指南:http://pytorch.org/2018/04/22/0_4_0-migration-guide.html本部分的內容(主要核心變更)包含在遷移指南中。
  • 給訓練踩踩油門:編寫高效的PyTorch代碼技巧
    作者:vahidk前言這是一份 PyTorch 教程和最佳實踐筆記,目錄如下所示:首先 PyTorch 的安裝可以根據官方文檔進行操作:https://pytorch.org>同樣,默認調用 parameters() 會返回其所有子模塊的參數:net = Net()for p in net.parameters(): print(p)當然也有一些預定義的模塊是作為包容其他模塊的容器,最常用的就是
  • 兩行代碼統計模型參數量與FLOPs,這個PyTorch小工具值得一試
    PyTorch-OpCounter GitHub 地址:https://github.com/Lyken17/pytorch-OpCounterOpCouterPyTorch-OpCounter 的安裝和使用都非常簡單,並且還能定製化統計規則,因此那些特殊的運算也能自定義地統計進去。
  • PyTorch框架歷史和特性更迭與安裝過程
    創建好環境之後,可以使用conda activate pytorch來激活剛剛創建的虛擬環境,其中pytorch是創建的虛擬環境的名字。如果要退出虛擬環境,可以使用conda deactivate命令。
  • Pytorch中的分布式神經網絡訓練
    跨GPU的模型拆分跨GPU拆分模型非常簡單,不需要太多代碼更改。 在設置網絡本身時,可以將模型的某些部分移至特定的GPU。 之後,在通過網絡轉發數據時,數據也需要移動到相應的GPU。 下面是執行相同操作的PyTorch代碼段。
  • Pytorch框架安裝方法(基於Anaconda環境和Pycharm IDE)
    1.6 單擊啟動Anaconda Prompt 創建虛擬「房間」通過conda創建一個名為:pytorch的虛擬「房間」,可以方便未來對不同版本的PyTorch進行管理,具體方法如下:conda create -n pytorch python=3.61.7 查看創建的「房間」方法:conda info --envs
  • 雲計算學習:用PyTorch實現一個簡單的分類器
    所以我總結了一下自己當初學習的路線,準備繼續深入鞏固自己的 pytorch 基礎;另一方面,也想從頭整理一個教程,從沒有接觸過 pytorch 開始,到完成一些最新論文裡面的工作。以自己的學習筆記整理為主線,大家可以針對參考。第一篇筆記,我們先完成一個簡單的分類器。
  • 大家心心念念的PyTorch Windows官方支持來了
    GitHub 發布地址:https://github.com/pytorch/pytorch/releasesPyTorch 官網:http://pytorch.org/全面支持高級索引快速傅立葉變換神經網絡:計算時的存儲權衡bottleneck-識別代碼中熱點