tensor 各种类型操作


哈喽哈喽,大家好。这篇文章是看了B站“大大的小番茄”这位博主的视频后,做的笔记,方便日后不记得了回来查看(脑子总是记不住东西!!!)。这位博主的视频讲解非常的好,建议大家可以直接看视频(我的笔记也挺好的,哈哈哈)“大大的小番茄”的B站视频。ok,下面就开始正式学习吧

静态图和动态图的区别

静态图:tf 动态图:pytorch

静态图:定义好变量的类型定义好操作后,最后把数值输入进去即可

动态图:定义了变量,每操作一次就赋值一次后,不需要定义操作

什么是梯度

简单的理解:就是导数,导数在某一点的函数值

使用pytorch求导
# y=a^2*x+b*x+c 当x=1的时候,y对a b c 求偏导

import torch
from torch import autograd

x = torch.tensor(1.0)
a = torch.tensor(1.0, requires_grad=True)
b = torch.tensor(2.0, requires_grad=True)
c = torch.tensor(3.0, requires_grad=True)

y = a ** 2 * x + b * x + c
print("求偏导前:", a.grad, b.grad, c.grad)  # 因为还没有求导,所以都是None
grad = autograd.grad(y, [a, b, c])  # 现在才是真正求偏导的时候,y是输入 后面的列表是它的变量
print("求偏导后:", grad[0], grad[1], grad[2])

# 结果:
求偏导前: None None None
求偏导后: tensor(2.) tensor(1.) tensor(1.)
Lesson1 创建tensor的方式
1.list导入tensor
import torch
c=torch.tensor([2.5,8,1.3])
d=torch.tensor([[2,2.3,5.9,1],
				[2,2.3,5.9,1]])
print(c.dim(),d.sim()) #1 2
print(c.shape,d.shape) #torch.Size([3]) torch.Size([2, 4])
2.torch.FloatTensor()大写方式导入

输入是wh,输出是w行,h列。写多少个数字,就是多少维度

  • torch.FloatTensor(w,h)
  • torch.IntTensor(w,h)
  • torch.Tensor(w,h)
import torch
a=torch.FloatTensor(3,2) #创建3行两列的tensor数据
print(a)

[Out]:
tensor([[0., 0.],
        [0., 0.],
        [0., 0.]])
3.初始化的tensor数据

什么未初始化的tensor数据呢,其实就是会生成特别大或者特别小的tensor,在神经网络中,我们对网络进行初始化的时候,参数不能啥都不给,这样的话网络会失效,所以我们就给它一个很小很小的值,要么很大的值,保证网络的运行,后续训练模型的时候对参数进行优化的时候,优化的就是这些参数。

​ 注意:像torch.FloatTensor() torch.IntTensor() 都是属于初始化的tensor数据

  • torch.empty() # 生成一个空的容器,一个假的东西,后续用到就会使用新的tensor进行替换 类比:函数的参数:None
import torch
a=torch.empty(2)
b=torch.empty(2,3)
c=torch.empty(2,3,4)


a
Out[14]: tensor([0., 0.])
b
Out[15]: 
tensor([[2.3694e-38, 2.3694e-38, 2.3694e-38],
        [2.3694e-38, 2.3694e-38, 2.3694e-38]])
c
Out[16]: 
tensor([[[1.0469e-38, 9.6429e-39, 1.0561e-38, 7.3470e-39],
         [6.1531e-39, 8.9082e-39, 1.0010e-38, 4.5918e-39],
         [4.5918e-39, 4.2245e-39, 4.2245e-39, 8.4489e-39]],
        [[9.9184e-39, 9.4592e-39, 1.0102e-38, 8.4490e-39],
         [1.1112e-38, 9.5511e-39, 1.0102e-38, 9.5510e-39],
         [9.9184e-39, 9.2755e-39, 1.0561e-38, 1.0286e-38]]])
4.均匀分布

创建范围0到1的tensor类型数据

  • torch.randn()
import torch
a=torch.randn(2,3)


a
Out[20]: 
tensor([[ 1.7187, -1.3488, -0.3442],
        [ 0.6220, -1.5147,  1.0261]])


5.xxx_like(tensor.obj)

复制tensor对象的shape,数据重新赋值

import torch
a=torch.arange(9.).reshape(3,3)
b=torch.randn_like(a)

a
Out[25]: 
tensor([[0., 1., 2.],
        [3., 4., 5.],
        [6., 7., 8.]])

b
Out[27]: 
tensor([[ 0.4354,  0.4370, -0.5914],
        [-0.8935, -0.1714, -0.0261],
        [ 0.7370, -0.0225, -1.2903]])
