PyTorch中Tensor的維度變換實(shí)現(xiàn)
對于 PyTorch 的基本數(shù)據(jù)對象 Tensor (張量),在處理問題時(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è)新的張量,對輸入的制定位置插入維度 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 的視圖,其中通過將 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 就無法改變,而且尺寸不為 1 的維度必須要和原來一樣填寫進(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ò)大為原來的 4 倍,列方向擴(kuò)大為原來的 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) 的簡寫函數(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]]])
可以對多維度的張量進(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ì)交換指定維度的尺寸,不限于兩兩交換。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解如何使用SQLAlchemy連接數(shù)據(jù)庫
這篇文章主要為大家詳細(xì)介紹了如何使用 SQLAlchemy 連接數(shù)據(jù)庫、建立模型、操作表、以及查詢操作表數(shù)據(jù)等內(nèi)容,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11python單例模式原理與創(chuàng)建方法實(shí)例分析
這篇文章主要介紹了python單例模式原理與創(chuàng)建方法,結(jié)合實(shí)例形式分析了Python單例模式的概念、原理、定義、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-10-10設(shè)置python3為默認(rèn)python的方法
我們知道在Windows下多版本共存的配置方法就是改可執(zhí)行文件的名字,配置環(huán)境變量。接下來通過本文給大家介紹設(shè)置python3為默認(rèn)python的方法,一起看看吧2018-10-10python 實(shí)現(xiàn)list或string按指定分段
今天小編就為大家分享一篇python 實(shí)現(xiàn)list或string按指定分段,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12node命令行服務(wù)器(http-server)和跨域的實(shí)現(xiàn)
本文主要介紹了node命令行服務(wù)器(http-server)和跨域的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02python中的多線程鎖lock=threading.Lock()使用方式
這篇文章主要介紹了python中的多線程鎖lock=threading.Lock()使用方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06