tags: [笔记, Pytorch]
categories: [笔记, Pytorch]

Pytorch用法教程

相关配置

  1. #导入相关包
  2. import torch
  3. import numpy as np
  4. #设置单元格全部行的输出结果
  5. from IPython.core.interactiveshell import InteractiveShell
  6. InteractiveShell.ast_node_interactivity = "all"

torch.cuda.Event()

默认情况下,GPU 操作是异步的。当您调用使用 GPU 的函数时,操作将排入特定设备,但不一定要在以后执行。这允许我们并行执行更多计算,包括在 CPU 或其他 GPU 上的操作。

通常,异步计算的效果对于调用者是不可见的,因为 (1) 每个设备按照它们排队的顺序执行操作,以及 (2) PyTorch 在 CPU 和 GPU 之间或两个 GPU 之间复制数据时自动执行必要的同步。因此,计算将如同每个操作同步执行一样进行。

您可以通过设置环境变量强制进行同步计算 CUDA_LAUNCH_BLOCKING=1。这在 GPU 上发生错误时非常方便。(使用异步执行时,直到实际执行操作后才会报告此类错误,因此堆栈跟踪不会显示请求的位置。)

异步计算的结果是没有同步的时间测量是不精确的。要获得精确的测量结果,应该在测量之前调用torch.cuda.synchronize(),或者使用torch.cuda.Event记录时间如下:

  1. start_event = torch.cuda.Event(enable_timing=True)
  2. end_event = torch.cuda.Event(enable_timing=True)
  3. start_event.record()
  4. # 在这里执行一些操作
  5. end_event.record()
  6. torch.cuda.synchronize() # Wait for the events to be recorded!
  7. elapsed_time_ms = start_event.elapsed_time(end_event)
  1. ---------------------------------------------------------------------------
  2. NameError Traceback (most recent call last)
  3. <ipython-input-1-ec7600a08e47> in <module>
  4. ----> 1 start_event = torch.cuda.Event(enable_timing=True)
  5. 2 end_event = torch.cuda.Event(enable_timing=True)
  6. 3 start_event.record()
  7. 4
  8. 5 # 在这里执行一些操作
  9. NameError: name 'torch' is not defined

torch.clamp()操作用法

torch.clamp(input, min, max, out=None) → Tensor

使得输入的所有元素夹到[min, max]范围内。让min_value和max_value分别为min和max,这会返回:y_i =min(max(x_i, min_value), max_value)

  1. a = torch.randn(4)
  2. a
  3. torch.clamp(a, min=-0.5, max=0.5)
  1. tensor([-0.5281, -1.0857, 0.4811, -0.2452])
  2. tensor([-0.5000, -0.5000, 0.4811, -0.2452])

tirch.Tensor.cuda()用法

CPU tensor转GPU tensor

torch.Tensor的属性值is_cuda

is_cuda:Is True if the Tensor is stored on the GPU, False otherwise.

torch中的掩码

masked_fill()

maskedfill(mask, value)

Fills elements of self tensor with value where mask is True. The shape of mask must be broadcastable with the shape of the underlying tensor.在mask值为1的位置处用value填充。

参数: - mask (ByteTensor)-二进制掩码 - value (Tensor)-用来填充的值

  1. import torch.nn.functional as F
  2. import numpy as np
  3. a = torch.Tensor([1,2,3,4])
  4. a = a.masked_fill(mask = torch.LongTensor([1,1,0,0]).type(torch.bool), value=-np.inf)
  5. print(a)
  6. b = F.softmax(a,dim=0)
  7. print(b)
  1. tensor([-inf, -inf, 3., 4.])
  2. tensor([0.0000, 0.0000, 0.2689, 0.7311])

torch.from_numpy()用法

Creates a Tensor from a numpy.ndarray.

用torch.from_numpy这个方法将numpy类转换成tensor类

Pytorch Tensor的索引与切片

一般索引

根据Tensor的shape,从前往后索引,依次在每个维度上做索引。

  1. import torch
  2. a = torch.rand(4, 3, 28, 28)
  3. print(a[0].shape) #取到第一个维度
  4. print(a[0, 0].shape) # 取到二个维度
  5. print(a[1, 2, 2, 4]) # 具体到某个元素
  6. '''
  7. 创建了一个shape=[4, 3, 28, 28]的Tensor,我们可以理解为4张图片,每张图片有3个通道,每个通道是28x28的图像数据。
  8. a代表这个Tensor,a后面跟着的列表[]表示对Tensor进行索引,
  9. '''
  1. torch.Size([3, 28, 28])
  2. torch.Size([28, 28])
  3. tensor(0.3142)