6.整数随机数

创建n~m范围的随机整数—(负数也可以)

  • torch.randint(n,m,[w,h])

创建均匀正太分布,值的大小在0到1

  • torch.randn(w,h)
import torch
a=torch.randint(-3,3[3,3])

Out[40]: 
tensor([[-2,  4, -3],
        [ 6,  4,  8],
        [-3,  0, -3]])
7.正太分布

创建均值为n,标准差为m的正太分布tensor数据,mean设置的n的shape,dtype 要等同于std的m的shape

  • torch.normal(mean=torch.tensor([n],std=torch.tensor([m])))
import torch

# 生成4个点 4个点的均值 标准差分别在括号中一一对应,每个元素来自不同正太分布
a=torch.normal(mean=torch.tensor([2.,3.,4.]),std=torch.tensor([1.0,1.0,1.0]))

a
Out[44]: tensor([1.9255, 4.4596, 4.6520])


# 构造指定维度,形状,元素来自同一个正太分布。可以指定他的size
b=torch.normal(mean=3,std=1.2,size=(2,3))
b
Out[46]: 
tensor([[5.0904, 2.4876, 4.8012],
        [2.3248, 1.4059, 3.6965]])
    

8.等差的tensor数据

创建一个从start 到 end中,取step数量的等差数据

  • torch.linspace(start,end,step)
import torch
l1 = torch.linspace(0, 10, 4) # 0到10 取4个等间距的数据
l2 = torch.linspace(0, 11, 4)
l3=torch.linspace(1,10,4)
print(l1,"\n",l2) 
print(l3)

# tensor([ 0.0000,  3.3333,  6.6667, 10.0000]) 
 tensor([ 0.0000,  3.6667,  7.3333, 11.0000])
 tensor([ 1.,  4.,  7., 10.])
9.获取tensor的大小(占用内存的大小)
  • torch.numel(tensor对象) 或者 tensor对象.numel()
import torch
p=torch.randn(2,3,28,28)
print(p.numel()) #4704 计算方式2*3*28*28
print(torch.numel(p)) # 4704
10.从numpy中导入tensor

torch.from_numpy()

import torch
import numpy as np
b=np.array([2,3,4,5])
print(torch.from_numpy(b)) #tensor([2, 3, 4, 5], dtype=torch.int32)#
11.创建对角线为1的矩阵
import torch
e3=torch.eye(4,5)
print(e3)

#
tensor([[1., 0., 0., 0., 0.],
        [0., 1., 0., 0., 0.],
        [0., 0., 1., 0., 0.],
        [0., 0., 0., 1., 0.]])
12.full使用什么数值进行填充张量
import torch
a=torch.full([2,3,4],5) #创建一个2页 3行 4列的矩阵,并且使用5来填充
print(a)

# 
tensor([[[5, 5, 5, 5],
         [5, 5, 5, 5],
         [5, 5, 5, 5]],
        [[5, 5, 5, 5],
         [5, 5, 5, 5],
         [5, 5, 5, 5]]])

b=torch.full([],6)
print(b)#tensor(6) 这是标量

13.生成打乱顺序的tensor
import torch
x=torch.randperm(10)
print(x)
# tensor([2, 6, 5, 0, 8, 7, 3, 9, 1, 4])
Lesson2 切片,变形
一个维度索引

每一个中括号,就意味着对应张量的第几位,如同下面的a[0]就对应“4”这个维度 a【0】【1】就对应“4”和“3”这两个维度

import torch
a=torch.randn(4,3,28,28)#意义:4张图片,每张图片3通道(RGB),每张图片是28*28大小
print(a[0].shape) #第0个维度上,也就是“4”这个所在的维度上取第一个,打印出它的shape
#意义:取出第一张图片,打印出它的形状

print(a[1].shape) #第0个维度上,也就是“4”这个所在的维度上取第二个,打印出它的shape
#意义:取出第二张图片,打印出它的形状

print(a[2][1].shape)# 在第0个维度上,也就是“4”这个所在的维度上的第3个下,第1维度取第一个并打印出它的shape
#意义:取出第三张图片,并获取到该图片的第二个通道,打印出它的形状

print(a[1]==a[1,:,:]) #它们是等价的
结果如下:
# torch.Size([3, 28, 28])
# torch.Size([3, 28, 28])
# torch.Size([28, 28])
# True
两个维度进行索引

在数组中,中括号里面的逗号其实就是指向某个维度,比如a[1,2,3]就代表第0维度上的第一个值的下面的第二个维度上的第二个值的下面的第三个维度上的第三个值

