首页 > 其他分享 >4-1.张量的结构操作

4-1.张量的结构操作

时间:2024-07-10 22:55:51浏览次数:17  
标签:tensor torch 张量 60 print 操作 100 结构

文章最前: 我是Octopus,这个名字来源于我的中文名–章鱼;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github ;这博客是记录我学习的点点滴滴,如果您对 Python、Java、AI、算法有兴趣,可以关注我的动态,一起学习,共同进步。

本篇我们介绍张量的结构操作。

张量结构操作主要包括:张量创建,索引切片,维度变换,合并分割。

import torch 
print("torch.__version__="+torch.__version__) 
torch.__version__=2.0.1

一,创建张量

张量创建的许多方法和numpy中创建array的方法很像。

import numpy as np
import torch 
a = torch.tensor([1,2,3],dtype = torch.float)
print(a)
tensor([1., 2., 3.])
b = torch.arange(1,10,step = 2)
print(b)
tensor([1, 3, 5, 7, 9])

c = torch.linspace(0.0,2*3.14,10)
print(c)
tensor([0.0000, 0.6978, 1.3956, 2.0933, 2.7911, 3.4889, 4.1867, 4.8844, 5.5822,
        6.2800])

d = torch.zeros((3,3))
print(d)
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])

a = torch.ones((3,3),dtype = torch.int)
b = torch.zeros_like(a,dtype = torch.float)
print(a)
print(b)

tensor([[1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]], dtype=torch.int32)
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])

torch.fill_(b,5)
print(b)
tensor([[5., 5., 5.],
        [5., 5., 5.],
        [5., 5., 5.]])

#均匀随机分布
torch.manual_seed(0)
minval,maxval = 0,10
a = minval + (maxval-minval)*torch.rand([5])
print(a)
tensor([4.9626, 7.6822, 0.8848, 1.3203, 3.0742])

#正态分布随机
b = torch.normal(mean = torch.zeros(3,3), std = torch.ones(3,3))
print(b)

tensor([[ 0.5507,  0.2704,  0.6472],
        [ 0.2490, -0.3354,  0.4564],
        [-0.6255,  0.4539, -1.3740]])

#正态分布随机
mean,std = 2,5
c = std*torch.randn((3,3))+mean
print(c)
tensor([[16.2371, -1.6612,  3.9163],
        [ 7.4999,  1.5616,  4.0768],
        [ 5.2128, -8.9407,  6.4601]])

#整数随机排列
d = torch.randperm(20)
print(d)
tensor([ 3, 17,  9, 19,  1, 18,  4, 13, 15, 12,  0, 16,  7, 11,  2,  5,  8, 10,
         6, 14])

#特殊矩阵
I = torch.eye(3,3) #单位矩阵
print(I)
t = torch.diag(torch.tensor([1,2,3])) #对角矩阵
print(t)

tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])
tensor([[1, 0, 0],
        [0, 2, 0],
        [0, 0, 3]])


二 ,索引切片

张量的索引切片方式和numpy几乎是一样的。切片时支持缺省参数和省略号。

可以通过索引和切片对部分元素进行修改。

此外,对于不规则的切片提取,可以使用torch.index_select, torch.masked_select, torch.take

如果要通过修改张量的某些元素得到新的张量,可以使用torch.where,torch.masked_fill,torch.index_fill

#均匀随机分布
torch.manual_seed(0)
minval,maxval = 0,10
t = torch.floor(minval + (maxval-minval)*torch.rand([5,5])).int()
print(t)

tensor([[4, 7, 0, 1, 3],
        [6, 4, 8, 4, 6],
        [3, 4, 0, 1, 2],
        [5, 6, 8, 1, 2],
        [6, 9, 3, 8, 4]], dtype=torch.int32)

#第0行
print(t[0])
tensor([4, 7, 0, 1, 3], dtype=torch.int32)

#倒数第一行
print(t[-1])
tensor([6, 9, 3, 8, 4], dtype=torch.int32)

