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