import torch
a=torch.randn(4,3,28,28)
print(a[0,1].shape) #在“4”这个维度下的第一个 下面的 “3”这个维度下的 第一个值
#意义:取出第一张图片 的 第一个通道。所以结果就是28*28

结果如下:
# torch.Size([28, 28])


Lesson5_创建tensor(中)
1.索引

索引其实就是索求,引出。那么将一个东西拿出来,得到他的形状就是索引

  • 对一个维度进行索引

    import torch
    
    # 意义:4张图片 每张3通道每个通道28x28大小
    a=torch.randn(4,3,28,28)
    
    # a[n] 表示第0个维度上 第n个值
    # 意义:取出4张图片中的这个维度中的  第一张图片
    print(a[0].shape) #torch.Size([3, 28, 28])
    
    
  • 对两个维度进行索引

    import torch
    
    # 意义:4张图片 每张3通道每个通道28x28大小
    a=torch.randn(4,3,28,28)
    
    # a[n,m] 表示第0个维度上第n个值  第1个维度上第m个值 所以中括号中逗号分割的是维度
    # 意义:取出第1张图片,第1通道上的,像素矩阵信息为28*28
    print(a[0,0].shape) # torch.Size([28, 28])
    print(a[0][0].shape) # torch.Size([28, 28]) 等价于上面
    print(a[2,2].shape) #torch.Size([28, 28]) 意义:取出第3张图片,第3通道上的,像素矩阵信息为28*28
    
  • 对三,四维度进行索引

    import torch
    
    # 意义:4张图片 每张3通道每个通道28x28大小
    a=torch.randn(4,3,28,28)
    
    # 意义:第3张图中,第3通道上,第4行上的形状
    print(a[2,2,3].shape) # torch.Size([28])  在实际场景中没啥意义
    
    # 意义:第1张图片,第2个通道,第14行14列,某个像素点的信息,是一个标量
    print(a[0,1,13,13].shape) #torch.Size([])
    
2.切片

连续多个维度的连续索引就是切片,将一堆的东西分成好几分,每一份都有好几个

  • 第一个维度进行切片

    import torch
    
    # 意义:4张图片 每张3通道每个通道28x28大小
    a=torch.randn(4,3,28,28)
    
    # 意义:a[:n] 第0个维度上 从第n个取到n-1个
    # 取出前两张图片上所有通道的像素信息
    print(a[:2].shape) # torch.Size([2, 3, 28, 28])
    
    
  • 对两个维度进行切片

    import torch
    
    # 意义:4张图片 每张3通道每个通道28x28大小
    a=torch.randn(4,3,28,28)
    
    # 意义:a[:n,:m]第0个维度上 从第0个取到第n-1个,第1个维度上 从第0个取到第m-1个
    # 取出前两张图片,每张图片取前两个通道的像素信息--->连续切片
    print(a[:2,:2].shape) # torch.Size([2, 2, 28, 28])
    
  • 冒号的用法

    import torch
    
    # 意义:4张图片 每张3通道每个通道28x28大小
    a=torch.randn(4,3,28,28)
    
    # 从第2张图片取到最后一张图片 通道是从第1个通道取到第2个通道
    print(a[2:,:2].shape) # torch.Size([2, 2, 28, 28])
    print(a[1:3, :2, 2:16:4, 14:].shape)  # torch.Size([2, 2, 4, 14])
    
    
    # :n 表示切片[0,n)
    # n: 表示切片[n,-1] 这个-1就是表示可以取到最后一个
    # : 表示全部提取
    #  start:end 表示[start:end)
    # start:end:step 表示[start,end),以step为间隔(步长)提取
    # 如果是a[:6:-1] 结果就是[9, 8, 7] 因为下标从0开始数到6 值是“6”而又开所以娶不到6 又因为负数 所以是反向向
    # 倒叙只能使用torch.flip()
    # 意义:4张图片进行倒叙排列
    torch.flip(a,dims=[0]) # 第一个维度进行倒叙
    
  • 索引和切片结合

    import torch
    
    # 意义:4张图片 每张3通道每个通道28x28大小
    a=torch.randn(4,3,28,28)
    
    # 意义: 第0张图片,最后1个通道的像素信息  这里之所以会是1 28 28 是因为第二个维度是索引的方式,索引的时候,是会将东西取出来,可类比上面索引操作
    # 索引的时候,它的shape情况
    print(a[:1, -1].shape)  # torch.Size([1, 28, 28])
    print(a[:1, -1, :].shape)  # torch.Size([1, 28, 28])等同于上方,只是上面的可以忽略引号
    
    # 意义: 第0张到第1张图片(也就是前两张图片),最后1个通道的像素信息
    print(a[:2, -1].shape)  # torch.Size([2, 28, 28]) 这个打印结果的2表示前两张图片
    
  • 获取索引位置下标

    import torch
    
    # 4张图片 每张3通道 每个通道28x28大小
    a = torch.randn(4, 3, 28, 28)
    
    # 意义:# 在a中的第0个维度中,取第1张和第3张图片 并打印shape
    # 解释:结果是2张图片,3个通道,28*28大小
    # 0 就是a的第一个维度 torch.tensor([0, 2])的0 2是a的第一个维度中的 取索引 0  2
    print(a.index_select(0, torch.tensor([0, 2])).shape) #torch.Size([2, 3, 28, 28])
    
    # 所有图片中 获取第1 和第2通道上 所有的像素信息
    print(a.index_select(1,torch.tensor([0,2])).shape) #torch.Size([4, 2, 28, 28])
    
    
