tags: [笔记, Pytorch]
categories: [笔记, Pytorch]
Pytorch 用法教程
相关配置
1 | #导入相关包 |
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) |
1 | --------------------------------------------------------------------------- |
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) |
1 | tensor([-0.5281, -1.0857, 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 |
1 | tensor([-inf, -inf, 3., 4.]) |
torch.from_numpy()用法
Creates a Tensor from a numpy.ndarray.
用 torch.from_numpy 这个方法将 numpy 类转换成 tensor 类
Pytorch Tensor 的索引与切片
一般索引
根据 Tensor 的 shape,从前往后索引,依次在每个维度上做索引。
1 | import torch |
1 | torch.Size([3, 28, 28]) |
普通的切片索引
注意负值的索引即表示倒数第几个元素,-2 就是倒数第二个元素。
1 | import torch |
1 | torch.Size([2, 3, 28, 28]) |
index_select()选择特定索引
选择特定下标有时候很有用,比如上面的 a 这个 Tensor 可以看作 4 张 RGB(3 通道)的 MNIST 图像,长宽都是 28px。那么在第一维度上可以选择特定的图片,在第二维度上选择特定的通道。
1 | # 选择第一张和第三张图 |
1 | torch.Size([2, 3, 28, 28]) |
注意:index_select()的第二个索引参数必须是 Tensor 类型
任意多的维度
在索引中使用…可以表示任意多的维度。
1 | import torch |
1 | torch.Size([4, 3, 28, 28]) |
mask 索引
可以获取满足一些条件的值的位置索引,然后用这个索引去取出这些位置的元素。
1 | import torch |
1 | tensor([[-0.3195, -0.3623, -0.6834, 0.5384], |
注意:最后取出的 大于 0.5 的 Tensor 的 shape 已经被摊平(变为一维)。
take 索引
take 索引是基于目标 Tensor 的 flatten 形式下的,即摊平后的 Tensor 的索引。
1 | import torch |
1 | tensor([[3, 7, 2], |
pytotch 中类似于 numpy 的花式索引,即以任意维 tensor 作为索引
需整理,参考https://blog.csdn.net/xpy870663266/article/details/101597144
一维 Tensor 作为索引
在 Numpy 中,我们可以传入数组作为索引,称为花式索引。这里只演示使用两个一维 List 的例子。
1 | a=np.arange(18).reshape(6,3) |
1 | array([[ 0, 1, 2], |
而在 PyTorch 中,如果使用两个整数 List/一维 Tensor 作为索引,所起的作用是相同的。
1 | w=torch.arange(18).view(6,3) |
1 | tensor([[ 0, 1, 2], |
二维 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 |
1 | tensor([[ 0, 1, 2], |
使用 Tensor 作为 List 的索引
当 Tensor 仅含有一个整数时,可以作为 List 的索引,相当于取出该整数作为索引。若含有多个整数,则报错。
1 | import torch |
1 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] |
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] |
1 | torch.Size([2, 3]) |
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 |
1 | tensor([[[ 0.8953, -0.4839, -0.6158], |
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) |
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]) |
1 | tensor([[1, 2, 3, 1, 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 的列表
pad*sequence 沿新维度堆叠张量列表,并将它们填充为相等的长度。 例如,如果输入是大小为 L x 的序列列表,并且 batchfirst 为 False,否则为 T x B x *。
B 是批次大小。它等于序列中元素的数量。T 是最长序列的长度。L 是序列的长度。*是任意数量的尾部维度,包括 None。
1 | from torch.nn.utils.rnn import pad_sequence |
1 | torch.Size([3, 25, 300]) |
自动微分
1 | x = torch.ones(2, 2, requires_grad=True) |
1 | tensor([[1., 1.], |
1 | y = x + 2 |
1 | tensor([[3., 3.], |
1 | z = y * y * 3 |
1 | tensor([[27., 27.], |
1 | out.backward() |
1 | tensor([[22.5000, 22.5000], |
1 | #现在让我们看一个雅可比向量积的例子: |
1 | tensor([ -80.3993, 178.1791, -1355.1229], grad_fn=<MulBackward0>) |
1 | v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float) |
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 |
1 | tensor([ 0.4590, 0.8841, -0.6945]) |
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]) |
1 | tensor([ 0.7000, -1.2000, 0.0000, 2.3000]) |
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(()) |
1 | tensor(1.7658) |
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)) |
1 | torch.Size([2, 3, 4]) |
torch.einsum()用法
爱因斯坦简记法:是一种由爱因斯坦提出的,对向量、矩阵、张量的求和运算的求和简记法。
1 | #矩阵求和 |
1 | tensor(145) |
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) |
1 | tensor([ 66, 210]) |
一维 Tensor 与一维 Array 的形状区别
1 | torch.tensor([1,2]).shape |
1 | torch.Size([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) |
1 | tensor([ 0.3418, -0.9971, -1.3957, -0.2646, -0.8354, -1.3760, 0.3042, 0.4878, |
PyTorch 使用 tensorboardX.SummaryWriter
tensorboardX 用于训练、验证时自动记录数据绘图。但大多数情况只看 loss,lr,accu 这些曲线,就先总结这些,什么 images,audios 以后需要再总结。
- 安装:pip install tensorboardX
- 调用
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)
1 |
|
- 本文作者: YuT
- 本文链接: https://ytno1.github.io/archives/39ef698d.html
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!