普通的切片索引

注意负值的索引即表示倒数第几个元素,-2就是倒数第二个元素。

  1. import torch
  2. # 譬如:4张图片,每张三个通道,每个通道28行28列的像素
  3. a = torch.rand(4, 3, 28, 28)
  4. # 在第一个维度上取后0和1,等同于取第一、第二张图片
  5. print(a[:2].shape)
  6. # 在第一个维度上取0和1,在第二个维度上取0,
  7. # 等同于取第一、第二张图片中的第一个通道
  8. print(a[:2, :1, :, :].shape)
  9. # 在第一个维度上取0和1,在第二个维度上取1,2,
  10. # 等同于取第一、第二张图片中的第二个通道与第三个通道
  11. print(a[:2, 1:, :, :].shape)
  12. # 在第一个维度上取0和1,在第二个维度上取1,2,
  13. # 等同于取第一、第二张图片中的第二个通道与第三个通道
  14. print(a[:2, -2:, :, :].shape)
  15. # 使用step隔行采样
  16. # 在第一、第二维度取所有元素,在第三、第四维度隔行采样
  17. # 等同于所有图片所有通道的行列每个一行或者一列采样
  18. # 注意:下面的代码不包括28
  19. print(a[:, :, 0:28:2, 0:28:2].shape)
  20. print(a[:, :, ::2, ::2].shape) # 等同于上面语句
  1. torch.Size([2, 3, 28, 28])
  2. torch.Size([2, 1, 28, 28])
  3. torch.Size([2, 2, 28, 28])
  4. torch.Size([2, 2, 28, 28])
  5. torch.Size([4, 3, 14, 14])
  6. torch.Size([4, 3, 14, 14])

index_select()选择特定索引

选择特定下标有时候很有用,比如上面的a这个Tensor可以看作4张RGB(3通道)的MNIST图像,长宽都是28px。那么在第一维度上可以选择特定的图片,在第二维度上选择特定的通道。

  1. # 选择第一张和第三张图
  2. print(a.index_select(0, torch.tensor([0, 2])).shape)
  3. # 选择R通道和B通道
  4. print(a.index_select(1, torch.tensor([0, 2])).shape)
  5. # 选择图像的0~8行
  6. print(a.index_select(2, torch.arange(8)).shape)
  1. torch.Size([2, 3, 28, 28])
  2. torch.Size([4, 2, 28, 28])
  3. torch.Size([4, 3, 8, 28])

注意:index_select()的第二个索引参数必须是Tensor类型

任意多的维度

在索引中使用…可以表示任意多的维度。

  1. import torch
  2. a = torch.rand(4, 3, 28, 28)
  3. # 等与a
  4. print(a[...].shape)
  5. # 第一张图片的所有维度
  6. print(a[0, ...].shape)
  7. # 所有图片第二通道的所有维度
  8. print(a[:, 1, ...].shape)
  9. # 所有图像所有通道所有行的第一、第二列
  10. print(a[..., :2].shape)
  1. torch.Size([4, 3, 28, 28])
  2. torch.Size([3, 28, 28])
  3. torch.Size([4, 28, 28])
  4. torch.Size([4, 3, 28, 2])

mask索引

可以获取满足一些条件的值的位置索引,然后用这个索引去取出这些位置的元素。

  1. import torch
  2. a = torch.randn(3, 4)
  3. print(a)
  4. # 生成a这个Tensor中大于0.5的元素的掩码
  5. mask = a.ge(0.5)
  6. print(mask)
  7. # 1.取出a这个Tensor中大于0.5的元素
  8. val = torch.masked_select(a, mask)
  9. print(val)
  10. print(val.shape)
  11. # 2.or直接用mask索引
  12. print(a[mask])
  1. tensor([[-0.3195, -0.3623, -0.6834, 0.5384],
  2. [ 0.8215, 0.4409, 1.2699, 1.6882],
  3. [ 0.7391, 2.2220, -0.7828, 0.8776]])
  4. tensor([[False, False, False, True],
  5. [ True, False, True, True],
  6. [ True, True, False, True]])
  7. tensor([0.5384, 0.8215, 1.2699, 1.6882, 0.7391, 2.2220, 0.8776])
  8. torch.Size([7])
  9. tensor([0.5384, 0.8215, 1.2699, 1.6882, 0.7391, 2.2220, 0.8776])

