PyTorch中Tensor的維度變換實(shí)現(xiàn)
對(duì)于 PyTorch 的基本數(shù)據(jù)對(duì)象 Tensor (張量),在處理問(wèn)題時(shí),需要經(jīng)常改變數(shù)據(jù)的維度,以便于后期的計(jì)算和進(jìn)一步處理,本文旨在列舉一些維度變換的方法并舉例,方便大家查看。
維度查看:torch.Tensor.size()
查看當(dāng)前 tensor 的維度
舉個(gè)例子:
>>> import torch >>> a = torch.Tensor([[[1, 2], [3, 4], [5, 6]]]) >>> a.size() torch.Size([1, 3, 2])
張量變形:torch.Tensor.view(*args) → Tensor
返回一個(gè)有相同數(shù)據(jù)但大小不同的 tensor。 返回的 tensor 必須有與原 tensor 相同的數(shù)據(jù)和相同數(shù)目的元素,但可以有不同的大小。一個(gè) tensor 必須是連續(xù)的 contiguous() 才能被查看。
舉個(gè)例子:
>>> x = torch.randn(2, 9)
>>> x.size()
torch.Size([2, 9])
>>> x
tensor([[-1.6833, -0.4100, -1.5534, -0.6229, -1.0310, -0.8038, 0.5166, 0.9774,
0.3455],
[-0.2306, 0.4217, 1.2874, -0.3618, 1.7872, -0.9012, 0.8073, -1.1238,
-0.3405]])
>>> y = x.view(3, 6)
>>> y.size()
torch.Size([3, 6])
>>> y
tensor([[-1.6833, -0.4100, -1.5534, -0.6229, -1.0310, -0.8038],
[ 0.5166, 0.9774, 0.3455, -0.2306, 0.4217, 1.2874],
[-0.3618, 1.7872, -0.9012, 0.8073, -1.1238, -0.3405]])
>>> z = x.view(2, 3, 3)
>>> z.size()
torch.Size([2, 3, 3])
>>> z
tensor([[[-1.6833, -0.4100, -1.5534],
[-0.6229, -1.0310, -0.8038],
[ 0.5166, 0.9774, 0.3455]],
[[-0.2306, 0.4217, 1.2874],
[-0.3618, 1.7872, -0.9012],
[ 0.8073, -1.1238, -0.3405]]])
可以看到 x 和 y 、z 中數(shù)據(jù)的數(shù)量和每個(gè)數(shù)據(jù)的大小都是相等的,只是尺寸或維度數(shù)量發(fā)生了改變。
壓縮 / 解壓張量:torch.squeeze()、torch.unsqueeze()
- torch.squeeze(input, dim=None, out=None)
將輸入張量形狀中的 1 去除并返回。如果輸入是形如(A×1×B×1×C×1×D),那么輸出形狀就為: (A×B×C×D)
當(dāng)給定 dim 時(shí),那么擠壓操作只在給定維度上。例如,輸入形狀為: (A×1×B),squeeze(input, 0) 將會(huì)保持張量不變,只有用 squeeze(input, 1),形狀會(huì)變成 (A×B)。
返回張量與輸入張量共享內(nèi)存,所以改變其中一個(gè)的內(nèi)容會(huì)改變另一個(gè)。
舉個(gè)例子:
>>> x = torch.randn(3, 1, 2)
>>> x
tensor([[[-0.1986, 0.4352]],
[[ 0.0971, 0.2296]],
[[ 0.8339, -0.5433]]])
>>> x.squeeze().size() # 不加參數(shù),去掉所有為元素個(gè)數(shù)為1的維度
torch.Size([3, 2])
>>> x.squeeze()
tensor([[-0.1986, 0.4352],
[ 0.0971, 0.2296],
[ 0.8339, -0.5433]])
>>> torch.squeeze(x, 0).size() # 加上參數(shù),去掉第一維的元素,不起作用,因?yàn)榈谝痪S有2個(gè)元素
torch.Size([3, 1, 2])
>>> torch.squeeze(x, 1).size() # 加上參數(shù),去掉第二維的元素,正好為 1,起作用
torch.Size([3, 2])
可以看到如果加參數(shù),只有維度中尺寸為 1 的位置才會(huì)消失
- torch.unsqueeze(input, dim, out=None)
返回一個(gè)新的張量,對(duì)輸入的制定位置插入維度 1
返回張量與輸入張量共享內(nèi)存,所以改變其中一個(gè)的內(nèi)容會(huì)改變另一個(gè)。
如果 dim 為負(fù),則將會(huì)被轉(zhuǎn)化 dim+input.dim()+1
接著用上面的數(shù)據(jù)舉個(gè)例子:
>>> x.unsqueeze(0).size()
torch.Size([1, 3, 1, 2])
>>> x.unsqueeze(0)
tensor([[[[-0.1986, 0.4352]],
[[ 0.0971, 0.2296]],
[[ 0.8339, -0.5433]]]])
>>> x.unsqueeze(-1).size()
torch.Size([3, 1, 2, 1])
>>> x.unsqueeze(-1)
tensor([[[[-0.1986],
[ 0.4352]]],
[[[ 0.0971],
[ 0.2296]]],
[[[ 0.8339],
[-0.5433]]]])
可以看到在指定的位置,增加了一個(gè)維度。
擴(kuò)大張量:torch.Tensor.expand(*sizes) → Tensor
返回 tensor 的一個(gè)新視圖,單個(gè)維度擴(kuò)大為更大的尺寸。 tensor 也可以擴(kuò)大為更高維,新增加的維度將附在前面。 擴(kuò)大 tensor 不需要分配新內(nèi)存,只是僅僅新建一個(gè) tensor 的視圖,其中通過(guò)將 stride 設(shè)為 0,一維將會(huì)擴(kuò)展位更高維。任何一個(gè)一維的在不分配新內(nèi)存情況下可擴(kuò)展為任意的數(shù)值。
舉個(gè)例子:
>>> x = torch.Tensor([[1], [2], [3]])
>>> x.size()
torch.Size([3, 1])
>>> x.expand(3, 4)
tensor([[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.]])
>>> x.expand(3, -1)
tensor([[1.],
[2.],
[3.]])
原數(shù)據(jù)是 3 行 1 列,擴(kuò)大后變?yōu)?3 行 4 列,方法中填 -1 的效果與 1 一樣,只有尺寸為 1 才可以擴(kuò)大,如果不為 1 就無(wú)法改變,而且尺寸不為 1 的維度必須要和原來(lái)一樣填寫進(jìn)去。
重復(fù)張量:torch.Tensor.repeat(*sizes)
沿著指定的維度重復(fù) tensor。 不同于 expand(),本函數(shù)復(fù)制的是 tensor 中的數(shù)據(jù)。
舉個(gè)例子:
>>> x = torch.Tensor([1, 2, 3])
>>> x.size()
torch.Size([3])
>>> x.repeat(4, 2)
[1., 2., 3., 1., 2., 3.],
[1., 2., 3., 1., 2., 3.],
[1., 2., 3., 1., 2., 3.]])
>>> x.repeat(4, 2).size()
torch.Size([4, 6])
原數(shù)據(jù)為 1 行 3 列,按行方向擴(kuò)大為原來(lái)的 4 倍,列方向擴(kuò)大為原來(lái)的 2 倍,變?yōu)榱?4 行 6 列。
變化時(shí)可以看成是把原數(shù)據(jù)作成一個(gè)整體,再按指定的維度和尺寸重復(fù),變成一個(gè) 4 行 2 列的矩陣,其中的每一個(gè)單位都是相同的,再把原數(shù)據(jù)放到每個(gè)單位中。
矩陣轉(zhuǎn)置:torch.t(input, out=None) → Tensor
輸入一個(gè)矩陣(2維張量),并轉(zhuǎn)置0, 1維。 可以被視為函數(shù) transpose(input, 0, 1) 的簡(jiǎn)寫函數(shù)。
舉個(gè)例子:
>>> x = torch.randn(3, 5)
>>> x
tensor([[-1.0752, -0.9706, -0.8770, -0.4224, 0.9776],
[ 0.2489, -0.2986, -0.7816, -0.0823, 1.1811],
[-1.1124, 0.2160, -0.8446, 0.1762, -0.5164]])
>>> x.t()
tensor([[-1.0752, 0.2489, -1.1124],
[-0.9706, -0.2986, 0.2160],
[-0.8770, -0.7816, -0.8446],
[-0.4224, -0.0823, 0.1762],
[ 0.9776, 1.1811, -0.5164]])
>>> torch.t(x) # 另一種用法
tensor([[-1.0752, 0.2489, -1.1124],
[-0.9706, -0.2986, 0.2160],
[-0.8770, -0.7816, -0.8446],
[-0.4224, -0.0823, 0.1762],
[ 0.9776, 1.1811, -0.5164]])
必須要是 2 維的張量,也就是矩陣,才可以使用。
維度置換:torch.transpose()、torch.Tensor.permute()
- torch.transpose(input, dim0, dim1, out=None) → Tensor
返回輸入矩陣 input 的轉(zhuǎn)置。交換維度 dim0 和 dim1。 輸出張量與輸入張量共享內(nèi)存,所以改變其中一個(gè)會(huì)導(dǎo)致另外一個(gè)也被修改。
舉個(gè)例子:
>>> x = torch.randn(2, 4, 3)
>>> x
tensor([[[-1.2502, -0.7363, 0.5534],
[-0.2050, 3.1847, -1.6729],
[-0.2591, -0.0860, 0.4660],
[-1.2189, -1.1206, 0.0637]],
[[ 1.4791, -0.7569, 2.5017],
[ 0.0098, -1.0217, 0.8142],
[-0.2414, -0.1790, 2.3506],
[-0.6860, -0.2363, 1.0481]]])
>>> torch.transpose(x, 1, 2).size()
torch.Size([2, 3, 4])
>>> torch.transpose(x, 1, 2)
tensor([[[-1.2502, -0.2050, -0.2591, -1.2189],
[-0.7363, 3.1847, -0.0860, -1.1206],
[ 0.5534, -1.6729, 0.4660, 0.0637]],
[[ 1.4791, 0.0098, -0.2414, -0.6860],
[-0.7569, -1.0217, -0.1790, -0.2363],
[ 2.5017, 0.8142, 2.3506, 1.0481]]])
>>> torch.transpose(x, 0, 1).size()
torch.Size([4, 2, 3])
>>> torch.transpose(x, 0, 1)
tensor([[[-1.2502, -0.7363, 0.5534],
[ 1.4791, -0.7569, 2.5017]],
[[-0.2050, 3.1847, -1.6729],
[ 0.0098, -1.0217, 0.8142]],
[[-0.2591, -0.0860, 0.4660],
[-0.2414, -0.1790, 2.3506]],
[[-1.2189, -1.1206, 0.0637],
[-0.6860, -0.2363, 1.0481]]])
可以對(duì)多維度的張量進(jìn)行轉(zhuǎn)置
- torch.Tensor.permute(dims)
將 tensor 的維度換位
接著用上面的數(shù)據(jù)舉個(gè)例子:
>>> x.size()
torch.Size([2, 4, 3])
>>> x.permute(2, 0, 1).size()
torch.Size([3, 2, 4])
>>> x.permute(2, 0, 1)
tensor([[[-1.2502, -0.2050, -0.2591, -1.2189],
[ 1.4791, 0.0098, -0.2414, -0.6860]],
[[-0.7363, 3.1847, -0.0860, -1.1206],
[-0.7569, -1.0217, -0.1790, -0.2363]],
[[ 0.5534, -1.6729, 0.4660, 0.0637],
[ 2.5017, 0.8142, 2.3506, 1.0481]]])
直接在方法中填入各個(gè)維度的索引,張量就會(huì)交換指定維度的尺寸,不限于兩兩交換。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
釘釘群自定義機(jī)器人消息Python封裝的實(shí)例
今天小編就為大家分享一篇釘釘群自定義機(jī)器人消息Python封裝的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
Python下應(yīng)用opencv 實(shí)現(xiàn)人臉檢測(cè)功能
OpenCV是如今最流行的計(jì)算機(jī)視覺庫(kù),今天我們通過(guò)本文給大家分享Python下應(yīng)用opencv 實(shí)現(xiàn)人臉檢測(cè)功能,感興趣的朋友跟隨小編一起看看吧2019-10-10
python中斷time.sleep一種更優(yōu)雅的方式:event.wait
這篇文章主要介紹了python中斷time.sleep一種更優(yōu)雅的方式:event.wait,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
python調(diào)用cmd命令時(shí)遇到的路徑空格問(wèn)題和中文亂碼的解決
這篇文章主要介紹了python調(diào)用cmd命令時(shí)遇到的路徑空格問(wèn)題和中文亂碼的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02
pip 錯(cuò)誤unused-command-line-argument-hard-error-in-future解決辦法
這篇文章主要介紹了Python包管理器pip安裝軟件時(shí)出現(xiàn)unused-command-line-argument-hard-error-in-future錯(cuò)誤的解決辦法,需要的朋友可以參考下2014-06-06
python開發(fā)中module模塊用法實(shí)例分析
這篇文章主要介紹了python開發(fā)中module模塊用法,以實(shí)例形式較為詳細(xì)的分析了Python中模塊的功能、定義及相關(guān)使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
Python連接MySQL并使用fetchall()方法過(guò)濾特殊字符
這篇文章主要介紹了Python連接MySQL的方法并講解了如何使用fetchall()方法過(guò)濾特殊字符,示例環(huán)境為Ubuntu操作系統(tǒng),需要的朋友可以參考下2016-03-03

