首頁 > 軟體

Pytorch上下取樣函數之F.interpolate陣列取樣操作詳解

2022-04-06 13:01:00

什麼是上取樣

上取樣,在深度學習框架中,可以簡單的理解為任何可以讓你的影象變成更高解析度的技術。 最簡單的方式是重取樣和插值:將輸入圖片input image進行rescale到一個想要的尺寸,而且計算每個點的畫素點,使用如雙線性插值bilinear等插值方法對其餘點進行插值。

Unpooling是在CNN中常用的來表示max pooling的逆操作。這是從2013年紐約大學Matthew D. Zeiler和Rob Fergus發表的《Visualizing and Understanding Convolutional Networks》中參照的:因為max pooling不可逆,因此使用近似的方式來反轉得到max pooling操作之前的原始情況;

F.interpolate——陣列取樣操作

torch.nn.functional.interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None, recompute_scale_factor=None)

功能:利用插值方法,對輸入的張量陣列進行上下取樣操作,換句話說就是科學合理地改變陣列的尺寸大小,儘量保持資料完整。

輸入:

  • input(Tensor):需要進行取樣處理的陣列。
  • size(int或序列):輸出空間的大小
  • scale_factor(float或序列):空間大小的乘數
  • mode(str):用於取樣的演演算法。'nearest'| 'linear'| 'bilinear'| 'bicubic'| 'trilinear'| 'area'。預設:'nearest'
  • align_corners(bool):在幾何上,我們將輸入和輸出的畫素視為正方形而不是點。如果設定為True,則輸入和輸出張量按其角畫素的中心點對齊,保留角畫素處的值。如果設定為False,則輸入和輸出張量通過其角畫素的角點對齊,並且插值使用邊緣值填充用於邊界外值,使此操作在保持不變時獨立於輸入大小scale_factor。
  • recompute_scale_facto(bool):重新計算用於插值計算的 scale_factor。當scale_factor作為引數傳遞時,它用於計算output_size。如果recompute_scale_factor的False或沒有指定,傳入的scale_factor將在插值計算中使用。否則,將根據用於插值計算的輸出和輸入大小計算新的scale_factor(即,如果計算的output_size顯式傳入,則計算將相同 )。注意當scale_factor 是浮點數,由於舍入和精度問題,重新計算的 scale_factor 可能與傳入的不同。

注意:

  • 輸入的張量陣列裡面的資料型別必須是float。
  • 輸入的陣列維數只能是3、4或5,分別對應於時間、空間、體積取樣。
  • 不對輸入陣列的前兩個維度(批次和通道)取樣,從第三個維度往後開始取樣處理。
  • 輸入的維度形式為:批次(batch_size)×通道(channel)×[可選深度]×[可選高度]×寬度(前兩個維度具有特殊的含義,不進行取樣處理)
  • size與scale_factor兩個引數只能定義一個,即兩種取樣模式只能用一個。要麼讓陣列放大成特定大小、要麼給定特定係數,來等比放大陣列。
  • 如果size或者scale_factor輸入序列,則必須匹配輸入的大小。如果輸入四維,則它們的序列長度必須是2,如果輸入是五維,則它們的序列長度必須是3。
  • 如果size輸入整數x,則相當於把3、4維度放大成(x,x)大小(輸入以四維為例,下面同理)。
  • 如果scale_factor輸入整數x,則相當於把3、4維度都等比放大x倍。
  • mode是’linear’時輸入必須是3維的;是’bicubic’時輸入必須是4維的;是’trilinear’時輸入必須是5維的
  • 如果align_corners被賦值,則mode必須是'linear','bilinear','bicubic'或'trilinear'中的一個。
  • 插值方法不同,結果就不一樣,需要結合具體任務,選擇合適的插值方法。

補充:

一圖看懂align_corners=True與False的區別,從4×4上取樣成8×8。一個是按四角的畫素點中心對齊,另一個是按四角的畫素角點對齊。

圖片轉自:https://discuss.pytorch.org/t/what-we-should-use-align-corners-false/22663/9

程式碼案例

一般用法

import torch.nn.functional as F
import torch

a=torch.arange(12,dtype=torch.float32).reshape(1,2,2,3)
b=F.interpolate(a,size=(4,4),mode='bilinear')
# 這裡的(4,4)指的是將後兩個維度放縮成4*4的大小
print(a)
print(b)
print('原陣列尺寸:',a.shape)
print('size取樣尺寸:',b.shape)

輸出結果,一二維度大小不會發生變化

# 原陣列
tensor([[[[ 0.,  1.,  2.],
          [ 3.,  4.,  5.]],

         [[ 6.,  7.,  8.],
          [ 9., 10., 11.]]]])
