如何从slim-tensorflow版InceptionNet v3模型最后一层提取特征?
从微调后的slim-tensorflow InceptionNet v3提取最后一层特征
嘿,看你已经搞定了InceptionNet v3的微调,现在想要从最后一层提取特征对吧?结合你提到的两种模型恢复方式,我给你整理了具体的实现步骤,两种方式各有优势,你可以根据需求选:
方法一:通过.meta文件恢复完整图结构提取特征
你已经写了部分恢复代码,接下来的核心是找到对应特征的张量。在slim实现的InceptionNet v3中,默认的预分类特征层(也就是我们常说的最后一层特征)是InceptionV3/PreLogits,下面是补全后的代码:
import tensorflow as tf from tensorflow.contrib import slim # 你的文件路径 checkpoint_meta = './fine_tuned_model/model.ckpt-233700.meta' checkpoint_dir = './fine_tuned_model/' with tf.Session() as sess: # 导入.meta文件恢复图结构 new_saver = tf.train.import_meta_graph(checkpoint_meta) # 从ckpt文件恢复权重 new_saver.restore(sess, tf.train.latest_checkpoint(checkpoint_dir)) # 获取当前图对象 graph = tf.get_default_graph() # 定位最后一层特征张量:注意要加`:0`后缀表示张量的第一个输出 feature_tensor = graph.get_tensor_by_name('InceptionV3/PreLogits:0') # 获取输入占位符(默认是'input:0',如果训练时改了名字要替换) input_tensor = graph.get_tensor_by_name('input:0') # 假设你已经完成了输入图片的预处理(和训练时一致) preprocessed_images = 你的预处理函数(原始图片数据) # 运行会话提取特征 features = sess.run(feature_tensor, feed_dict={input_tensor: preprocessed_images}) # 输出特征形状,InceptionV3的PreLogits是2048维,所以形状是[batch_size, 2048] print("提取的特征形状:", features.shape)
小技巧:如果你不确定特征层的名字,可以用print([op.name for op in graph.get_operations()])打印图中所有操作的名字,找到你需要的那一层后,记得在名字后面加:0才是对应的张量。
方法二:重新构建模型结构并恢复权重
这种方法不需要依赖.meta文件,直接用slim的API重新定义模型,再加载ckpt权重,灵活性更高,适合你清楚模型结构的场景:
import tensorflow as tf from tensorflow.contrib.slim.nets import inception from tensorflow.contrib import slim # 你的ckpt文件路径 checkpoint_path = './fine_tuned_model/model.ckpt-233700' # InceptionV3默认输入尺寸是299x299,和训练时保持一致 input_size = 299 # 定义输入占位符 inputs = tf.placeholder(tf.float32, [None, input_size, input_size, 3]) # 构建InceptionV3模型,is_training设为False表示推理模式 with slim.arg_scope(inception.inception_v3_arg_scope()): logits, end_points = inception.inception_v3( inputs, num_classes=你的微调类别数, # 替换成你训练时的类别数量 is_training=False ) # end_points字典里包含了所有中间层输出,'PreLogits'就是我们要的最后一层特征 feature_tensor = end_points['PreLogits'] # 定义saver,只恢复训练过的变量(避免新增变量导致的恢复失败) saver = tf.train.Saver(slim.get_variables_to_restore()) with tf.Session() as sess: # 加载权重 saver.restore(sess, checkpoint_path) # 预处理输入图片(必须和训练时的预处理逻辑完全一致,比如归一化到[-1,1]) preprocessed_images = 你的预处理函数(原始图片数据) # 提取特征 features = sess.run(feature_tensor, feed_dict={inputs: preprocessed_images}) print("提取的特征形状:", features.shape)
注意事项
- 预处理必须和训练一致:比如InceptionV3默认是将图片像素值归一化到
[-1, 1],推理时一定要遵循同样的规则,否则特征会失效 - 如果微调时修改了模型结构(比如自定义了最后几层),方法二中的
num_classes要和你训练时的设置匹配 - 如果你需要的是卷积层/池化层的原始输出,也可以从
end_points里找对应的键,比如'InceptionV3/Logits/AvgPool_1a_8x8/AvgPool'对应的是8x8平均池化输出,形状是[batch_size, 1, 1, 2048],可以用tf.squeeze(feature_tensor)把它压缩成[batch_size, 2048]
内容的提问来源于stack exchange,提问作者talos1904
相关产品推荐
相关产品推荐

