精华内容
下载资源
问答
  • 预训练参数
    千次阅读
    2019-07-14 11:29:04

    1.在没有改变原网络结构的情况下

    model = resnet50()
    model = model.load_state_dict(torch.load('model.pth'))

    torch.load('model.pth')会把网络参数加载到一个有序字典当中, 然后把这个有序字典传递给model.load_state_dict()。

    2.在只改变原网络结构的某一层或某几层的情况下

    在不同的实际需求下,我们通常要对网络结构进行修改,比如ResNet50原来对1000个类别进行分类,而我们的任务只有10类的话,我们就要修改ResNet50的全连接层。而其它层不变,这时我们就可以通过加载预训练的网络参数来加速训练过程,提高准确率。

    方法1:

    # 将原始网络结构与修改后网络结构相同的键值对放到一个有序字典当中,不相同的键值对则被删除
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model.state_dict()}
    # 将这个有序字典传给load_state_dict
    model.load_state_dict(pretrained_dict)

    方法2:

    model.load_state_dict(pretrained_dict, strict=False)

    strict参数控制是否要求传入的有序字典是否与model的有序字典完全相同,若为False,则会加载相同的键的值,若为True,只要有一个不同的地方都会报错。

    3. 在网络结构被魔改的情况下

    首先说一下“魔改”的定义:网络结构得到了不同的封装,比如原网络结构是很多卷积层被放到同一个nn.sequential当中,而现在这些卷积层被放到了不同的nn.sequential当中(顺序没变),这使得储放网络参数的有序字典的键值发生变化,但实际上如果网络结构没有变的话,第二种情况就没法用了。但通过仔细的对前面Pytorch加载预训练参数的观察下,我们发现,我们只要将要加载的预训练参数放到一个有序字典当中就行了。

    net_path_PRE = 'pretrained/model.pth'
    pretrained_model = pretrain_model()
    pretrained_model.load_state_dict(torch.load(net_path_PRE))
    pretrained_dict = pretrained_model.state_dict()
    
    model_dict = model.state_dict()
    model_keys = []
    
    for k, v in model_dict.items():
        model_keys.append(k)
    
    # 我的网络只在原网络结构的后面添加了一些卷积层,而前面的网络被nn.sequential重新封装,
    # 所以前面的预训练参数完封不动的加载到我的网络当中
    i = 0
    for k, v in pretrained_dict.items():
        model_dict[model_keys[i]] = v
        i += 1
    
    self.net.load_state_dict(model_dict)

    4. 如果网络用到了多GPU训练,这种情况保存的网络参数加载时要通过以下代码加载

    net_path = 'pretrained/model_e48.pth'
    if net_path is not None:
        checkpoint1 = torch.load(net_path)
        new_state_dict = OrderedDict()
        for k, v in checkpoint1['model_state_dict'].items():
            name = k[7:]  # 多GPU训练保存的net的有序字典的键会多出《'modle.》七个字符,所以要去掉
            new_state_dict[name] = v
        self.net.load_state_dict(new_state_dict)

    总结:可能还有其它各种各样的情况,万能公式就是:想办法把要加载的预训练参数放到有序字典,并传给model.load_state_dict

    更多相关内容
  • 今天主要主要谈谈Pytorch是如何加载预训练模型的参数以及代码的实现过程。 直接加载预选脸模型 如果我们使用的模型和预训练模型完全一样,那么我们就可以直接加载别人的模型,还有一种情况,我们在训练自己模型的...
  • VGG16预训练参数(VGG16_pretrained)
  • 三位从Mask R-CNN就开始合作的大神搭档,刚刚再次联手,一文“终结”了ImageNet预训练时代。 他们所针对的是当前计算机视觉研究中的一种常规操作:管它什么任务,拿来ImageNet预训练模型,迁移学习一下。 但是,...

    何恺明,RBG,Piotr Dollár。

    三位从Mask R-CNN就开始合作的大神搭档,刚刚再次联手,一文“终结”了ImageNet预训练时代。

    他们所针对的是当前计算机视觉研究中的一种常规操作:管它什么任务,拿来ImageNet预训练模型,迁移学习一下。

    但是,预训练真的是必须的吗?

    这篇重新思考ImageNet预训练(Rethinking ImageNet Pre-training)就给出了他们的答案。

    FAIR(Facebook AI Research)的三位研究员从随机初始状态开始训练神经网络,然后用COCO数据集目标检测和实例分割任务进行了测试。结果,丝毫不逊于经过ImageNet预训练的对手。

    甚至能在没有预训练、不借助外部数据的情况下,和COCO 2017冠军平起平坐。

    结果

    训练效果有图有真相。

    他们用2017版的COCO训练集训练了一个Mask R-CNN模型,基干网络是用了群组归一化(GroupNorm)的ResNet-50 FPN。
    在这里插入图片描述
    随后,用相应的验证集评估随机权重初始化(紫色线)和用ImageNet预训练后再微调(灰色线)两种方法的边界框平均检测率(AP)。

    可以看出,随机权重初始化法开始不及预训练方法效果好,但随着迭代次数的增加,逐渐达到了和预训练法相当的结果。

    为了探索多种训练方案,何恺明等人尝试了在不同的迭代周期降低学习率。

    结果显示,随机初始化方法训练出来的模型需要更多迭代才能收敛,但最终收敛效果不比预训练再微调的模型差。

    主干网络换成ResNet-101 FPN,这种从零开始训练的方法依然呈现出一样的趋势:从零开始先是AP不及预训练法,多次迭代后两者终趋于不分上下。
    在这里插入图片描述
    效果究竟能有多好?答案前面也说过了,和COCO 2017冠军选手平起平坐。

    从零开始模型的效果,由COCO目标检测任务来证明。在2017版验证集上,模型的bbox(边界框)和mask(实例分割)AP分别为50.9和43.2;

    他们还在2018年竞赛中提交了这个模型,bbox和mask AP分别为51.3和43.6。
    在这里插入图片描述
    这个成绩,在没有经过ImageNet预训练的单模型中是最好的。

    这是一个非常庞大的模型,使用了ResNeXt-152 8×32d基干,GN归一化方法。从这个成绩我们也能看出,这个大模型没有明显过拟合,非常健壮(robust)。

    实验中,何恺明等人还用ImageNet预训练了同样的模型,再进行微调,成绩没有任何提升。

    这种健壮性还有其他体现。

    比如说,用更少的数据进行训练,效果还是能和预训练再微调方法持平。何恺明在论文中用**“Even more surprising”**来形容这个结果。

    当他们把训练图像数量缩减到整个COCO数据集的1/3(35000张图)、甚至1/10(10000张图)时,经过多次迭代,随机初始化看起来还略优于预训练法的效果。
    在这里插入图片描述
    不过,10000张图已经是极限,继续降低数据量就不行了。当他们把训练数据缩减到1000张图片,出现了明显的过拟合。

    怎样训练?

    想抛弃ImageNet预训练,用不着大动干戈提出个新架构。不过,两点小改动在所难免。

    第一点是模型的归一化方法,第二点是训练长度。

    我们先说模型归一化(Normalization)。

    因为目标检测任务的输入数据通常分辨率比较高,导致批次大小不能设置得太大,所以,批归一化(Batch Normalization,BN)不太适合从零开始训练目标检测模型。

    于是,何恺明等人从最近的研究中找了两种可行的方法:群组归一化(Group Normalization,GN)和同步批归一化(Synchronized Batch Normalization,SyncBN)。
    在这里插入图片描述
    GN是吴育昕和何恺明合作提出的,发表在ECCV 2018上,还获得了最佳论文荣誉提名。这种归一化方法把通道分成组,然后计算每一组之内的均值和方差。它的计算独立于批次维度,准确率也不受批次大小影响。

    SyncBN则来自旷视的MegDet,和香港中文大学Shu Liu等人的CVPR 2018论文Path Aggregation Network for Instance Segmentation。这是一种跨GPU计算批次统计数据来实现BN的方法,在使用多个GPU时增大了有效批次大小。

    归一化方法选定了,还要注意收敛问题简单说是要多训练几个周期

    道理很简单:你总不能指望一个模型从随机初始化状态开始训练,还收敛得跟预训练模型一样快吧。

    所以,要有耐心,多训练一会儿。
    在这里插入图片描述
    也就是说,要想从随机初始化状态开始训练,要有大量样本。

    到底要不要用ImageNet预训练?

    这篇论文还贴心地放出了从实验中总结的几条结论:

    • 不改变架构,针对特定任务从零开始训练是可行的。
    • 从零开始训练需要更多迭代周期,才能充分收敛。
    • 在很多情况下,甚至包括只用10000张COCO图片,从零开始训练的效果不逊于用ImageNet预训练模型微调。
    • 用ImageNet预训练能加速在目标任务上的收敛。
    • ImageNet预训练未必能减轻过拟合,除非数据量极小。
    • 如果目标任务对定位比识别更敏感,ImageNet预训练的作用较小。

    所以,关于ImageNet预训练的几个关键问题也就有了答案:

    它是必需的吗?并不是,只要目标数据集和计算力足够,直接训练就行。这也说明,要提升模型在目标任务上的表现,收集目标数据和标注更有用,不要增加预训练数据了。

    它有帮助吗?当然有,它能在目标任务上数据不足的时候带来大幅提升,还能规避一些目标数据的优化问题,还缩短了研究周期。

    我们还需要大数据吗?需要,但一般性大规模分类级的预训练数据集就不用了,在目标领域收集数据更有效。

    我们还要追求通用表示吗?依然需要,这还是个值得赞赏的目标。

    想更深入地理解这个问题,请读论文:
    Rethinking ImageNet Pre-training
    Kaiming He,Ross Girshick,PiotrDollár
    https://arxiv.org/abs/1811.08883

    转载:何恺明“终结”ImageNet预训练时代:从0开始训练神经网络,效果比肩COCO冠军

    展开全文
  • pytorch 预训练层的使用方法 将其他地方训练好的网络,用到新的网络里面 加载预训练网络 1.原先已经训练好一个网络 AutoEncoder_FC() 2.首先加载该网络,读取其存储的参数 3.设置一个参数集 cnnpre = AutoEncoder_...
  • pytorch的resnet-18在cifar-10的预训练模型
  • 1. 保存与加载模型参数import tensorflow as tftensorflow的保存和加载是通过tf.train.Saver类实现的, 她的构造函数是def __init__(self, var_list=None, reshape=False, sharded=False, ...

    1. 保存与加载模型参数

    import tensorflow as tf

    tensorflow的保存和加载是通过tf.train.Saver类实现的, 她的构造函数是

    def __init__(self,
                   var_list=None,
                   reshape=False,
                   sharded=False,
                   max_to_keep=5,
                   keep_checkpoint_every_n_hours=10000.0,
                   name=None,
                   restore_sequentially=False,
                   saver_def=None,
                   builder=None,
                   defer_build=False,
                   allow_empty=False,
                   write_version=saver_pb2.SaverDef.V2,
                   pad_step_number=False,
                   save_relative_paths=False):

    其中

    • var_list: 要保存/恢复的变量列表,or dict of names to variables. 如果为空,则默认所有的变量
    • reshape: 当shape不一样时是否允许恢复参数
    • sharded: if True, instructs the saver to shard checkpoints per device.
    • max_to_keep: 最多保存的checkpoints. Defaults to 5. checkpoints的区分在save时传递的global_step参数,用来表示第几次迭代。
    • keep_checkpoint_every_n_hours: How often to keep checkpoints. 每几个hour保留一个checkpoint
    • .....

    保存:saver.save(session, saved_path, global_step=None)

    恢复:saver.restore(session, saved_path) 保存的文件有四种:

    1. checkpoint,保存最近保存的模型的文件名,因此我们能够知道最近的模型名,可以通过调用tf.train.latest_checkpoint(dir)获知
    2. .meta 图的结构,变量等信息
    3. .data 参数值
    4. .index 索引文件

    使用示例:

    tf.reset_default_graph()
    v1=tf.get_variable('v1', shape=[6], dtype=tf.float32, initializer=tf.truncated_normal_initializer())
    v2=tf.get_variable('v2', shape=[6], dtype=tf.float32, initializer=tf.random_normal_initializer())
    
    saver=tf.train.Saver()
    
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        print('v1', sess.run(v1))
        print('v2', sess.run(v2))
        saver.save(sess, 'save/model')
    v1 [ 1.88005733 -0.99327284 -1.19482517 -0.46593472 -0.1329312  -1.63472843]
    v2 [-1.03660548 -1.61874151 -1.5886656   0.45553902 -1.24812245 -0.90952981]
    
    tf.reset_default_graph()
    v1=tf.get_variable('v1', shape=[6], dtype=tf.float32, initializer=tf.truncated_normal_initializer())
    v2=tf.get_variable('v2', shape=[6], dtype=tf.float32, initializer=tf.random_normal_initializer())
    
    saver=tf.train.Saver()
    
    with tf.Session() as sess:
        saver.restore(sess, tf.train.latest_checkpoint('save/'))
        print('v1', sess.run(v1))
        print('v2', sess.run(v2))
        
    INFO:tensorflow:Restoring parameters from save/model
    
    
    INFO:tensorflow:Restoring parameters from save/model
    
    
    v1 [ 1.88005733 -0.99327284 -1.19482517 -0.46593472 -0.1329312  -1.63472843]
    v2 [-1.03660548 -1.61874151 -1.5886656   0.45553902 -1.24812245 -0.90952981]
    

    至此,我们可以简单使用。但是当我们需要加载模型的时候呢,可以使用tf.train.import_meta_graph(), tensor获取通过tf.get_default_graph().get_tensor_by_name('') (不过一般我们都会有原来图的代码,所以一般不会用到。)

    tf.reset_default_graph()
    tf.train.import_meta_graph('save/model.meta')
    saver=tf.train.Saver()
    with tf.Session() as sess:
        saver.restore(sess, 'save/model')
        print(sess.run(tf.get_default_graph().get_tensor_by_name("v1:0")))
    INFO:tensorflow:Restoring parameters from save/model
    [ 1.88005733 -0.99327284 -1.19482517 -0.46593472 -0.1329312  -1.63472843]
    

    介绍完基本使用,接下来如果我们的模型只有一部分是要加载参数时

    tf.reset_default_graph()
    v1=tf.get_variable('v1', shape=[6], dtype=tf.float32, initializer=tf.truncated_normal_initializer())
    v2=tf.get_variable('v2', shape=[6], dtype=tf.float32, initializer=tf.random_normal_initializer())
    v2=tf.get_variable('v3', shape=[6], dtype=tf.float32, initializer=tf.random_normal_initializer())
    
    saver=tf.train.Saver()
    
    with tf.Session() as sess:
        saver.restore(sess, tf.train.latest_checkpoint('save/'))
        print('v1', sess.run(v1))
        print('v2', sess.run(v2))

    这个时候会报NotFoundError (see above for traceback): Key v3 not found in checkpoint 解决办法就是saver初始化要加上要保存的参数列表:

    tf.reset_default_graph()
    v1=tf.get_variable('v1', shape=[6], dtype=tf.float32, initializer=tf.truncated_normal_initializer())
    v2=tf.get_variable('v2', shape=[6], dtype=tf.float32, initializer=tf.random_normal_initializer())
    v2=tf.get_variable('v3', shape=[6], dtype=tf.float32, initializer=tf.random_normal_initializer())
    
    saver=tf.train.Saver([v1, v2])
    
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        print('v1', sess.run(v1))
        print('v2', sess.run(v2))
        saver.save(sess, 'save/model')
        saver.restore(sess, tf.train.latest_checkpoint('save/'))
        print('v1', sess.run(v1))
        print('v2', sess.run(v2))
    v1 [ 0.39415926  0.24765804  1.26394165  0.62132704  1.0527215   1.55297732]
    v2 [ 0.56525308  1.07240736 -0.15881526 -1.1062392  -0.76180184  1.05873036]
    INFO:tensorflow:Restoring parameters from save/model
    v1 [ 0.39415926  0.24765804  1.26394165  0.62132704  1.0527215   1.55297732]
    v2 [ 0.56525308  1.07240736 -0.15881526 -1.1062392  -0.76180184  1.05873036]
    

    现在,当我们想要预训练的时候,就可以将预训练的相关参数放在列表中,然后保存。


    my github: https://github.com/xiaoqinzhe/blog/tree/master/tensorflow/save_load_model

    展开全文
  • 后面增添了如何加载同层的预训练参数以及到底要不要用ImageNet预训练的解析。 1. Pytorch中加入注意力机制 第一步:找到ResNet源代码 在里面添加通道注意力机制和空间注意力机制 通道注意力机制 class ...

    后面增添了如何加载同层的预训练参数以及到底要不要用ImageNet预训练的解析。

    1. Pytorch中加入注意力机制

    第一步:找到ResNet源代码

    在里面添加通道注意力机制和空间注意力机制

    通道注意力机制

    class ChannelAttention(nn.Module):
        def __init__(self, in_planes, ratio=16):
            super(ChannelAttention, self).__init__()
            self.avg_pool = nn.AdaptiveAvgPool2d(1)
            self.max_pool = nn.AdaptiveMaxPool2d(1)
    
            self.fc1   = nn.Conv2d(in_planes, in_planes // 16, 1, bias=False)
            self.relu1 = nn.ReLU()
            self.fc2   = nn.Conv2d(in_planes // 16, in_planes, 1, bias=False)
    
            self.sigmoid = nn.Sigmoid()
    
        def forward(self, x):
            avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))
            max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))
            out = avg_out + max_out
            return self.sigmoid(out)
    

    空间注意力机制

    class SpatialAttention(nn.Module):
        def __init__(self, kernel_size=7):
            super(SpatialAttention, self).__init__()
    
            assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
            padding = 3 if kernel_size == 7 else 1
    
            self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
            self.sigmoid = nn.Sigmoid()
    
        def forward(self, x):
            avg_out = torch.mean(x, dim=1, keepdim=True)
            max_out, _ = torch.max(x, dim=1, keepdim=True)
            x = torch.cat([avg_out, max_out], dim=1)
            x = self.conv1(x)
            return self.sigmoid(x)
    

    在ResNet网络中添加注意力机制

    注意点:因为不能改变ResNet的网络结构,所以CBAM不能加在block里面(也可以加在block里面,此时网络不能加载预训练参数),因为加在block里面网络结构发生了变化,所以不能用预训练参数。加在最后一层卷积和第一层卷积不改变网络,可以用预训练参数。

    class ResNet(nn.Module):
    
        def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,
                     groups=1, width_per_group=64, replace_stride_with_dilation=None,
                     norm_layer=None):
            super(ResNet, self).__init__()
            if norm_layer is None:
                norm_layer = nn.BatchNorm2d
            self._norm_layer = norm_layer
    
            self.inplanes = 64
            self.dilation = 1
            if replace_stride_with_dilation is None:
                # each element in the tuple indicates if we should replace
                # the 2x2 stride with a dilated convolution instead
                replace_stride_with_dilation = [False, False, False]
            if len(replace_stride_with_dilation) != 3:
                raise ValueError("replace_stride_with_dilation should be None "
                                 "or a 3-element tuple, got {}".format(replace_stride_with_dilation))
            self.groups = groups
            self.base_width = width_per_group
            self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
                                   bias=False)
            self.bn1 = norm_layer(self.inplanes)
            self.relu = nn.ReLU(inplace=True)
    
            # 网络的第一层加入注意力机制
            self.ca = ChannelAttention(self.inplanes)
            self.sa = SpatialAttention()
    
            self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
            self.layer1 = self._make_layer(block, 64, layers[0])
            self.layer2 = self._make_layer(block, 128, layers[1], stride=2,
                                           dilate=replace_stride_with_dilation[0])
            self.layer3 = self._make_layer(block, 256, layers[2], stride=2,
                                           dilate=replace_stride_with_dilation[1])
            self.layer4 = self._make_layer(block, 512, layers[3], stride=2,
                                           dilate=replace_stride_with_dilation[2])
            # 网络的卷积层的最后一层加入注意力机制
            self.ca1 = ChannelAttention(self.inplanes)
            self.sa1 = SpatialAttention()
    
            self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
            self.fc = nn.Linear(512 * block.expansion, num_classes)
    
            for m in self.modules():
                if isinstance(m, nn.Conv2d):
                    nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
                    nn.init.constant_(m.weight, 1)
                    nn.init.constant_(m.bias, 0)
    
            # Zero-initialize the last BN in each residual branch,
            # so that the residual branch starts with zeros, and each residual block behaves like an identity.
            # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
            if zero_init_residual:
                for m in self.modules():
                    if isinstance(m, Bottleneck):
                        nn.init.constant_(m.bn3.weight, 0)
                    elif isinstance(m, BasicBlock):
                        nn.init.constant_(m.bn2.weight, 0)
    
        def _make_layer(self, block, planes, blocks, stride=1, dilate=False):
            norm_layer = self._norm_layer
            downsample = None
            previous_dilation = self.dilation
            if dilate:
                self.dilation *= stride
                stride = 1
            if stride != 1 or self.inplanes != planes * block.expansion:
                downsample = nn.Sequential(
                    conv1x1(self.inplanes, planes * block.expansion, stride),
                    norm_layer(planes * block.expansion),
                )
    
            layers = []
            layers.append(block(self.inplanes, planes, stride, downsample, self.groups,
                                self.base_width, previous_dilation, norm_layer))
            self.inplanes = planes * block.expansion
            for _ in range(1, blocks):
                layers.append(block(self.inplanes, planes, groups=self.groups,
                                    base_width=self.base_width, dilation=self.dilation,
                                    norm_layer=norm_layer))
    
            return nn.Sequential(*layers)
    
        def forward(self, x):
            x = self.conv1(x)
            x = self.bn1(x)
            x = self.relu(x)
    
            x = self.ca(x) * x
            x = self.sa(x) * x
    
            x = self.maxpool(x)
    
            x = self.layer1(x)
            x = self.layer2(x)
            x = self.layer3(x)
            x = self.layer4(x)
    
            x = self.ca1(x) * x
            x = self.sa1(x) * x
    
    
            x = self.avgpool(x)
            x = x.reshape(x.size(0), -1)
            x = self.fc(x)
    
            return x
    
    请详细阅读代码加的位置:
    # 网络的第一层加入注意力机制
    self.ca = ChannelAttention(self.inplanes)
    self.sa = SpatialAttention()
    

    # 网络的卷积层的最后一层加入注意力机制
    self.ca1 = ChannelAttention(self.inplanes)
    self.sa1 = SpatialAttention()
    
    forWord部分代码
    x = self.ca(x) * x
    x = self.sa(x) * x
    
    x = self.maxpool(x)
    
    x = self.layer1(x)
    x = self.layer2(x)
    x = self.layer3(x)
    x = self.layer4(x)
    
    x = self.ca1(x) * x
    x = self.sa1(x) * x
    

    请大家详细阅读,一定能看懂的。

    2. 扩充知识

    2.1 加载预训练参数

    1.增添在自己写的网络中加载预训练参数:

    model_path = resnet18-5c106cde.pth' # 预训练参数的位置
    model = resnet50()
    model_dict = model.state_dict() # 网络层的参数
    # 需要加载的预训练参数
    pretrained_dict = torch.load(model_path)['state_dict']  # torch.load得到是字典,我们需要的是state_dict下的参数                         
    # 删除pretrained_dict.items()中model所没有的东西
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}  # 只保留预训练模型中,自己建的model有的参数
    model_dict.update(pretrained_dict)  # 将预训练的值,更新到自己模型的dict中
    model.load_state_dict(model_dict)  # model加载dict中的数据,更新网络的初始值
    

    或者按照评论区Mr DaYang同学给出的方法,修改之后如下:

    model_path = 'https://download.pytorch.org/models/resnet18-5c106cde.pth' # 预训练参数的位置
    # 自己重写的网络
    model = resnet50()
    model_dict = model.state_dict() # 网络层的参数
    # 需要加载的预训练参数
    pretrained_dict = torch.load(model_path)['state_dict']  # torch.load得到是字典,我们需要的是state_dict下的参数
    pretrained_dict = {k.replace('module.', ''): v for k, v in
                               pretrained_dict.items()}  # 因为pretrained_dict得到module.conv1.weight,但是自己建的model无module,只是conv1.weight,所以改写下。
                               
    # 删除pretrained_dict.items()中model所没有的东西
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}  # 只保留预训练模型中,自己建的model有的参数
    model_dict.update(pretrained_dict)  # 将预训练的值,更新到自己模型的dict中
    model.load_state_dict(model_dict)  # model加载dict中的数据,更新网络的初始值
    

    按照上述步骤按层读取参数还是报错, 解决方案有以下两种:

    1. model.load_state_dict(torch.load(PATH), strict=False)里面的strict参数没有设置成False。如果是strict=True表示严格按照字典读取(修改网络结构后会报错),所以可以将strict设置为False,这样就能避免这种情况了。
    2. (万能)在pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}构造词典的过程中,删除那些不能加载预训练的k,假设你现在报错的模型是classifier.1.weightclassifier.1.bias,那就可以改为pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict and k not in ['classifier.1.weight', 'classifier.1.bias']}

    对于注意力机制的个人理解:

    1. 网络越深、越宽、结构越复杂,注意力机制对网络的影响就越小。
    2. 在网络中加上CBAM不一定带来性能上的提升,对性能影响因素有数据集、网络自身、注意力所在的位置等等。
    3. 建议直接在网络中加上SE系列,大部分情况下性能都会有提升的。

    CBAM的解析:CBAM:卷积注意力机制模块

    贴出一些和SE相关的:SE-Inception v3架构的模型搭建(keras代码实现)PyTorch Hub发布!一行代码调用所有模型:torch.hub

    ResNet(CBAM)源码解析链接,增加ResNet的图:ResNet_CBAM源码

    2.2 到底要不要用ImageNet预训练?

    相关论文链接:Rethinking ImageNet Pre-training

    这篇论文是Kaiming He, Ross Girshick, Piotr Dollár之作,这篇重新思考ImageNet预训练(Rethinking ImageNet Pre-training)就给出了他们的答案。

    FAIR(Facebook AI Research)的三位研究员从随机初始状态开始训练神经网络,然后用COCO数据集目标检测和实例分割任务进行了测试。结果,丝毫不逊于经过ImageNet预训练的对手。

    甚至能在没有预训练、不借助外部数据的情况下,和COCO 2017冠军平起平坐。

    这里贴出来该论文的实验结果:

    他们用2017版的COCO训练集训练了一个Mask R-CNN模型,基干网络是用了群组归一化(GroupNorm)的ResNet-50 FPN。

    在这里插入图片描述
    随后,用相应的验证集评估随机权重初始化(紫色线)和用ImageNet预训练后再微调(灰色线)两种方法的边界框平均检测率(AP)。

    可以看出,随机权重初始化法开始不及预训练方法效果好,但随着迭代次数的增加,逐渐达到了和预训练法相当的结果。

    为了探索多种训练方案,何恺明等人尝试了在不同的迭代周期降低学习率。

    结果显示,随机初始化方法训练出来的模型需要更多迭代才能收敛,但最终收敛效果不比预训练再微调的模型差。

    主干网络换成ResNet-101 FPN,这种从零开始训练的方法依然呈现出一样的趋势:从零开始先是AP不及预训练法,多次迭代后两者终趋于不分上下。

    在这里插入图片描述

    效果究竟能有多好?答案前面也说过了,和COCO 2017冠军选手平起平坐。

    从零开始模型的效果,由COCO目标检测任务来证明。在2017版验证集上,模型的bbox(边界框)和mask(实例分割)AP分别为50.9和43.2;

    他们还在2018年竞赛中提交了这个模型,bbox和mask AP分别为51.3和43.6。

    这个成绩,在没有经过ImageNet预训练的单模型中是最好的。

    这是一个非常庞大的模型,使用了ResNeXt-152 8×32d基干(如下表),GN归一化方法。从这个成绩我们也能看出,这个大模型没有明显过拟合,非常健壮(robust)。
    在这里插入图片描述

    实验中,何恺明等人还用ImageNet预训练了同样的模型,再进行微调,成绩没有任何提升。

    这种健壮性还有其他体现。

    比如说,用更少的数据进行训练,效果还是能和预训练再微调方法持平。何恺明在论文中用Even more surprising来形容这个结果。

    当他们把训练图像数量缩减到整个COCO数据集的1/3(35000张图)、甚至1/10(10000张图)时,经过多次迭代,随机初始化看起来还略优于预训练法的效果。

    在这里插入图片描述

    不过,10000张图已经是极限,继续降低数据量就不行了。当他们把训练数据缩减到1000张图片,出现了明显的过拟合。

    想抛弃ImageNet预训练,用不着大动干戈提出个新架构。不过,两点小改动在所难免。

    第一点是模型的归一化方法,第二点是训练长度。

    我们先说模型归一化(Normalization)。

    因为目标检测任务的输入数据通常分辨率比较高,导致批次大小不能设置得太大,所以,批归一化(Batch Normalization,BN)不太适合从零开始训练目标检测模型。

    于是,何恺明等人从最近的研究中找了两种可行的方法:群组归一化(Group Normalization,GN)和同步批归一化(Synchronized Batch Normalization,SyncBN)。

    在这里插入图片描述
    GN是吴育昕和何恺明合作提出的,发表在ECCV 2018上,还获得了最佳论文荣誉提名。这种归一化方法把通道分成组,然后计算每一组之内的均值和方差。它的计算独立于批次维度,准确率也不受批次大小影响。

    SyncBN则来自旷视的MegDet,和香港中文大学Shu Liu等人的CVPR 2018论文Path Aggregation Network for Instance Segmentation。这是一种跨GPU计算批次统计数据来实现BN的方法,在使用多个GPU时增大了有效批次大小。

    归一化方法选定了,还要注意收敛问题,简单说是要多训练几个周期。

    道理很简单:你总不能指望一个模型从随机初始化状态开始训练,还收敛得跟预训练模型一样快吧。

    所以,要有耐心,多训练一会儿。
    在这里插入图片描述
    也就是说,要想从随机初始化状态开始训练,要有大量样本。

    这篇论文还贴心地放出了从实验中总结的几条结论:

    1. 不改变架构,针对特定任务从零开始训练是可行的。
    2. 从零开始训练需要更多迭代周期,才能充分收敛。
    3. 在很多情况下,甚至包括只用10000张COCO图片,从零开始训练的效果不逊于用ImageNet预训练模型微调。
    4. 用ImageNet预训练能加速在目标任务上的收敛。
    5. ImageNet预训练未必能减轻过拟合,除非数据量极小。
    6. 如果目标任务对定位比识别更敏感,ImageNet预训练的作用较小。

    所以,关于ImageNet预训练的几个关键问题也就有了答案:

    它是必需的吗?并不是,只要目标数据集和计算力足够,直接训练就行。这也说明,要提升模型在目标任务上的表现,收集目标数据和标注更有用,不要增加预训练数据了。

    它有帮助吗?当然有,它能在目标任务上数据不足的时候带来大幅提升,还能规避一些目标数据的优化问题,还缩短了研究周期。

    我们还需要大数据吗?需要,但一般性大规模分类级的预训练数据集就不用了,在目标领域收集数据更有效。

    我们还要追求通用表示吗?依然需要,这还是个值得赞赏的目标。

    展开全文
  • Bert预训练相关参数梳理 作者:白鹿 第一阶段:CreatePretrainData阶段 参数名称 参数说明 do_lower_case 是否忽略大小写 max_seq_length 每条训练数据的最大长度,过长的会截取,不够的会进行padding ...
  • tensorflow加载CNN-F/VGG-F预训练参数

    千次阅读 2019-11-21 20:44:05
    CNN-F 即 VGG-F,这里分析、比较几个 CNN-F/VGG-F 参数文件
  • 预训练AlexNet模型参数

    2018-09-13 13:35:02
    深度学习AlexNet模型预训练参数,.npy格式,深度学习入门可尝试练习
  • Pytorch对自定义模型加载预训练参数

    千次阅读 2019-12-13 16:33:00
    如果直接重新写一个模型而没有预训练参数的话,训练任务的效果就会很差.为了使用预训练的参数,而又使模型适合我们的需求,所以需要对已经加载参数的模型修改结构.下面我将介绍使用它的方法. Pytorch加载预训练模型 ...
  • 1. 预训练参数保存 def savecheckpoint(model,dir): para=model.state_dict() torch.save(para, dir) 2. 预训练参数加载 def LoadParameter(_structure, _parameterDir): """ :param _structure: model :...
  • 参数 模型
  • Pytorch使用预训练模型的部分参数

    千次阅读 2020-11-04 10:55:01
    在进行神经网络训练时,一般我们需要使用预训练模型的参数,但是有时候我们需要对网络的层进行调整,就会导致预训练的模型参数和我们的模型参数不一样,这样我们就只能使用预训练模型中的部分参数 操作: 使用方法很...
  • 关于预训练模型一些参数的说明

    千次阅读 2021-11-12 21:50:38
    对于训练轮数:一般对于纯预训练模型或者与其他模型联合应用,可以先设定一个限制条件,例如设定:如果超过1000个batch效果还没有提升就停止训练。epoch次数一般为3-4次就可以完成。 即便是3-4次可能也需要2-3个...
  • 在解决一个任务时,我会选择加载预训练模型并逐步fine-tune。比如,分类任务中,优异的深度学习网络有很多。 ResNet, VGG, Xception等等… 并且这些模型参数已经在imagenet数据集中训练的很好了,可以直接拿过来用。...
  • pytorch加载预训练模型部分参数

    千次阅读 2020-08-17 11:33:02
    resnet = models.resnet50(pretrained=True) new_state_dict = resnet.state_dict() ...for k in new_state_dict.keys(): ... if k in dd.keys() and not k.startswith('fc'): #不使用全连接的参数 print('y
  • 今天小编就为大家分享一篇tensorflow获取预训练模型某层参数并赋值到当前网络指定层方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 导入预训练模型在通常情况下都能加快模型收敛,提升模型性能。但根据实际任务需求,自己搭建的模型往往和通用的Backbone并不能做到网络层的完全一致,无非就是少一些层和多一些层两种情况。 1. 自己模型层数较少 ...
  • 第1章torchvision与预训练模型的自动下载 第2章 预训练模型的手工下载 第3章 网络介绍 第4章 前置条件:系统库的导入 第5章 预训练模型的导入 5.1 模型的创建 5.2 模型参数的导入 5.3 模型参数的应用 5.4...
  • Mask R-CNN预训练权重

    2022-05-26 19:06:56
    Mask R-CNN数据标注和模型训练 ... 使用Mask R-CNN标注自定义...本资源是教程中所需要加载的预训练模型,提供一个便捷的下载链接,大家也可以去噼里啪啦教程中给定的链接进行下载。 详细标注过程,及模型训练见教程。
  • 说明 ... 准备在coco数据集上预训练.... 预训练完以后, retinanethead部分, 由于类数目尺寸不匹配, 所以希望只加载bacnbone以及fpn部分的参数. 保存的checkpoints本质上为一个字典, 所以只需要把head部...
  • 一:查看预训练模型的参数(以Alexnet为例): path = 'I:/迅雷下载/alexnet-owt-4df8aa71.pth' pretrained_dict = torch.load(path) for k, v in pretrained_dict.items(): # k 参数名 v 对应参数值 print(k) ...
  • inception_v2预训练模型

    2020-09-24 14:06:10
    当神经网络具有许多参数时,它们的效果最佳,这使它们成为功能强大的函数逼近器。但是,这意味着必须对非常大的数据集进行训练。由于从头开始训练模型可能是一个非常耗费计算量的过程,需要几天甚至几周的时间,因此...
  • 利用pytorch预训练resnet模型并保存模型及参数Resnet模型简介预训练模型及保存输出结果 Resnet模型简介 若将输入设为X,将某一有参网络层设为H,那么以X为输入的此层的输出将为H(X)。一般的CNN网络如Alexnet/VGG等会...
  • 这个参数仅针对SAE模型,并且只有在第一次启动的时候可以配置,配置完之后,一旦中断训练之后,这个预训练环节就结束了。 ​ 上图为预训练的效果图,这个界面红红绿绿配上灰色,看起来还挺好看。...
  • 使用pytorch 加载预训练VGG模型,以及参数,将参数保存到本地文件***.pth 修改VGG最后一层分类层为3,原本训练分类数为10类,所以预训练模型的参数不能完全匹配新建的模型结构,但除最后一层外,其余参数可以重用 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 78,683
精华内容 31,473
关键字:

预训练参数