注意:最后取出的 大于0.5的Tensor的shape已经被摊平(变为一维)。

take索引

take索引是基于目标Tensor的flatten形式下的,即摊平后的Tensor的索引。

  1. import torch
  2. a = torch.tensor([[3, 7, 2], [2, 8, 3]])
  3. print(a)
  4. print(torch.take(a, torch.tensor([0, 1, 5])))
  1. tensor([[3, 7, 2],
  2. [2, 8, 3]])
  3. tensor([3, 7, 3])

pytotch中类似于numpy的花式索引,即以任意维tensor作为索引

需整理,参考https://blog.csdn.net/xpy870663266/article/details/101597144

一维Tensor作为索引

在Numpy中,我们可以传入数组作为索引,称为花式索引。这里只演示使用两个一维List的例子。

  1. a=np.arange(18).reshape(6,3)
  2. a
  3. a[[1,2,3],[0,1,2]] # 相当于选择了下标分别为[1,0], [2,1], [3,2]的元素
  1. array([[ 0, 1, 2],
  2. [ 3, 4, 5],
  3. [ 6, 7, 8],
  4. [ 9, 10, 11],
  5. [12, 13, 14],
  6. [15, 16, 17]])
  7. array([ 3, 7, 11])

而在PyTorch中,如果使用两个整数List/一维Tensor作为索引,所起的作用是相同的。

  1. w=torch.arange(18).view(6,3)
  2. w
  3. w[[1,2,3],[0,1,2]]
  4. w[torch.tensor([1,2,3]),torch.tensor([0,1,2])]
  1. tensor([[ 0, 1, 2],
  2. [ 3, 4, 5],
  3. [ 6, 7, 8],
  4. [ 9, 10, 11],
  5. [12, 13, 14],
  6. [15, 16, 17]])
  7. tensor([ 3, 7, 11])
  8. tensor([ 3, 7, 11])

二维Tensor作为索引

下面的例子使用了二维Tensor作为索引,注意把[[1,2,3],[0,1,2]]和上一小节的两个一维Tensor[1,2,3],[0,1,2]区分开。通过下面的例子可以发现,二维Tensor作为索引时,每个索引中的元素都作为w的第一维度的下标(即行号)用于选择w中第一维的元素。例如二维索引[[1,2,3],[0,1,2]]中的3选出了w的第四行[ 9, 10, 11]。 下面例子中,索引形状为[2,3],将索引中的每个元素用被索引的Tensor中对应行号的行替换之后,由于每一行有三列,故得到了[2,3,3]的结果。

  1. w
  2. w[torch.LongTensor([[1,2,3],[0,1,2]])]
  1. tensor([[ 0, 1, 2],
  2. [ 3, 4, 5],
  3. [ 6, 7, 8],
  4. [ 9, 10, 11],
  5. [12, 13, 14],
  6. [15, 16, 17]])
  7. tensor([[[ 3, 4, 5],
  8. [ 6, 7, 8],
  9. [ 9, 10, 11]],
  10. [[ 0, 1, 2],
  11. [ 3, 4, 5],
  12. [ 6, 7, 8]]])

使用Tensor作为List的索引

当Tensor仅含有一个整数时,可以作为List的索引,相当于取出该整数作为索引。若含有多个整数,则报错。

  1. import torch
  2. a=[x for x in range(10)]
  3. a
  4. a[torch.tensor([[1]])] # 相当于a[1]
  5. a[torch.tensor([[[5]]])] # 相当于a[5]
  6. a[torch.tensor([[1,2]])] # 多于1个整数,报错
  1. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  2. 1
  3. 5
  4. ---------------------------------------------------------------------------
  5. TypeError Traceback (most recent call last)
  6. <ipython-input-15-ac7aa2680cfc> in <module>
  7. 7 a[torch.tensor([[[5]]])] # 相当于a[5]
  8. 8
  9. ----> 9 a[torch.tensor([[1,2]])] # 多于1个整数,报错
  10. TypeError: only integer tensors of a single element can be converted to an index

torch.cat()用法

在pytorch中,常见的拼接函数主要是两个,分别是:stack()、cat()。

