<p>Cannot say anything about your own data, but the penultimate layer of Inception V3 for Grad-CAM visualization is indeed <code>mixed10</code> (idx 310), as reported in the notebook you have linked to:</p>
<blockquote>
<p>310 is concatenation before global average pooling</p>
</blockquote>
<p>Rationale: since the output of <code>conv2d_94</code> (299) is connected downstream with other convolutional layers (or concatenations of), like <code>mixed9_1</code>, <code>concatenate_2</code> etc., by definition it cannot be the penultimate <em>convolutional</em> layer; <code>mixed10</code>, on the other hand, is not - on the contrary, it is just one layer before the final average pooling one. That the penultimate layer should be a convolutional, and not a pooling one, is <strong>suggested</strong> from <a href="https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/first_edition/5.4-visualizing-what-convnets-learn.ipynb" rel="nofollow noreferrer">Chollet's exchibition</a>, where for VGG he uses <code>block5_conv3</code>, and not <code>block5_pool</code> which is immediately afterwards (although truth is, even using <code>block5_pool</code> seems to give very similar visual results).</p>
<p>Let me elaborate a little, and explain the emphasis on &quot;suggested&quot; above...</p>
<p>As many other things in current deep learning research &amp; practice, Grad-CAM is a <em>heuristic</em>, not a &quot;hard&quot; scientific method; as such, there are recommendations &amp; expectations on how to use it and what the results might be, but not hard rules (and &quot;appropriate&quot; layers). Consider the following excerpt from the <a href="https://arxiv.org/pdf/1611.07450.pdf" rel="nofollow noreferrer">original paper</a> (end of section 2, emphasis mine):</p>
<blockquote>
<p>We <strong>expect</strong> the last convolutional layers to
have the best compromise between high-level semantics and
detailed spatial information, so we use these feature maps to
compute Grad-CAM and Guided Grad-CAM.</p>
</blockquote>
<p>i.e. there are indeed recommendations &amp; expectations, as I already said, but a certain experimenting &amp; free-wheeling attitude is expected...</p>
<hr />
<p>Now, assuming you are following <a href="https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/first_edition/5.4-visualizing-what-convnets-learn.ipynb" rel="nofollow noreferrer">Chollet's notebook</a> on the subject (i.e. using pure Keras, and not the Keras-vis package),  these are the <strong>changes</strong> in the  code you need in order to make it work with Inception V3:</p>

<pre class="lang-python prettyprint-override"><code># cell 24
from keras import backend as K
from keras.applications.inception_v3 import InceptionV3
K.clear_session()
K.set_learning_phase(0) # needs to be set BEFORE building the model
model = InceptionV3(weights='imagenet')

# in cell 27
from keras.applications.inception_v3 import preprocess_input, decode_predictions
img = image.load_img(img_path, target_size=(299, 299)) # different size than VGG

# in cell 31:
last_conv_layer = model.get_layer('mixed10')
for i in range(2048):  # was 512 for VGG
    conv_layer_output_value[:, :, i] *= pooled_grads_value[i]
</code></pre>
<p>And the resulting superimposed heatmap on the original <code>creative_commons_elephant.jpg</code> image should look like this:</p>
<p><a href="https://i.stack.imgur.com/5GNMh.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/5GNMh.jpg" alt="enter image description here" /></a></p>
<p>which, arguably, is not <em>that</em> different than the respective image by VGG produced in Chollet's notebook (although admittedly the heatmap is indeed more spread, and it does not seem to conform to Chollet's narrative about 'focusing on the ears')...</p>
What is the appropriate penultimate layer for Grad-CAM visualization on Inception V3?
<p>I've been trying to visualize heatmaps for Inception V3. It was my understanding the penultimate layer should be the last convolutional layer, which would be <code>conv2d_94</code> (idx 299). However, this gives very coarse maps (big regions). I tried to use another layer <code>mixed10</code> (idx 310) as suggested in <a href="https://github.com/Abhijit-2592/Keras-custom-callbacks/blob/master/how%20to%20use%20grad-cam%20in%20inceptionv3_copy.ipynb" rel="nofollow noreferrer">this notebook</a> for issue as described <a href="https://github.com/raghakot/keras-vis/issues/65" rel="nofollow noreferrer">here</a> and while the regions are smaller, it still doesn't look great. Some others do seem to use <code>conv2d_94</code>, like <a href="https://github.com/raghakot/keras-vis/issues/23" rel="nofollow noreferrer">here</a>.</p>

<p>I understand it might indicate my model is simply not paying attention to the right things, but also conceptually I'm confused which layer should be used. What is an appropriate penultimate layer?</p>

<p>I'm using Keras 2.2.0 with <code>visualize_cam</code> from <code>keras-vis</code>. </p>

<pre><code>heatmap = visualize_cam(model, layer_idx, filter_indices=classnum, seed_input=preprocess_img, backprop_modifier=None)
</code></pre>

<p>Where <code>layer_idx</code> is the idx of <code>dense_2</code>.</p>

<p>I've tried not defining <code>penultimate_layer</code>, which according to the <a href="https://raghakot.github.io/keras-vis/vis.visualization/#visualize_cam" rel="nofollow noreferrer">documentation</a> sets the parameter to the nearest penultimate <code>Conv</code> or <code>Pooling</code> layer. This gives the same results as <code>penultimate_layer=299</code>.</p>