# 取樣後的陣列
tensor([[[[ 0.0000,  0.6250,  1.3750,  2.0000],
          [ 0.7500,  1.3750,  2.1250,  2.7500],
          [ 2.2500,  2.8750,  3.6250,  4.2500],
          [ 3.0000,  3.6250,  4.3750,  5.0000]],

         [[ 6.0000,  6.6250,  7.3750,  8.0000],
          [ 6.7500,  7.3750,  8.1250,  8.7500],
          [ 8.2500,  8.8750,  9.6250, 10.2500],
          [ 9.0000,  9.6250, 10.3750, 11.0000]]]])
原陣列尺寸: torch.Size([1, 2, 2, 3])
size取樣尺寸: torch.Size([1, 2, 4, 4])
# 規定三四維度放縮成4*4大小

size與scale_factor的區別:輸入序列時

import torch.nn.functional as F
import torch

a=torch.arange(4*512*14*14,dtype=torch.float32).reshape(4,512,14,14)
b=F.interpolate(a,size=(28,56),mode='bilinear')
c=F.interpolate(a,scale_factor=(4,8),mode='bilinear')
print('原陣列尺寸:',a.shape)
print('size取樣尺寸:',b.shape)
print('scale_factor取樣尺寸:',c.shape)

輸出結果

原陣列尺寸: torch.Size([4, 512, 14, 14])
size取樣尺寸: torch.Size([4, 512, 28, 56])
# 第三維度放大成28,第四維度放大成56
scale_factor取樣尺寸: torch.Size([4, 512, 56, 112])
# 第三維度放大4倍,第四維度放8倍

size與scale_factor的區別:輸入整數時

import torch.nn.functional as F
import torch

a=torch.arange(4*512*14*14,dtype=torch.float32).reshape(4,512,14,14)
b=F.interpolate(a,size=28,mode='bilinear')
c=F.interpolate(a,scale_factor=4,mode='bilinear')
print('原陣列尺寸:',a.shape)
print('size取樣尺寸:',b.shape)
print('scale_factor取樣尺寸:',c.shape)

輸出結果

原陣列尺寸: torch.Size([4, 512, 14, 14])
size取樣尺寸: torch.Size([4, 512, 28, 28])
# 三四維度陣列被放大成28*28
scale_factor取樣尺寸: torch.Size([4, 512, 56, 56])
# 三四維度陣列被放大了4倍

align_corners=True與False的區別

import torch.nn.functional as F
import torch

a=torch.arange(18,dtype=torch.float32).reshape(1,2,3,3)
b=F.interpolate(a,size=(4,4),mode='bicubic',align_corners=True)
c=F.interpolate(a,size=(4,4),mode='bicubic',align_corners=False)

print(a)
print(b)
print(c)

輸出結果,具體效果會因mode插值方法而異

tensor([[[[ 0.,  1.,  2.],
          [ 3.,  4.,  5.],
          [ 6.,  7.,  8.]],

         [[ 9., 10., 11.],
          [12., 13., 14.],
          [15., 16., 17.]]]])
# align_corners=True
tensor([[[[ 0.0000,  0.5741,  1.4259,  2.0000],
          [ 1.7222,  2.2963,  3.1481,  3.7222],
          [ 4.2778,  4.8519,  5.7037,  6.2778],
          [ 6.0000,  6.5741,  7.4259,  8.0000]],

         [[ 9.0000,  9.5741, 10.4259, 11.0000],
          [10.7222, 11.2963, 12.1481, 12.7222],
          [13.2778, 13.8519, 14.7037, 15.2778],
          [15.0000, 15.5741, 16.4259, 17.0000]]]])
# align_corners=False
tensor([[[[-0.2871,  0.3145,  1.2549,  1.8564],
          [ 1.5176,  2.1191,  3.0596,  3.6611],
          [ 4.3389,  4.9404,  5.8809,  6.4824],
          [ 6.1436,  6.7451,  7.6855,  8.2871]],

         [[ 8.7129,  9.3145, 10.2549, 10.8564],
          [10.5176, 11.1191, 12.0596, 12.6611],
          [13.3389, 13.9404, 14.8809, 15.4824],
          [15.1436, 15.7451, 16.6855, 17.2871]]]])

擴充套件:

在計算機視覺中,interpolate函數常用於影象的放大(即上取樣操作)。比如在細粒度識別領域中,注意力圖有時候會對特徵圖進行裁剪操作,將有用的部分裁剪出來,裁剪後的影象往往尺寸小於原始特徵圖,這時候如果強制轉換成原始影象大小,往往是無效的,會丟掉部分有用的資訊。所以這時候就需要用到interpolate函數對其進行上取樣操作,在保證影象資訊不丟失的情況下,放大影象,從而放大影象的細節,有利於進一步的特徵提取工作。

官方檔案
torch.nn.functional.interpolate:https://pytorch.org/docs/stable/generated/torch.nn.functional.interpolate.html?highlight=interpolate#torch.nn.functional.interpolate

總結

到此這篇關於Pytorch上下取樣函數之F.interpolate陣列取樣操作的文章就介紹到這了,更多相關Pytorch F.interpolate陣列取樣內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com