3.筛选函数
  • mask函数

    按照条件筛选

    import torch
    x=torch.randn(3,4)
    mask=x.ge(0.5) # x中大于等于0.5的位置上记为True 否则为Fasle
    print(torch.masked_select(x,mask)) #tensor([1.0259, 1.3513, 0.9164, 1.1191, 0.6029])
    print(x[mask]) #结果等同于上面
    
    #mask结果:
    tensor([[ True, False, False, False],
            [ True,  True,  True, False],
            [False,  True,  True, False]])
    
  • take 函数

    将高维度张量打平一维,再按照指定位置进行索引

    import torch
    
    #s=torch.randperm(8).reshape(2,4)
    
    s=torch.tensor([[4,3,5],
                   [2,6,7]])
    # 做法就是将上面的2维数组打平成[4,3,5,2,6,7],然后取这个一维数组中下标0 3 -2的元素
    print(torch.take(s,torch.tensor([0,3,-2])))#tensor([4, 2, 6])
    
Lesson5_创建tensor(下)
1.转置
  • t()

    只对二维的张量转置

    import torch
    a=torch.rand(3,4)
    print(a.t().shape) #torch.Size([4, 3])
    
  • torch.transpose()

    对高维度的转置,一次只能对两个维度进行操作

    import torch
    t=torch.randn(4,3,32,32)
    print(t.shape) #torch.Size([4, 3, 32, 32])
    # transpose只能对两个维度进行交换,所以你这里写transpose(1,3) 还是transpose(3,1)都是一样的,就是要求1和3交换
    t1=t.transpose(1,3) #torch.Size([4, 32, 32, 3]) # 改变了数据的维度信息,结构,数据 (会改变原始数据)
    
    t2=torch.tanspose(t,1,3) # 结果等同于上面
    
  • transpose改变原数据说明

    有点类似于浅拷贝,都是内存的共享

    import torch
    
    x=torch.arange(6).reshape(2,3)
    y=torch.transpose(x,0,1)
    print("x:",x,"\n","y:",y)
    #结果:
    x: tensor([[0, 1, 2],
               [3, 4, 5]]) 
     y: tensor([[0, 3],
               [1, 4],
               [2, 5]])
    
    
    
    y[0,0]=11 # 此时我们改变转置后的数组y
    print(x,"\n",y) #我们发现只改变了y 但是x也发生了变化
    #结果:
    tensor([[11,  1,  2],
            [ 3,  4,  5]]) 
    tensor([[11,  3],
            [ 1,  4],
            [ 2,  5]])
    
    
  • contiguous的使用

    切断两个tensor的联系,使用后让变化后的tensor和原来的数据没有联系,没有内存的共享

    我们知道transpose是在原数据上进行改变的,view也是在原数据上改变的。当两个函数同时使用会报错:数据不连续了。

    import torch
    
    t=torch.randn(4,3,32,32)
    t2=t.transpose(1,3).view(4,32*3*32)#会报错
    
    # 报错原因:transpose对t进行了原数据的改变,而view也是对原数据改变,而不是对t.tranpose后的数据修改的,均共享内存。由于transpose改变了数据,所以导致数据和内存不一致就会报数据不连续
    
    """
    解决方式
    """
    #方式1.使用reshape
    t=torch.randn(4,3,32,32)
    t2=t.transpose(1,3).reshape(4,32*3*32)
    print(t2.shape)
    
    #方式2.使用contiguous()
    t=torch.randn(4,3,32,32)
    t1=torch.transpose(t,1,3).contiguous().view(4,3*32*32)
    
    
  • permute 多个维度多次转置

    import torch
      
    z=torch.randn(4,3,28,32)
    print(z.transpose(1,3).transpose(1,2).shape) #torch.Size([4, 28, 32, 3])
    # permute 设置好当前维度信息由原始数据中的哪个维度变换而来
    print(z.permute(0,2,3,1).shape) #torch.Size([4, 28, 32, 3])
    
Lesson6_tesnor_advanced1
1.广播机制–broadcasting

在数学中,二维的数据是不可以和一维的数据进行计算的。而在torch中有一个广播机制,它会自动对低维度的数组进行扩展,填充。这个扩展和填充并不是真正意义的增加了数据,只是改变了对数据的理解。

使用代码复现原理:

会自动unsqueeze 然后expand操作

import torch
a=torch.tensor([[2,3,4],[2,2,2]]) #torch.Size([2, 3])
b=torch.tensor([2,2,2]) #torch.Size([3])
res1=a+b

# 推演过程
b1=torch.unsqueeze(b,0) #torch.Size([1, 3])
b2=b1.expand((2,3)) #torch.Size([2, 3])
res2=a+b2


print(torch.all(torch.eq(res1,res2))) # True
2.实际中应用
# [4,3,32,32] +[32,32]:每张图片,每个通道 加上一个基底
# [4,3,32,32] +[3,1,1]:每张图片,每个通道 加上一个固定的像素值
# [4,3,32,32] +[1,1,1,1]:每张图片,每个通道,每个像素信息都加一个像素点
Lesson6_tesnor_advance2

主要是对张量的运算和拆分

1.拼接和拆分
  • cat 和 stack 拼接

    cat合并条件:要拼接的维度的size可以不一样,其他的维度的size必须一样

    stack合并条件:张量的shape必须一样,是一模一样

    区别:cat是内部拼接,stack外部拼接。cat拼接后维度dim不变,stack拼接后维度

    import torch
    
    # n个班 m个学生 k们课
    a=torch.randn(4,32,8)
    b=torch.randn(5,32,8)
    c=torch.randn(3,32,4)
    print(torch.cat([a,b],dim=0).shape)# torch.Size([9, 32, 8])  在0维度拼接起来 a班和b班合并
    
    # print(torch.cat([a,c],dim=0).shape)
    # 报错,就是因为没有符合上面的合并条件
    # 报错意思就是除了0维度外,其他的维度size要一致
    #RuntimeError: torch.cat(): Sizes of tensors must match except in dimension 0. Got 8 and 4 in dimension 2 (The offending index is 1)
    
    ######################################stack      
    
    a=torch.rand(32,8)
    b=torch.rand(32,8)
    c=torch.rand(22,8)
    print(torch.stack([a,b],dim=0).shape) # torch.Size([2, 32, 8])
    print(torch.stack([a,b],dim=1).shape)#torch.Size([32, 2, 8])
    # print(torch.stack([a,c],dim=0).shape) #因为shape不一致
    # RuntimeError: stack expects each tensor to be equal size, but got [32, 8] at entry 0 and [22, 8] at entry 1
    
  • split 和 chunk 拆分

    split拆分条件:拆分的数量一定要等于要拆分的维度的数量

    split:按照长度拆分

    chunk:按照数量拆分

    import torch
    ################### split
    c=torch.randn(4,32,8)
    d=torch.randn(5,32,8)
    # 在指定的维度对tensor拆分,按照长度拆分
    c1,c2=c.split(2,dim=0)# 在0维度上,将c拆分为2分,也就是将“4”这个维度分成2份
    print(c1.shape,c2.shape) #torch.Size([2, 32, 8]) torch.Size([2, 32, 8])
    d1,d2=d.split([3,2],dim=0) # 在0维度上将5拆分为2和3各两份
    print(d1.shape,d2.shape) # torch.Size([3, 32, 8]) torch.Size([2, 32, 8])
    e,f,g=d.split([2,1,2],dim=0)
    print(e.shape,f.shape,g.shape) #torch.Size([2, 32, 8]) torch.Size([1, 32, 8]) torch.Size([2, 32, 8])
    
    ################### chunk
    # chunk 按照数量拆分
    c=torch.randn(8,32,8)
    t=torch.randn(9,32,8)
    # 在指定维度上对shape平均分成:shape/n块
    c1,c2=c.chunk(2,dim=0)
    print(c1.shape,c2.shape) #torch.Size([4, 32, 8]) torch.Size([4, 32, 8])  8/2=4所以每个都是一样的shape
    # 不整除呢? 尽可能让余数变小
    d,e,f=c.chunk(3,dim=0)
    print(d.shape,e.shape,f.shape) #torch.Size([3, 32, 8]) torch.Size([3, 32, 8]) torch.Size([2, 32, 8])
    
