Pytorch expand和repeat
admin
2024-02-27 23:12:00
0

       在torch中,如果要改变某一个tensor的维度,可以利用view、expand、repeat、transpose和permute等方法,这里对这些方法的一些容易混淆的地方做个总结。

​expand和repeat函数是pytorch中常用于进行张量数据复制和维度扩展的函数,但其工作机制差别很大,本文对这两个函数进行对比。

1 torch.expand()

  • 作用: expand()函数可以将张量广播到新的形状。
  • 注意: 只能对维度值为1的维度进行扩展,无需扩展的维度,维度值不变,对应位置可写上原始维度大小或直接写作-1;且扩展的Tensor不会分配新的内存,只是原来的基础上创建新的视图并返回,返回的张量内存是不连续的。类似于numpy中的broadcast_to函数的作用。如果希望张量内存连续,可以调用contiguous函数。

expand函数用于将张量中单数维的数据扩展到指定的size。

首先解释下什么叫单数维(singleton dimensions),张量在某个维度上的size为1,则称为单数维。比如zeros(2,3,4)不存在单数维,而zeros(2,1,4)在第二个维度(即维度1)上为单数维。expand函数仅仅能作用于这些单数维的维度上。
参数*sizes用于逐个指定各个维度扩展后的大小(也可以理解为拓展的次数),对于不需要或者无法(即非单数维)进行扩展的维度,对应位置可写上原始维度大小或直接写作-1。
expand函数可能导致原始张量的升维,其作用在张量前面的维度上(在tensor的低维增加更多维度),因此通过expand函数可将张量数据复制多份(可理解为沿着第一个batch的维度上)。
 

import torch
a = tensor([1, 0, 2])
b = a.expand(2, -1)   # 第一个维度为升维,第二个维度保持原阳
# b为   tensor([[1, 0, 2],  [1, 0, 2]])a = torch.tensor([[1], [0], [2]])
b = a.expand(-1, 2)   # 保持第一个维度,第二个维度只有一个元素,可扩展
# b为  tensor([[1, 1],
#              [0, 0],
#              [2, 2]])a = torch.Tensor([[1,2,3]])
'''
tensor([[1.,2.,3.]]
)
torch.Size([1, 3])
'''aa = a.expand(4, 3)  # 也可写为a.expand(4, -1)  对于某一个维度上的值为1的维度,# 可以在该维度上进行tensor的复制,若大于1则不行
'''
tensor([[1.,2.,3.],[1.,2.,3.],[1.,2.,3.],[1.,2.,3.]]
)
'''a = torch.Tensor([[1,2,3], [4, 5, 6]])
'''
tensor([[1.,2.,3.],[4.,5.,6.]]
)
torch.Size([2, 3])
'''
a = a.expand(4,6) # 最高几个维度的参数必须和原始shape保持一致,否则报错
'''
RuntimeError: The expanded size of the tensor (6) must match 
the existing size (3) at non-singleton dimension 1.
'''aa = a.expand(1,2,3) # 可以在tensor的低维增加更多维度
'''
tensor([[[1.,2.,3.],[4.,5.,6.]]]
)
'''
aaa = a.expand(2,2,3)  # 可以在tensor的低维增加更多维度,同时在新增加的低维度上进行tensor的复制
'''
tensor([[[1.,2.,3.],[4.,5.,6.]],[[1.,2.,3.],[4.,5.,6.]]]
)
'''aaa = a.expand(2,3,2) # 不可在更高维增加维度,否则报错
'''
RuntimeError: The expanded size of the tensor (2) must match the 
existing size (3) at non-singleton dimension 2.
'''aaaa = a.expand(2, -1, -1) # 最高几个维度的参数可以用-1,表示和原始维度一致
'''
tensor([[[1.,2.,3.],[4.,5.,6.]],[[1.,2.,3.],[4.,5.,6.]]]
)
'''# expand返回的张量与原版张量具有相同内存地址
print(aaaa.storage()) # 存储区的数据,说明expand后的a,aa,aaa,aaaa是共享storage的,
# 只是tensor的头信息区设置了不同的数据展示格式,从而使得a,aa,aaa,aaaa呈现不同的tensor形式
'''
1.0
2.0
3.0
4.0
5.0
6.0
'''