#第1行第3列
print(t[1,3])
print(t[1][3])
tensor(4, dtype=torch.int32)
tensor(4, dtype=torch.int32)

#第1行至第3行
print(t[1:4,:])
tensor([[6, 4, 8, 4, 6],
        [3, 4, 0, 1, 2],
        [5, 6, 8, 1, 2]], dtype=torch.int32)
#第1行至最后一行,第0列到最后一列每隔两列取一列
print(t[1:4,:4:2])

tensor([[6, 8],
        [3, 0],
        [5, 8]], dtype=torch.int32)

#可以使用索引和切片修改部分元素
x = torch.Tensor([[1,2],[3,4]])
x.data[1,:] = torch.tensor([0.0,0.0])
x
tensor([[1., 2.],
        [0., 0.]])

a = torch.arange(27).view(3,3,3)
print(a)
tensor([[[ 0,  1,  2],
         [ 3,  4,  5],
         [ 6,  7,  8]],

        [[ 9, 10, 11],
         [12, 13, 14],
         [15, 16, 17]],

        [[18, 19, 20],
         [21, 22, 23],
         [24, 25, 26]]])
#省略号可以表示多个冒号
print(a[...,1])
tensor([[ 1,  4,  7],
        [10, 13, 16],
        [19, 22, 25]])

以上切片方式相对规则,对于不规则的切片提取,可以使用torch.index_select, torch.take, torch.gather, torch.masked_select.

考虑班级成绩册的例子,有4个班级,每个班级5个学生,每个学生7门科目成绩。可以用一个4×5×7的张量来表示。

minval=0
maxval=100
scores = torch.floor(minval + (maxval-minval)*torch.rand([4,5,7])).int()
print(scores)
tensor([[[55, 95,  3, 18, 37, 30, 93],
         [17, 26, 15,  3, 20, 92, 72],
         [74, 52, 24, 58,  3, 13, 24],
         [81, 79, 27, 48, 81, 99, 69],
         [56, 83, 20, 59, 11, 15, 24]],

        [[72, 70, 20, 65, 77, 43, 51],
         [61, 81, 98, 11, 31, 69, 91],
         [93, 94, 59,  6, 54, 18,  3],
         [94, 88,  0, 59, 41, 41, 27],
         [69, 20, 68, 75, 85, 68,  0]],

        [[17, 74, 60, 10, 21, 97, 83],
         [28, 37,  2, 49, 12, 11, 47],
         [57, 29, 79, 19, 95, 84,  7],
         [37, 52, 57, 61, 69, 52, 25],
         [73,  2, 20, 37, 25, 32,  9]],

        [[39, 60, 17, 47, 85, 44, 51],
         [45, 60, 81, 97, 81, 97, 46],
         [ 5, 26, 84, 49, 25, 11,  3],
         [ 7, 39, 77, 77,  1, 81, 10],
         [39, 29, 40, 40,  5,  6, 42]]], dtype=torch.int32)
#抽取每个班级第0个学生,第2个学生,第4个学生的全部成绩
torch.index_select(scores,dim = 1,index = torch.tensor([0,2,4]))

tensor([[[55, 95,  3, 18, 37, 30, 93],
         [74, 52, 24, 58,  3, 13, 24],
         [56, 83, 20, 59, 11, 15, 24]],

        [[72, 70, 20, 65, 77, 43, 51],
         [93, 94, 59,  6, 54, 18,  3],
         [69, 20, 68, 75, 85, 68,  0]],

        [[17, 74, 60, 10, 21, 97, 83],
         [57, 29, 79, 19, 95, 84,  7],
         [73,  2, 20, 37, 25, 32,  9]],

        [[39, 60, 17, 47, 85, 44, 51],
         [ 5, 26, 84, 49, 25, 11,  3],
         [39, 29, 40, 40,  5,  6, 42]]], dtype=torch.int32)
#抽取每个班级第0个学生,第2个学生,第4个学生的第1门课程,第3门课程,第6门课程成绩
q = torch.index_select(torch.index_select(scores,dim = 1,index = torch.tensor([0,2,4]))
                   ,dim=2,index = torch.tensor([1,3,6]))