2.基本运算,点对点的运算

下面的运算都是点对点的运算,并非矩阵的运算。代码中不同维度之所以相加,一定要牢记广播机制:torch.unsqueeze()然后expand()

  • 加法 torch.add +

    点对点的加法

    import torch
    
    a=torch.full([3,5],3)
    b=torch.full([3,5],1)
    res1=torch.add(a,b) 
    res2=a+b # 等同于上面
    print(torch.all(torch.eq(res1,res2))) # tensor(True)
    
    
  • 减法 torch.sub -

    import torch
    
    a=torch.full([3,5],3)
    b=torch.full([3,5],1)
    res1=torch.sub(a,b)
    res2=a-b # 等同于上面
    print(torch.all(torch.eq(res1,res2))) # tensor(True)
    
  • 乘法 torch.mul *

    a=torch.full([3,5],3)
    b=torch.full([3,5],2)
    res1=torch.mul(a,b)
    res2=a-b# 等同于上面
    print(torch.all(torch.eq(res1,res2))) # tensor(True)
    
  • 除法 torch.div /

    a=torch.full([3,5],3)
    b=torch.full([3,5],2)
    res1=torch.div(a,b)
    res2=a/b #等同于上面
    print(torch.all(torch.eq(res1,res2))) # tensor(True)
    
3.基本运算,矩阵运算
  • 二维张量乘法 torch.mm @

    该API仅限于二维的张量,矩阵相乘规则:[m,n] *[n,l] =>[m,l]

    import torch
    a=torch.full([2,2],3.)
    b=torch.arange(6.).reshape(2,3)
    res1=torch.mm(a,b)
    res2=a@b #等同于上面
    print(torch.all(torch.eq(res1,res2))) # tensor(True)
    
  • 高维度张量乘法 torch.matmul

    3d 4d张量运算条件:除了最后两个维度,前面所有维度必须相同,最后两个维度要满足矩阵的乘法条件

    结果:前面俩个维度一致,最后的维度,取决于矩阵乘法的结果

    import torch
    
    a=torch.rand(4,3,28,64)
    b=torch.rand(4,3,64,32)
    c=torch.rand(5,3,64,32)
    
    print(torch.matmul(a,b).shape) #torch.Size([4, 3, 28, 32])
    # print(torch.matmul(a,c).shape) # 报错,因为前面的两个维度不相等
    
  • 次方运算 power() **

    张量中每个元素都进行次方的运算

    import torch
    
    a=torch.full([2,2,2],3)
    print(a.pow(4))# 每个元素都做一个4次方的运算
    print(a**4)
     
    
  • 根号 sqrt() 和 根号倒数 rsqrt()

    sqrt() :张量的每个元素都进行根号运算.

    rsqrt():张量的每个元素进行根号运算后,取倒数

    import torch
    
    a=torch.full([2,2,2],9)
    print(a.sqrt()) # 元素都是3的张量
    
    print(a.rsqrt()) # 元素都是1/3的张量
    
  • 自然对数e torch.exp

    矩阵的每个元素都进行e的n次方。注意是e的n次方,而不是n的e次方

    import torch
    # 自然对数e
    a=torch.exp(torch.ones(2,2)) # 先生成2*2全是1的矩阵,然后每个位置都是e的1次方,主要是e的1次方不是1的e次方
    print(a)
    # log以e为底,log2()就是以2为底 log10就是以10为底
    print(torch.log(a))
    
  • 近似计算floor() ceil()

    floor向下取整 ceil向上取整

    import torch
    a=torch.tensor(3.1415926545757)
    print(a.floor()) #tensor(3.)
    print(a.ceil()) #tensor(4.)
    
  • 取整数部分trunc() 取小数部分frac()

    import torch
    a=torch.tensor(3.1415926545757)
    print(a.trunc(),a.frac()) #tensor(3.) tensor(0.1416)
    
  • 梯度截断 clamp

    梯度离散:梯度信息非常小,接近于0。梯度爆炸:梯度非常大

    梯度截断主要用于:当梯度过大时候,我们将梯度最大值和最小值限定在一个数值,让梯度稳定下来

    import torch
    a=torch.arange(10).reshape(2,5)
    # 把a限定在[2,5]之类,小于2用2替换,大于5用5替换
    grad=a.clamp(2,5)
    
    # a:
    tensor([[0, 1, 2, 3, 4],
            [5, 6, 7, 8, 9]])
    
    #grad:
    tensor([[2, 2, 2, 3, 4],
            [5, 5, 5, 5, 5]])
    
    
