簡體   English   中英

解決:如何將tf.gradients與tf.data.dataset和keras模型結合

[英]Solved: How to combine tf.gradients with tf.data.dataset and keras models

我正在嘗試構建使用tf.data.dataset批處理和迭代器的工作流。 出於性能原因,我實際上是在嘗試避免使用占位符-> feed_dict循環工作流程。

我正在嘗試實現的過程涉及grad-cam(這需要相對於CNN最終卷積層的損耗梯度)作為中間步驟,理想情況下,我希望能夠對其進行嘗試幾種Keras預先訓練的模型,包括非順序模型,例如ResNet。

我發現,大多數grad-cam實現都依賴於對Tensorflow中感興趣的CNN的手工制作。 我找到了一個針對keras模型的實現https://github.com/jacobgil/keras-grad-cam ,在該示例之后,我得到了


def safe_norm(x):
    return x / tf.sqrt(tf.reduce_mean(x ** 2) + 1e-8)
vgg_ = VGG19()

dataset = tf.data.Dataset.from_tensor_slices((filenames))

#preprocessing...

it = dataset.make_one_shot_iterator()

files, batch = it.get_next()
conv5_4 = vgg_.layers[-6]
h_k, w_k, c_k = conv5_4.output.shape[1:]

vgg_model = Model(inputs=vgg_.input, outputs=vgg_.output)
conv_model = Model(inputs=vgg_.input, outputs=conv5_4.output)
probs = vgg_model(batch)
predicted_class = tf.argmax(probs, axis=-1)

layer_name = 'block5_conv4'
target_layer = lambda x: target_category_loss(x, predicted_class, n_categories)
x = Lambda(target_layer)(vgg_model.outputs[0])
model = Model(inputs=vgg_model.inputs[0], outputs=x)

loss = K.sum(model.output, axis=-1)
conv_output =  [l for l in model.layers if l.name is layer_name][0].output
grads = Lambda(safe_norm)(K.gradients(loss, [conv_output])[0])
gradient_function = K.function([model.input], [conv_output, grads])

output, grads_val = gradient_function([batch])
weights = tf.reduce_mean(grads_val, axis = (1, 2))
cam = tf.ones([batch_size, h_k, w_k], dtype = tf.float32)

cam += tf.reduce_sum(output * tf.reshape(weights, [-1, 1, 1, weights.shape[-1]]), axis=-1)

cam = tf.squeeze(tf.image.resize_images(images=tf.expand_dims(cam, axis=-1), size=(224, 224)))
cam = tf.maximum(cam, 0)
heatmap = cam / tf.reshape(tf.reduce_max(cam, axis=[1, 2]), shape=[-1, 1, 1])

問題在於, gradient_function([batch])返回一個numpy數組,其值由第一批決定,因此heatmap不會隨后heatmap評估而改變。

我試圖以各種方式用Model替換K.function ,但是似乎沒有任何效果。 我通常最終會或者與一個錯誤提示grads計算結果為None或者一個模型或另一期待一個feed_dict和不接收一個。

此代碼可挽救嗎? 除了多次遍歷數據(一次獲取所有grad-cams,然后再次擁有它們,然后再次使用)或使用占位符和feed_dicts之外,還有更好的方法嗎?

編輯:


def safe_norm(x):
    return x / tf.sqrt(tf.reduce_mean(x ** 2) + 1e-8)
vgg_ = VGG19()

dataset = tf.data.Dataset.from_tensor_slices((filenames))

#preprocessing...

it = dataset.make_one_shot_iterator()

files, batch = it.get_next()
conv5_4 = vgg_.layers[-6]
h_k, w_k, c_k = conv5_4.output.shape[1:]

vgg_model = Model(inputs=vgg_.input, outputs=vgg_.output)
conv_model = Model(inputs=vgg_.input, outputs=conv5_4.output)
probs = vgg_model(batch)
predicted_class = tf.argmax(probs, axis=-1)

layer_name = 'block5_conv4'
target_layer = lambda x: target_category_loss(x, predicted_class, n_categories)
x = Lambda(target_layer)(vgg_model.outputs[0])
model = Model(inputs=vgg_model.inputs[0], outputs=x)

loss = K.sum(model.output, axis=-1)
conv_output =  [l for l in model.layers if l.name is layer_name][0].output
grads = Lambda(safe_norm)(K.gradients(loss, [conv_output])[0])
gradient_function = K.function([model.input], [conv_output, grads])

output, grads_val = gradient_function([batch])
weights = tf.reduce_mean(grads_val, axis = (1, 2))
cam = tf.ones([batch_size, h_k, w_k], dtype = tf.float32)

cam += tf.reduce_sum(output * tf.reshape(weights, [-1, 1, 1, weights.shape[-1]]), axis=-1)

cam = tf.squeeze(tf.image.resize_images(images=tf.expand_dims(cam, axis=-1), size=(224, 224)))
cam = tf.maximum(cam, 0)
heatmap = cam / tf.reshape(tf.reduce_max(cam, axis=[1, 2]), shape=[-1, 1, 1])

# other operations on heatmap and batch ...

# ...

output_function = K.function(model.input, [node1, ..., nodeN])

for batch in range(n_batches):
    outputs1, ... , outputsN = output_function(batch)

給我每批所需的輸出。

是的, K.function返回numpy數組,因為它會評估圖形中的符號計算。 我認為您應該做的是將所有符號保持在K.function ,並在獲得梯度之后,使用numpy執行Grad-CAM權重和最終顯着性圖的所有計算。

然后,您可以對數據集進行迭代,對新的一批數據求gradient_function函數,並計算顯着性圖。

如果要保留所有符號,則不應使用K.function來生成梯度函數,而應使用符號梯度( K.gradient的輸出,不包含lambda)和卷積特征圖( conv_output )並執行顯着圖在此基礎上進行計算,然后構建一個函數(使用K.function )以獲取模型輸入,並輸出顯着性圖。

希望解釋夠了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM