详解Pytorch中的requires_grad、叶子节点与非叶子节点、with torch.no_grad()、model.eval()、model.train()、BatchNorm层
requires_grad
requires_grad
意为是否需要计算梯度- 使用
backward()
函数反向传播计算梯度时,并不是计算所有tensor的梯度,只有满足下面条件的tensor的梯度才会被计算:1. 当前tensor的require_grad=True
(代码示例一);2. 依赖于该tensor的所有tensor的require_grad=True
,即可以获得依赖于该tensor的所有tensor的梯度值(代码示例二)。 - 在所有的
require_grad=True
中- 默认情况下,非叶子节点的梯度值在反向传播过程中使用完后就会被清除,不会被保留。
- 默认情况下,只有叶子节点的梯度值能够被保留下来。
- 被保留下来的叶子节点的梯度值会存入
tensor
的grad属性
中,在optimizer.step()
过程中会更新叶子节点的data属性
值,从而实现参数的更新。
代码示例
示例一:require_grad=True时才会计算梯度
import torch
import torch.nn as nn
import torch.optim as optim
import random
import os
import numpy as npdef seed_torch(seed=1029):random.seed(seed)os.environ['PYTHONHASHSEED'] = str(seed) # 为了禁止hash随机化,使得实验可复现np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.torch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.deterministic = Trueseed_torch()# 定义一个网络
class net(nn.Module):def __init__(self, num_class=10):super(net, self).__init__()self.pool1 = nn.AvgPool1d(2)self.bn1 = nn.BatchNorm1d(3)self.fc1 = nn.Linear(12, 4)def forward(self, x):x = self.pool1(x)x = self.bn1(x)x = x.reshape(x.size(0), -1)x = self.fc1(x)return x# 定义网络
model = net()# 定义loss
loss_fn = nn.CrossEntropyLoss()# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=1e-2)# 定义训练数据
x = torch.randn((3, 3, 8))model.fc1.weight.requires_grad = False # fc1.weight不计算梯度
print(model.fc1.weight.grad)
print(model.fc1.bias.grad) # fc1.bias计算梯度output = model(x)
target = torch.tensor([1, 1, 1])
loss = loss_fn(output, target)loss.backward()print(model.fc1.weight.grad)
print(model.fc1.bias.grad)
结果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
None
None
None
tensor([ 0.1875, -0.8615, 0.3708, 0.3033])
示例二:使用detach()使非叶子节点被剥离计算图不计算梯度值(requires_grad=False)时,被该非叶子节点依赖的叶子节点不计算梯度,即使该叶子节点的requires_grad=True
import torch
import torch.nn as nn
import torch.optim as optim
import random
import os
import numpy as npdef seed_torch(seed=1029):random.seed(seed)os.environ['PYTHONHASHSEED'] = str(seed) # 为了禁止hash随机化,使得实验可复现np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.torch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.deterministic = Trueseed_torch()# 定义一个网络
class net(nn.Module):def __init__(self, num_class=10):super(net, self).__init__()self.pool1 = nn.AvgPool1d(2)self.bn1 = nn.BatchNorm1d(3)self.fc1 = nn.Linear(12, 4)def forward(self, x):x = self.pool1(x)x = self.bn1(x)x = x.reshape(x.size(0), -1)x = x.detach() # 将非叶子节点剥离成叶子节点 x.requires_grad = False x.grad_fn=Noney = self.fc1(x)return y# 定义网络
model = net()# 定义loss
loss_fn = nn.CrossEntropyLoss()# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=1e-2)# 定义训练数据
x = torch.randn((3, 3, 8))# 训练前叶子结点 bn1.weight 的参数情况
print(model.bn1.weight.requires_grad)
print(model.bn1.weight.grad)# 训练前叶子结点 fc1.weight 的参数情况
print(model.fc1.weight.requires_grad)
print(model.fc1.weight.grad)output = model(x)
target = torch.tensor([1, 1, 1])
loss = loss_fn(output, target)loss.backward()# 训练后叶子结点 bn1.weight 的参数情况
print(model.bn1.weight.requires_grad)
print(model.bn1.weight.grad)# 训练后叶子结点 fc1.weight 的参数情况
print(model.fc1.weight.requires_grad)
print(model.fc1.weight.grad)
结果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
True
None
True
None
True
None
True
tensor([[ 0.0053, 0.0341, 0.0272, 0.0231, -0.1196, 0.0164, 0.0442, 0.1511,-0.1146, 0.2443, -0.0513, -0.0404],[ 0.1127, 0.0141, 0.1857, -0.3597, 0.5626, 0.1670, -0.0569, -0.6800,0.5046, -1.0340, 0.2865, 0.2857],[-0.0225, -0.0370, 0.0581, 0.0509, -0.2231, 0.1119, 0.0313, 0.2887,-0.1560, 0.5342, -0.0799, -0.0358],[-0.0955, -0.0112, -0.2710, 0.2857, -0.2199, -0.2953, -0.0185, 0.2402,-0.2340, 0.2555, -0.1553, -0.2095]])
叶子节点与非叶子节点
tensor
可分为两类:叶子节点和非叶子节点- 可通过
is_leaf
来判断一个tensor是否为叶子节点
叶子结点
叶子节点可以理解成不依赖其他tensor的tensor
在pytorch中,神经网络层中的权值weight和偏差bias的tensor均为叶子节点;自己定义的tensor例如a=torch.tensor([1.0])定义的节点是叶子节点
import torch a=torch.tensor([1.0])a.is_leaf Trueb=a+1 b.is_leaf True
- 可以看出b竟然也是叶节点!这件事可以这样理解,单纯从数值关系上b=a+1,b确实依赖a。但是从pytorch的看来,一切是为了反向求导,a的requires_grad属性为False,其不要求获得梯度,那么a这个tensor在反向传播时其实是“无意义”的,可认为是游离在计算图之外的,故b仍然为叶子节点,如下图
- 可以看出b竟然也是叶节点!这件事可以这样理解,单纯从数值关系上b=a+1,b确实依赖a。但是从pytorch的看来,一切是为了反向求导,a的requires_grad属性为False,其不要求获得梯度,那么a这个tensor在反向传播时其实是“无意义”的,可认为是游离在计算图之外的,故b仍然为叶子节点,如下图
再例如下图的计算图,本来是叶子节点是可以正常进行反向传播计算梯度的:
但是使用detach()函数将某一个非叶子节点剥离成为叶子节点后
无论requires_grad属性为何值,原先的叶子节点求导通路中断,便无法获得梯度数值了。其次,如上所示,对于需要求导的tensor,其requires_grad属性必须为True,例如对于下图中最上面的叶子节点,pytorch不会自动计算其导数。
非叶子节点
在默认情况下,非叶子节点中保存了pytorch计算图的另一种元素:运算(grad_fn)
,运算就是加减乘除、开方、幂指对、三角函数等可求导运算,有了运算才可以求叶子结点的梯度。
# 定义一个网络
class net(nn.Module):def __init__(self, num_class=10):super(net, self).__init__()self.pool1 = nn.AvgPool1d(2)self.bn1 = nn.BatchNorm1d(3)self.fc1 = nn.Linear(12, 4)def forward(self, x):x = self.pool1(x)x = self.bn1(x)x = x.reshape(x.size(0), -1)print(x)y = self.fc1(x)return y# 定义网络
model = net()# 定义loss
loss_fn = nn.CrossEntropyLoss()# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=1e-2)# 定义训练数据
x = torch.randn((3, 3, 8))output = model(x)
# 结果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
tensor([[-0.2112, -1.1580, 0.9010, -0.3500, -0.3878, 1.9242, -0.3629, 0.6713,0.4996, 2.3366, 0.1928, 0.7291],[-0.7056, -0.4324, -1.8940, 1.7456, -0.7856, -1.8655, -0.4469, 0.7612,-0.8044, 0.4850, -0.7059, -1.0746],[ 0.4769, 1.4226, 0.3125, -0.1074, -0.7744, -0.5955, 0.9378, 0.9242,-1.3836, 0.8161, -0.4706, -0.6202]], grad_fn=<ViewBackward>)
with torch.no_grad()
torch.no_grad()
是一个上下文管理器,用来禁止梯度的计算,通常用在网络推断(eval
)中,可以减少计算内存的使用量被
torch.no_grad()
包裹起来的部分不会被追踪梯度,虽然仍可以前向传播进行计算得到输出,但计算过程(grad_fn
)不会被记录,也就不能反向传播更新参数。具体地,对非叶子节点来说- 非叶子节点的
requires_grad
属性变为了False
- 非叶子节点的
grad_fn
属性变为了None
这样便不会计算非叶子节点的梯度。因此,虽然叶子结点(模型各层的可学习参数)的
requires_grad
属性没有改变(依然为True
),也不会计算梯度,grad
属性为None
,且如果使用loss.backward()
会报错(因为第一个非叶子节点(loss
)的requires_grad
属性为False
,grad_fn
属性为None
)。因此,模型的可学习参数不会更新。- 非叶子节点的
torch.no_grad()
不会影响dropout
和batchnorm
层在train
和eval
时的行为
代码示例
import torch
import torch.nn as nn
import torch.optim as optim
import random
import os
import numpy as npdef seed_torch(seed=1029):random.seed(seed)os.environ['PYTHONHASHSEED'] = str(seed) # 为了禁止hash随机化,使得实验可复现np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.torch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.deterministic = Trueseed_torch()# 定义一个网络
class net(nn.Module):def __init__(self, num_class=10):super(net, self).__init__()self.pool1 = nn.AvgPool1d(2)self.bn1 = nn.BatchNorm1d(3)self.fc1 = nn.Linear(12, 4)def forward(self, x):x = self.pool1(x)x = self.bn1(x)x = x.reshape(x.size(0), -1)print("非叶子节点的requires_grad: ", x.requires_grad) # 非叶子节点的wrequires_gradprint("非叶子节点的grad_fn: ", x.grad_fn) # 非叶子节点的grad_fny = self.fc1(x)return y# 定义网络
model = net()# 定义loss
loss_fn = nn.CrossEntropyLoss()# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=1e-2)# 定义训练数据
x = torch.randn((3, 3, 8))print("包裹前fc1.weight的requires_grad: ", model.fc1.weight.requires_grad) # 包裹前fc1.weight的requires_gradwith torch.no_grad():print("包裹后fc1.weight的requires_grad: ", model.fc1.weight.requires_grad) # 包裹后fc1.weight的requires_gradprint("训练前的fc1.weight.grad: ", model.fc1.weight.grad) # 训练前的fc1.weight.gradoutput = model(x)target = torch.tensor([1, 1, 1])loss = loss_fn(output, target)# 实际不会这么写 这里是为了验证不会计算grad 会报错loss.backward()print("训练后的fc1.weight.grad: ", model.fc1.weight.grad) # 训练后的fc1.weight.grad
结果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
包裹前fc1.weight的requires_grad: True
包裹后fc1.weight的requires_grad: True
训练前的fc1.weight.grad: None
非叶子节点的requires_grad: False
非叶子节点的grad_fn: None
Traceback (most recent call last):File "/home/jyzhang/test/net.py", line 66, in <module>loss.backward()File "/home/jyzhang/anaconda3/envs/bbn/lib/python3.9/site-packages/torch/tensor.py", line 245, in backwardtorch.autograd.backward(self, gradient, retain_graph, create_graph, inputs=inputs)File "/home/jyzhang/anaconda3/envs/bbn/lib/python3.9/site-packages/torch/autograd/__init__.py", line 145, in backwardVariable._execution_engine.run_backward(
RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
# element 0 of tensors指的是计算出的loss
model.eval()
底层分析
因为自定义的网络以及自定义的网络中的各个层都继承于nn.Module这个父类,nn.Module存在一个
training
的属性,默认为True
,所以,model.eval()
使得自定义的网络以及自定义的网络中的各个层的training
属性变为了False
class net(nn.Module):def __init__(self):super(net, self).__init__()self.bn = nn.BatchNorm1d(3, track_running_stats=True)def forward(self, x):return self.bn(x)model = net() model.eval() print(model.training) print(model.bn.training)# 输出 (bbn) jyzhang@admin2-X10DAi:~/test$ python net.py False False
在PyTorch中进行validation时,会使用
model.eval()
切换到测试模式该模式用于通知
dropout层
和batchnorm层
切换至val
模式- 在
val
模式下,dropout
层会让所有的激活单元都通过,而batchnorm
层会停止计算和更新mean
和var
,直接使用在训练阶段已经学出的mean
和var
值(这里的学习是指在训练阶段数据前向传播的过程中累积更新的mean和var值) - 关于对
batchnorm
层的影响的详细分析见下面的batch_normalization层
部分,这里坑很多!!!
- 在
该模式不会影响各层的gradient计算行为,即gradient计算和存储与training模式一样,(代码示例一),具体地
- 叶子结点(模型各层的可学习参数)的
requires_grad
属性没有改变(依然为True
) - 非叶子节点的
requires_grad
属性为True
- 非叶子节点的
grad_fn
属性不为None
- 因此,该模式不会影响各层的gradient计算行为,甚至
loss.backward()
还能正常运行计算梯度(通常不使用)
- 叶子结点(模型各层的可学习参数)的
注意,训练完train样本后,生成的模型model要用来测试样本。在model(test)之前,需要加上model.eval(),否则的话,有输入数据,即使不训练,相同的数据输出结果也会改变。这是model中含有BN层和Dropout所带来的的性质 (代码示例二)
如果不在意显存大小和计算时间的话,仅仅使用model.eval()已足够得到正确的validation/test的结果(在validation/test时不写
loss.backward()
);而with torch.no_grad()则是更进一步加速和节省gpu空间(因为不用计算和存储梯度),从而可以更快计算,也可以跑更大的batch来测试。
代码示例一
import torch
import torch.nn as nn
import torch.optim as optim
import random
import os
import numpy as npdef seed_torch(seed=1029):random.seed(seed)os.environ['PYTHONHASHSEED'] = str(seed) # 为了禁止hash随机化,使得实验可复现np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.torch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.deterministic = Trueseed_torch()# 定义一个网络
class net(nn.Module):def __init__(self, num_class=10):super(net, self).__init__()self.pool1 = nn.AvgPool1d(2)self.bn1 = nn.BatchNorm1d(3)self.fc1 = nn.Linear(12, 4)def forward(self, x):x = self.pool1(x)x = self.bn1(x)x = x.reshape(x.size(0), -1)print("非叶子节点的requires_grad: ", x.requires_grad) # 非叶子节点的wrequires_gradprint("非叶子节点的grad_fn: ", x.grad_fn) # 非叶子节点的grad_fny = self.fc1(x)return y# 定义网络
model = net()# 定义loss
loss_fn = nn.CrossEntropyLoss()# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=1e-2)# 定义训练数据
x = torch.randn((3, 3, 8))print("切换至eval前fc1.weight的requires_grad: ", model.fc1.weight.requires_grad) # 切换至eval前fc1.weight的requires_gradmodel.eval()print("切换至eval后fc1.weight的requires_grad: ", model.fc1.weight.requires_grad) # 切换至eval前fc1.weight的requires_gradoutput = model(x)target = torch.tensor([1, 1, 1])
loss = loss_fn(output, target)# 一般不这么使用,只是为了验证eval不改变各节点的梯度计算行文
loss.backward()
print("反向传播后model.fc1.weight.grad: ", model.fc1.weight.grad) # 反向传播后model.fc1.weight.grad
结果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
切换至eval前fc1.weight的requires_grad: True
切换至eval后fc1.weight的requires_grad: True
非叶子节点的requires_grad: True
非叶子节点的grad_fn: <ViewBackward object at 0x7f656790a040>
反向传播后model.fc1.weight.grad: tensor([[-0.0395, -0.0310, -0.0322, -0.0101, -0.1166, -0.0275, -0.0164, 0.0703,-0.0346, 0.1522, -0.0075, -0.0020],[ 0.1980, 0.1494, 0.2325, -0.0340, 0.5011, 0.2446, 0.1040, -0.2942,0.1612, -0.5969, 0.0538, 0.0527],[-0.0783, -0.0664, -0.0703, -0.0085, -0.2122, -0.0585, -0.0395, 0.1268,-0.0598, 0.2753, -0.0148, -0.0059],[-0.0801, -0.0521, -0.1300, 0.0526, -0.1723, -0.1586, -0.0480, 0.0971,-0.0669, 0.1695, -0.0315, -0.0449]])
代码示例二
import torch
import torch.nn as nn
import torch.optim as optim
import random
import os
import numpy as npdef seed_torch(seed=1029):random.seed(seed)os.environ['PYTHONHASHSEED'] = str(seed) # 为了禁止hash随机化,使得实验可复现np.random.seed(seed)torch.manual_seed(seed)torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.torch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.deterministic = Trueseed_torch()# 定义一个网络
class net(nn.Module):def __init__(self, num_class=10):super(net, self).__init__()self.pool1 = nn.AvgPool1d(2)self.bn1 = nn.BatchNorm1d(3)self.fc1 = nn.Linear(12, 4)def forward(self, x):x = self.pool1(x)x = self.bn1(x)x = x.reshape(x.size(0), -1)y = self.fc1(x)return y# 定义网络
model = net()# 定义loss
loss_fn = nn.CrossEntropyLoss()# 定义优化器
optimizer = optim.SGD(model.parameters(), lr=1e-2)# 定义训练数据
x1 = torch.randn((1, 3, 8))
x2 = torch.randn((1, 3, 8))
x3 = torch.randn((1, 3, 8))
x4 = torch.randn((1, 3, 8))# 切换至eval模式之前
print(model.bn1.running_mean)
model(x1)
print(model.bn1.running_mean)
model(x2)
print(model.bn1.running_mean)# 切换至eval模式之后
model.eval()
print(model.bn1.running_mean)
model(x3)
print(model.bn1.running_mean)
model(x4)
print(model.bn1.running_mean)# 再次切换至train模式
model.train()
print(model.bn1.running_mean)
model(x1)
print(model.bn1.running_mean)
model(x2)
print(model.bn1.running_mean)
结果
(bbn) jyzhang@admin2-X10DAi:~/test$ python net.py
tensor([0., 0., 0.])
tensor([-0.0287, 0.0524, -0.0517])
tensor([-0.0249, 0.0314, -0.0441])
tensor([-0.0249, 0.0314, -0.0441])
tensor([-0.0249, 0.0314, -0.0441])
tensor([-0.0249, 0.0314, -0.0441])
tensor([-0.0249, 0.0314, -0.0441])
tensor([-0.0511, 0.0806, -0.0914])
tensor([-0.0450, 0.0568, -0.0798])
model.train()
作用跟model.eval()
正好相反,具体分析类比model.eval()
batch_normalization层
Pytorch中的BatchNorm
API
Pytorch中的BatchNorm的API主要有:
torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True, device=None, dtype=None)
参数说明
num_features
输入维度是(N, C, L)时,num_features应该取C;这里N是batch size,C是数据的channel,L是数据长度
输入维度是(N, C)时,num_features应该取C;这里N是batch size,C是数据的channel,每个channel代表一种特征,省略了C
eps
对输入数据进行归一化时加在分母上,防止除零
momentum
更新全局均值
running_mean
和方差running_var
时使用该值进行平滑affine
设为True时,BatchNorm层才会有学习参数学习参数
γ、β\gamma、 \beta γ、β
否则不包含这两个变量,变量名是weight
和bias
track_running_stats
设为True时,表示跟踪整个训练过程中的batch的统计特性,得到方差和均值,而不只是仅仅依赖与当前输入的batch的统计特性,BatchNorm层会统计全局均值
running_mean
和方差running_var
参数详解
总述
由于上文提到的model.train()
和model.eval()
控制了training
属性,track_running_stats
参数又表示是否跟踪整个训练过程中的batch的统计特性,因此,这两个属性组合会出现不同的计算行为,值得注意
详解
首先声明一下归一化公式
在batch normalization中,使用的归一化公式为:
y=x−E[x]Var[x]+ϵy=\frac{x-E[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}} y=Var[x]+ϵx−E[x]
其中,E[x]表示均值,Var[x]表示方差再说明一下参数
affine
,如果affine=True
,则会在通过归一化公式对batch数据进行归一化后,对归一化后的batch进行仿射变换,即乘以模块内部的weight
(初值是[1., 1., 1., 1.])然后加上模块内部的bias
(初值是[0., 0., 0., 0.]),这两个变量是可学习参数,会在反向传播时得到更新。training=True, track_running_stats=True
这是我们常见的训练时的参数设置,即
model.train()
起作用时的常见设置此时,存在均值
running_mean
(初值是[0., 0., 0., 0.])和方差running_var
(初值是[1., 1., 1., 1.]),且均值running_mean
和方差running_var
会跟踪不同batch数据的mean和variance进行更新,更新公式为
xnew =(1−momentum )×xcur +momentum ×xbatch x_{\text {new }}=(1-\text { momentum }) \times x_{\text {cur }}+\text { momentum } \times x_{\text {batch }} \text {} xnew =(1− momentum )×xcur + momentum ×xbatch
xcur x_{\text {cur }}xcur 表示更新前的running_mean
和running_var
,xbatch x_{\text {batch }}xbatch 表示当前batch的均值和无偏样本方差(分母是N-1)。但是,在当前batch进行归一化(即使用上述归一化公式)时,使用的均值是当前batch的均值,方差是当前batch的有偏样本方差(分母是N),而不是
running_mean
和running_var
。
training=True, track_running_stats=False
- 此时,就不存在均值
running_mean
和方差running_var
,均值running_mean
和方差running_var
的值为None
,因此,均值running_mean
和方差running_var
就不会跟踪不同batch数据的mean和variance进行更新 - 此时,在当前batch进行归一化(即使用上述归一化公式)时,使用的均值是当前batch的均值,方差是当前batch的有偏样本方差(分母是N),而不是
running_mean
和running_var
。
- 此时,就不存在均值
training=False, track_running_stats=True
- 这是我们常见的验证和测试时的参数设置,即
model.eval()
起作用时的常见设置 - 此时,存在均值
running_mean
(初值是[0., 0., 0., 0.])和方差running_var
(初值是[1., 1., 1., 1.]),但均值running_mean
和方差running_var
不会跟踪不同batch数据的mean和variance进行更新。 - 在当前batch进行归一化(即使用上述归一化公式)时,使用的均值和方差分别是
running_mean
和running_var
- 这是我们常见的验证和测试时的参数设置,即
training=False, track_running_stats=False
- 此时,就不存在均值
running_mean
和方差running_var
,均值running_mean
和方差running_var
的值为None
,因此,均值running_mean
和方差running_var
就不会跟踪不同batch数据的mean和variance进行更新; - 当前batch进行归一化(即使用上述归一化公式)时,使用的均值是当前batch的均值,方差是当前batch的有偏样本方差(分母是N)
- 跟
training=True, track_running_stats=False
情况相同
- 此时,就不存在均值
参考博客
[1] https://zhuanlan.zhihu.com/p/259160576
[2] https://blog.csdn.net/weixin_39228381/article/details/107896863#BatchNorm1d%E8%AE%AD%E7%BB%83%E6%97%B6%E5%89%8D%E5%90%91%E4%BC%A0%E6%92%AD
[3] https://www.zhihu.com/question/282672547
详解Pytorch中的requires_grad、叶子节点与非叶子节点、with torch.no_grad()、model.eval()、model.train()、BatchNorm层相关推荐
- python中squeeze函数_详解pytorch中squeeze()和unsqueeze()函数介绍
squeeze的用法主要就是对数据的维度进行压缩或者解压. 先看torch.squeeze() 这个函数主要对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的 ...
- tensor torch 构造_详解Pytorch中的网络构造
背景 在PyTroch框架中,如果要自定义一个Net(网络,或者model,在本文中,model和Net拥有同样的意思),通常需要继承自nn.Module然后实现自己的layer.比如,在下面的示例中 ...
- 详解PyTorch中的ModuleList和Sequential
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者丨小占同学@知乎(已授权) 来源丨https://zhuanla ...
- 详解pytorch中的常见的Tensor数据类型以及类型转换
文章目录 概览 Tensor的构建 补充 类型转换 附录 概览 本文主要讲pytorch中的常见的Tensor数据类型,例如:float32,float64,int32,int64.构造他们分别使用如 ...
- 收藏 | 详解PyTorch中的ModuleList和Sequential
点上方计算机视觉联盟获取更多干货 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:作者丨小占同学@知乎(已授权) 来源丨https://zhuanlan.zhihu.com/p/7520666 ...
- 详解PyTorch中的contiguous
目录 前言 PyTorch中的is_contiguous是啥? 行优先 为什么需要 contiguous ? 为什么不在view 方法中默认调用contiguous方法? 前言 contiguous ...
- 一文详解Pytorch中的优化器Optimizer
本文将结合源码与代码示例详细解析Optimizer的五大方法. 1. 前言 优化器主要用在模型训练阶段,用于更新模型中可学习的参数.torch.optim提供了多种优化器接口,比如Adam.RAdam ...
- 详解PyTorch中的copy_()函数、detach()函数、detach_()函数和clone()函数
参考链接: copy_(src, non_blocking=False) → Tensor 参考链接: detach() 参考链接: detach_() 参考链接: clone() → Tensor ...
- 一文详解pytorch的“动态图”与“自动微分”技术
前言 众所周知,Pytorch是一个非常流行且深受好评的深度学习训练框架.这与它的两大特性"动态图"."自动微分"有非常大的关系."动态图" ...
最新文章
- 一些关于“数据挖掘介”技术的有用文档
- Apache Camel简化SOA实施进程
- android 代码 日历 重复事件设置,日历重复/重复事件 - 最佳存储方法
- ASP.NET Core on K8S学习初探(3)部署API到K8S
- C++:18---函数模板(template)
- 百度AI快车道深圳专场,揭秘CV目标检测核心技术
- 40 行代码搞定主题词提取
- WindStyle ExifInfo for Windows Live Writer发布
- hmcl手机版下载_【HMCL启动器下载】HMCL我的世界启动器电脑版 v3.2.144 最新版-开心电玩...
- 直流电机、减速器、编码器与TB6612FNG知识整理
- Python学习笔记(六)函数(Function)
- ios逆向工具theos安装和使用tweak替换和卸载
- powerbuilder的dw中使用graph风格,当横轴是日期时,如何显示才能完整显示日期?
- 解决电脑蓝牙可以连接手机电脑等设备却无法连接到耳机的问题
- 唠唠 U盘格式 (Normal:FAT32 NTFS exFAT)以及U盘格式化选什么格式好???
- 高通平台开发系列讲解(充电篇)充电管理芯片PM7250B详解
- SSD固态硬盘能否恢复--争议
- 文献阅读笔记-CSC-数据集-A Hybrid Approach to Automatic Corpus Generation for Chinese Spelling Check
- (英文版)吴恩达机器学习第三周笔记
- ceph报“mon node3 is low on available space”
热门文章
- SpringMVC基础三
- 记录Pytorch在Linux环境下安装出现的pillow相关问题解决
- power supply frameware 框架
- 小身材也有强劲性能,树莓派2代B型图形界面搞机
- SQL DATENAME(month,getdate())返回的数据为英文日期及把日期转为字符去比较的性能问题
- 511遇见易语言流程控制返回和结束和销毁
- lucene geohash 在外卖场景中,商家不规则多边形配送范围技术应用
- [GXYCTF2019]BabySQli
- 飞腾CPU服务器系统安装问题
- nacos问题: Load balancer does not have available server for client:xxx解决办法