Lesson6_tesnor_advance3

主要为统计计算

1.norm求范数

一维张量求范数可以理解为求向量的模长范数 高维度可以理解为矩阵范数 两个范数公式均为不同

  • 一维张量,即向量范数

    • 一范数:求绝对值

    • 二范数:勾股定理

    • 三范数:有些复杂,请看公式

  • 矩阵范数

    • 一范数:每一列的每个元素求绝对值,然后相加

    • 二范数:每一行每一列的元素平方后求和再开根号

    • 三范数:所有元素三次方求和再开三次方

在这里插入图片描述

  • dim=1

    import torch
    a=torch.full([8],1.)
    f1=a.norm(1) # 一范数,8个1求和然后绝对值 所以是8.
    f2=a.norm(2) # 二范数,8个1每一个都平方后求和,再开根号
    f3=a.norm(3) # 三范数,8个1每一个元素求绝对值后进行3次方,然后求和后开根号3
    
    print(f1,f2,f3)#tensor(8.) tensor(2.8284) tensor(2.)
    
    
  • dim=2

    import torch
    a=torch.full([8],1.).reshape(2,4)
    # a的样子:
    # [1,1,1,1]
    # [1,1,1,1]
    
    f1=a.norm(1) #每一列的每个元素求绝对值之和,这里有4列,每一列都是|1+1|,所有是8
    f2=a.norm(2) #每个元素平方后求和开根号 1+1+...+1=8 开根号就是2.8284
    f3=a.norm(3) #所有元素三次方求和再开三次方
    print(f1,f2,f3)#(tensor(8.), tensor(2.8284), tensor(2.))
    
  • dim=3

    import torch
    a=torch.full([8],1.)
    # dim=3 计算方式与上方公式一致
    c=a.view(2,2,2)
    print(c.norm(1),c.norm(2),c.norm(3))#tensor(8.) tensor(2.8284) tensor(2.)
    
  • 指定维度上的范数

    import torch
    a=torch.arange(0,8.).reshape(2,4)
    #a的样子:tensor([[0., 1., 2., 3.],
    #       		   [4., 5., 6., 7.]])
      
      
    f1=a.norm(1,dim=0) #在0维度上取1范数,|0|+|4|,|5|+|1|,|2|+|6|,|3|+|7|
    f2=a.norm(2,dim=0) #在0维度上取2范数,sqrt(0^2+4^),sqrt(5^2+1^2),sqrt(3^2+7^2)
    print(f1,f2) #(tensor([ 4.,  6.,  8., 10.]), tensor([4.0000, 5.0990, 6.3246, 7.6158]))
      
    f3=a.norm(1,dim=1)#在1维度上取1范数,|0|+|1|+|2|+|3|,|4|+|5|+|6|+|7|
    print(f3) #tensor([ 6., 22.])
    
2.统计属性
  • 最大,最小,均值,阶乘,求和

    import torch
    x=torch.arange(8).view(2,4).float()
    #x的样子:tensor([[0., 1., 2., 3.],
    #        		 [4., 5., 6., 7.]])
    
    
    print(x.min()) #tensor(0.) 求二维矩阵最小值
    print(x.max()) #tensor(7.)
    print(x.mean()) #tensor(3.5000)
    # 如果不指定维度,他会自动打平后运算
    print(x.prod())# 阶乘--->所有元素相乘0x1x2x...7
    print(x.sum()) #tensor(28.)
    
    
    #################### 在特定维度上求最值
    print(x.min(dim=0)) #会有两个返回值,一个是最值的结果,一个是最值所在的位置,这里indices都是0,是因为,我们对比第一个维度 所以[0., 1., 2., 3.]和[4., 5., 6., 7.]分别看成一个对象,这里indices就是指最值的在第一个维度中的第0个
    
    #结果:
    #torch.return_types.min(
    #values=tensor([0., 1., 2., 3.]),
    #indices=tensor([0, 0, 0, 0]))
    