print(q)
tensor([[[95, 18, 93],
         [52, 58, 24],
         [83, 59, 24]],

        [[70, 65, 51],
         [94,  6,  3],
         [20, 75,  0]],

        [[74, 10, 83],
         [29, 19,  7],
         [ 2, 37,  9]],

        [[60, 47, 51],
         [26, 49,  3],
         [29, 40, 42]]], dtype=torch.int32)
#抽取第0个班级第0个学生的第0门课程,第2个班级的第3个学生的第1门课程,第3个班级的第4个学生第6门课程成绩
#take将输入看成一维数组,输出和index同形状
s = torch.take(scores,torch.tensor([0*5*7+0,2*5*7+3*7+1,3*5*7+4*7+6]))
s
tensor([55, 52, 42], dtype=torch.int32)
#抽取分数大于等于80分的分数(布尔索引)
#结果是1维张量
g = torch.masked_select(scores,scores>=80)
print(g)

tensor([95, 93, 92, 81, 81, 99, 83, 81, 98, 91, 93, 94, 94, 88, 85, 97, 83, 95,
        84, 85, 81, 97, 81, 97, 84, 81], dtype=torch.int32)

以上这些方法仅能提取张量的部分元素值,但不能更改张量的部分元素值得到新的张量。

如果要通过修改张量的部分元素值得到新的张量,可以使用torch.where,torch.index_fill 和 torch.masked_fill

torch.where可以理解为if的张量版本。

torch.index_fill的选取元素逻辑和torch.index_select相同。

torch.masked_fill的选取元素逻辑和torch.masked_select相同。

#如果分数大于60分,赋值成1,否则赋值成0
ifpass = torch.where(scores>60,torch.tensor(1),torch.tensor(0))
print(ifpass)

tensor([[[0, 1, 0, 0, 0, 0, 1],
         [0, 0, 0, 0, 0, 1, 1],
         [1, 0, 0, 0, 0, 0, 0],
         [1, 1, 0, 0, 1, 1, 1],
         [0, 1, 0, 0, 0, 0, 0]],

        [[1, 1, 0, 1, 1, 0, 0],
         [1, 1, 1, 0, 0, 1, 1],
         [1, 1, 0, 0, 0, 0, 0],
         [1, 1, 0, 0, 0, 0, 0],
         [1, 0, 1, 1, 1, 1, 0]],

        [[0, 1, 0, 0, 0, 1, 1],
         [0, 0, 0, 0, 0, 0, 0],
         [0, 0, 1, 0, 1, 1, 0],
         [0, 0, 0, 1, 1, 0, 0],
         [1, 0, 0, 0, 0, 0, 0]],

        [[0, 0, 0, 0, 1, 0, 0],
         [0, 0, 1, 1, 1, 1, 0],
         [0, 0, 1, 0, 0, 0, 0],
         [0, 0, 1, 1, 0, 1, 0],
         [0, 0, 0, 0, 0, 0, 0]]])

#将每个班级第0个学生,第2个学生,第4个学生的全部成绩赋值成满分
torch.index_fill(scores,dim = 1,index = torch.tensor([0,2,4]),value = 100)
#等价于 scores.index_fill(dim = 1,index = torch.tensor([0,2,4]),value = 100)

