pytorch 方法笔记

torch

transpose

torch.transpose(input, dim0, dim1) → Tensor

input上的第dim0维和第dim1维进行转置

假设

>>>input.shape=(128,32,12,64)

torch.transpose(input,1,2).shape=(128,12,32,64)

masked_select

torch.masked_select(input, mask, *, out=None) → Tensor

根据mask上的bool取值,对input上的值进行取舍,若mask位置上取值为1那么input对应位置上的值保留下来,最终输出一个一维数据

参数

  • input:input tensor
  • mask:这个tensor值应当为bool类型(就是0、1或者True、False这种二取值类型)

>>>a = torch.Tensor([[4,5,7], [3,9,8],[2,3,4]])
>>>b = torch.Tensor([[1,1,0], [0,0,1],[1,0,1]]).type(torch.ByteTensor)
>>>c = torch.masked_select(a,b)
>>>print(c) 
tensor([4.,5.8.2.,4.])

max

torch.Tensor

scatter

scatter_(dim, index, src, reduce=None) → Tensor

官网地址
pytorch中torch.Tensor.scatter用法

src中所有相应的值根据index中的坐标值来写入到目标值中。

参数

  • dim:表示在某个维度上进行操作,可以是0,1,2.....
  • index:索引数组,tensor,数据类型为整数
  • src:根据里面的值进行填充,src可以为一个数值或者tensor
  • reduce

For a 3-D tensor, self is updated as:

self[index[i][j][k]][j][k] = src[i][j][k]       # if dim == 0
self[i][index[i][j][k]][k] = src[i][j][k]       # if dim == 1
self[i][j][index[i][j][k]] = src[i][j][k]        # if dim == 2

示例

import torch 
>>>input = torch.randn(2, 4)
>>>print(input)
tensor([[-0.6482,  1.1430,  0.4962,  0.9425],
        [ 0.0092, -0.2958,  0.2240, -0.6358]])
>>>output = torch.zeros(2, 5)
>>>index = torch.tensor([[3, 1, 2, 0], [1, 2, 0, 3]])
>>>output = output.scatter(1, index, input)
>>>print(output)
tensor([[ 0.9425,  1.1430,  0.4962, -0.6482,  0.0000],
        [ 0.2240,  0.0092, -0.2958, -0.6358,  0.0000]])

示例中是对dim=1进行修改,故其修改是

  1. output[0][index[0][0]] = src[0][0] ,即output[0][3] = -0.6482
  2. output[0][index[0][1]] = src[0][1] ,即output[0][1] = 1.1430
  3. output[0][index[0][2]] = src[0][2] ,即output[0][2] = 0.4962
  4. output[0][index[0][3]] = src[0][3] ,即output[0][0] = 0.9425
  5. output[1][index[1][0]] = src[1][0] ,即output[1][1] = 0.0092
  6. ⋯ \cdots
  7. 最终得到上面示例的值

unsqueeze

官网地址

torch.unsqueeze(input, dim) → Tensor

相当于在指定的dim上增加一维

>>>a = torch.Tensor([1,2,3,4,5,6])
>>>b = a.unsqueeze(0)
>>>b  #b.shape=(1,6)
 tensor([[1., 2., 3., 4., 5., 6.]])
 >>>b = a.unsqueeze(1)
 >>>b  #b.shape(6,1)
 tensor([[1.],
        [2.],
        [3.],
        [4.],
        [5.],
        [6.]])

squeeze

这个与unsqueeze相反,去掉相应维数

repeat

对某个tensor在相应的维度上进行重复

>>> import torch
>>> 
>>> a = torch.randn(33, 55)
>>> a.size()
torch.Size([33, 55])
>>> 这个(1,1)相当于在第0维和第1维分别重复1次,即不变
>>> a.repeat(1, 1).size()
torch.Size([33, 55])
>>> 这个(2,1)相当于在第0维和第1维分别重复2次和1次,即行的维度变为2>>> a.repeat(2,1).size()
torch.Size([66, 55])
>>> 
>>> a.repeat(1,2).size()
torch.Size([33, 110])
>>> 若是repeat参数的个数超过tensor的维数,则会添加一维
>>> a.repeat(1,1,2).size()
torch.Size([1, 33, 110])
参数的长度必须长于tensor的维度个数,否则报错
>>>a.repeat(1).size()
>RuntimeError: Number of dimensions of repeat dims can not be smaller than number of dimensions of tensor

masked_fill

masked_fill(mask, value)

参数

  • mask:必须是一个二值型, 0 0 0 1 1 1TrueFalse等,mask.size(0)必须与tensor的size(0)相等
  • value: 根据mask中的True对应的位置填充为这个值