一般torch.cat()是为了把函数torch.stack()得到的tensor进行拼接而存在的。参考链接torch.stack(), 但是本文主要说cat()。

torch.cat() 和python中的内置函数cat(), 在使用和目的上,是没有区别的。

torch.cat(): 在给定维度上对输入的张量序列seq 进行拼接操作。

语法:outputs = torch.cat(inputs, dim=0) → Tensor

参数
inputs : 待连接的张量序列,可以是任意相同Tensor类型的python 序列
dim : 选择的扩维, 必须在0到len(inputs[0])之间,沿着此维连接张量序列。

注意
输入数据必须是序列,序列中数据是任意相同的shape的同类型tensor。
维度不可以超过输入数据的任一个张量的维度

  1. # 准备数据,每个的shape都是[2,3]
  2. # x1
  3. x1 = torch.tensor([[11,21,31],[21,31,41]],dtype=torch.int)
  4. x1.shape # torch.Size([2, 3])
  5. # x2
  6. x2 = torch.tensor([[12,22,32],[22,32,42]],dtype=torch.int)
  7. x2.shape # torch.Size([2, 3])
  8. # 合成inputs
  9. 'inputs为2个形状为[2 , 3]的矩阵 '
  10. inputs = [x1, x2]
  11. print(inputs)
  12. # 查看结果, 测试不同的dim拼接结果
  13. torch.cat(inputs, dim=0).shape
  14. torch.cat(inputs, dim=1).shape
  15. torch.cat(inputs, dim=2).shape
  1. torch.Size([2, 3])
  2. torch.Size([2, 3])
  3. 'inputs为2个形状为[2 , 3]的矩阵 '
  4. [tensor([[11, 21, 31],
  5. [21, 31, 41]], dtype=torch.int32), tensor([[12, 22, 32],
  6. [22, 32, 42]], dtype=torch.int32)]
  7. torch.Size([4, 3])
  8. torch.Size([2, 6])
  9. ---------------------------------------------------------------------------
  10. IndexError Traceback (most recent call last)
  11. <ipython-input-17-166e5a9372e2> in <module>
  12. 16 torch.cat(inputs, dim=1).shape
  13. 17
  14. ---> 18 torch.cat(inputs, dim=2).shape
  15. IndexError: Dimension out of range (expected to be in range of [-2, 1], but got 2)

nn.Embedding()用法

个人理解:这是一个矩阵类,里面初始化了一个随机矩阵,矩阵行数是字典的大小,列宽是用来表示字典中每个元素的特征向量,向量的维度根据你想要表示的元素的复杂度而定。类实例化之后可以根据字典中元素的下标来查找元素对应的向量。

参数
num_embeddings (python:int) – 词典的大小尺寸,比如总共出现5000个词,那就输入5000。此时index为(0-4999)
embedding_dim (python:int) – 嵌入向量的维度,即用多少维来表示一个元素。
padding_idx (python:int, optional) – 填充id,如果给定,则填充时遇到padding_idx时,用(初始化为零)的嵌入向量来填充。
max_norm (python:float, optional) – 最大范数,如果嵌入向量的范数超过了这个界限,就要进行再归一化。
norm_type (python:float, optional) – 指定利用什么范数计算,并用于对比max_norm,默认为2范数。
scale_grad_by_freq (boolean, optional) – 根据单词在mini-batch中出现的频率,对梯度进行放缩。默认为False.
sparse (bool, optional) – 若为True,则与权重矩阵相关的梯度转变为稀疏张量。

输入:(*),嵌入矩阵,IntTensor or LongTensor

输出:(,H),其中是输入形状,H = embeddding_dim

  1. # an Embedding module containing 10 tensors of size 3
  2. embedding = torch.nn.Embedding(10, 3)
  3. # a batch of 2 samples of 4 indices each
  4. input = torch.LongTensor([[1,2,4,5],[4,3,2,9]])
  5. embedding(input)
  6. # example with padding_idx
  7. embedding = torch.nn.Embedding(10, 3, padding_idx=5)
  8. input = torch.LongTensor([[0,2,0,5]])
  9. embedding(input)
  1. tensor([[[ 0.8953, -0.4839, -0.6158],
  2. [ 0.0080, 1.8228, 1.5201],
  3. [ 1.9881, 1.6257, 0.3809],
  4. [ 0.9000, -0.0256, -0.6423]],
  5. [[ 1.9881, 1.6257, 0.3809],
  6. [-2.5488, -0.0816, -1.1412],
  7. [ 0.0080, 1.8228, 1.5201],
  8. [ 1.5346, -0.1341, 0.7297]]], grad_fn=<EmbeddingBackward>)
  9. tensor([[[ 0.9047, -1.0269, -1.8386],
  10. [ 1.8361, -0.9710, 1.1253],
  11. [ 0.9047, -1.0269, -1.8386],
  12. [ 0.0000, 0.0000, 0.0000]]], grad_fn=<EmbeddingBackward>)