1.1 expand_as

 可视为expand的另一种表达,其size通过函数传递的目标张量的size来定义。

import torch
a = torch.tensor([1, 0, 2])
b = torch.zeros(2, 3)
c = a.expand_as(b)  # a照着b的维度大小进行拓展
# c为 tensor([[1, 0, 2],
#        [1, 0, 2]])

2 tensor.repeat()

  • 作用:和expand()作用类似,均是将tensor广播到新的形状。
  • 注意:不允许使用维度-1,1即为不变。

前文提及expand仅能作用于单数维,那对于非单数维的拓展,那就需要借助于repeat函数了。

tensor.repeat(*sizes)

参数*sizes指定了原始张量在各维度上复制的次数。整个原始张量作为一个整体进行复制,这与Numpy中的repeat函数截然不同,而更接近于tile函数的效果。

与expand不同,repeat函数会真正的复制数据并存放于内存中。repeat开辟了新的内存空间,torch.repeat返回的张量在内存中是连续的

import torch
a = torch.tensor([1, 0, 2])
b = a.repeat(3,2)  # 在轴0上复制3份,在轴1上复制2份
# b为 tensor([[1, 0, 2, 1, 0, 2],
#        [1, 0, 2, 1, 0, 2],
#        [1, 0, 2, 1, 0, 2]])import torch
a = torch.Tensor([[1,2,3]])
'''
tensor([[1.,2.,3.]]
)
'''aa = a.repeat(4, 3) # 维度不变,在各个维度上进行数据复制
'''
tensor([[1.,2.,3.,1.,2.,3.,1.,2.,3.],[1.,2.,3.,1.,2.,3.,1.,2.,3.],[1.,2.,3.,1.,2.,3.,1.,2.,3.],[1.,2.,3.,1.,2.,3.,1.,2.,3.]]
)
'''a = torch.Tensor([[1,2,3], [4, 5, 6]])
'''
tensor([[1.,2.,3.],[4.,5.,6.]]
)
'''
aa = a.repeat(4,6) # 维度不变,在各个维度上进行数据复制
'''
tensor([[1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.],[4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.],[1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.],[4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.],[1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.],[4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.],[1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.,1.,2.,3.],[4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.,4.,5.,6.]]
)
'''aaa = a.repeat(1,2,3) # 可以在tensor的低维增加更多维度,并在各维度上复制数据
'''
tensor([[[1.,2.,3.,1.,2.,3.,1.,2.,3.],[4.,5.,6.,4.,5.,6.,4.,5.,6.],[1.,2.,3.,1.,2.,3.,1.,2.,3.],[4.,5.,6.,4.,5.,6.,4.,5.,6.]]]
)
'''
aaaa = a.repeat(2,3,1) # 可以在tensor的高维增加更多维度,并在各维度上复制数据
'''
tensor([[[1.,2.,3.],[4.,5.,6.],[1.,2.,3.],[4.,5.,6.],[1.,2.,3.],[4.,5.,6.]],[[1.,2.,3.],[4.,5.,6.],[1.,2.,3.],[4.,5.,6.],[1.,2.,3.],[4.,5.,6.]]]
)
'''aaaaa = a.repeat(2, 3, -1) 
'''
RuntimeError: Trying to create tensor with negative dimension -3: [2,6,-3]
'''print(aaaa.storage()) # 存储区的数据,说明repeat后的a,aa,aaa,aaaa是有各自独立的storage的
'''
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
1.0
2.0
3.0
4.0
5.0
6.0
'''

2.1 repeat_intertile

Pytorch中,与Numpyrepeat函数相类似的函数为torch.repeat_interleave

torch.repeat_interleave(input, repeats, dim=None)

参数input为原始张量,repeats为指定轴上的复制次数,而dim为复制的操作轴,若取值为None则默认将所有元素进行复制,并会返回一个flatten之后一维张量。与repeat将整个原始张量作为整体不同,repeat_interleave操作是逐元素的。

a = torch.tensor([[1], [0], [2]])
b = torch.repeat_interleave(a, repeats=3)   # 结果flatten
# b为tensor([1, 1, 1, 0, 0, 0, 2, 2, 2])c = torch.repeat_interleave(a, repeats=3, dim=1)  # 沿着axis=1逐元素复制
# c为tensor([[1, 1, 1],
#        [0, 0, 0],
#        [2, 2, 2]])

