深度学习-模型相关(一)

 二、模型的修改/参数固定/与模型添加层

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环境

8.1、anaconda环境安装

8.2、cuda环境安装

8.3、cudnn加速器安装

8.4、pytorch安装

8.5、tensorflow安装

8.6、d2l 安装

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值