用训练好的模型进行微调的时候,图片经过resnet18网络层,生成的tensor的值全部是nan

img

img

img

img

img


训练的时候是正常的,但是生成的pt模型在微调的时候会出现问题

如果出来的tensor就是nan,那有多种可能。
1你保存的pt有问题,先试试不微调(也就是不用优化器更新),直接导入pt模型,然后输入样本,看看输出正常吗。
2微调时,新的样本跟你训练的样本差异太大,导致反向传播时梯度太大了,所以更新后参数有些变成了NAN。试试把梯度截断,也就是限制每轮优化时,梯度不能大于某个值。
3GPU某些计算单元坏了,这种现象我遇见过,本来正常的代码,跑着跑着,不管怎么调,输出都是NAN。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7761321
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:TensorFlow2迁移学习实战(九):搭建残差网络ResNet-101,实现对花的精准分类
  • 除此之外, 这篇博客: 视觉问答——使用预训练模型提取特征以及特征融合的代码学习(未完待续,tensorflow实现)中的 (2)使用预训练的resnet-152/101来提取图像特征 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    非常幸运的是,tensorflow里面集成好了resnet-50/101/152,我们可以直接调用。调用需要用到的库包括:

    from tensorflow.contrib.slim.nets import resnet_v2
    from tensorflow.contrib.slim.python.slim.nets.resnet_utils import resnet_arg_scope

    调用方法:

    with slim.arg_scope(resnet_arg_scope(is_training=False)):
        net, end_points = resnet_v2.resnet_v2_152(data_set)

    resnet-50和101都是一样的调用思路,net是网络最终的返回,大小是(1,1,1,2048),endpoint里面保存了resnet各个网络层节点信息。加入我们要用resnet提取图片特征,抽出中间的一个层,那么可以用如下的方法:

    # 随机读取一张图片,将其变成448*448的
    image = io.imread('0.png')
    image = transform.resize(image, (448, 448))
    
    # 由于一张图像是一个三维立方体,我们要将其变为四维张量
    data_set = np.empty((1, 448, 448, 3), dtype="float32")
    data_set[0, :, :, :] = image
    
    # 构建resnet网络
    with slim.arg_scope(resnet_arg_scope):
        net, end_points = resnet_v2.resnet_v2_152(data_set)
    
    # 运行网络
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        sess.run(net)
        
        # 随便记录其中中间的某一层
        show_img = end_points['resnet_v2_152/block1/unit_1/bottleneck_v2/conv1'][0].eval()
    
    # 输出一下这一层的大小,是(112,112,64)
    print(show_img.shape)
    
    # 随便拿一个feature map输出一下
    io.imshow(show_img[:, :, 0])
    io.show()

    这个feature map输出的结果和原图如下所示:

    最后还有resnet_arg_scope是可以修改的,比如可以修改成下面的这种方式:

    def resnet_arg_scope(is_training=True,                              # 训练标记
                         weight_decay=0.0001,                           # 权重衰减速率
                         batch_norm_decay=0.997,                        # BN的衰减速率
                         batch_norm_epsilon=1e-5,                       # BN的epsilon默认1e-5
                         batch_norm_scale=True):                        # BN的scale默认值
    
      batch_norm_params = {                                             # 定义batch normalization(标准化)的参数字典
          'is_training': is_training,
          'decay': batch_norm_decay,
          'epsilon': batch_norm_epsilon,
          'scale': batch_norm_scale,
          'updates_collections': tf.GraphKeys.UPDATE_OPS,
      }
    
      with slim.arg_scope(                                              # 通过slim.arg_scope将[slim.conv2d]的几个默认参数设置好
          [slim.conv2d],
          weights_regularizer=slim.l2_regularizer(weight_decay),        # 权重正则器设置为L2正则
          weights_initializer=slim.variance_scaling_initializer(),      # 权重初始化器
          activation_fn=tf.nn.relu,                                     # 激活函数
          normalizer_fn=slim.batch_norm,                                # 标准化器设置为BN
          normalizer_params=batch_norm_params):
        with slim.arg_scope([slim.batch_norm], **batch_norm_params):
          with slim.arg_scope([slim.max_pool2d], padding='SAME') as arg_sc: # ResNet原论文是VALID模式,SAME模式可让特征对齐更简单
            return arg_sc                                               # 最后将基层嵌套的arg_scope作为结果返回

    (3)使用预训练的faster rcnn来提取图像特征


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^