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

4-1张量的结构操作

时间:2024-03-07 23:44:05浏览次数:21  
标签:10 tensor torch 张量 print 操作 100 结构

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

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

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]])
"""

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

"""

# 特殊矩阵
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]])
"""

2.索引切片

张量的索引切片方式和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)
"""

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

# 第一行至第三行
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

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

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个学生,第四个学生的全部成绩
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个学生的第一门课程,第三门课程,第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个学生的第一门课程,第3个班级的第四个学生的第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]))
print(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
"""
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)
"""

3.维度变换

维度变换相关哈数主要有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)
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])
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
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())
"""
tensor([[1, 2, 3],
        [4, 5, 6]])
tensor([[1, 4],
        [2, 5],
        [3, 6]])
"""

4.合并分割

可以用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和aixs参数名可以混用
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.]])
"""

标签:10,tensor,torch,张量,print,操作,100,结构
From: https://www.cnblogs.com/lotuslaw/p/18060065

相关文章

  • YAML 语法简介与 C# 操作示例
    〇、简介YAML(YetAnotherMarkupLanguage)另一种标记语言。YAML是一种较为人性化的数据序列化语言,可以配合目前大多数编程语言使用。YAML的语法比较简洁直观,特点是使用空格来表达层次结构,其最大优势在于数据结构方面的表达,所以YAML更多应用于编写配置文件,其文件一般以.yml......
  • 【学习笔记】 - 基础数据结构 :Link-Cut Tree(进阶篇)
    前言LCT没题写可以去写树剖和一些线段树合并的题练手LCT的概念原本的树剖是对树进行剖分,剖分为重边和轻边LCT则是对于树分为虚边和实边,特殊的,LCT可以没有虚边(例:银河英雄传说v2)单独被包含在一个实链里的点称作孤立点在树剖中,我们使用线段树/树状数组来维护重链在Link-Cut......
  • Hbase的底层操作原理
    1、HBase读流程 1)Client先访问zookeeper,从meta表读取region的位置,然后读取meta表中的数据。meta中又存储了用户表的region信息;2)根据namespace、表名和rowkey在meta表中找到对应的region信息;3)找到这个region对应的regionserver;4)查找对应的region;5)先从MemStore找数据,如果没有,再......
  • 【VMware ESXi】如何在独立的ESXi主机上配置vTPM并安装Windows 11操作系统。
    根据微软发布的Windows11操作系统要求,这个版本的系统需要硬件支持受信任的平台模块(TPM)才能进行安装和使用,不然就会提示你“这台电脑无法运行Windows11。这台电脑不符合安装此版本的Windows所需的最低系统要求。有关详细信息,请访问https://aka.ms/WindowsSysReq”错误。关于受......
  • SDI 通常指的是“System Deployment Image”,即系统部署映像。这是一个包含操作系统、
    SDI通常指的是“SystemDeploymentImage”,即系统部署映像。这是一个包含操作系统、应用程序和设置的映像文件,用于在多台计算机上进行相同配置的系统部署。如果您想要在Windows上读取用户的SDI文件,您可以按照以下步骤进行操作:使用DISM工具:Windows提供了一个名为DIS......
  • 快捷方式在Windows操作系统中提供了一种方便快捷地访问程序或文件的方法,可以分别存在
    快捷方式在Windows操作系统中提供了一种方便快捷地访问程序或文件的方法,可以分别存在于桌面、开始菜单和任务栏等位置。下面是关于快捷方式在不同位置的技术原理:桌面快捷方式:桌面快捷方式实际上是一个.lnk文件,它包含了指向目标文件或程序的路径信息以及其他属性。创建桌面快捷......
  • 操作系统概述
    概念,功能,目标os的四个特征os的发展与分类os的运行机制中断和异常系统调用os体系结构......
  • Centos7下新硬盘的挂载操作
    1、查看当前硬盘使用情况df-h 2、查看磁盘分配情况注意区分,物理磁盘与设备(其实就是磁盘分区)的概念,一块物理磁盘可以对应N个分区,即设备BOOT信息fdisk-l如图所示vdb磁盘还未被使用,现在开始分配。 3、磁盘分配使用m查看详细命令,n添加一块新分区,默认最多只能有四个......
  • 基本操作之——Object移除操作
    remove_obj—Removeobjectsfromaniconicobjecttuple.从图形数组中移除对象**Thisexampledemonstratesvarioususecasesfortheremove_objoperator.*此示例演示了remove_obj运算符的各种用例*dev_update_off()dev_close_window()dev_open_window(0,0,......
  • 基本操作之——Object差异
    obj_diff—Calculatethedifferenceoftwoobjecttuples.计算两个对象的差异*region类型获取内容差异*image类型/XLDs类型仅比较内存地址差异*mixed类型(如image和xld的混合类型)**obj_diff使用read_image(Image,'particle')threshold(Image,Regio......