import%20marimo%0A%0A__generated_with%20%3D%20%220.20.1%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%0A%20%20%20%20return%20mo%2C%20np%2C%20plt%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20tensorflow%20as%20tf%0A%20%20%20%20from%20tensorflow.keras.preprocessing.image%20import%20load_img%0A%20%20%20%20from%20tensorflow.keras.applications.resnet50%20import%20(%0A%20%20%20%20%20%20%20%20ResNet50%2C%0A%20%20%20%20%20%20%20%20decode_predictions%2C%0A%20%20%20%20)%0A%20%20%20%20import%20cv2%0A%0A%20%20%20%20return%20ResNet50%2C%20cv2%2C%20decode_predictions%2C%20load_img%2C%20tf%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Counterfactual%20explanation%0A%0A%20%20%20%20By%20negating%20the%20value%20of%20%24%5Cfrac%7B%5Cpartial%20y%5E%7Bc%7D%7D%7B%5Cpartial%20A%5E%7Bk%7D%7D%24%2C%20we%20can%20produce%20a%20map%20of%20regions%20that%20would%20lower%20the%20network's%20confidence%20in%20its%20prediction.%20This%20is%20useful%20when%20two%20competing%20objects%20are%20present%20in%7C%20the%20image.%20We%20can%20produce%20a%20%22counterfactual%22%20image%20with%20these%20regions%20masked%20out%2C%20which%20should%20give%20a%20higher%20confidence%20in%20the%20original%20prediction.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(ResNet50%2C%20tf)%3A%0A%20%20%20%20model%20%3D%20ResNet50()%0A%0A%20%20%20%20%23%20Get%20logits%20instead%20of%20softmax%0A%20%20%20%20logits_model%20%3D%20tf.keras.Model(inputs%3Dmodel.inputs%2C%20outputs%3Dmodel.layers%5B-1%5D.output)%0A%20%20%20%20last_conv_layer%20%3D%20model.get_layer(%22conv5_block3_out%22)%0A%20%20%20%20last_conv_layer_model%20%3D%20tf.keras.Model(model.inputs%2C%20last_conv_layer.output)%0A%0A%20%20%20%20classifier_input%20%3D%20tf.keras.Input(shape%3Dlast_conv_layer.output.shape%5B1%3A%5D)%0A%20%20%20%20x%20%3D%20classifier_input%0A%20%20%20%20for%20layer_name%20in%20%5B%22avg_pool%22%2C%20%22predictions%22%5D%3A%0A%20%20%20%20%20%20%20%20x%20%3D%20model.get_layer(layer_name)(x)%0A%20%20%20%20classifier_model%20%3D%20tf.keras.Model(classifier_input%2C%20x)%0A%20%20%20%20return%20classifier_model%2C%20last_conv_layer_model%2C%20logits_model%0A%0A%0A%40app.cell%0Adef%20_(load_img%2C%20np)%3A%0A%20%20%20%20multiobject_image%20%3D%20np.array(%0A%20%20%20%20%20%20%20%20load_img(%22.%2Fdata%2Fcat_and_dog.jpg%22%2C%20target_size%3D(224%2C%20224%2C%203))%0A%20%20%20%20)%0A%20%20%20%20return%20(multiobject_image%2C)%0A%0A%0A%40app.cell%0Adef%20_(classifier_model%2C%20last_conv_layer_model%2C%20multiobject_image%2C%20np%2C%20tf)%3A%0A%20%20%20%20with%20tf.GradientTape()%20as%20tape%3A%0A%20%20%20%20%20%20%20%20last_conv_layer_output%20%3D%20last_conv_layer_model(%0A%20%20%20%20%20%20%20%20%20%20%20%20multiobject_image%5Bnp.newaxis%2C%20...%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20tape.watch(last_conv_layer_output)%0A%20%20%20%20%20%20%20%20preds%20%3D%20classifier_model(last_conv_layer_output)%0A%20%20%20%20%20%20%20%20top_pred_index%20%3D%20tf.argmax(preds%5B0%5D)%0A%20%20%20%20%20%20%20%20top_class_channel%20%3D%20preds%5B%3A%2C%20top_pred_index%5D%0A%20%20%20%20return%20last_conv_layer_output%2C%20tape%2C%20top_class_channel%0A%0A%0A%40app.cell%0Adef%20_(last_conv_layer_output%2C%20tape%2C%20top_class_channel)%3A%0A%20%20%20%20grads%20%3D%20tape.gradient(top_class_channel%2C%20last_conv_layer_output)%0A%20%20%20%20return%20(grads%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20negative%20of%20the%20gradients%20is%20taken%2C%20to%20target%20the%20regions%20that%20do%20not%20contribute%20towards%20strengthen%20the%20network's%20predictions.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(grads%2C%20last_conv_layer_output%2C%20tf)%3A%0A%20%20%20%20pooled_grads%20%3D%20tf.reduce_mean(-1%20*%20grads%2C%20axis%3D(0%2C%201%2C%202))%0A%20%20%20%20last_conv_layer_output_%20%3D%20last_conv_layer_output.numpy()%5B0%5D%0A%20%20%20%20pooled_grads%20%3D%20pooled_grads.numpy()%0A%20%20%20%20for%20i%20in%20range(pooled_grads.shape%5B-1%5D)%3A%0A%20%20%20%20%20%20%20%20last_conv_layer_output_%5B%3A%2C%20%3A%2C%20i%5D%20*%3D%20pooled_grads%5Bi%5D%0A%20%20%20%20return%20(last_conv_layer_output_%2C)%0A%0A%0A%40app.cell%0Adef%20_(cv2%2C%20last_conv_layer_output_%2C%20np)%3A%0A%20%20%20%20%23%20Average%20over%20all%20the%20filters%20to%20get%20a%20single%202D%20array%0A%20%20%20%20ctfcl_gradcam%20%3D%20np.mean(last_conv_layer_output_%2C%20axis%3D-1)%0A%20%20%20%20%23%20Normalise%20the%20values%0A%20%20%20%20ctfcl_gradcam%20%3D%20np.clip(ctfcl_gradcam%2C%200%2C%20np.max(ctfcl_gradcam))%20%2F%20np.max(%0A%20%20%20%20%20%20%20%20ctfcl_gradcam%0A%20%20%20%20)%0A%20%20%20%20ctfcl_gradcam%20%3D%20cv2.resize(ctfcl_gradcam%2C%20(224%2C%20224))%0A%20%20%20%20return%20(ctfcl_gradcam%2C)%0A%0A%0A%40app.cell%0Adef%20_(ctfcl_gradcam%2C%20multiobject_image%2C%20plt)%3A%0A%20%20%20%20plt.imshow(multiobject_image)%0A%20%20%20%20plt.imshow(ctfcl_gradcam%2C%20alpha%3D0.5)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20We%20can%20mask%20out%20the%20region%20identified%20by%20the%20counterfactual%20map%2C%20and%20re-run%20the%20predictions%2C%20where%20we%20should%20see%20a%20higher%20confidence%20in%20the%20outputs.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(ctfcl_gradcam%2C%20cv2%2C%20multiobject_image)%3A%0A%20%20%20%20mask%20%3D%20cv2.resize(ctfcl_gradcam%2C%20(224%2C%20224))%0A%20%20%20%20mask%5Bmask%20%3E%200.1%5D%20%3D%20255%0A%20%20%20%20mask%5Bmask%20!%3D%20255%5D%20%3D%200%0A%20%20%20%20mask%20%3D%20mask.astype(bool)%0A%20%20%20%20ctfctl_image%20%3D%20multiobject_image.copy()%0A%20%20%20%20ctfctl_image%5Bmask%5D%20%3D%20(0%2C%200%2C%200)%0A%20%20%20%20return%20(ctfctl_image%2C)%0A%0A%0A%40app.cell%0Adef%20_(ctfctl_image%2C%20plt)%3A%0A%20%20%20%20plt.imshow(ctfctl_image)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(ctfctl_image%2C%20decode_predictions%2C%20logits_model%2C%20np%2C%20tf)%3A%0A%20%20%20%20decode_predictions(%0A%20%20%20%20%20%20%20%20tf.nn.softmax(logits_model(ctfctl_image%5Bnp.newaxis%2C%20...%5D)).numpy()%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
560f06dc2ac13b34dcaffe339bc4d430