tensor([[[100, 100, 100, 100, 100, 100, 100],
         [ 17,  26,  15,   3,  20,  92,  72],
         [100, 100, 100, 100, 100, 100, 100],
         [ 81,  79,  27,  48,  81,  99,  69],
         [100, 100, 100, 100, 100, 100, 100]],

        [[100, 100, 100, 100, 100, 100, 100],
         [ 61,  81,  98,  11,  31,  69,  91],
         [100, 100, 100, 100, 100, 100, 100],
         [ 94,  88,   0,  59,  41,  41,  27],
         [100, 100, 100, 100, 100, 100, 100]],

        [[100, 100, 100, 100, 100, 100, 100],
         [ 28,  37,   2,  49,  12,  11,  47],
         [100, 100, 100, 100, 100, 100, 100],
         [ 37,  52,  57,  61,  69,  52,  25],
         [100, 100, 100, 100, 100, 100, 100]],

        [[100, 100, 100, 100, 100, 100, 100],
         [ 45,  60,  81,  97,  81,  97,  46],
         [100, 100, 100, 100, 100, 100, 100],
         [  7,  39,  77,  77,   1,  81,  10],
         [100, 100, 100, 100, 100, 100, 100]]], dtype=torch.int32)
#将分数小于60分的分数赋值成60分
b = torch.masked_fill(scores,scores<60,60)
#等价于b = scores.masked_fill(scores<60,60)
b

tensor([[[60, 95, 60, 60, 60, 60, 93],
         [60, 60, 60, 60, 60, 92, 72],
         [74, 60, 60, 60, 60, 60, 60],
         [81, 79, 60, 60, 81, 99, 69],
         [60, 83, 60, 60, 60, 60, 60]],

        [[72, 70, 60, 65, 77, 60, 60],
         [61, 81, 98, 60, 60, 69, 91],
         [93, 94, 60, 60, 60, 60, 60],
         [94, 88, 60, 60, 60, 60, 60],
         [69, 60, 68, 75, 85, 68, 60]],

        [[60, 74, 60, 60, 60, 97, 83],
         [60, 60, 60, 60, 60, 60, 60],
         [60, 60, 79, 60, 95, 84, 60],
         [60, 60, 60, 61, 69, 60, 60],
         [73, 60, 60, 60, 60, 60, 60]],

        [[60, 60, 60, 60, 85, 60, 60],
         [60, 60, 81, 97, 81, 97, 60],
         [60, 60, 84, 60, 60, 60, 60],
         [60, 60, 77, 77, 60, 81, 60],
         [60, 60, 60, 60, 60, 60, 60]]], dtype=torch.int32)

三,维度变换

维度变换相关函数主要有 torch.reshape(或者调用张量的view方法), torch.squeeze, torch.unsqueeze, torch.transpose

torch.reshape 可以改变张量的形状。

torch.squeeze 可以减少维度。

torch.unsqueeze 可以增加维度。

torch.transpose/torch.permute 可以交换维度。

# 张量的view方法有时候会调用失败,可以使用reshape方法。

torch.manual_seed(0)
minval,maxval = 0,255
a = (minval + (maxval-minval)*torch.rand([1,3,3,2])).int()
print(a.shape)
print(a)

torch.Size([1, 3, 3, 2])
tensor([[[[126, 195],
          [ 22,  33],
          [ 78, 161]],

         [[124, 228],
          [116, 161],
          [ 88, 102]],

         [[  5,  43],
          [ 74, 132],
          [177, 204]]]], dtype=torch.int32)
# 改成 (3,6)形状的张量
b = a.view([3,6]) #torch.reshape(a,[3,6])
print(b.shape)
print(b)


torch.Size([3, 6])
tensor([[126, 195,  22,  33,  78, 161],
        [124, 228, 116, 161,  88, 102],
        [  5,  43,  74, 132, 177, 204]], dtype=torch.int32)
# 改回成 [1,3,3,2] 形状的张量
c = torch.reshape(b,[1,3,3,2]) # b.view([1,3,3,2]) 
print(c)
tensor([[[[126, 195],
          [ 22,  33],
          [ 78, 161]],

         [[124, 228],
          [116, 161],
          [ 88, 102]],

         [[  5,  43],
          [ 74, 132],
          [177, 204]]]], dtype=torch.int32)

如果张量在某个维度上只有一个元素,利用torch.squeeze可以消除这个维度。

torch.unsqueeze的作用和torch.squeeze的作用相反。

a = torch.tensor([[1.0,2.0]])
s = torch.squeeze(a)
print(a)
print(s)
print(a.shape)
print(s.shape)

