二、模型的修改/参数固定/与模型添加层
1、网络模型增添/继承修改
pytorch中修改网络(增减层,修改层参数)_sequential修改类别数-CSDN博客
1.1、resnet50重构
import torch
import torch.nn as nn
from torch.nn import functional as F
class ResNet50BasicBlock(nn.Module):
def __init__(self, in_channel, outs, kernerl_size, stride, padding):
super(ResNet50BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channel, outs[0], kernel_size=kernerl_size[0], stride=stride[0], padding=padding[0])
self.bn1 = nn.BatchNorm2d(outs[0])
self.conv2 = nn.Conv2d(outs[0], outs[1], kernel_size=kernerl_size[1], stride=stride[0], padding=padding[1])
self.bn2 = nn.BatchNorm2d(outs[1])
self.conv3 = nn.Conv2d(outs[1], outs[2], kernel_size=kernerl_size[2], stride=stride[0], padding=padding[2])
self.bn3 = nn.BatchNorm2d(outs[2])
def forward(self, x):
out = self.conv1(x)
out = F.relu(self.bn1(out))
out = self.conv2(out)
out = F.relu(self.bn2(out))
out = self.conv3(out)
out = self.bn3(out)
return F.relu(out + x)
class ResNet50DownBlock(nn.Module):
def __init__(self, in_channel, outs, kernel_size, stride, padding):
super(ResNet50DownBlock, self).__init__()
# out1, out2, out3 = outs
# print(outs)
self.conv1 = nn.Conv2d(in_channel, outs[0], kernel_size=kernel_size[0], stride=stride[0], padding=padding[0])
self.bn1 = nn.BatchNorm2d(outs[0])
self.conv2 = nn.Conv2d(outs[0], outs[1], kernel_size=kernel_size[1], stride=stride[1], padding=padding[1])
self.bn2 = nn.BatchNorm2d(outs[1])
self.conv3 = nn.Conv2d(outs[1], outs[2], kernel_size=kernel_size[2], stride=stride[2], padding=padding[2])
self.bn3 = nn.BatchNorm2d(outs[2])
self.extra = nn.Sequential(
nn.Conv2d(in_channel, outs[2], kernel_size=1, stride=stride[3], padding=0),
nn.BatchNorm2d(outs[2])
)
def forward(self, x):
x_shortcut = self.extra(x)
out = self.conv1(x)
out = self.bn1(out)
out = F.relu(out)
out = self.conv2(out)
out = self.bn2(out)
out = F.relu(out)
out = self.conv3(out)
out = self.bn3(out)
return F.relu(x_shortcut + out)
class ResNet50(nn.Module):
def __init__(self):
super(ResNet50, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = nn.Sequential(
ResNet50DownBlock(64, outs=[64, 64, 256], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]),
ResNet50BasicBlock(256, outs=[64, 64, 256], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]),
ResNet50BasicBlock(256, outs=[64, 64, 256], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]),
)
self.layer2 = nn.Sequential(
ResNet50DownBlock(256, outs=[128, 128, 512], kernel_size=[1, 3, 1], stride=[1, 2, 1, 2], padding=[0, 1, 0]),
ResNet50BasicBlock(512, outs=[128, 128, 512], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]),
ResNet50BasicBlock(512, outs=[128, 128, 512], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0]),
ResNet50DownBlock(512, outs=[128, 128, 512], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1], padding=[0, 1, 0])
)
self.layer3 = nn.Sequential(
ResNet50DownBlock(512, outs=[256, 256, 1024], kernel_size=[1, 3, 1], stride=[1, 2, 1, 2], padding=[0, 1, 0]),
ResNet50BasicBlock(1024, outs=[256, 256, 1024], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1],
padding=[0, 1, 0]),
ResNet50BasicBlock(1024, outs=[256, 256, 1024], kernerl_size=[1, 3, 1], stride=[1, 1, 1, 1],
padding=[0, 1, 0]),
ResNet50DownBlock(1024, outs=[256, 256, 1024], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1],
padding=[0, 1, 0]),
ResNet50DownBlock(1024, outs=[256, 256, 1024], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1],
padding=[0, 1, 0]),
ResNet50DownBlock(1024, outs=[256, 256, 1024], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1],
padding=[0, 1, 0])
)
self.layer4 = nn.Sequential(
ResNet50DownBlock(1024, outs=[512, 512, 2048], kernel_size=[1, 3, 1], stride=[1, 2, 1, 2],
padding=[0, 1, 0]),
ResNet50DownBlock(2048, outs=[512, 512, 2048], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1],
padding=[0, 1, 0]),
ResNet50DownBlock(2048, outs=[512, 512, 2048], kernel_size=[1, 3, 1], stride=[1, 1, 1, 1],
padding=[0, 1, 0])
)
self.avgpool = nn.AvgPool2d(kernel_size = 7,stride=1,ceil_mode=False)
# self.avgpool = nn.AdaptiveAvgPool2d(output_size=(1, 1))
self.fc = nn.Linear(2048, 10)
# 使用卷积代替全连接
self.conv11=nn.Conv2d(2048, 10, kernel_size=1, stride=1, padding=0)
def forward(self, x):
out = self.conv1(x)
out = self.maxpool(out)
out = self.layer1(out)
out = self.layer2(out)
out = self.layer3(out)
out = self.layer4(out)
out = self.avgpool(out)
out=self.conv11(out)
out = out.reshape(x.shape[0], -1)
# out = self.fc(out)
return out
if __name__ == '__main__':
x = torch.randn(1, 3, 224, 224)
net = ResNet50()
out = net(x)
print('out.shape: ', out.shape)
print(out)
输出索引:
net = ResNet50()
print(net.layer1[0])
# 输出
ResNet50DownBlock(
(conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1))
(bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))
(bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(extra): Sequential(
(0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1))
(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
首先加载ResNet50模型,如果如果需要加载模型本身的参数,需要使用pretrained=True,代码如下
import torchvision
from torchvision import models
resnet50 = models.resnet50(pretrained=True) #pretrained=True 加载模型以及训练过的参数
print(resnet50) # 打印输出观察一下resnet50到底是怎么样的结构
打印输出后ResNet50部分结构如下图,其中红框的全连接层是需要关注的点。全连接层中,“resnet50” 的out_features=1000,这也就是说可以进行class=1000的分类。
1.2、自定义网络模型
首先加载ResNet50模型,如果如果需要加载模型本身的参数,需要使用pretrained=True,代码如下
import torchvision
from torchvision import models
resnet50 = models.resnet50(pretrained=True) #pretrained=True 加载模型以及训练过的参数
print(resnet50) # 打印输出观察一下resnet50到底是怎么样的结构
那么对于网络的修改怎样可以快速的去除model本身的网络层呢?
去除后两层
resnet_layer = nn.Sequential(*list(model.children())[:-2])
一个继承nn.module的model它包含一个叫做children()的函数,这个函数可以用来提取出model每一层的网络结构,在此基础上进行修改即可,修改方法如下(去除后两层):
class Net(nn.Module):
def __init__(self , model): #此处的model参数是已经加载了预训练参数的模型,方便继承预训练成果
super(Net, self).__init__()
#取掉model的后两层
self.resnet_layer = nn.Sequential(*list(model.children())[:-2])
self.transion_layer = nn.ConvTranspose2d(2048, 2048, kernel_size=14, stride=3)
self.pool_layer = nn.MaxPool2d(32)
self.Linear_layer = nn.Linear(2048, 8)
def forward(self, x):
x = self.resnet_layer(x)
x = self.transion_layer(x)
x = self.pool_layer(x)
x = x.view(x.size(0), -1)
x = self.Linear_layer(x)
return x
1.3、自定义模块如何添加到网络
引用:7.6. 残差网络(ResNet) — 动手学深度学习 2.0.0 documentation (d2l.ai)
残差快实现如下:
import torch
from torch import nn
from torch.nn import functional as F
from d2l import torch as d2l
class Residual(nn.Module): #@save
def __init__(self, input_channels, num_channels,
use_1x1conv=False, strides=1):
super().__init__()
self.conv1 = nn.Conv2d(input_channels, num_channels,
kernel_size=3, padding=1, stride=strides)
self.conv2 = nn.Conv2d(num_channels, num_channels,
kernel_size=3, padding=1)
if use_1x1conv:
self.conv3 = nn.Conv2d(input_channels, num_channels,
kernel_size=1, stride=strides)
else:
self.conv3 = None
self.bn1 = nn.BatchNorm2d(num_channels)
self.bn2 = nn.BatchNorm2d(num_channels)
def forward(self, X):
Y = F.relu(self.bn1(self.conv1(X)))
Y = self.bn2(self.conv2(Y))
if self.conv3:
X = self.conv3(X)
Y += X
return F.relu(Y)
ResNet的前两层跟之前介绍的GoogLeNet中的一样: 在输出通道数为64、步幅为2的7×7卷积层后,接步幅为2的3×3的最大汇聚层。 不同之处在于ResNet每个卷积层后增加了批量规范化层
b1 = nn.Sequential(nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
nn.BatchNorm2d(64), nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
下面我们来实现这个模块。注意,我们对第一个模块做了特别处理。
def resnet_block(input_channels, num_channels, num_residuals,
first_block=False):
blk = []
for i in range(num_residuals):
if i == 0 and not first_block:
blk.append(Residual(input_channels, num_channels,
use_1x1conv=True, strides=2))
else:
blk.append(Residual(num_channels, num_channels))
return blk
接着在ResNet加入所有残差块,这里每个模块使用2个残差块
b2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))
b3 = nn.Sequential(*resnet_block(64, 128, 2))
b4 = nn.Sequential(*resnet_block(128, 256, 2))
b5 = nn.Sequential(*resnet_block(256, 512, 2))
最后,与GoogLeNet一样,在ResNet中加入全局平均汇聚层,以及全连接层输出。
net = nn.Sequential(b1, b2, b3, b4, b5,
nn.AdaptiveAvgPool2d((1,1)),
nn.Flatten(), nn.Linear(512, 10))
1.4、共享参数
python 中的类的类方法参数self_python类定义中每个成员方法都必须要有一个self参数,但在调用该成员方法时不必为-CSDN博客
传入类中的self修饰的参数为共享参数,另一个类中使这个参数为类的私有属性
用文心一言解析
class MetaTrainer(object):
"""The class that contains the code for the meta-train phase and meta-eval phase.包含元训练阶段和元评估阶段代码的类"""
def __init__(self, args):
# Set the folder to save the records and checkpoints 设置文件夹以保存记录和检查点
log_base_dir = './logs/'
if not osp.exists(log_base_dir):
os.mkdir(log_base_dir)
meta_base_dir = osp.join(log_base_dir, 'meta')
if not osp.exists(meta_base_dir):
os.mkdir(meta_base_dir)
save_path1 = '_'.join([args.dataset, args.model_type, 'MTL']) # 这是使用 Python 的 join 方法将一个列表中的元素连接起来,并使用下划线 _ 作为分隔符
save_path2 = 'shot' + str(args.shot) + '_way' + str(args.way) + '_query' + str(args.train_query) + \
'_step' + str(args.step_size) + '_gamma' + str(args.gamma) + '_lr1' + str(args.meta_lr1) + '_lr2' + str(args.meta_lr2) + \
'_batch' + str(args.num_batch) + '_maxepoch' + str(args.max_epoch) + \
'_baselr' + str(args.base_lr) + '_updatestep' + str(args.update_step) + \
'_stepsize' + str(args.step_size) + '_' + args.meta_label
args.save_path = meta_base_dir + '/' + save_path1 + '_' + save_path2
ensure_path(args.save_path)
# Set args to be shareable in the class 将参数设置为可在类中共享
self.args = args
# Load meta-train set 加载元训练集
self.trainset = Dataset('train', self.args) # 传入self参数 传入共享属性
self.train_sampler = CategoriesSampler(self.trainset.label, self.args.num_batch, self.args.way, self.args.shot + self.args.train_query)
self.train_loader = DataLoader(dataset=self.trainset, batch_sampler=self.train_sampler, num_workers=8, pin_memory=True)
1.5、模型函数
1.self.module
# 遍历self.module() :nn.Module类方法初始化模型权重
for m in self.modules(): # 首先来讲一下nn.Module类中的一个方法:self.modules(), 他会返回该网络中的所有modules.
if isinstance(m, self.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
2.tqdm
tqdmtqdm进度条 在pytorch中的使用_tqdm dataloader-CSDN博客tqdm
用在dataloader上其实是对每个batch和batch总数做的进度条,我也是在训练比较慢时写出来看看训练到哪了
【python第三方库】tqdm——超详细解读-CSDN博客
训练深度学习模型
train_dataloader = DataLoader(training_data,batch_size=64) #64张图片为一个包
# 模型训练
# 定义训练的轮数,即迭代次数
epochs = 5
# 导入进度条模块,tqdm可以让我们在训练过程中看到每个epoch的进度
from tqdm import tqdm
# 循环进行指定轮数的训练
for epoch in range(epochs):
# for data,targets in tqdm(train_loadr,leave=False) # 进度显示在一行
for data,targets in tqdm(train_dataloader):
# 将数据移动到指定设备,如果可能的话。例如,如果你使用GPU进行计算,这将会把数据移到GPU
# 上。
data = data.to(device=device)
targets = targets.to(device=device)
# 正向传播,模型对输入的数据进行计算,得到预测的结果
scores = model(data)
# 计算损失,这个损失是模型预测的结果与实际目标之间的差距
loss = loss_fn(scores,targets)
# 反向传播,根据损失计算出梯度,这个过程是在每个训练步骤中计算损失对模型参数的梯度
optimizer.zero_grad() # 清空之前的梯度缓存
loss.backward() # 计算梯度
# 使用优化器更新模型参数,这个过程是根据前面计算的梯度来更新模型参数,实现下降学习。
optimizer.step() # 使用优化器更新模型参数
元学习应用tqdm,,下面的batch 装载了样本和标签两个对象。
# Using tqdm to read samples from train loader 用tqdm读取装载机样本
tqdm_gen = tqdm.tqdm(self.train_loader) # 数据加载器
for i, batch in enumerate(tqdm_gen, 1):
# Update global count number 更新全局计数
global_count = global_count + 1
if torch.cuda.is_available():
data, _ = [_.cuda() for _ in batch]
else:
data = batch[0] # batch[0] 为数据那一类,batch[1] 为表外你那一类
p = self.args.shot * self.args.way
data_shot, data_query = data[:p], data[p:]
# Output logits for model 输出模型的logits
logits = self.model((data_shot, label_shot, data_query))
# Calculate meta-train loss
loss = F.cross_entropy(logits, label)
# Calculate meta-train accuracy
3、torch.autograd.grad
手动更新参数
一文解释 PyTorch求导相关 (backward, autograd.grad) - 知乎 (zhihu.com)
grad = torch.autograd.grad(loss, self.base_learner.parameters())
# 自动更新学习率
fast_weights = list(map(lambda p: p[1] - self.update_lr * p[0], zip(grad,self.base_learner.parameters())))
logits_q = self.base_learner(embedding_query, fast_weights)
4、argparse
Python系列之:argparse和vars_vars(args)-CSDN博客
import argparse
#第1步:使用argparse首先创建一个ArgumentParser对象
parser = argparse.ArgumentParser(description='Ods dependency check')
#第2步:添加变量
parser.add_argument('-value', default="true", help="enable check or not", choices=['true', 'false'])
parser.add_argument('-config', help="path of config json file")
parser.add_argument('-server', help="debezium database server name")
parser.add_argument('-time',help="data end time str")
#第3步:解析输入变量
args = parser.parse_args()
print(args)
#Namespace(value='true', config=None, server=None, time=None)
print(args.value)
#true
print(args.config)
#None
print(args.server)
#None
print(args.time)
#None
#vars() 函数返回对象object的属性和属性值的字典对象。
args = vars(parser.parse_args())
print(args)
#{'value': 'true', 'config': None, 'server': None, 'time': None}
5、批量标准化
引用:nn.BatchNorm2d——批量标准化操作解读-CSDN博客
torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1,
affine=True, track_running_stats=True, device=None, dtype=None)
2、模型冻结
冻结层:
[ pytorch ] 基本使用丨3. finetune冻结层操作 + 学习率超参数设置丨_finetune 怎么设置-CSDN博客
2.1、finetune冻结层操作
【超详细小白必懂】Pytorch 直接加载ResNet50模型和参数实现迁移学习_torchvision.models.resnet50_Dukixytapoo.的博客-CSDN博客
由于我们正常所使用的分类场景大概率与resnet50的分类数不一样,所以在调用时,要使用out_features=分类数进行调整。假设我们采用CIFAR10数据集(10 class)进行测试,那么我们就需要修改全连接层,out_features=10。具体代码如下
resnet50 = models.resnet50(pretrained=True)
num_ftrs = resnet50.fc.in_features
for param in resnet50.parameters():
param.requires_grad = False #False:冻结模型的参数,也就是采用该模型已经训练好的原始参数。只需要训练我们自己定义的Linear层
#保持in_features不变,修改out_features=10
resnet50.fc = nn.Sequential(nn.Linear(num_ftrs,10),
nn.LogSoftmax(dim=1))
3、模型的保存与加载
3.1、模型的保存
如何将Python训练好的模型保存下来(可使用or继续训练)_python训练好的模型保存调用-CSDN博客
1、使用pickle保存
[ pytorch ] 基本使用丨2. 训练好的模型参数的保存以及调用丨_训练结束后怎么调用参数矩阵-CSDN博客
pickle是Python标准库中的一个模块,它可以将Python对象序列化为二进制格式,以便于存储和传输。可以使用pickle将训练好的模型保存到磁盘上,以备将来使用
# 1、保存模型
import pickle
# train the model
model = ...
# save the model
with open('my_model.pkl', 'wb') as f:
pickle.dump(model, f)
# 2、加载模型
import pickle
# load the saved model
with open('my_model.pkl', 'rb') as f:
model = pickle.load(f)
# predict using the loaded model
model.predict(X)
# 3、加载模型训练
import pickle
# load the saved model
with open('my_model.pkl', 'rb') as f:
model = pickle.load(f)
# continue training the model
model.fit(X_train, y_train)
# save the updated model
with open('my_updated_model.pkl', 'wb') as f:
pickle.dump(model, f)
2、使用joblib-大模型
joblib是一个用于将Python对象序列化为磁盘文件的库,专门用于 大型数组。它可以高效地处理大型数据集和模型。对于大型机器学习模型
,使用joblib可能比pickle更快
保存模型
import joblib
# train the model
model = ...
# save the model
joblib.dump(model, 'my_model.joblib')
加载模型
import joblib
# load the saved model
model = joblib.load('my_model.joblib')
# predict using the loaded model
model.predict(X)
继续训练模型
import joblib
# load the saved model
model = joblib.load('my_model.joblib')
# continue training the model
model.fit(X_train, y_train)
# save the updated model
joblib.dump(model, 'my_updated_model.joblib')
3、使用HDF5-保存米星(保存权重)
HDF5是一种用于存储大型科学数据集的文件格式,常用于存储深度学习模型的权重
。
3.2、模型与模型参数保存
1、模型参数保存
引用:(42 封私信 / 51 条消息) Pytorch训练结束后保存模型参数,接着再加载这个模型参数,继续训练但是训练效果变差很多? - 知乎 (zhihu.com)
原因:因为你加载后,如果仅恢复模型权重,而忽视了其他超参数等。此时的训练不能认为和中断前的是同一次训练,在恢复初期loss很可能会升高,并且有可能会错过解空间的局部最优值。
需要注意到,torch.save函数时可以将你想要保存的东西都存在dict中,保存到磁盘的。所以,针对这种情形,在保存的时候不要只保存模型参数,还应该保存优化器参数。参见以下代码
看上述链接评论
作者:Yichao Cai
链接:https://www.zhihu.com/question/482169025/answer/2081124014
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
net = ResNet()
loss = MSE()
optimizer = torch.optim.SGD(net.parameters(), lr=0.001)
"""
正常训练的代码
"""
net.train()
for epoch in range(total_epochs):
...
for x, y in dataloader:
...
loss = ...
loss.backward()
optimizer.step()
state_dict = {"net": net.state_dict(), "optimizer": optimizer.state_dict(), "epoch": epoch}
torch.save(state_dict, "model_path/model.pth")
"""
中断后,加载权重继续训练
"""
checkpoint = torch.load("model_path/model.pth")
current_epoch = checkpoint["epoch"]
net.load_state_dict(checkpoint['net'])
optimizer.load_state_dict(checkpoint['optimizer'])
net.train()
for epoch in range(current_epoch , total_epochs):
...
for x, y in dataloader:
...
loss = ...
loss.backward()
optimizer.step()
state_dict = {"net": net.state_dict(), "optimizer": optimizer.state_dict(), "epoch": epoch}
torch.save(state_dict, "model_path/model.pth")
模型参数保存与加载的
3.3、模型权重与偏置
4.2. 多层感知机的从零开始实现 — 动手学深度学习 2.0.0 documentation (d2l.ai)
4、不同层学习率的设置
在深度学习中,几乎所有的神经网络层都可以设置学习率,包括卷积层、池化层、全连接层等。这些层通常都使用梯度下降法进行优化,因此学习率是优化过程中一个重要的超参数。
对于卷积层和池化层,它们是深度学习中常用的两种特征提取层,通常被用于图像处理和计算机视觉任务中。这些层的参数更新速度可以通过学习率来控制。学习率的值决定了每次更新参数的步长大小,如果学习率设置得过大,参数更新步长也会过大,可能导致模型训练不稳定;如果学习率设置得过小,参数更新步长也会过小,可能导致模型训练速度变慢。
4.1、所有层学习率设置
举例
optimizer = optim.SGD(net.parameters(), lr=0.001 )
4.2、不同层学习率举例
Pytorch不同层设置不同学习率_pytorch不同参数设置不同的学习率_呆呆象呆呆的博客-CSDN博客
4.3、学习率动态调整
5、不同层优化器设置
6、权重初始化
深入浅出Pytorch函数——torch.nn.init.kaiming_normal_-CSDN博客
6.1、自定义模型初始化
class ResNetMtl(nn.Module):
def __init__(self, layers=[4, 4, 4], mtl=True):
super(ResNetMtl, self).__init__()
if mtl:
self.Conv2d = Conv2dMtl
block = BasicBlockMtl
else:
self.Conv2d = nn.Conv2d
block = BasicBlock
cfg = [160, 320, 640]
self.inplanes = iChannels = int(cfg[0]/2)
self.conv1 = self.Conv2d(3, iChannels, kernel_size=3, stride=1, padding=1)
self.bn1 = nn.BatchNorm2d(iChannels)
self.relu = nn.ReLU(inplace=True)
self.layer1 = self._make_layer(block, cfg[0], layers[0], stride=2)
self.layer2 = self._make_layer(block, cfg[1], layers[1], stride=2)
self.layer3 = self._make_layer(block, cfg[2], layers[2], stride=2)
self.avgpool = nn.AvgPool2d(10, stride=1)
# 遍历self.module() :nn.Module类方法初始化模型权重
for m in self.modules(): # 首先来讲一下nn.Module类中的一个方法:self.modules(), 他会返回该网络中的所有modules.
if isinstance(m, self.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
6.2、不同层模型初始化
7、环境导入导出
7.1、anaconda环境到处
Anaconda 中使用 conda 配置虚拟环境与管理安装包 - 知乎 (zhihu.com)
先进入这个环境
7.2. 导出或导入至 txt 文件
(1)使用 pip 导出/导入至 txt:
用 pip 导出:(可导出 package 准确版本号)
python -m pip freeze > requirements.txt
注意:pip 导出只适用于该环境中的 packages 都是用 pip 安装的情况。 如果其中有用 conda 安装的 package,可以导出,但是之后要从这个 requirements.txt 导入虚拟环境,就会报错,无法安装。
pip list --format=freeze > requirements.txt
# 导出
用 pip 导入:
注意:该虚拟环境要有 pip。没有的话,先安装 pip: conda install pip
,然后:
python -m pip install -r requirements.txt
requirements中的@file问题怎么解决_python requirements file_爱学习的贝塔的博客-CSDN博客
pip list --format=freeze > requirements.txt
(2)使用 conda 导出/导入至 txt:
用 conda 导出:conda list --explicit > pkgs.txt
注意:conda 导出到 txt文件的是 用 conda 安装的 packages 对应的下载链接,而用 pip 安装的 packges 不会导出。
用 conda 导入:(在 base 环境中运行)
conda create -n NEWENV --file pkgs.txt
可以看到,这个语句就是在 conda create -n NEWENV
的基础上加上了 packages 的安装配置,也就是用 conda 新建虚拟环境,同时通过 pkgs.txt 的链接,下载安装其中的 packages。
看到这里你可能要问,用 pip 或 conda 导出虚拟环境到 txt 文件,都分别只适用于只有 pip 安装包或只有 conda 安装包的情形。如果环境中既有 conda 安装、又有 pip 安装的 packages,应该怎么办呢?
方法就是导出为 yml 文件。前面介绍使用 conda 导出虚拟环境到 yml 文件时,举了一个例子:导出安装有NumPy(conda 安装)和 see(pip 安装)的虚拟环境至 yml 文件。yml 文件中会包含 NumPy 和 see 的配置,可以从该 yml 文件导入生成名为 ENVNAME 的虚拟环境。
7.3、环境导入
Anaconda 虚拟环境创建、激活、删除、导入/导出_anaconda导入环境_老板来碗小面加蛋~的博客-CSDN博客
Anaconda创建、激活、退出、删除环境及管理环境中的包相关命令——最新全面直观版_anaconda退出环境指令_寒冢人家的博客-CSDN博客
8、环境安装
anaconda环境