nn.Linear()用法

语法:CLASS torch.nn.Linear(in_features, out_features, bias=True)

参数

in_features -每个输入样本的大小

out_features -每个输出样本的大小

bias-如果设置为False,层将不会学习附加偏差。默认值:真正的

Shape:
Input: (N, , H_in) where means any number of additional dimensions and H_in = in_features

Output: (N, *, H_out) where all but the last dimension are the same shape as the input and H_out = out_features .

  1. m = torch.nn.Linear(20, 30)
  2. input = torch.randn(128, 20)
  3. output = m(input)
  4. print(output.size())
  1. torch.Size([128, 30])

nn.Parameter()用法

首先可以把这个函数理解为类型转换函数,将一个不可训练的类型Tensor转换成可以训练的类型parameter并将这个parameter绑定到这个module里面(net.parameter()中就有这个绑定的parameter,所以在参数优化的时候可以进行优化的),所以经过类型转换这个Tensor就成为了模型中根据训练可以改动的参数了。使用这个函数的目的也是想让某些变量在学习的过程中不断的修改其值以达到最优化。

torch.repeat(*sizes) -> Tensor

沿着指定的维度重复这个张量。

参数:sizes (torch.Size or int…),沿每个维度重复这个张量的次数

  1. x = torch.tensor([1, 2, 3])
  2. x.repeat(4, 2)
  3. x.repeat(4, 2, 1).size()
  1. tensor([[1, 2, 3, 1, 2, 3],
  2. [1, 2, 3, 1, 2, 3],
  3. [1, 2, 3, 1, 2, 3],
  4. [1, 2, 3, 1, 2, 3]])
  5. torch.Size([4, 2, 3])

Tensors操作

torch.nn.utils.rnn.pad_sequence()用法

torch.nn.utils.rnn.pad_sequence(sequences, batch_first=False, padding_value=0.0)

使用padding_value填充可变长度Tensor的列表

padsequence沿新维度堆叠张量列表,并将它们填充为相等的长度。 例如,如果输入是大小为L x 的序列列表,并且batchfirst为False,否则为T x B x

B是批次大小。它等于序列中元素的数量。T是最长序列的长度。L是序列的长度。*是任意数量的尾部维度,包括None。

  1. from torch.nn.utils.rnn import pad_sequence
  2. a = torch.ones(25, 300)
  3. b = torch.ones(22, 300)
  4. c = torch.ones(15, 300)
  5. pad_sequence([a, b, c],batch_first=True).size()
  1. torch.Size([3, 25, 300])

自动微分

  1. x = torch.ones(2, 2, requires_grad=True)
  2. print(x)
  1. tensor([[1., 1.],
  2. [1., 1.]], requires_grad=True)
  1. y = x + 2
  2. print(y)
  1. tensor([[3., 3.],
  2. [3., 3.]], grad_fn=<AddBackward0>)
  1. z = y * y * 3
  2. out = z.mean()
  3. print(z, out)
  1. tensor([[27., 27.],
  2. [27., 27.]], grad_fn=<MulBackward0>) tensor(27., grad_fn=<MeanBackward0>)
  1. out.backward()
  2. #打印梯度 d(out)/dx
  3. print(x.grad)
  4. # print(out.grad)
  1. tensor([[22.5000, 22.5000],
  2. [22.5000, 22.5000]])
  1. #现在让我们看一个雅可比向量积的例子:
  2. x = torch.randn(3, requires_grad=True)
  3. y = x * 2
  4. while y.data.norm() < 1000:
  5. y = y * 2
  6. print(y)
  1. tensor([ -80.3993, 178.1791, -1355.1229], grad_fn=<MulBackward0>)
  1. v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
  2. y.backward(v)
  3. print(x.grad)
  1. tensor([5.1200e+01, 5.1200e+02, 5.1200e-02])