tensor([[1., 2.]])
tensor([1., 2.])
torch.Size([1, 2])
torch.Size([2])
#在第0维插入长度为1的一个维度

d = torch.unsqueeze(s,axis=0)  
print(s)
print(d)

print(s.shape)
print(d.shape)

tensor([1., 2.])
tensor([[1., 2.]])
torch.Size([2])
torch.Size([1, 2])

torch.transpose可以交换张量的维度,torch.transpose常用于图片存储格式的变换上。

如果是二维的矩阵,通常会调用矩阵的转置方法 matrix.t(),等价于 torch.transpose(matrix,0,1)。

minval=0
maxval=255
# Batch,Height,Width,Channel
data = torch.floor(minval + (maxval-minval)*torch.rand([100,256,256,4])).int()
print(data.shape)

# 转换成 Pytorch默认的图片格式 Batch,Channel,Height,Width 
# 需要交换两次
data_t = torch.transpose(torch.transpose(data,1,2),1,3)
print(data_t.shape)


data_p = torch.permute(data,[0,3,1,2]) #对维度的顺序做重新编排
data_p.shape 

torch.Size([100, 256, 256, 4])
torch.Size([100, 4, 256, 256])





torch.Size([100, 4, 256, 256])

matrix = torch.tensor([[1,2,3],[4,5,6]])
print(matrix)
print(matrix.t()) #等价于torch.transpose(matrix,0,1)


tensor([[1, 2, 3],
        [4, 5, 6]])
tensor([[1, 4],
        [2, 5],
        [3, 6]])

四,合并分割

可以用torch.cat方法和torch.stack方法将多个张量合并,可以用torch.split方法把一个张量分割成多个张量。

torch.cat和torch.stack有略微的区别,torch.cat是连接,不会增加维度,而torch.stack是堆叠,会增加维度。

a = torch.tensor([[1.0,2.0],[3.0,4.0]])
b = torch.tensor([[5.0,6.0],[7.0,8.0]])
c = torch.tensor([[9.0,10.0],[11.0,12.0]])

abc_cat = torch.cat([a,b,c],dim = 0)
print(abc_cat.shape)
print(abc_cat)

torch.Size([6, 2])
tensor([[ 1.,  2.],
        [ 3.,  4.],
        [ 5.,  6.],
        [ 7.,  8.],
        [ 9., 10.],
        [11., 12.]])
abc_stack = torch.stack([a,b,c],axis = 0) #torch中dim和axis参数名可以混用
print(abc_stack.shape)
print(abc_stack)

torch.Size([3, 2, 2])
tensor([[[ 1.,  2.],
         [ 3.,  4.]],

        [[ 5.,  6.],
         [ 7.,  8.]],

        [[ 9., 10.],
         [11., 12.]]])
torch.cat([a,b,c],axis = 1)

tensor([[ 1.,  2.,  5.,  6.,  9., 10.],
        [ 3.,  4.,  7.,  8., 11., 12.]])
torch.stack([a,b,c],axis = 1)
tensor([[[ 1.,  2.],
         [ 5.,  6.],
         [ 9., 10.]],

        [[ 3.,  4.],
         [ 7.,  8.],
         [11., 12.]]])

torch.split是torch.cat的逆运算,可以指定分割份数平均分割,也可以通过指定每份的记录数量进行分割。

print(abc_cat)
a,b,c = torch.split(abc_cat,split_size_or_sections = 2,dim = 0) #每份2个进行分割
print(a)
print(b)
print(c)
tensor([[ 1.,  2.],
        [ 3.,  4.],
        [ 5.,  6.],
        [ 7.,  8.],
        [ 9., 10.],
        [11., 12.]])
tensor([[1., 2.],
        [3., 4.]])
tensor([[5., 6.],
        [7., 8.]])
tensor([[ 9., 10.],
        [11., 12.]])
