如何在推理期间从训练模型的每一层获取特征图?
How to get the feature maps from each layers of a trained model during inference time?
我已经实施并训练了来自 following website, and using the author's source code 的模型:
我现在运行一个图像通过训练好的网络,想得到每个阶段的网络输出(feature maps等).
我的方法
为此,我尝试从完整模型(在我的代码中称为 sizedModel
)的层组中制作子模型并检查它们的输出。
我第一次这样做了L1(Conv2D)
L1_inp = sizedModel.layers[1].input
L1_out = sizedModel.layers[1].output
Layer1 = Model(L1_inp,L1_out)
L1_result = Layer1.predict(
tf.expand_dims(tf.expand_dims(lrImage, axis=0), axis=3)
)
# Save feature maps to greyscale images
Xresult = tf.squeeze(L1_result)
for i in range(Xresult.shape[2]):
data = (Xresult[:,:,i].numpy() * 255).astype(np.uint8)
filename = 'tmp_test/result'+str(i).zfill(2)+'.png'
Image.fromarray(data).save(filename)`
.predict()
在该模型上的结果是张量形状 (1,360,640,12)
,这是预期的,图像看起来很好。
我现在正尝试将该张量输入图中标记为 L2 的层 (sizedModel.layers[2-8])。
我知道如何做到这一点的唯一方法是在新模型中隔离。为此,我正在做:
# 从 L1 (1,360,640,12) 的输出中获取输入形状
_input = tf.keras.Input(shape=L1_result.shape, name="input_layer")
# First "tf_op_layer_strided_slice" from large model
_split = largeModel.layers[2](_input)
# First "L2-0 (Conv 3x3)" from large model
_conv = largeModel.layers[5](_split)
这导致
# ValueError:L2-0 层的输入 0 与层不兼容:输入形状的预期轴 -1
# 具有值 4 但接收到形状为 [None, 1, 360, 4, 12]
的输入
# Build sub-model from these two layers of the large model
Layer2 = Model(_input,_conv)
# Pass first sub-model (L1) output to this model
Result_L2 = Layer2.predict(L1_result)
为什么第L2-0
层的Input 0
不兼容?
有没有更简单的方法来单独调试每一层的输出?
如果我正确理解你的问题,你想获得模型每一层的输出特征图。通常,正如我们在评论框中提到的,具有 一个(或多个)输入 和 一个(或多个)输出 的模型。但是为了检查内层的激活特征图,我们可以采用一些策略。一些可能的场景:(1)。想在运行-时间或训练时间内得到每一层的输出特征图。 (2)。想在推理时或训练后得到每一层的输出特征图。正如你引用的那样:
I am now running an image through the trained network and want to get
the network output (feature maps etc.) at every stage.
那转到数字2,在推理时间得到特征图。以下是执行此操作的简单可能解决方法。首先,我们建立一个模型,然后在训练之后,我们将修改训练模型以获得其中每一层的特征图(技术上创建相同的模型并进行一些修改)。
# The model we trained
input
|
conv1
|
conv2
|
conv3
|
output
|
# The modified model we use for inference
input
|
conv1 --> outputA [Get Feature Mpas]
|
conv2 --> outputB [G. F. M.]
|
conv3 --> outputC [G. F. M.]
|
output
|
我正在使用您在 post 中引用的来自 here 的模型定义。
def buildModel(inputSize=(9,9), networkWidth=[48, 24], parBlockSize=12):
....
....
return tf.keras.models.Model(inputs=input, outputs=output)
现在,我们遍历层并获取每个层的输出并构建一个新模型。
model = buildModel(...)
features_list = [layer.output for layer in model.layers]
activations_model = tf.keras.Model(inputs=model.input, outputs=features_list)
现在,如果我们将一些输入传递给 activations_model
,我们将得到不止一个输出,这与 model
不同,我们只得到最后一层输出。
img = np.random.random((1, 128, 128, 1)).astype("float32")
activations = activations_model.predict(img)
for i, _ in enumerate(activations):
print(activations[i].shape)
(1, 128, 128, 1)
(1, 124, 124, 48)
(1, 124, 124, 12)
(1, 124, 124, 12)
(1, 124, 124, 12)
(1, 124, 124, 12)
(1, 122, 122, 8)
(1, 122, 122, 8)
(1, 122, 122, 8)
(1, 122, 122, 8)
(1, 122, 122, 32)
(1, 122, 122, 24)
(1, 122, 122, 12)
(1, 122, 122, 12)
(1, 120, 120, 8)
(1, 120, 120, 8)
(1, 120, 120, 16)
(1, 120, 120, 4)
(1, 240, 240, 1)
因此,我们有来自单个实例的总 1 + 48 + 12*6 + 8*6 + 32 + 24 + 16 + 4 + 1 = 246
个特征图。现在,我们可以随心所欲地保存这些特征图了。
layer_names = []
for layer in model.layers:
layer_names.append(layer)
for i, (layer_name, layer_activation) in enumerate(zip(layer_names, activations)):
n_features = layer_activation.shape[-1]
feat_maps = tf.squeeze(layer_activation)
print(feat_maps.shape)
if n_features == 1:
tf.keras.preprocessing.image.save_img(
f'tmp/{layer_name.name}_{n_features}.png',
tf.expand_dims(feat_maps, axis=-1))
else:
for n_feature in range(n_features):
feat_map = feat_maps[:, :, n_feature]
tf.keras.preprocessing.image.save_img(
f'tmp/{layer_name.name}_{n_feature}.png',
tf.expand_dims(feat_map, axis=-1))
我已经实施并训练了来自 following website, and using the author's source code 的模型:
我现在运行一个图像通过训练好的网络,想得到每个阶段的网络输出(feature maps等).
我的方法
为此,我尝试从完整模型(在我的代码中称为 sizedModel
)的层组中制作子模型并检查它们的输出。
我第一次这样做了L1(Conv2D)
L1_inp = sizedModel.layers[1].input
L1_out = sizedModel.layers[1].output
Layer1 = Model(L1_inp,L1_out)
L1_result = Layer1.predict(
tf.expand_dims(tf.expand_dims(lrImage, axis=0), axis=3)
)
# Save feature maps to greyscale images
Xresult = tf.squeeze(L1_result)
for i in range(Xresult.shape[2]):
data = (Xresult[:,:,i].numpy() * 255).astype(np.uint8)
filename = 'tmp_test/result'+str(i).zfill(2)+'.png'
Image.fromarray(data).save(filename)`
.predict()
在该模型上的结果是张量形状 (1,360,640,12)
,这是预期的,图像看起来很好。
我现在正尝试将该张量输入图中标记为 L2 的层 (sizedModel.layers[2-8])。
# First "tf_op_layer_strided_slice" from large model
_split = largeModel.layers[2](_input)
# First "L2-0 (Conv 3x3)" from large model
_conv = largeModel.layers[5](_split)
这导致 # ValueError:L2-0 层的输入 0 与层不兼容:输入形状的预期轴 -1 # 具有值 4 但接收到形状为 [None, 1, 360, 4, 12]
的输入# Build sub-model from these two layers of the large model
Layer2 = Model(_input,_conv)
# Pass first sub-model (L1) output to this model
Result_L2 = Layer2.predict(L1_result)
为什么第L2-0
层的Input 0
不兼容?
有没有更简单的方法来单独调试每一层的输出?
如果我正确理解你的问题,你想获得模型每一层的输出特征图。通常,正如我们在评论框中提到的,具有 一个(或多个)输入 和 一个(或多个)输出 的模型。但是为了检查内层的激活特征图,我们可以采用一些策略。一些可能的场景:(1)。想在运行-时间或训练时间内得到每一层的输出特征图。 (2)。想在推理时或训练后得到每一层的输出特征图。正如你引用的那样:
I am now running an image through the trained network and want to get the network output (feature maps etc.) at every stage.
那转到数字2,在推理时间得到特征图。以下是执行此操作的简单可能解决方法。首先,我们建立一个模型,然后在训练之后,我们将修改训练模型以获得其中每一层的特征图(技术上创建相同的模型并进行一些修改)。
# The model we trained
input
|
conv1
|
conv2
|
conv3
|
output
|
# The modified model we use for inference
input
|
conv1 --> outputA [Get Feature Mpas]
|
conv2 --> outputB [G. F. M.]
|
conv3 --> outputC [G. F. M.]
|
output
|
我正在使用您在 post 中引用的来自 here 的模型定义。
def buildModel(inputSize=(9,9), networkWidth=[48, 24], parBlockSize=12):
....
....
return tf.keras.models.Model(inputs=input, outputs=output)
现在,我们遍历层并获取每个层的输出并构建一个新模型。
model = buildModel(...)
features_list = [layer.output for layer in model.layers]
activations_model = tf.keras.Model(inputs=model.input, outputs=features_list)
现在,如果我们将一些输入传递给 activations_model
,我们将得到不止一个输出,这与 model
不同,我们只得到最后一层输出。
img = np.random.random((1, 128, 128, 1)).astype("float32")
activations = activations_model.predict(img)
for i, _ in enumerate(activations):
print(activations[i].shape)
(1, 128, 128, 1)
(1, 124, 124, 48)
(1, 124, 124, 12)
(1, 124, 124, 12)
(1, 124, 124, 12)
(1, 124, 124, 12)
(1, 122, 122, 8)
(1, 122, 122, 8)
(1, 122, 122, 8)
(1, 122, 122, 8)
(1, 122, 122, 32)
(1, 122, 122, 24)
(1, 122, 122, 12)
(1, 122, 122, 12)
(1, 120, 120, 8)
(1, 120, 120, 8)
(1, 120, 120, 16)
(1, 120, 120, 4)
(1, 240, 240, 1)
因此,我们有来自单个实例的总 1 + 48 + 12*6 + 8*6 + 32 + 24 + 16 + 4 + 1 = 246
个特征图。现在,我们可以随心所欲地保存这些特征图了。
layer_names = []
for layer in model.layers:
layer_names.append(layer)
for i, (layer_name, layer_activation) in enumerate(zip(layer_names, activations)):
n_features = layer_activation.shape[-1]
feat_maps = tf.squeeze(layer_activation)
print(feat_maps.shape)
if n_features == 1:
tf.keras.preprocessing.image.save_img(
f'tmp/{layer_name.name}_{n_features}.png',
tf.expand_dims(feat_maps, axis=-1))
else:
for n_feature in range(n_features):
feat_map = feat_maps[:, :, n_feature]
tf.keras.preprocessing.image.save_img(
f'tmp/{layer_name.name}_{n_feature}.png',
tf.expand_dims(feat_map, axis=-1))