1. 程式人生 > 其它 >pytorch常用函式積累

pytorch常用函式積累

可以訪問我的知乎:https://zhuanlan.zhihu.com/p/478576485

官方文件:https://pytorch.org/docs/master/torch.html

中文文件:https://pytorch-cn.readthedocs.io/zh/latest/

torch基礎

  1. torch.device():將使用GPU訓練模型

    device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
    # 如果多個GPU
    model = Model()
    if torch.cuda.device_count() > 1:
    	model = nn.DataParallel(model,device_ids=[0,1,2])
    model.to(device)
    
  2. torch.permute():張量維度轉換

    a = torch.randn(16, 16, 3) 
    b = a.permute(2,0,1)
    # b.shape=(3,16,16)
    
  3. torch.cat():拼接張量

    torch.cat((A,B),0)  # 第0維向下拼接,列數必須一致(其他維都必須一致)
    torch.cat((A,B),0)  # 第1維向右拼接,行數必須一致(其他維都必須一致)
    
  4. tensor.contiguous() :深拷貝

  5. torch.clamp(input, min, max) :輸入input張量每個元素的值限制在區間 [min,max]內,返回一個新張量

  6. torch.save():儲存模型(引數)

    import torch
    state ={''net':model.state_dict(),'optimizer':optimizer.state_dict(), 'epoch':epoch}
    torch.save(state, filename)  # state['net']也能是model ; filename:'*.pt(h)/*.pkl'(均二進位制儲存)
    -------------------------------------------------------------------
    checkpoint = torch.load(filename)
    model.load_state_dict(checkpoint['net'])
    optimizer.load_state_dict(checkpoint['optimizer'])
    start_epoch = checkpoint['epoch'] + 1    
    
  7. torch.squeeze() :去除取1的維度;torch.unsqueeze(i):增添第i維

  8. torch.gather(mytensor,i,index):對第i維按index索引並返回索引結果

  9. torch.sactter(mytensor,i,index,val):對第i維按index中索引值索引填val,返回填充後結果,可用於讀獨熱編碼,示例如下:

    def one_hot(labels,num_class):
        batch_size = len(labels)
        return torch.scatter(torch.zeros(batch_size,num_class),
                             1,labels.view(batch_size,1),1)
    

    [備註]:gather和sactter中index詳見

    https://blog.csdn.net/Teeyohuang/article/details/82186666

torch.nn as nn

詳見:https://blog.csdn.net/qq_33952811/article/details/108430097

  1. torch.nn.Conv2d():二維卷積

    卷積尺寸變化如下:

    [備註]:保證輸出高寬不變的\(p =[\displaystyle \frac{k-1}{2}]\)

    Conv2d(in_channels, out_channels, kernel_size, stride=1,padding=0, dilation=1, groups=1,bias=True, padding_mode=‘zeros’)
    # in_channels:輸入的通道數目 【必選】
    # out_channels: 輸出的通道數目 【必選】
    # kernel_size:卷積核的大小,型別為int 或者元組,當卷積是方形的時候,只需要一個整數邊長即可,卷積不是方形,要輸入一個元組表示 高和寬。【必選】
    # stride: 卷積每次滑動的步長為多少,預設是 1 【可選】
    # padding: 設定在所有邊界增加 值為 0 的邊距的大小(也就是在feature map 外圍增加幾圈 0 ),例如當 padding =1 的時候,如果原來大小為 3 × 3 ,那麼之後的大小為 5 × 5 。即在外圍加了一圈 0 。【可選】
    # dilation:控制卷積核之間的間距。 【可選】
    # groups:控制輸入和輸出之間的連線。【可選】
    # bias: 是否將一個 學習到的 bias 增加輸出中,預設是 True 。【可選】
    # padding_mode : 字串型別,可選擇 “zeros” 和 “circular”。【可選】
    
  2. torch.nn.ConvTranspose2d():二維轉置卷積

    • 卷積是將輸入m×m的矩陣輸出n×n的矩陣(shape減小)
    • 轉置卷積≠反捲積是將輸入n×n的矩陣輸出m×m的矩陣(shape增大)
    \[Y_{n^2×1} = W_{n^2×m^2} · X_{m^2×1} \to Y'_{m^2×1} = W^T_{m^2×n^2} · X'_{n^2×1}\\ \]
    • 形狀換算:
  1. torch.nn.Identity():佔位

    不處理,輸入即輸出,相當於網路的一層空層,用於殘差網路

  2. torch.nn.functional.interpolate():上下采樣時插值

    # default:(input, size=None, scale_factor=None, mode='nearest',       align_corners=None)
    # input:輸入張量
    # size:上/下采樣目標大小
    # scale_factor:標量獲元組,表示輸出大小為輸入的多少倍
    # mode:上取樣演算法,有'nearest', 'linear', 'bilinear', 'bicubic' ,    'trilinear'和'area'
    # align_corners:幾何上,我們認為輸入和輸出的畫素是正方形,而不是點。如果設定為True,則輸入和輸出張量由其角畫素的中心點對齊,從而保留角畫素處的值。如果設定為False,則輸入和輸出張量由它們的角畫素的角點對齊,插值使用邊界外值的邊值填充;當scale_factor保持不變時,使該操作獨立於輸入大小。僅當使用的演算法為'linear', 'bilinear', 'bilinear'or 'trilinear'時可以使用。預設設定為False
    

torchvision

  1. torchvision.utils.make_grid():輸出圖片矩陣,用於演算法效能效果比較

    make_grid()將若干影象以網格矩陣排列,save_image()用於儲存影象,兩函式引數類似

    # tensor:4D張量,形狀為(B x C x H x W),分別表示樣本數,通道數,影象高度,影象寬度。或者是一個影象列表
    # nrow:每行的圖片數量,預設值為8
    # padding:相鄰影象之間的間隔。預設值為2
    # normalize:如果為True,則把影象的畫素值通過range指定的最大值和最小值歸一化到0-1。預設為   False
    

    使用舉例:

    def show(img):
        npimg = img.numpy()
        plt.imshow(
            np.transpose(npimg, (1,2,0)), interpolation='nearest')
    show(make_grid(images, nrow=5, padding=10))    
    
  2. torchvision.transforms():影象增強(image augmentation)

    參考:https://blog.csdn.net/u011995719/article/details/85107009

    注意影象資料格式:

    • ndarray->HWC
    • tensor->CHW
    • PIL->HW
    import torchvision.transforms as transforms
    trans = [
    # 資料轉換
    transforms.ToPILImage(),
    transforms.ToTensor(),
    #-----------------------------------------------------
    # 隨機長寬裁剪
    transforms.RandomResizedCrop(size,scale=(0.08, 1.0)), 
    # 按比例把影象最小邊長放縮到256,另一邊同比例放縮
    transforms.Resize(256),  
    # 畫素值歸一化
    transforms.Normalize(mean,std), 
    # 修改輸入影象的4大引數值:brightness,contrast and saturation,hue,即亮度,對比度,飽和度和色度
    transforms.ColorJitter()  
    # 0.5機率水平翻轉
    transforms.RandomHorizontalFlip(),  
    # 從一張輸入影象中裁剪出5張指定大小的影象,包括影象九宮格的4個角的和一箇中心
    transforms.FiveCrop(size)
    # 隨機旋轉
    transforms.RandomRotation()  
    # 仿射變換
    torchvision.transforms.RandomAffine(degrees, translate=None, scale=None,    shear=None, resample=False, fillcolor=0) 
    ]
    transformer = transforms.Compose(trans)  # 整合影象批量預處理的所有規則
    

資料集

from torchvision.datasets import ImageFolder
dataset=ImageFolder(root, 
                    transform=None, 
    				target_transform=None, 
    				is_valid_file=None
                   )
'''引數說明'''
# root:圖片儲存的根目錄,即各類別資料夾所在目錄的上一級目錄。
# transform:對圖片進行預處理的操作(函式),原始圖片作為輸入,返回一個轉換後的圖片。
# target_transform:對圖片類別進行預處理的操作,輸入為 target,輸出對其的轉換。如果不傳該引數,即對 target 不做任何轉換,返回的順序索引 0,1, 2…
# is_valid_file:獲取影象檔案的路徑並檢查該檔案是否為有效檔案的函式(用於檢查損壞檔案)
'''返回的dataset都有以下三種屬性:'''
# self.classes:用一個 list 儲存類別名稱
# self.class_to_idx:類別對應的索引,與不做任何轉換返回的 target 對應
# self.imgs:儲存(img-path, class) tuple的 list

from torch.utils.data import DataLoader
DataLoader(dataset,batch_size, shuffle, num_workers)

遷移學習

派生新網路,以全連線卷積神經網路舉例:

from torchvision.models import resnet18
import torch.nn as nn

cnn = resnet18(pretrained=False)
FCN = nn.Sequential(*list(cnn.children())[:-2])  # 類似遷移學習,刪掉最後的平均池化層和全連線層,保留前面提取特徵的結構
FCN.add_module('final_conv',nn.Conv2d(in_channels=512,out_channels=21,kernel_size=1))  # 1*1卷積
FCN.add_module('transpose_conv',nn.ConvTranspose2d(in_channels=21,out_channels=21,kernel_size=64,stride=32,padding=16))

深度強化學習

torch.distributions():深度學習中的概率分佈

import torch
# 1.將pi列表的權重轉化為概率構建離散分佈
dist = torch.distributions.Categorical(logits=pi)
dist.sample()  # 按概率抽樣下標
dist.log_prob(action_batch)  # 對action_batch中每個元素重構成僅1個索引值為1的獨熱編碼序列,對每個序列計算交叉熵

# 2.構建(μ,σ)正態分佈
dist = torch.distributions.Normal  # 構建3個標準正態分佈
(loc=torch.Tensor([0,0,0]),scale=torch.Tensor([1,1,1]))
sample = dist.sample()   # 對每個正態分佈直接抽樣
rsample = dist.rsample() # 先在標準正態分佈上抽樣再μ+σx

以下內容強化學習策略梯度中使用:

當概率密度函式相對於其引數可微分時, 我們只需要sample()log_prob()來實現REINFORCE:從網路輸出中取樣一個動作, 將這個動作應用於一個環境中, 然後使用log_prob構造損失函式

from torch.distributions import Categorical
probs = policy_network(state)  # probs是特徵
m = Categorical(probs=probs)  # 更推薦使用logits=probs,這個還可以傳入未歸一化的引數
action = m.sample()
next_state, reward = env.step(action)
loss = -m.log_prob(action) * reward  # max->min
loss.backward()

實現隨機/策略梯度的另一種方法是使用來自rsample()方法的重新引數化技巧,其中引數化隨機變數可以通過無引數隨機變數的引數確定性函式構造. 因此, 重新引數化的樣本變得可微分。

from torch.distributions import Normal
params = policy_network(state)
m = Normal(loc)
action = m.rsample()
next_state, reward = env.step(action)  
loss = -reward
loss.backward()