print(abc_cat)
p,q,r = torch.split(abc_cat,split_size_or_sections =[4,1,1],dim = 0) #每份分别为[4,1,1]
print(p)
print(q)
print(r)
tensor([[ 1.,  2.],
        [ 3.,  4.],
        [ 5.,  6.],
        [ 7.,  8.],
        [ 9., 10.],
        [11., 12.]])
tensor([[1., 2.],
        [3., 4.],
        [5., 6.],
        [7., 8.]])
tensor([[ 9., 10.]])
tensor([[11., 12.]])

标签:tensor,torch,张量,60,print,操作,100,结构
From: https://blog.csdn.net/zy345293721/article/details/140270287

相关文章

  • 数据结构(Java):集合类LinkedList&集合类Stack
    1、集合类LinkedList1.1什么是LinkedListLinkedList的底层是一个双向链表的结构(故不支持随机访问):在LinkedList中,定义了first和last,分别指向链表的首节点和尾结点。每个节点中有一个成员用来存储数据,还有两个指针域next和prev分别存储下一个节点和上一个节点的地址。Link......
  • Oracle 11g dg switchover切换操作流程
    主库切换为物理备库查看主库的状态--获取/确认主库的状态信息以及保护模式SQL> set linesize 720SQL> col name for a10SQL> col open_mode for a10SQL> col database_role for a14SQL> col switchover_status for a16SQL> col force_logging for a8SQ......
  • 手写持久层框架------无需写sql语句即可完成对单表的CRUD操作。
    目的:巩固知识点技术栈:java+mysql+反射+自定义注解+泛型+jdbc持久层框架:与数据库交互的一层成为持久层。完成orm操作o(Object对象) r:(relative关系)  m:(mapping映射)。实体类---数据库表  属性---表的字段  实体类对象----一条记录  集合----表中多条记录手......
  • Python 数组类型转树形结构
    今天突然想用到这个功能 结果百度到的 基本是写乱糟糟的一堆代码 无奈只好亲自操刀话不多说,先上代码:classTools:@staticmethoddeflist_to_tree(data,pid=0):children=[itemforitemindataifitem['pid']==pid]forchildinchi......
  • Canvas:实现在线画板操作
    想象一下,用几行代码就能创造出如此逼真的图像和动画,仿佛将艺术与科技完美融合,前端开发的Canvas技术正是这个数字化时代中最具魔力的一环,它不仅仅是网页的一部分,更是一个无限创意的画布,一个让你的想象力自由驰骋的平台。目录基础页面搭建绘画操作按钮点击事件最后总结......
  • 代码随想录day20 二叉搜索树的最近公共祖先 | 二叉搜索树中的插入操作 | 删除二叉
    二叉搜索树的最近公共祖先二叉搜索树的最近公共祖先解题思路利用二叉搜索树的特性,公共祖先的值,就是在要找的两个值的区间里面知识点二叉搜索树心得想了一会如何利用二叉搜索树的特性。顺便复习了昨天做的题目二叉搜索树中的插入操作二叉搜索树中的插入操作解题思路在......
  • python列表:轻松搞懂列表的声明、遍历、常见操作
    一.列表的定义数据类型list,list是python内置的一种高级数据类型。list是一种有序的集合,基于链表实现在python中应用很广泛声明方式一:l0=[]print(l0,type(l0))l1=[1,2,3.2,'abc']print(l1,type(l1))声明方式二:l2=list()#只能将可迭代类型转化为列表类型......
  • 数据结构第19节 排序算法(1)
    冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。冒泡排序步骤详解假设我们有以下数组:int[]arr={64,34,25,12,22,11,90}......
  • 【数据结构】12.排序
    一、排序的概念及其运用1.1排序的概念排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j......
  • 【数据结构】—— 双向链表
    文章目录1、双向链表的概念2、双向链表的接口实现2.1结构2.2初始化申请节点2.3插入数据尾插头插指定位置之后插入数据2.4删除数据尾删头删指定位置删除2.5查找2.6打印2.7销毁3、链表和顺序表的区别4、问题与思考1、双向链表的概念双向链表(DoublyLinkedList)是......