关于pytorch中的tensor用法总结(好办法分享给大家)

tensor - 幕布 有思维导图模式。

  • 张量类型
    • 类型
      • - torch.FloatTensor/torch.float32:单精度浮点型tensor,即32位浮点型。 - torch.DoubleTensor/torch.float64:双精度浮点型tensor,即64位浮点型。 - torch.HalfTensor/torch.float16:半精度浮点型tensor,即16位浮点型。 - torch.ByteTensor/torch.uint8:无符号8位整型tensor。 - torch.CharTensor/torch.int8:有符号8位整型tensor。 - torch.ShortTensor/torch.int16:有符号16位整型tensor。 - torch.IntTensor/torch.int32:有符号32位整型tensor。 - torch.LongTensor/torch.int64:有符号64位整型tensor。
    • 方法
      • 查看类型:a.dtype
      • 修改默认类型:torch.set_default_tensor_type(torch.DoubleTensor) 此法仅修改本次文件,若注释掉后,再重启恢复float32类型。
      • 转换类型: ---------------- a.int() a.float() a.half() ---------------- type()方法:x.type(torch.IntTensor) to()方法:x.to(torch.half) type_as()方法:C=A.type_as(B)
    • 注意
      • 只有tensor.flaot32可以进行求导运算
  • 创建张量
    • torch.tensor()函数方法:
      • 语法:torch.tensor(data, dtype=None, device=None, requires_grad=False) 其中data可以是:list, tuple, NumPy ndarray, scalar和其他类型
      • A=torch.tensor([1,2,3,4])
      • B=torch.tensor((1.0,2,3,4),dtype=torch.float32,requires_grad=True) # 注意数据是用()括起来的,而不是[]。
    • torch.Tensor()类方法:
      • 根据已有数据创建张量: C=torch.Tensor([1,2,3,4])
      • 根据形状创建: C=torch.Tensor(2,3)
    • 特殊数值
      • torch.zeros(3,4)
      • torch.ones(3,4)
      • torch.eye(3)
      • torch.empty(3,4)
      • torch.full((3,4),fill_value=0.25)
    • torch.**_like(A张量)
      • B=torch.ones_like(A_tensor)
      • B=torch.zeros_like(A_tensor)
      • B=torch.rand_like(A_tensor)
    • numpy与tensor相互转换
      • torch.as_tensor(ndarray)
      • torch.from_numpy(ndarray)
      • torch.numpy(tensor)
      • 陷阱: pytorch考虑共享内存,对tensor修改j时会触发复制机会,不会影响numpy; 对numpy修改会同时改变tensor,但numpy不使用替换内存操作时,不会改变tensor。即nparray=nparray+1,表示会额外复制一份内存给nparray
    • 随机数
      • 种子:torch.manual_seed(数值)
      • 正态分布: A=torch.normal(mean=0.0, std=torch.tensor(1.0))
      • 在[0,1]区间生成均匀分布: torch.rand(形状,如3,4) torch.randn()
    • 特殊间隔
      • A=torch.arange(start=0,end=10,step=2)
      • 固定数量的等间隔: A=torch.linspace(start=1,end=10,steps=5)
      • 以对数为间隔: A=torch.logspace(start=0.1,end=1.0,steps=5)
    • torch.Tensor和torch.tensor的区别
      • torch.Tensor()是Python类,更明确的说,是默认张量类型torch.FloatTensor()的别名,torch.Tensor([1,2]) 会调用Tensor类的构造函数__init__,生成单精度浮点类型的张量。 而且可以生成空张量,但是torch.tensor()不可以生成空张量。
      • torch.tensor()仅仅是Python的函数,根据原始数据类型生成相应的类型
  • 张量操作
    • 操作分类
      • 从接口角度
        • torch.function
        • tensor.function
      • 从存储角度
        • a.add(b)
        • a.add_(b)
    • 改变形状
      • 查看形状: A.shape A.size()
      • 元素的个数: A.numel()
      • reshape():并不改变本身形状 A=torch.arange(0,8) A=A.reshape(2,4) A=torch.reshape(input=A,shape=(2,-1))
      • A.view(2,4) :改变形状:未改变自身。 比reshape更底层,但更不智能,只能作用于整块内存中的张量,但有些张量由不同数据块组成。
      • resize_():改变自身形状 A.resize_(2,4),但是参数不接受-1,如(2,-1)
      • 维度提升:指定维度插入新的维度。 B=torch.unsqueeze(A,dim=0)
      • 维度减小:移除指定或者所有维度大小为1的维度。 B=torch.squeeze(A,dim=1)
    • 扩展张量
      • expand()方法
        • ## 使用.expand()方法拓展张量 A = torch.arange(3) B = A.expand(3,-1) ---------------- tensor([[0, 1, 2], [0, 1, 2], [0, 1, 2]])
      • expand_as()
        • ## 使用.expand_as()方法拓展张量 C = torch.arange(6).reshape(2,3) B = A.expand_as(C) ------------------ tensor([[0, 1, 2], [0, 1, 2]])
      • repeat()方法
        • 把张量A看成整体,按形状进行重复填充: ## 使用.repeat()方法拓展张量 D = B.repeat(1,2,2) print(D) print(D.shape) --------------- tensor([[[0, 1, 2, 0, 1, 2], [0, 1, 2, 0, 1, 2], [0, 1, 2, 0, 1, 2], [0, 1, 2, 0, 1, 2]]]) torch.Size([1, 4, 6])
    • 获取张量元素
      • 同numpy切片
      • 根据筛选条件:torch.where(condition, x, y) 。 共有三个输入参数,第一个是condition判断条件,第二个是符合条件时取设置值x,第三个是不满足条件的设置值y。 torch.where(b>5, b, c) # 将b中值大于5和c中值不大于5的元素取出。
    • 拼接
      • torch.cat(): C=torch.cat((A,B),dim=n):在n维度连接张量AB
      • torch.stack():将多个张量按指定维度进行拼接。 D=torch.stack((A,B),dim=n)
    • 拆分
      • torch.chunk():将张量分割特定数量的块。 torch.chunk(A,2,dim=0)
      • torch.split():分割为特定数量块时,可以指定每个块的大小。
        • ## 将张量切分为块,指定每个块的大小 D1,D2,D3 = torch.split(D,[1,2,3],dim=1) print(D1) print(D2) print(D3) ------------------- tensor([[0.], [3.]]) tensor([[1., 2.], [4., 5.]]) tensor([[ 0., 2., 4.], [ 6., 8., 10.]])
    • 张量剪裁
      • 根据范围:torch.clamp(A,2,4)
        • A = torch.arange(6.0).reshape(2,3) torch.clamp(A,2.5,4) -------------- 若定义的区间,在原数据范围内,保留其定义值,若在之外,保留原数据边界值 tensor([[2.5000, 2.5000, 2.5000], [3.0000, 4.0000, 4.0000]])
      • 根据最大值:torch.clamp_max(A,5)
        • A = torch.arange(6.0).reshape(2,3) torch.clamp_max(A,4) -------------- 保留最大值以下数值 tensor([[0., 1., 2.], [3., 4., 4.]])
      • 根据最小值:torch.clamp_min(A,3)
        • A = torch.arange(6.0).reshape(2,3) torch.clamp_min(A,3) -------------- 保留最小值以上数值 tensor([[3., 3., 3.], [3., 4., 5.]])
      • 即保留最大值以下,或最小值以上的,包含此值。
      • 常用在梯度计算过程中,根据阈值进行数据截断,避免“梯度爆炸”
  • Variable与自动微分
    • 自动微分步骤
      • 步骤
        • # 输入数据是标量情况下: import torch # 创建需要进行求导的张量 x x = torch.tensor([2.0], requires_grad=True) # 定义计算图 y = x^2 y = x ** 2 # 对计算图进行反向传播 y.backward() # backward()只能在当前变量是标量的情况下使用 # 访问张量 x 的梯度 print(x.grad)
        • # 当输入数据不是标量时: # 需要使用聚合操作,转换成标量 import torch from torch.autograd import Variable x = torch.arange(1,5,dtype=torch.float32, requires_grad=True).reshape(2,2) # 使用.reshape(2,2)后,则生成的是非叶子节点 print(x.is_leaf) # False x = Variable(x, requires_grad=True) # 将x转换成叶子节点,之后才能梯度计算 print(x.is_leaf) # True y = torch.sum(x**2 + 2*x+1) # 聚合操作,才能使张量最后变成标量,才能使用backward y.backward() x.grad
      • backward():当梯度计算的张量经过一系列计算最终生成一个标量,便可用“标量的backward()”方法进行自动求导。
    • 控制梯度方法
      • torch.no_grad()
        • 使用with torch.no_grad()控制requires_grad属性的作用域
        • 使用装饰器@torch.no_grad()控制requires_grad作用域,限制函数级别的运算梯度,使张量的requires_grad失效
      • torch.enable_grad()
        • 可恢复被no_grad设置不需要计算的梯度。
        • 使用with torch.enable_grad()方式
        • 使用 装饰器 @torch.enable_grad()装饰函数后,该函数不再受with torch.no_grad()的影响
      • torch.set_grad_enabled()
        • 统一管理梯度。 参数:True或False
    • Variable对象
      • Variable内部结构
        • 分为头信息区(Tensor)和存储区(Storage)
        • 大多数操作只修改头信息。高级索引一般不共享storage,而普通索引共享storage.
        • tensor.contiguous方法可将不连续数据变成连续。
      • grad_fn
        • 该属性用于记录在回传计算中使用的计算图。 backward后自动销毁。
        • 只能经过计算,才有grad_fn。 没有梯度的张量,即使计算,也无grad_fn。
        • 语法:x.grad_fn, 返回True False
        • 作用:当使用标量的backward()方法进行自动求导时,该方法会自动调用每个变量的grad_fn属性,并将结果放到该变量的grad属性中。
        • 梯度函数grad_fn()可以被调用
          • import torch x = torch.ones(2,2,requires_grad=True) y = x ** 3 print(x.grad_fn) # 没有经过计算的tensor无此属性 print(y.grad_fn(x)) # 计算x的梯度,每一个值都将被计算,但可能不是此点的梯度 print(y.grad_fn)
          • import torch x = torch.tensor(2.0,requires_grad=True) y = x ** 3 print(x.grad_fn) # 没有经过计算的tensor无此属性 print(y.grad_fn(x)) # 计算x的梯度,但梯度不是x的导数,而是3*x**3,输出24 print(y.grad_fn) y.backward() print(x.grad) # 计算x的梯度,是3*x**2,输出12 print(y.grad_fn)
      • is_leaf
        • 在定义Variable对象时,属性requires_grad设为True时,则该对象被称为“叶子节点”。如果不是用此法生成的,均不是叶子节点。 叶子节点的grad_fn是None,因没有计算。
        • 作用:在反向链式求导过程中,为递归循环提供信号指示。如果反向链接求导遇到叶子节点,则终止递归。
        • 语法:x.is_leaf,返回True False
        • #当requires_grad=False,计算后的张量仍然是叶子节点 bb=torch.ones(10,requires_grad=False) print(bb.is_leaf) #True cc = bb + 3 print(cc.is_leaf) #True
        • #当requires_grad=True,计算后的张量不再是叶子节点 bb=torch.ones(10,requires_grad=True) print(bb.is_leaf) #True cc = bb + 3 print(cc.is_leaf) #False
      • detach()
        • (1)将对象分离成叶子节点
          • #当张量 requires_grad=True时,无法转换为numpy
          • import torch bb=torch.ones(10,requires_grad=True) # print(bb.numpy()) # 报错 print(bb.detach().numpy()) # 正确
        • (2)指定模型中参数的梯度
          • 参考:李金洪 Bert书
  • 张量计算
    • 基本运算
      • 幂:torch.pow(),或者**运算 B=torch.pow(A,3) B=A**3
      • 指数:torch.exp()
      • 对数:torch.log()
      • 平方根:torch.sqrt()
      • 平方根倒数:torch.rsqrt()
    • 比较大小
      • gt/lt/ge/le/eq/ne:大于/小于/大于等于/小于等于/等于/不等
    • 统计相关计算
      • torch.max():
      • torch.argmax():输出最大值所在位置. 处理分类结果时常用,用于统计每个分类数据中的最大值,从而得到模型最终的预测结果。
      • torch.min():
      • torch.argmin():
      • torch.sort():排序,输出结果和值在的原始位置。 降序:torch.sort(A,descending=True)
      • torch.mean():根据指定维度求平均值。torch.mean(B,dim=1,keepdim=True)
      • torch.sum()
      • torch.std():标准差
      • torch.var():方差
      • cumsum/cumprod:累加/累乘
    • 线性代数
      • t:转置
      • dot:内积
      • svd:奇异值分解
      • mm:矩阵乘法
      • inverse:矩阵的逆
        • ## 计算矩阵的逆 C = torch.rand(3,3) D = torch.inverse(C)
      • diag:矩阵对角线元素
        • ## 获取矩阵张量的上三角部分,input,需要是一个二维的张量 C = A.reshape(3,4) print(C) print(torch.diag(C,diagonal=0)) print(torch.diag(C,diagonal=1)) ------------------------------ tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) tensor([ 0, 5, 10]) tensor([ 1, 6, 11])
        • ## 提供对角线元素生成矩阵张量 torch.diag(torch.tensor([1,2,3])) ----------------------- tensor([[1, 0, 0], [0, 2, 0], [0, 0, 3]])
      • triu/tril:矩阵上三角/下三角
        • upper triangular matrix
          • ## 获取矩阵张量的上三角部分 torch.triu(A,diagonal=0)
        • lower triangular matrix
          • ## 获取矩阵张量的下三角部分 torch.tril(A,diagonal=0)
  • CPU和GPU
    • (1)b = a.cuda() : 将CPU内存复制到GPU中
    • (2) a = torch.tensor([2],device="cuda"): 直接在GPU中定义
    • (3) a.to(device)方法。推荐此法。 a = torch.tensor([1, 2, 3]) device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") a = a.to(device)
    • (4) 使用环境变量 CUDA_VISIBLE_DEVICES 来指定设备
    • 需要注意的是,使用GPU进行Tensor运算可能会比在CPU上慢,特别是在处理小型Tensor时。因此,建议仅在处理大型Tensor时使用GPU。
  • 广播法则
    • 广播是指在进行张量运算时,自动扩展张量的形状以匹配需要进行运算的张量的形状
    • 代码示例
      • import torch a = torch.arange(0,3).reshape(3, 1) b = torch.arange(10,14).reshape(1, 4) c = a + b print(a) print(b) print(c)
      • import torch a = torch.arange(0,6).reshape(2,3) b = torch.arange(10,14).reshape(4, 1, 1) c = a + b print(a) print(b) print(c)
    • 建议使用手动广播
      • unsqueeze/view
      • expand/expand_as
  • 钩子函数hook
    • 步骤
      • 要使用钩子函数, 首先需要定义一个钩子函数, 然后将其注册到需要监视的层中, 最后移除钩子。
    • 模型正向数据流处理结构中注册钩子函数hook。 每次 forward 时被调用。
      • import torch class MyModel(torch.nn.Module): def __init__(self): super(MyModel, self).__init__() self.conv1 = torch.nn.Conv2d(3, 16, 3) self.conv2 = torch.nn.Conv2d(16, 32, 3) self.conv3 = torch.nn.Conv2d(32, 64, 3) self.fc = torch.nn.Linear(64*2*2, 10) def forward(self, x): out = torch.relu(self.conv1(x)) out = torch.relu(self.conv2(out)) out = torch.relu(self.conv3(out)) out = out.view(-1, 64*2*2) out = self.fc(out) return out # 定义钩子函数,必须三个参数 def hook_fn(module, input, output): print(module) print('input:', input) print('output:', output) print('------------------------') model = MyModel() # 注册:在model.conv2层中使用register_forward_hook注册正向数据流处理hook hook = model.conv2.register_forward_hook(hook_fn) input = torch.randn(1, 3, 32, 32) output = model(input) # 移除钩子 hook.remove()
    • 模型反向结构中注册钩子函数hook。 每次 backward 时被调用。
      • import torch class MyModel(torch.nn.Module): def __init__(self): super(MyModel, self).__init__() self.conv1 = torch.nn.Conv2d(3, 16, 3) self.conv2 = torch.nn.Conv2d(16, 32, 3) self.conv3 = torch.nn.Conv2d(32, 64, 3) self.fc = torch.nn.Linear(64*2*2, 10) def forward(self, x): out = torch.relu(self.conv1(x)) out = torch.relu(self.conv2(out)) out = torch.relu(self.conv3(out)) out = out.view(-1, 64*2*2) out = self.fc(out) return out def hook_fn(module, grad_input, grad_output): print(module) print('grad_input:', grad_input) print('grad_output:', grad_output) print('------------------------') model = MyModel() hook = model.conv2.register_backward_hook(hook_fn) input = torch.randn(1, 3, 32, 32) output = model(input) output.mean().backward() hook.remove()
  • 关于维度
    • 归并操作,会沿着某个维度进行,形状可能发生变化。 指定dim,相当于对dim所指的维度进行操作。 或不指定,即对所有数进行操作。如a.sum() ------------------------- 假设形状是(m, n, k) 指定dim=0,输出形状是(1, n, k)或(n,k); 指定dim=1,输出形状是(m, 1, k)或(m,k); 指定dim=2,输出形状是(m, n, 1)或(m,n)。 ------------------------------------ 形状中是否有1,取决于参数keepdim,默认为False,不保留1,True,则保留1。
  • 乘法运算
    • 点积/内积
      • torch.mm:矩阵乘法。只适用于二维矩阵,要求第一个矩阵(nxm),第二个矩阵(mxp)。
        • a = torch.tensor([[5.,2.]]) b = torch.tensor([[2.,3.]]).view(2,1) print(torch.mm(a, b)) # 只适用于二维 print(torch.matmul(a, b)) # 适用于二维和多维 print(a @ b) # 与matmul等价
      • torch.matmul:张量乘法。可以适用于高维。 torch.matmul(a,b) 与 a @ b 等价。
      • torch.bmm:批量矩阵乘法。 要求第一个矩阵(bxnxm),第二个矩阵(bxmxp)。
        • input = torch.randn(10, 3, 4) mat2 = torch.randn(10, 4, 5) res = torch.bmm(input, mat2) res.size() torch.Size([10, 3, 5])
      • torch.dot: 对应位置相乘后再相加求和。 不同于 NumPy’s dot,仅支持一维数据。
        • a = torch.tensor([5.,2.]) b = torch.tensor([2.,3.]) print(a.dot(b)) 输出:tensor(16.)
    • 阿达玛积
      • 对应元素相乘,不再相加,要求矩阵行列相同,返回与原元素相同形状。 * 和 torch.mul 等价。
        • a = torch.tensor([5,2]) b = torch.tensor([2,3]) print(a*b) print(torch.mul(a,b)) 输出: tensor([10, 6]) tensor([10, 6])
    • 计算乘积
      • 乘积:prod
        • ## 按照行计算乘积 print(torch.prod(B,dim = 1,keepdim = True)) ## 按照列计算乘积 print(torch.prod(B,dim = 0,keepdim = True))
      • 累乘积:cumprod
        • ## 按照行计算累乘积 print(torch.cumprod(B,dim = 1)) ## 按照列计算累乘积 print(torch.cumprod(B,dim = 0))
    • 其它乘法
      • 除了上述常见的张量乘法运算,PyTorch还提供了很多其他的张量运算,如叉积运算(cross)、内积运算(dot)、外积运算(outer)、广播运算(broadcasting)等。
    • mul、mm、dot、mv
      • https://blog.csdn.net/weixin_42010722/article/details/122333051
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值