torch.diag()用法

torch.diag(input, diagonal=0, *, out=None) → Tensor
If input is a vector (1-D tensor), then returns a 2-D square tensor with the elements of input as the diagonal.
If input is a matrix (2-D tensor), then returns a 1-D tensor with the diagonal elements of input.

  1. #Get the square matrix where the input vector is the diagonal
  2. a = torch.randn(3)
  3. a
  4. torch.diag(a)
  5. torch.diag(a, 1)
  6. #Get the k-th diagonal of a given matrix
  7. a = torch.randn(3, 3)
  8. a
  9. torch.diag(a, 0)
  10. torch.diag(a, 1)
  1. tensor([ 0.4590, 0.8841, -0.6945])
  2. tensor([[ 0.4590, 0.0000, 0.0000],
  3. [ 0.0000, 0.8841, 0.0000],
  4. [ 0.0000, 0.0000, -0.6945]])
  5. tensor([[ 0.0000, 0.4590, 0.0000, 0.0000],
  6. [ 0.0000, 0.0000, 0.8841, 0.0000],
  7. [ 0.0000, 0.0000, 0.0000, -0.6945],
  8. [ 0.0000, 0.0000, 0.0000, 0.0000]])
  9. tensor([[ 0.3824, -0.6560, 1.8126],
  10. [ 0.0241, -0.8781, -1.3364],
  11. [-0.5124, 2.1753, 0.1158]])
  12. tensor([ 0.3824, -0.8781, 0.1158])
  13. tensor([-0.6560, -1.3364])

torch.sign()用法

torch.sign(input, *, out=None) → Tensor
Returns a new tensor with the signs of the elements of input.即输出input通过sign函数后的张量。

  1. a = torch.tensor([0.7, -1.2, 0., 2.3])
  2. print(a)
  3. torch.sign(a)
  1. tensor([ 0.7000, -1.2000, 0.0000, 2.3000])
  2. tensor([ 1., -1., 0., 1.])

torch.t()用法

torch.t(input) → Tensor
Expects input to be <= 2-D tensor and transposes dimensions 0 and 1.
0-D and 1-D tensors are returned as is. When input is a 2-D tensor this is equivalent to transpose(input, 0, 1).

  1. x = torch.randn(())
  2. x
  3. torch.t(x)
  4. x = torch.randn(3)
  5. x
  6. torch.t(x)
  7. x = torch.randn(2, 3)
  8. x
  9. torch.t(x)
  1. tensor(1.7658)
  2. tensor(1.7658)
  3. tensor([ 0.8564, 0.4923, -1.0440])
  4. tensor([ 0.8564, 0.4923, -1.0440])
  5. tensor([[-0.1147, -0.5785, 1.7228],
  6. [ 0.0507, -1.0331, 0.7053]])
  7. tensor([[-0.1147, 0.0507],
  8. [-0.5785, -1.0331],
  9. [ 1.7228, 0.7053]])

pytorch中@、*用法

@:对tensor进行矩阵相乘
*:对tensor进行矩阵进行逐元素相乘

torch.norm()用法

torch.norm(input, p=’fro’, dim=None, keepdim=False, out=None, dtype=None) #dim:要缩减的维度
Returns the matrix norm or vector norm of a given tensor.

  1. a = torch.rand((2,3,4))
  2. at = torch.norm(a,p=2,dim=1,keepdim=True) #保持维度
  3. af = torch.norm(a,p=2,dim=1,keepdim=False) #不保持维度
  4. print(a.shape)
  5. print(at.shape)
  6. print(af.shape)
  1. torch.Size([2, 3, 4])
  2. torch.Size([2, 1, 4])
  3. torch.Size([2, 4])

torch.einsum()用法

爱因斯坦简记法:是一种由爱因斯坦提出的,对向量、矩阵、张量的求和运算的求和简记法。

  1. #矩阵求和
  2. a = torch.arange(6).view(2, 3)
  3. b = torch.arange(6,12).reshape(2, 3)
  4. torch.einsum('ij,ij->', [a, b])
  5. #矩阵外积
  6. a = torch.arange(3)
  7. # a
  8. b = torch.arange(3,7)
  9. # b
  10. torch.einsum('i,j->ij', [a, b])
  1. tensor(145)
  2. tensor([[ 0, 0, 0, 0],
  3. [ 3, 4, 5, 6],
  4. [ 6, 8, 10, 12]])