3.位置索引
  • 最值位置索引 argmax argmin

    会返回最值的索引

    import torch
    x=torch.randperm(8).reshape(2,4).to(torch.float)
    #x的样子:tensor([[3., 6., 2., 0.],
    #       		 [4., 1., 7., 5.]])
    
    # flatten的样子:
    #tensor([3., 6., 2., 0., 4., 1., 7., 5.])
    
    print(x.argmin()) #最小值的位置索引,当不指定dim,会默认执行flatten()操作。  结果:tensor(3)
    print(x.argmax()) #tensor(6)
    
    ################### 在特定维度寻找最值位置索引
    # 在维度0上,纵向对比值的大小
    print(x.argmin(dim=0)) #tensor([0, 1, 0, 0])
    # 对比大小后,输出的结果和原来的数据dim保持一致
    print(x.argmin(dim=0,keepdim=True)) #tensor([[0, 1, 0, 0]])
    
    
  • 最值的前n个以及索引 topk()

    会有两个返回值,values是返回它的值, indices索引位置

    import torch
    
    ####################### 一维
    a=torch.tensor([1, 5, 3, 9, 2])
    # 输出最大值两个值以及索引
    values, indices = torch.topk(a, k=2) 
    print(values,indices) #(tensor([9, 5]), tensor([3, 1]))
    #输出最小值两个值以及索引
    values, indices = torch.topk(a, k=2,largest=False)
    print(values,indices) #(tensor([1, 2]), tensor([0, 4]))
    
    ####################### 二维
    b=torch.randperm(8).reshape(2,4)
    #b的样子:tensor([[5, 4, 7, 2],
    #        		 [6, 1, 0, 3]])
    
    #不指定维度,会将每一行最大的值输出
    values, indices = torch.topk(b,k=1)
    print(values, indices) # tensor([[7],[6]])  tensor([[2],[0]])
    # 说明:在b中有2行4列,因为不指定维度,所以它会将每行最大值输出。[5, 4, 7, 2]最大值是7,[6, 1, 0, 3]最大值是6.他们的位置在所在行的2 0 两个索引位置
    
    
    #指定维度
    values, indices = torch.topk(b,k=1,dim=0)
    print(values, indices) #(tensor([[6, 4, 7, 3]]), tensor([[1, 0, 0, 1]]))
    #说明:指定维度为0,而维度0的有两个,分别是[5, 4, 7, 2]和[6, 1, 0, 3]。所以会将他们各自的元素相互对比。5与6,4与1,7与0,2与3,所以输出tensor([[6, 4, 7, 3]]),而tensor([[1, 0, 0, 1]])是他们所在的dim=0里面的哪一行,也就是位置索引值
    
  • 第n小 kthvalue

    会有两个返回值,values是返回它的值, indices索引位置

    import torch
    a=torch.tensor([1, 5, 3, 9, 2])
    # 第2小的值==倒数第二大的值
    v,idx=a.kthvalue(2)
    print(v,idx) #(tensor(2), tensor(4))
    
4.比较操作
  • 类似python的操作 > < == >= <=

    import torch
    a=torch.arange(8)
    b=torch.full([8],3)
    
    # > a与b做对比,将大于b的数据拿出来
    print(a[a>b]) #tensor([4, 5, 6, 7])
    # 将a中大于5的取出来
    print(a[torch.gt(a,5)]) #tensor([6, 7])
    
    # <	a与b做对比,将小于b的数据拿出来
    print(a[a<b]) #tensor([0, 1, 2])
    
    # == a与b做对比,将等于b的数据拿出来
    print(a[a==b]) #tensor([3])
    
    
    # 判断两个同shape的张量是否相等
    a=torch.rand(2,3)
    b=torch.ones(2,3)
    print(torch.eq(a,b)) # 同shape的True False 的张量,是每个位置进行了对比
    print(torch.equal(a,b)) # 只返回是否全部相等,相等True 只要有一个不想等False
    print(a==b) # 等同torch.eq((a,b))
    
5.高阶操作
  • where 根据条件持续逻辑判断控制取值

    for i in range:
       if 条件:
           a[i]=x[i] 满足条件取值从x中找
       else:
           a[i]=y[i] 不满足条件取值从y中找
    
    import torch
    ####例子1.
    x=torch.zeros(2,2)
    y=torch.ones(2,2)
    condition=torch.tensor([[0.4,0.8],[0.7,0.3]])
    print(condition)
    # 若condition对应位置为>0.5 则该位置取自x的对应位置
    # 若condition对应位置为<0.5 则该位置取自y的对应位置
    print(torch.where(condition>0.5,x,y))
    # 结果:
    # tensor([[1., 0.],
    #         [0., 1.]])
    
    ####例子2.
    a=torch.arange(8)
    # a中大于5的取1,否则取自身
    print(torch.where(a>5,1,a)) #tensor([0, 1, 2, 3, 4, 5, 1, 1])
    

完结,撒花!!!!

在这里插入图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值