对象
:给定的序列化张量,即Tensor
型。
功能
:实现两个张量在指定维度上的拼接。
输出
:拼接后的张量。
函数以及参数
:torch.cat(tensor, dim),官方给出的有四个参数,但是我们平时只会用到前两个参数即可。
tensor
:有相同形状的张量序列,所有的张量需要有相同的形状才能够拼接,除非是在拼接维度上两个张量可以有不同的尺寸,或者两个张量都是空的。
dim
:两个张量或者多个张量拼接的维度。
应用实例1:两个张量形状相同
代码
:
import torch
x = torch.randn(2,4)
y = torch.randn(2,4)
print(f'x={x}','\n',f'y={y}')
print(f'z={torch.cat((x,y), 0)}')
输出
:
x=tensor([[-1.2870, -0.7040, 0.3016, -0.2970],
[-0.8151, -0.5236, -1.7680, 0.7675]])
y=tensor([[-1.4207, -0.2694, 0.2521, -0.7187],
[ 0.8776, -0.0352, -0.5094, 0.0602]])
z=tensor([[-1.2870, -0.7040, 0.3016, -0.2970],
[-0.8151, -0.5236, -1.7680, 0.7675],
[-1.4207, -0.2694, 0.2521, -0.7187],
[ 0.8776, -0.0352, -0.5094, 0.0602]])
应用实例2:多个张量形状相同
代码
:
import torch
x = torch.randn(2,4)
y = torch.randn(2,4)
print(f'x={x}','\n',f'y={y}')
print(f'z={torch.cat((x,y,x,y), 0)}')
输出
:
x=tensor([[ 0.4697, -0.4881, -2.0199, -0.8661],
[ 0.4911, -0.1259, 1.1939, 0.7730]])
y=tensor([[ 0.8633, 0.4438, -0.6975, 0.5440],
[ 0.1554, -1.6358, -1.2234, -0.6597]])
z=tensor([[ 0.4697, -0.4881, -2.0199, -0.8661],
[ 0.4911, -0.1259, 1.1939, 0.7730],
[ 0.8633, 0.4438, -0.6975, 0.5440],
[ 0.1554, -1.6358, -1.2234, -0.6597],
[ 0.4697, -0.4881, -2.0199, -0.8661],
[ 0.4911, -0.1259, 1.1939, 0.7730],
[ 0.8633, 0.4438, -0.6975, 0.5440],
[ 0.1554, -1.6358, -1.2234, -0.6597]])
应用实例3:两个张量形状不同,但只在拼接维度上
代码
:
import torch
x = torch.randn(3,4)
y = torch.randn(2,4)
print(f'x={x}','\n',f'y={y}')
print(f'z={torch.cat((x,y), 0)}')
x_1 = torch.randn(2,3)
y_1 = torch.randn(2,4)
print(f'x_1=\n{x_1}','\n',f'y_1=\n{y_1}')
print(f'z_1=\n{torch.cat((x_1,y_1), 1)}')
输出
:
x=tensor([[-0.1966, -0.9648, 1.2787, -1.4578],
[-1.2216, 0.1663, 0.5380, -0.0376],
[-1.7365, -0.4151, -1.0336, -0.6732]])
y=tensor([[ 1.4477, 0.3616, -0.1504, 0.4662],
[-1.1334, 1.3100, 0.1624, 0.8206]])
z=tensor([[-0.1966, -0.9648, 1.2787, -1.4578],
[-1.2216, 0.1663, 0.5380, -0.0376],
[-1.7365, -0.4151, -1.0336, -0.6732],
[ 1.4477, 0.3616, -0.1504, 0.4662],
[-1.1334, 1.3100, 0.1624, 0.8206]])
x_1=
tensor([[ 1.1418, 0.0774, 0.2047],
[-0.0673, -1.5794, 0.0131]])
y_1=
tensor([[ 1.4149, -1.9538, 0.1660, 1.1142],
[-1.6455, 0.5595, -0.1162, 0.8628]])
z_1=
tensor([[ 1.1418, 0.0774, 0.2047, 1.4149, -1.9538, 0.1660, 1.1142],
[-0.0673, -1.5794, 0.0131, -1.6455, 0.5595, -0.1162, 0.8628]])
Process finished with exit code 0
对象
:给定的张量,即Tensor
型。
功能
:在指定的维度上对张量进行重复扩充,也可以用来增加维度。
输出
:升维或扩充后的张量。
函数以及参数
:torch.tensor.repeat(size),size所在的索引表示扩充的维度的索引。
size
:表示张量在这个索引维度下的扩充倍数。
注意事项
:函数的参数量必须大于等于tensor的维度,如a.shape=(2,3),那么如果我们想扩充2倍a的第0个维度时,应该这么写a.repeat(2,1),对于不扩充的维度则写1。
应用实例1:一维张量扩充
代码
:
import torch
x = torch.randn(3)
print(f'x={x}')
print(f'x_1={x.repeat(2)}')
输出
:
x=tensor([-0.1485, 1.8445, 1.4257])
x_1=tensor([-0.1485, 1.8445, 1.4257, -0.1485, 1.8445, 1.4257])
应用实例2:多维张量扩充
代码
:
import torch
x = torch.randn(3, 4, 3)
print(f'x={x}')
#在第2个维度上扩充两倍,其他维度保持不变
print(f'x_1={x.repeat(1,1,2)}')
输出
:
x=tensor([[[-0.0294, 1.2902, 0.9825],
[-0.3032, 1.6733, 0.9163],
[ 0.3079, -0.0159, 0.2626],
[-0.2934, -0.6076, 0.1593]],
[[ 1.7661, -1.0698, 0.4074],
[-0.3660, -0.3219, 0.3732],
[-1.3314, -0.8263, -1.0793],
[ 1.2589, 0.1886, 0.5453]],
[[ 0.2520, -0.5695, -0.6685],
[ 0.5554, 0.0119, -0.5650],
[ 0.9733, -0.3812, 0.1963],
[-1.1284, 0.2561, 0.4507]]])
x_1=tensor([[[-0.0294, 1.2902, 0.9825, -0.0294, 1.2902, 0.9825],
[-0.3032, 1.6733, 0.9163, -0.3032, 1.6733, 0.9163],
[ 0.3079, -0.0159, 0.2626, 0.3079, -0.0159, 0.2626],
[-0.2934, -0.6076, 0.1593, -0.2934, -0.6076, 0.1593]],
[[ 1.7661, -1.0698, 0.4074, 1.7661, -1.0698, 0.4074],
[-0.3660, -0.3219, 0.3732, -0.3660, -0.3219, 0.3732],
[-1.3314, -0.8263, -1.0793, -1.3314, -0.8263, -1.0793],
[ 1.2589, 0.1886, 0.5453, 1.2589, 0.1886, 0.5453]],
[[ 0.2520, -0.5695, -0.6685, 0.2520, -0.5695, -0.6685],
[ 0.5554, 0.0119, -0.5650, 0.5554, 0.0119, -0.5650],
[ 0.9733, -0.3812, 0.1963, 0.9733, -0.3812, 0.1963],
[-1.1284, 0.2561, 0.4507, -1.1284, 0.2561, 0.4507]]])
应用实例3:张量维度扩充
代码
:
import torch
x = torch.randn(1,2)
print(f'x={x}')
#将a多扩充一个维度,这个维度扩充的倍数需要写在最前面,如此案例的3
print(f'x_1={x.repeat(3,1,1)}')
输出
:
x=tensor([[-0.2581, -0.8387]])
x_1=tensor([[[-0.2581, -0.8387]],
[[-0.2581, -0.8387]],
[[-0.2581, -0.8387]]])
对象
:张量Tensor。
功能
:根据输入张量的形状,生成同样形状的元素为单位1的新张量。
输出
:shape与输入张量相同的,元素全为1的张量。
函数以及参数
:torch.ones_like(tensor)。
tensor
:输入张量。
应用实例1:
代码
:
import torch
x = torch.randn(1,2)
y = torch.ones_like(x)
print(f'x={x}')
print(f'y={y}')
输出
:
x=tensor([[-0.8550, -1.1273]])
y=tensor([[1., 1.]])
对象
:张量Tensor。
功能
:根据输入张量的形状,生成同样形状的元素全为0的新张量。
输出
:shape与输入张量相同的,元素全为0的张量。
函数以及参数
:torch.ones_like(tensor)。
tensor
:输入张量。
应用实例1:
代码
:
import torch
x = torch.randn(1,2)
y = torch.zeros_like(x)
print(f'x={x}')
print(f'y={y}')
输出
:
x=tensor([[ 0.3998, -0.4588]])
y=tensor([[0., 0.]])
对象
:一个张量或两个Tensor。
功能
:通过对张量遍历(或对张量的某一个维度遍历)输出张量的最大值,也可以输入两个张量,通过比较两个张量间对应位置的元素,取最大值,最终输出所有位置上最大值构成的张量。
输出
:某个最大值,或者张量,以及最大值的索引。
函数以及参数
:torch.max(input_tensor,dim)。
input_tensor
:输入张量。
dim
:指定维度。
应用实例1:单维度
代码
:
import torch
x = torch.randn(1,4)
x_max = torch.max(x)
#dim=0是每列的最大值,dim=1是每行的最大值,返回最大值以及最大值索引
x_row,pos = torch.max(x, dim=1)
print(f'x={x}')
print(f'x_max={x_max}')
print(f'x_ans={x_row}')
print(f'max_pos={pos}')
输出
:
x=tensor([[ 1.7854, -0.5585, -0.5001, 0.4208]])
x_max=1.785356879234314
x_ans=tensor([1.7854])
max_pos=tensor([0])
应用实例2:多维度
代码
:
import torch
x = torch.randn(3,4)
x_max = torch.max(x)
#返回每行的最大值,以及最大值在对应行的索引
x_row,pos = torch.max(x, dim=1)
print(f'x={x}')
print(f'x_max={x_max}')
print(f'x_ans={x_row}')
print(f'max_pos={pos}')
输出
:
x=tensor([[-0.2816, -0.4243, 0.9465, 0.1041],
[ 0.5618, -1.4577, -0.2811, 1.6255],
[-0.9093, -1.6243, -0.5805, -0.3621]])
x_max=1.6254589557647705
x_ans=tensor([ 0.9465, 1.6255, -0.3621])
max_pos=tensor([2, 3, 3])
应用实例3:输入两个张量
代码
:
import torch
x = torch.randn(3,4)
y = torch.randn(3,4)
x_y = torch.max(x, y)
print(f'x={x}')
print(f'y={y}')
print(f'x_y={x_y}')
输出
:
x=tensor([[-0.0504, 1.5075, 0.7595, -0.1954],
[ 0.1285, -1.3820, 0.8436, 0.2701],
[ 0.2804, 0.9583, -0.1772, 1.0917]])
y=tensor([[-1.1441, 1.7095, 0.2986, -1.3146],
[ 0.8251, -0.4364, 1.0754, 0.2895],
[ 0.3503, -0.7810, -1.4669, 0.9201]])
x_y=tensor([[-0.0504, 1.7095, 0.7595, -0.1954],
[ 0.8251, -0.4364, 1.0754, 0.2895],
[ 0.3503, 0.9583, -0.1772, 1.0917]])
应用实例4:实例3基础上,选择输出的某个维度进行max,该场景常用于深度学习的正负样本匹配中
代码
:
import torch
x = torch.randn(2,3,2)
y = torch.randn(2,3,2)
x_y = torch.max(x, y)
#[0]表示输出的是元素的张量,[1]表示输出的元素的索引,该场景常用于深度学习的正负样本匹配中
x_y_ans = x_y.max(2)[0]
print(f'x={x}')
print(f'y={y}')
print(f'x_y={x_y}')
print(f'x_y_ans={x_y_ans}')
输出
:
x=tensor([[[ 0.2531, 0.1651],
[-0.4608, -1.2071],
[ 0.9032, -0.8951]],
[[ 0.2045, 0.5828],
[ 0.6315, 1.5716],
[-0.5640, -1.8911]]])
y=tensor([[[-0.1512, 1.3686],
[ 0.4760, -1.3106],
[ 0.2326, 0.4541]],
[[ 0.3184, -0.6637],
[-1.3316, -1.0620],
[-0.2468, -0.2879]]])
x_y=tensor([[[ 0.2531, 1.3686],
[ 0.4760, -1.2071],
[ 0.9032, 0.4541]],
[[ 0.3184, 0.5828],
[ 0.6315, 1.5716],
[-0.2468, -0.2879]]])
x_y_ans=tensor([[ 1.3686, 0.4760, 0.9032],
[ 0.5828, 1.5716, -0.2468]])
对象
:一个张量Tensor。
功能
:将张量按照我们想要切分的个数,以及切分的维度,将张量在指定维度上平均切分成n个张量。
输出
:切分后的n个张量。
函数以及参数
:torch.chunk(input_tensor,chunks,dims)。
input_tensor
:输入张量。
chunks
:切分出chunks个张量。
dim
:指定维度。
应用实例1:
代码
:
import torch
x = torch.randn(5,3)
#指定索引为1的维度,即3这个维度,分成2个tensor,因此一个tensor的维度为(5,2)
#另外一个tensor的维度为(5,1)
x_1,x_2 = x.chunk(2,1)
print(f'x={x}')
print(f'x_1={x_1}')
print(f'x_2={x_2}')
输出
:
x=tensor([[-1.4278, -0.3466, 1.1817],
[ 0.7366, 1.3741, 1.4865],
[-0.3405, -0.6658, 1.0279],
[-0.7094, -0.1081, 1.9509],
[-0.4722, -0.6317, -1.4544]])
x_1=tensor([[-1.4278, -0.3466],
[ 0.7366, 1.3741],
[-0.3405, -0.6658],
[-0.7094, -0.1081],
[-0.4722, -0.6317]])
x_2=tensor([[ 1.1817],
[ 1.4865],
[ 1.0279],
[ 1.9509],
[-1.4544]])
amp功能
:amp即使用混合精度学习的方式来训练网络,用于前向传播部分(包括loss的计算),不能用于反向传播的过程。
注意
:Pytorch1.5版本之前可以通过pip install apex,然后from apex import amp来调用amp.scale_loss,但是从Pytorch1.6开始之后的版本,调用时会导致报错。可以通过使用Pytorch自带的torch.cuda.amp来代替。
autocast功能
:在进入autocast上下文之后,cuda ops会自动把tensor的数据类型转换为半精度浮点型,从而在不损失训练精度的情况下加快运算。
GradScaler功能
:可以通过放大loss的值来防止梯度消失underflow
使用方法1:
from torch.cuda.amp import autocast
from torch.optim import SGD
model = Net().cuda()
optimizer = SGD(...)
model.train()
for epoch in epochs:
for step, data in enumerate(train_loader):
optimizer.zero_grad()
with amp.autocast():
output = model(data)
total_loss = compute_loss(output, GT)
total_loss.backward()
optimizer.step()
使用方法2:加入GradScaler
from torch.cuda.amp import autocast
from torch.optim import SGD
model = Net().cuda()
optimizer = SGD(...)
model.train()
#在训练最开始之前实例化一个GradScaler对象
scaler = amp.GradScaler()
for epoch in epochs:
for step, data in enumerate(train_loader):
optimizer.zero_grad()
with amp.autocast():
output = model(data)
total_loss = compute_loss(output, GT)
scaler.scale(total_loss).backward()
scaler.step(optimizer)
scaler.update()
对象
:给定的张量,即Tensor
型。
功能
:返回一个新的张量,这个张量从当前的计算图中分离出来,但仍指向原变量的存储位置,但是这个张量在计算图中不再计算梯度与更新梯度。
注意
:修改分离出来的tensor时,同样会改变原来的tensor,因为他们都指向同一个地址。
应用实例1:当使用detach()分离tensor
代码
:
import torch
a = torch.tensor([1., 2., 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
# 添加detach(),c的requires_grad为False
c = out.detach()
print(c)
输出
:
None
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward0>)
tensor([0.7311, 0.8808, 0.9526])
应用实例2:当使用detach()分离tensor但并没有改变tensor的值时,对其进行backward()不会有问题
代码
:
import torch
a = torch.tensor([1., 2., 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
# 添加detach(),c的requires_grad为False
c = out
print(c)
# 使用新生成的Variable进行反向传播
c.sum().backward()
print(a.grad)
输出
:
None
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward0>)
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward0>)
tensor([0.1966, 0.1050, 0.0452])
应用实例3:当使用detach()分离tensor,但对分离出来的tensor进行求梯度时,会有问题。
代码
:
import torch
a = torch.tensor([1., 2., 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
# 添加detach(),c的requires_grad为False
c = out.detach()
print(c)
# 使用新生成的Variable进行反向传播
c.sum().backward()
print(a.grad)
输出
:
None
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward0>)
tensor([0.7311, 0.8808, 0.9526])
RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
应用实例4:当使用detach()分离tensor并更改时,即使对原张量进行求梯度,也会有问题。
代码
:
import torch
a = torch.tensor([1., 2., 3.], requires_grad=True)
print(a.grad)
out = a.sigmoid()
print(out)
# 添加detach(),c的requires_grad为False
c = out.detach()
print(c)
# 使用新生成的Variable进行反向传播
c.sum().backward()
print(a.grad)
输出
:
None
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward0>)
tensor([0.7311, 0.8808, 0.9526])
tensor([0., 0., 0.])
tensor([0., 0., 0.], grad_fn=<SigmoidBackward0>)
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [3]], which is output 0 of SigmoidBackward0, is at version 1; expected version 0 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
引用自:pytorch:.detach()、.detach_()的作用和区别
对象
:所有计算得到的张量结果
功能
:在该模块下,所有计算得到的张量的requires_grad都会被设置成false,即不再进行反向传播,也不求导。
注意
:通常伴随with使用,即with torch.no_grad():
应用实例1:
代码
:
x = torch.randn(10, 5, requires_grad = True)
y = torch.randn(10, 5, requires_grad = True)
z = torch.randn(10, 5, requires_grad = True)
with torch.no_grad():
w = x + y + z
print(w.requires_grad)
print(w.grad_fn)
print(w.requires_grad)
输出
:
False
None
False
对象
:张量运算后的结果。
功能
:根据张量的运算方式,来求输入的梯度变化,即求导或者求偏导。
应用实例1:
代码
:
x = torch.tensor([1,2], dtype=torch.float32, requires_grad=True)
y = x + 1
print(y)
z = torch.mean(y**2)
print(z)
z.backward()
print(x.grad)
输出
:
tensor([2., 3.], grad_fn=<AddBackward0>)
tensor(6.5000, grad_fn=<MeanBackward0>)
tensor([2., 3.])
应用实例2:
代码
:
x = torch.tensor([1,2], dtype=torch.float32, requires_grad=True)
y = x.sigmoid()
print(y)
y.sum().backward()
print(x.grad)
输出
:
tensor([0.7311, 0.8808], grad_fn=<SigmoidBackward0>)
tensor([0.1966, 0.1050])
应用实例3:
代码
:
x = torch.tensor([1,2,3], dtype=torch.float32, requires_grad=True)
y = x.sigmoid()
print(y)
y.backward(torch.ones_like(x))
print(x.grad)
输出
:
tensor([0.7311, 0.8808, 0.9526], grad_fn=<SigmoidBackward0>)
tensor([0.1966, 0.1050, 0.0452])
细品这三个案例之间的区别~