torch.sum()用法

参数
input (Tensor) – the input tensor.
dim (int or tuple of python:ints) – the dimension or dimensions to reduce. 要缩减的维度
keepdim (bool) – whether the output tensor has dim retained or not.

  1. b = torch.arange(2 * 3 * 4).view(2, 3, 4)
  2. # b
  3. torch.sum(b, (2, 1))
  1. tensor([ 66, 210])

一维Tensor与一维Array的形状区别

  1. torch.tensor([1,2]).shape
  2. np.array([1,2]).shape
  1. torch.Size([2])
  2. (2,)

torch.max()用法

torch.max(input, dim, keepdim=False, *, out=None) -> (Tensor, LongTensor)

Returns a namedtuple (values, indices) where values is the maximum value of each row of the input tensor in the given dimension dim. And indices is the index location of each maximum value found (argmax).
If keepdim is True, the output tensors are of the same size as input except in the dimension dim where they are of size 1. Otherwise, dim is squeezed (see torch.squeeze()), resulting in the output tensors having 1 fewer dimension than input.

Parameters
input (Tensor) – the input tensor.
dim (int) – the dimension to reduce.
keepdim (bool) – whether the output tensor has dim retained or not. Default: False.

Keyword Arguments
out (tuple, optional) – the result tuple of two output tensors (max, max_indices)

a = torch.randn(4, 4)
a
torch.max(a, 1)
#只取值不取索引
torch.max(a, 1).values

torch.cumsum用法

torch.cumsum(input, dim, *, dtype=None, out=None) → Tensor
Returns the cumulative sum of elements of input in the dimension dim.

  1. a = torch.randn(10)
  2. a
  3. torch.cumsum(a, dim=0)
  1. tensor([ 0.3418, -0.9971, -1.3957, -0.2646, -0.8354, -1.3760, 0.3042, 0.4878,
  2. 0.2004, -0.8370])
  3. tensor([ 0.3418, -0.6552, -2.0509, -2.3155, -3.1509, -4.5268, -4.2227, -3.7349,
  4. -3.5345, -4.3715])

PyTorch使用tensorboardX.SummaryWriter

tensorboardX用于训练、验证时自动记录数据绘图。但大多数情况只看loss,lr,accu这些曲线,就先总结这些,什么images,audios以后需要再总结。

  1. 安装:pip install tensorboardX
  2. 调用
    from tensorboardX import SummaryWriter
    writer = SummaryWriter(‘log’)
    writer相当于日志,保存你要做图的所有信息。SummaryWriter(‘log’)会在当前项目目录下建立一个文件夹log,存放画图用的文件。刚开始的时候是空的。
    训练的循环中,每次写入图像名称,loss数值, n_iteration:writer.add_scalar(‘Train/Loss’, loss.data[0], niter)
    验证的循环中,写入预测的准确度即可:writer.add_scalar(‘Test/Accu’, correct/total, niter)
    为了看得清楚一点,我把整个train_eval写一起了
    def train_eval(epoch):
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
    inputs, labels = data
    inputs, labels = Variable(inputs), Variable(labels)
    optimizer.zero_grad()
    outputs = net(inputs)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()
    running_loss += loss.data[0]
    #每2000个batch显示一次当前的loss和accu
    if i % 2000 == 1999:
    print(‘[epoch: %d, batch: %5d] loss: %.3f’ %
    (epoch + 1, i+1, running_loss / 2000))
    running_loss = 0.0
    print(‘[epoch: %d, batch: %5d] Accu: %.3f’ %(epoch + 1, i+1, correct/total))```

    每10个batch画个点用于loss曲线

    if i % 10 == 0: niter = epoch * len(trainloader) + i writer.add_scalar(‘Train/Loss’, loss.data[0], niter)

    每500个batch全验证集检测,画个点用于Accu

    if i % 500 == 0: correct = 0 total = 0 for data in testloader: images, target = data res = net(Variable(images)) _, predicted = torch.max(res.data, 1) total += labels.size(0) correct += (predicted == target).sum() writer.add_scalar(‘Test/Accu’, correct/total, niter) ```

3.显示

会发现刚刚的log文件夹里面有文件了。在命令行输入如下,载入刚刚做图的文件(那个./log要写完整的路径)

tensorboard —logdir=./log

在浏览器输入:

http://0.0.0.0:6006/

就可以看到我们做的两个图了