>>> a=torch.tensor([1,0,2,3])
>>>  a.masked_fill(mask = torch.ByteTensor([1,1,0,0]), value=torch.tensor(-1e9))
>>> tensor([-1.0000e+09, -1.0000e+09,  2.0000e+00,  3.0000e+00])

contiguous

contiguous(memory_format=torch.contiguous_format) → Tensor

view只能用在contiguous的variable上。
如果在view之前用了transpose,permute等,需要用contiguous来返回一个contiguous copy

有些tensor并不是占用一整块内存,而是由不同的数据块组成,而tensor的view()操作依赖于内存是整块的,这需要执行contiguous()这个函数,把tensor变成在内存中连续分布的形式。

判断是否contiguous用torch.Tensor.is_contiguous()

expand

torch.nn

torch.nn.utils.rnn.pad_packed_sequence

rnn.pad_packed_sequence(sequence, batch_first=False, padding_value=0.0, total_length=None)

官方文档地址

Pytorch中的RNN之pack_padded_sequence()和pad_packed_sequence()

为什么有pad和pack操作?

举例,假如这个batch有5个sample

在这里插入图片描述
如果不用pack和pad操作会有一个问题,什么问题呢?
上图中,句子"Yes"只有一个单词,但是padding了多余的符号来填充,这回导致LSTM对它的表示通过了很多无用的字符,这样得到的句子表示会有误差,更直观的如下图:
在这里插入图片描述
正确的做法应该是什么样呢?
在上面这个例子,我们想要得到的表示仅仅是LSTM过完单词"Yes"之后的表示,通过了多个无用的得到的表示:如下图

在这里插入图片描述

torch.nn.utils.rnn.pack_padded_sequence()

这里的pack,理解成压紧比较好。将一个填充过的变长序列压紧。(填充时候,会有冗余,所以压紧)
在这里插入图片描述
pack之后,原来填充的占位符被删掉。

输入的形状可以是 T × B × ∗ T \times B \times * T×B×.

  • T是最长序列长度
  • B是batch size
  • * 表示任意维度
  • batch_first=True,那么相应的input size就是 B × T × ∗ B \times T \times * B×T×.

参数说明

  • input(Variable):变长序列 被填充后的 batch
  • lengths(list[int]) Variable中每个序列的长度,保证序列的长度是从大到小排列
  • batch_first(bool,optional):若是 T r u e True True,input的形状应该是 B × T × s i z e B \times T \times size B×T×size

返回值:
一个PackedSequence对象

示例

import torch
import torch.nn as nn
from torch.nn.utils.rnn import pack_padded_sequence,pad_packed_sequence

tensor_in = torch.FloatTensor([[2,3,4],[1,0,0]]).resize_(2,3,1)
#表示
>>>seq_lengths=[3,1]
>>>pack = pack_padded_sequence(tensor_in,seq_lengths,batch_first=True)
>>>pack
PackedSequence(data=tensor([[2.],
        [1.],
        [3.],
        [4.]]), batch_sizes=tensor([2, 1, 1]), sorted_indices=None, unsorted_indices=None)

torch.nn.utils.rnn.pad_packed_sequence()
填充packed_sequence
上面提到的函数的功能是将一个填充后的变长序列压紧。 这个操作和pack_padded_sequence()是相反的。把压紧的序列再填充回来。填充时会初始化为0。

返回的Varaible的值的size是 T × B × ∗ , T×B×*, T×B×, T T T 是最长序列的长度,B 是 batch_size,如果 batch_first= T r u e True True,那么返回值是 B × T × ∗ B×T×* B×T×

Batch中的元素将会以它们长度的逆序排列。

参数说明:

  • sequence (PackedSequence) – 将要被填充的 batch
  • batch_first (bool, optional) – 如果为 T r u e True True,返回的数据的格式为 B × T × ∗ B×T×* B×T×

nn.LSTM

CLASStorch.nn.LSTM(*args, **kwargs)

