项目场景:
需要将模型中某层输出的中间特征图矩阵以及特征向量打印成图片。这里使用Matplotlib库将矩阵以及向量转换成图片输出:
def normalization(data): # NORMALIZE TO [0,1]
_range = np.max(data) - np.min(data)
data = (data - np.min(data)) / _range # [0,1]
return data
def fm_vis(feats, save_dir, save_name):
save_dir = os.path.join(save_dir, save_name)
if not os.path.exists(save_dir):
os.makedirs(save_dir)
feats = normalization(feats[0].cpu().data.numpy())
for idx in range(min(feats.shape[0], 8)): #CHANNLE NUMBER
fms = feats[idx, :, :]
plt.imshow(fms)
plt.savefig(os.path.join(save_dir, save_name + '_' + str(idx) + ".png"))
问题描述
中间层输出的特征向量的打印结果有误,这里特征向量的维度是[1,8,1,1],得到以下结果:
但是向量中每个元素的值实际是不同的:
s_b: tensor([[[[ 1.4696]],
[[ 0.3728]],
[[-2.0147]],
[[ 1.1435]],
[[ 0.1433]],
[[ 0.5699]],
[[-0.1782]],
[[-0.4495]]]], device='cuda:0')
即便通过上采样将向量转换成矩阵再输出,结果还是相同:
s_b = s_b.reshape(1, 1, 2, 4)
fm_vis(s_b, out_dir, "s_b_vis")
原因分析:
具体出错原因还没有找到,但该段代码在输出中间特征图矩阵时表现正常:
因为每个特征通道上的像素值都有所差异,因此如果将向量上八个不同的值平凑在同一个2D空间上,是否就可以正常输出?
解决方案:
将特征向量的维度从[1,8,1,1]转为[1,1,2,4],这样同一个2D平面内的像素之间存在一定差异,就嫩像矩阵一样正常输出:
s_b = s_b.reshape(1, 1, 2, 4)
fm_vis(s_b, out_dir, "s_b_vis")
得到结果:
讨论:
由于我的代码在定义模型时就设置了对指定特征图和特征向量进行显式输出,因此这里可以像普通图像一样打印成图片,但是对于一个普通模型(比如AlexNet),要在不更改模型定义的前提下获取指定层的特征图输出,可以使用“钩子函数”,具体建议参考如下仓库:
GitHub - cjf8899/FeatureMap_Visualize_Pytorch at 58d09f39cd640fe7380eee1e2adcb4c4336c07ab