总结
相同:
(1)都可以扩展维度,或在某个维度上进行tensor的复制

区别:
(1)参数意义不同,repeat的参数表示沿某维度的数据复制倍数,可为大于0的任何整数值;expand的参数表示tensor对应的维度上的值,且只有增加新的低维度时表示沿该低维度的数据复制倍数,其他参数必须和原始tensor保持一致
(2)返回的结果的存储区不同,repeat返回的tensor会重新拥有一个独立存储区,而expand返回的tensor则与原始tensor共享存储区

相关内容

热门资讯

起点订购APP贵金属订购交易欺...   互联网上充斥着白银、铂金、铜等现货贵金属投资公司的宣传,通过不实的贵金属现货APP吸引投资者,但...
全新易购APP高额手续费的期货...   全新易购APP白银铂金现货订购出现严重的损失,投资者在这个平台根本赚不到钱,开始还好,后面的交易...
银行板块震荡上扬 中国银行等股... 观点网讯:7月8日,银行板块震荡上扬,中国银行、农业银行、建设银行、成都银行、工商银行等股纷纷上扬。...
AI Agent进入深水区:企... AI Agent从技术概念走向商业落地,企业付费意愿成为检验产品价值的唯一标准。过去两年大量AI创业...
一通智投APP内幕交易欺骗投资...   一通智投APP虚假现货订购交易为非法期货,投资者被宣传广告给诱导,下载了一通智投APP,结果在这...
港股科技股全线大涨!跌多了是基... 港股市场近日整体有明显反弹的科技股今日再度集体走强,恒生科技指数拉升涨超3%。个股中,联想涨超8%,...
一场博览会,看透低空经济风口全... 文丨许佳慧 低空经济风起,谁是真正的弄潮儿? 【观赛道:题材风口开启,全链布局成型】 低空经济有多火...
黄金单边牛市没那么快回来?预测... 黄金这波反弹刚冒头,没人敢直接砸重仓赌方向。Polymarket上的交易显示,黄金7月触及4300美...
超颖电子布局“A+H”:一季度... 瑞财经 吴文婷7月6日,超颖电子发布公告称,为满足公司业务发展需要,深入推进国际化战略,打造国际化资...
偏袒?阿根廷球员扇耳光+飞铲无... 北京时间7月8日,2026年世界杯1/8决赛,阿根廷3-2逆转埃及晋级八强。不过,本场比赛的判罚在赛...
原创 高... 在国际关系的复杂棋局中,盟友与对手从来都不是一成不变的。最近,俄罗斯通过中间渠道从日本进口航空燃油的...
优质药食同源食材选购指南:甘草... 在现代保健理念中,药食同源的概念越来越受到重视。许多人开始关注如何选购优质的药食同源食材,以便更好地...
AI产业进展提振信心,科创创业... 截至7月8日11点15分,上证指数涨0.28%,深证成指跌0.28%,创业板指涨0.51%。油气开采...
将多色3D打印提速5倍,消费级... 消费级3D打印企业快造科技(Snapmaker)近日完成10亿元C轮融资。本轮由凯辉基金领投,好未来...
“物理AI第一股”来了!Mom... 2026年7月8日,全球领先的物理AI公司Momenta正式在港交所挂牌上市,股票代码为6880.H...
投资需求增长的核心动力是什么? 在金融市场中,投资需求的增长受到多种因素的综合推动,这些因素构成了投资需求增长的核心动力。 首先,经...
苏州得鹿食品有限公司成立 注册... 天眼查App显示,近日,苏州得鹿食品有限公司成立,法定代表人为周锋,注册资本50万人民币,经营范围为...
刚刚,又一家厦门企业在港股上市... 最新消息! 厦门又迎来一家上市公司! 7月8日 厦门瑞为信息技术股份有限公司 (以下简称“瑞为技术”...
韩国综合指数转涨,盘初一度跌近... 8日,韩国综合指数转涨,一度涨超1.6%,现涨0.7%,盘初一度跌近4%。个股方面,SK海力士涨近4...
原创 7... 四千多欧洲人因为高温没了命,大半是装不起买不起空调的独居老人。现在老百姓抢着买能解决问题的中国空调,...