参数

  • input_size – 输入特征维数:(特征向量的长度,如2048

  • hidden_size – 隐层状态的维数:(每个LSTM单元或者时间步的输出的ht的维度,单元内部有权重与偏差计算)

  • num_layers – RNN层的个数:(在竖直方向堆叠的多个相同个数单元的层数),默认为1

  • bias – 隐层状态是否带bias,默认为true

  • batch_first – 是否输入输出的第一维为batchsize

  • dropout – 是否在除最后一个RNN层外的RNN层后面加dropout层,默认False

  • bidirectional – 是否是双向RNN,默认为false
    输入
    Inputs: input, (h_0, c_0)

  • input:(seq_len, batch, input_size)时间步数或序列长度,batch数,输入特征维度。如果设置了batch_first,则batch为第一维,即( batch,seq_len, input_size)

  • (h_0,c_0):设置下图中输入到第一层的隐藏状态的参数

输出
Outputs: output, (h_n, c_n)

  • output:(seq_len, batch, hidden_size * num_directions)包含每一个时刻的输出特征,如果设置了batch_first,则batch为第一维,( batch,seq_len, input_size)

  • (h_n, c_n) :隐层状态各个层的最后一个时步的隐含状态,所以与序列长度seq_len是没有关系的

全面理解LSTM网络及输入,输出,hidden_size等参数

在这里插入图片描述

nn.ZeroPad2d

官方地址
torch.nn.ZeroPad2d(padding: Union[T, Tuple[T, T, T, T]])

用于卷积网络中的填充,使用0进行填充

参数

  • padding:若是int类型,则在上下左右全部填充padding个,若是一个四元组,则分别表示(left,right,top,bottom)
>>> m = nn.ZeroPad2d(2)
>>> input = torch.randn(1, 1, 3, 3)
>>> input
tensor([[[[-0.1678, -0.4418,  1.9466],
          [ 0.9604, -0.4219, -0.5241],
          [-0.9162, -0.5436, -0.6446]]]])
>>> m(input)
tensor([[[[ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.0000,  0.0000, -0.1678, -0.4418,  1.9466,  0.0000,  0.0000],
          [ 0.0000,  0.0000,  0.9604, -0.4219, -0.5241,  0.0000,  0.0000],
          [ 0.0000,  0.0000, -0.9162, -0.5436, -0.6446,  0.0000,  0.0000],
          [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000,  0.0000]]]])
>>> # using different paddings for different sides
>>> m = nn.ZeroPad2d((1, 1, 2, 0))
>>> m(input)
tensor([[[[ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.0000,  0.0000,  0.0000,  0.0000,  0.0000],
          [ 0.0000, -0.1678, -0.4418,  1.9466,  0.0000],
          [ 0.0000,  0.9604, -0.4219, -0.5241,  0.0000],
          [ 0.0000, -0.9162, -0.5436, -0.6446,  0.0000]]]])

nn.NLLLoss

参考文章

Pytorch详解NLLLoss和CrossEntropyLoss

输入 m m m张图片,每张图片有 n n n个类别。
例如,三张图片三个分类,如下

In [1]: input = torch.randn((3,3))
Out[1]:
tensor([[-0.4020, -0.5205,  0.7815],
        [ 0.0290, -1.6085,  0.0041],
        [-1.3974, -0.5234, -1.1656]])    

假设图片的三个类别分别是🐱、🐕、🐖(猫、狗、猪)

上面的输出就是机器认为每张图应该被分为的类别是什么,对上面使用Softmax查看概率分布


In [2]: sm = nn.Softmax(dim=1)

In [3]: sm(input)
Out[3]:
tensor([[0.1940, 0.1723, 0.6336],
        [0.4609, 0.0896, 0.4495],
        [0.2147, 0.5146, 0.2707]])

softmax取对数,这是为了防止概率值太小造成溢出

In [4]: torch.log(sm(input))
Out[4]:
tensor([[-1.6398, -1.7583, -0.4563],
        [-0.7747, -2.4122, -0.7996],
        [-1.5384, -0.6644, -1.3066]])

概率值越小,取对数后越小,概率值越大,取对数之后越接近0

NLLLoss的结果就是把上面的输出与Label对应的那个值拿出来,再去掉负号,再求均值。
假设我们现在Target[0,2,1](第一张图片是猫,第二张是猪,第三张是狗)。
第一行取第 0 0 0个元素,第二行取第 2 2 2个,第三行取第 1 1 1个,去掉负号,结果是: [ 1.6398 , 0.7996 , 0.6644 ] [1.6398,0.7996,0.6644] [1.6398,0.7996,0.6644]。再求个均值,结果是: 1.0346 1.0346 1.0346

In [5]: loss = nn.NLLLoss()

In [6]: target = torch.tensor([0,2,1])

In [7]: loss(input,target)
Out[7]: tensor(0.3071)

In [8]: loss(torch.log(sm(input)),target)
Out[8]: tensor(1.0346)

nn.LogSoftmax

上一节中的torch.log(sm(input)) 就等价于这个函数

nn.CrossEntropyLoss

它就相当于nn.LogSoftmax+nn.NLLLoss

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值