Skip to content

Commit

Permalink
Merge pull request #27 from philipperemy/heatmap2
Browse files Browse the repository at this point in the history
heatmap
  • Loading branch information
Philippe Rémy authored Mar 12, 2019
2 parents 72f0227 + ce29e49 commit ff48d0a
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 53 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,12 @@ dense_2/Softmax:0
(128, 10)
```

We can also visualise the activations. Here's another example using VGG16:
We can visualise the activations. Here's another example using VGG16:

```
cd examples
python vgg16.py
```

<p align="center">
<img src="assets/cat.jpg">
Expand All @@ -114,6 +119,18 @@ We can also visualise the activations. Here's another example using VGG16:
<br><i>Outputs of the first convolutional layer of VGG16.</i>
</p>

Also, we can visualise the heatmaps of the activations:

```
cd examples
python heat_map.py
```

<p align="center">
<img src="assets/heatmap.png">
</p>


### Repo views (since 2018/10/31)
[![HitCount](http://hits.dwyl.io/philipperemy/keras-activations.svg)](http://hits.dwyl.io/philipperemy/keras-activations)

Binary file added assets/heatmap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions examples/heat_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import decode_predictions
from keras.applications.vgg16 import preprocess_input
from keras.preprocessing.image import img_to_array

model = VGG16()

from PIL import Image
import requests
from io import BytesIO
import numpy as np

url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Gatto_europeo4.jpg/250px-Gatto_europeo4.jpg'
response = requests.get(url)
image = Image.open(BytesIO(response.content))
image = image.crop((0, 0, 224, 224))
image = img_to_array(image)
arr_image = np.array(image)
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
image = preprocess_input(image)
yhat = model.predict(image)
label = decode_predictions(yhat)
label = label[0][0]
print('{} ({})'.format(label[1], label[2] * 100))

import keract

model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
activations = keract.get_activations(model, image)
keract.display_heatmaps(activations, arr_image)
22 changes: 1 addition & 21 deletions examples/vgg16.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from keras.applications.vgg16 import decode_predictions
from keras.applications.vgg16 import preprocess_input
from keras.preprocessing.image import img_to_array
from keras.preprocessing.image import load_img

model = VGG16()

Expand All @@ -13,10 +12,7 @@
url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Gatto_europeo4.jpg/250px-Gatto_europeo4.jpg'
response = requests.get(url)
image = Image.open(BytesIO(response.content))
image = image.crop((0, 0, 244, 244))
image.save('cat.jpg')

image = load_img('cat.jpg', target_size=(224, 224))
image = image.crop((0, 0, 224, 224))
image = img_to_array(image)
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
image = preprocess_input(image)
Expand All @@ -33,19 +29,3 @@
activations = keract.get_activations(model, image)
first = activations.get('block1_conv1/Relu:0')
keract.display_activations(activations)
#
# import matplotlib.pyplot as plt
#
# fig = plt.figure(figsize=(12, 12))
#
# rows = 8
# columns = 8
#
# first = activations.get('block1_conv1/Relu:0')
#
# for i in range(1, columns * rows + 1):
# img = first[0, :, :, i - 1]
# fig.add_subplot(rows, columns, i)
# plt.imshow(img)
# plt.axis('off')
# plt.show()
2 changes: 1 addition & 1 deletion keract/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from keract.keract import *

__version__ = '2.3.0'
__version__ = '2.4.0'
60 changes: 31 additions & 29 deletions keract/keract.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,69 +58,71 @@ def get_activations(model, x, layer_name=None):
return result


def display_activations(activations,save=False):
def display_activations(activations, save=False):
import matplotlib.pyplot as plt
max_rows = 8
max_columns = 8
for layer_name, first in activations.items():
print(layer_name, first.shape, end=' ')
if first.shape[0] != 1:
for layer_name, acts in activations.items():
print(layer_name, acts.shape, end=' ')
if acts.shape[0] != 1:
print('-> Skipped. First dimension is not 1.')
continue
if len(first.shape) <= 2:
if len(acts.shape) <= 2:
print('-> Skipped. 2D Activations.')
continue
print('')
fig = plt.figure(figsize=(12, 12))
plt.axis('off')
plt.title(layer_name)
for i in range(1, min(max_columns * max_rows + 1, first.shape[-1] + 1)):
img = first[0, :, :, i - 1]
for i in range(1, min(max_columns * max_rows + 1, acts.shape[-1] + 1)):
img = acts[0, :, :, i - 1]
fig.add_subplot(max_rows, max_columns, i)
plt.imshow(img)
plt.axis('off')
if save:
plt.savefig(layer_name.split("/")[0]+".png",bbox_inches="tight")
plt.savefig(layer_name.split('/')[0] + '.png', bbox_inches='tight')
else:
plt.show()
def display_heatmaps(activations,image,save=False):


def display_heatmaps(activations, image, save=False):
from PIL import Image
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
import numpy as np
max_rows = 8
max_columns = 8
for layer_name, first in activations.items():
print(layer_name, first.shape, end=' ')
if first.shape[0] != 1:
for layer_name, acts in activations.items():
print(layer_name, acts.shape, end=' ')
if acts.shape[0] != 1:
print('-> Skipped. First dimension is not 1.')
continue
if len(first.shape) <= 2:
if len(acts.shape) <= 2:
print('-> Skipped. 2D Activations.')
continue
print('')
fig = plt.figure(figsize=(12, 12))
plt.axis('off')
plt.title(layer_name)
#computes values rquired to scale the activaions (which will form our heat map) to be in range 0-1
# computes values required to scale the activations (which will form our heat map) to be in range 0-1
scaler = MinMaxScaler()
scaler.fit(first.reshape(-1,1))
for i in range(1, min(max_columns * max_rows + 1, first.shape[-1] + 1)):
img = first[0, :, :, i - 1]
#scales the activaions (which will form our heat map) to be in range 0-1
img=scaler.transform(img)
#resizes heatmap to be same dimesions of image
img=Image.fromarray(img)
img=img.resize((image.shape[0],image.shape[1]),Image.BILINEAR)
img=np.array(img)
scaler.fit(acts.reshape(-1, 1))
for i in range(1, min(max_columns * max_rows + 1, acts.shape[-1] + 1)):
img = acts[0, :, :, i - 1]
# scale the activations (which will form our heat map) to be in range 0-1
img = scaler.transform(img)
# resize heatmap to be same dimensions of image
img = Image.fromarray(img)
img = img.resize((image.shape[0], image.shape[1]), Image.BILINEAR)
img = np.array(img)
fig.add_subplot(max_rows, max_columns, i)
#displays the image
plt.imshow(image)
#overlays a 70% tranparent heatmap onto the image
#Lowest actiavtons are dark, highest are dark red, mid are yellow
plt.imshow(img,alpha=0.3,cmap="jet",interpolation="bilinear")
# display the image
plt.imshow(image / 255.0)
# overlay a 70% transparent heat map onto the image
# Lowest activations are dark, highest are dark red, mid are yellow
plt.imshow(img, alpha=0.3, cmap='jet', interpolation='bilinear')
plt.axis('off')
if save:
plt.savefig(layer_name.split("/")[0]+".png",bbox_inches="tight")
plt.savefig(layer_name.split('/')[0] + '.png', bbox_inches='tight')
else:
plt.show()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='keract',
version='2.3.0',
version='2.4.0',
description='Keras Activations and Gradients',
author='Philippe Remy',
license='MIT',
Expand Down

0 comments on commit ff48d0a

Please sign in to comment.