Tensorflow加载预训练ResNet-50,猫狗大战正确率95%


之所以想搞这个,起因是想实现RCNN。因为电脑配置太差,自己预训练根本跑不起来,百度了解到官方是有提供预训练权重的,开开心心拿来用,特此记录。

Kaggle猫狗大战比赛链接
预训练权重下载链接

一.核心代码

预处理,即预处理特征。我们可以把这个想象为一个黑盒子,我们把图片喂进去,这个盒子帮助我们提取并选择特征,我们把盒子的输出喂给全连接层来得到我们自己的需要的输出。

import tensorflow as tf
import tensorflow.contrib.slim as slim
from tensorflow.contrib.slim.nets import resnet_v1

def resnet(inputs, training):
    net, endpoints = resnet_v1.resnet_v1_50(inputs, num_classes=None, is_training=training)
    net = tf.squeeze(net, axis=[1, 2])
    return net

net = resnet(input_images, training)
final_opt = tf.layers.dense(inputs=net, units=2)

那么为什么调用封装好的模型比我们自己训练要好呢?因为我们通过读取ckpt权重,规定了卷积层的初始化参数。正常训练的时候,我们是随机初始化满足高斯分布或其他分布的参数 ,通过随机梯度下降来更新参数寻求更好的模型效果。而在训练前规定初始化参数,相当于规定了一个大致的更新趋势,让我们的梯度下降收敛更快,也避免了梯度消失或爆炸等问题。

sess = tf.Session() 
sess.run(tf.global_variables_initializer())
saver = tf.train.Saver()
variable_restore_op = slim.assign_from_checkpoint_fn('model/resnet_v1_50.ckpt',
                                                     slim.get_trainable_variables(),
                                                     ignore_missing_vars=True)# 一定要设置为True
variable_restore_op(sess) 

二.问题总结

主要遇到了两个问题:

1.训练时正确率很快达到90%+,测试结果全部归为一类

经查阅,主要从以下几方面排查问题:
数据和标签是否匹配
如果两者不匹配,网络根本不会收敛,但很明显网络有在收敛,只是学习发生了错误,所以此项排除。
梯度是否成功回传
由于调用的都是封装好的函数,所以这个问题可能性很小,为确保不是,我在cifar-10数据集上跑了一下本模型,发现效果正常,所以此项排除。
调整参数,如learning_rate,batch_size
调整后,仍很快达到90%+,且由于电脑性能不够,不能尝试更高的批次大小,此项排除。
数据是否不均衡,一个batch内是否都是一个类别
猫狗均为12500张,数据肯定是均衡的。而二分类问题,由于数据未打乱或不够散,很容易发生一个batch都是一个类别的情况。改变数据喂入策略,对于一个batch(batch_size为64),拿出32张猫和32张狗,将这64张图片打乱后喂入。训练开始,正确率从50%开始稳步上升,问题解决了。
:测试集也需要打乱,否则正确率仍不能有效的上升。
训练结果如下
在这里插入图片描述
提交Kaggle评测得分如下
(要求提交的是预测为狗的概率,所以Score为误差)
在这里插入图片描述

2.加载预训练模型报missing警告

在这里插入图片描述
问题出在这两段代码上:

# with slim.arg_scope(resnet_utils.resnet_arg_scope()):
    net = resnet(input_images, training)
    print(net.shape)

variable_restore_op = slim.assign_from_checkpoint_fn('model/resnet_v1_50.ckpt',
                                                    slim.get_trainable_variables(),
                                                    ignore_missing_vars=True)

是否加with那一行决定了是否会报警告,经查阅,加上with这一行代表加载所有权重里的参数,或者我们自己重写scope,则可以加载我们想要的参数。但是我们的模型是不需要那么多参数的,因此我们设置ignore_missing_vars=True,忽略缺失的参数,模型效果反而会更好,这也是为什么这个参数要设置为True的原因。

三.网络结构

X = tf.placeholder(tf.float32, shape = [None, input_size], name='x')
Y = tf.placeholder(tf.float32, shape = [None, num_classes], name='y')
training = tf.placeholder(tf.bool, name="training")
keep_prob = tf.placeholder(tf.float32, name="keep_prob")

input_images = tf.reshape(X, [-1, 112, 112, 3])
            
input_images = tf.image.per_image_standardization(input_images)

# with slim.arg_scope(resnet_utils.resnet_arg_scope()):
net = resnet(input_images, training)
print(net.shape)

net = tf.layers.dropout(inputs=net, rate=keep_prob)

final_opt = tf.layers.dense(inputs=net, units=2)
tf.add_to_collection('pred_network', final_opt)
print(net.shape)
print(final_opt.shape)

# 学习率衰减
global_step = tf.Variable(0, trainable=False)

boundaries = [2000, 4000, 6000, 8000]
values = [0.005, 0.001, 0.0005, 0.0001, 0.00005]
learning_rate = tf.train.piecewise_constant(global_step, boundaries, values)
    
# 对输出层计算交叉熵损失
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=Y, logits=final_opt))
l2_loss = weight_decay * tf.add_n([tf.nn.l2_loss(tf.cast(v, tf.float32)) for v in tf.trainable_variables()])
tf.summary.scalar('l2_loss', l2_loss)
loss = loss + l2_loss

# 定义优化器
optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=0.9)
# optimizer = tf.train.AdamOptimizer(learning_rate=0.002)
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
    opt = optimizer.minimize(loss, global_step=global_step)

sess = tf.Session() 
sess.run(tf.global_variables_initializer())
saver = tf.train.Saver()
variable_restore_op = slim.assign_from_checkpoint_fn('model/resnet_v1_50.ckpt',
                                                    slim.get_trainable_variables(),
                                                    ignore_missing_vars=True)
variable_restore_op(sess)

参考资料如下

解决二分类问题正确率始终在50%的解决办法(CatDog超详细)

TensorFlow 使用预训练模型 ResNet-50

Tensorflow如何直接使用预训练模型(vgg16为例)

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Tensorflow 2.0 中,可以使用 `tf.keras.models.load_model()` 函数来加载预训练权重文件。具体步骤如下: 1. 安装相应的预训练模型,例如 ResNet50,可以使用以下命令: ```python !pip install tensorflow==2.0.0 !pip install tensorflow_hub==0.7.0 !pip install tensorflow_datasets==2.0.0 !pip install tensorflow_probability==0.8.0 ``` 2. 导入相应的模型和预处理函数: ```python import tensorflow as tf import tensorflow_hub as hub import tensorflow_datasets as tfds # 加载 ResNet50 模型 model = tf.keras.applications.ResNet50(weights='imagenet') # 加载预处理函数 preprocess_input = tf.keras.applications.resnet50.preprocess_input ``` 3. 使用 `tf.keras.models.load_model()` 函数加载预训练权重文件: ```python # 加载预训练权重文件 model.load_weights('path/to/weights.h5') ``` 4. 对输入数据进行预处理,并使用加载的模型进行预测: ```python # 加载测试数据 test_data, test_info = tfds.load('cats_vs_dogs', split='test', with_info=True) # 对测试数据进行预处理 test_data = test_data.map(lambda x: (preprocess_input(tf.image.resize(x['image'], (224, 224))), x['label'])) test_data = test_data.batch(32) # 使用加载的模型进行预测 results = model.predict(test_data) ``` 其中,`path/to/weights.h5` 是预训练权重文件的路径。在加载预训练权重文件之前,需要先加载相应的模型,以确保预训练权重文件与模型的结构相同。在预测时,需要对输入数据进行预处理,以符合模型的输入要求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值