philipperemy/keract

Calling get_activations in a loop causing problems

hbarovertwo opened this issue · 10 comments

Hopefully someone can point me in the right direction.
I'm using get_activations to do some computations on different layer's output and do something with the result. The workflow is like:

model = VGG16()
model.compile(...)
for item in list:
load_img
get_activations(model, img)
# do stuff with activation layers

each time I loop through takes longer and longer. I've narrowed it down to the get_activations call that is causing the issue. It takes more time each iteration to get the activations. What is a workaround here?

@philipperemy I've narrowed it down to the _evaluate call in get_activations.

@hbarovertwo Could it be possible that the model gets re-compiled everytime the function is called? Do you have a code snippet that I can try to investigate too?

image
300 calls. y-axis is seconds.

I don't see any major problem here. It does not look like it's increasing over time. There are some outliers though.

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

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)
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'])

from time import time
import matplotlib.pyplot as plt
times = []
for i in range(1000):
    a = time()
    activations = keract.get_activations(model, image)
    times.append(time() - a)
    print(times[-1], 'seconds')
    if i % 100 == 0 and i > 0:
        plt.plot(times)
        plt.show()

I'll do a run now and plot the times as well. I compile the model once outside the loop as you do, and loop through a list of unique images. It seems the bug appears when getting activations for different images.

foo

And here is the snippet of code that causes the behavior @philipperemy

import os
import numpy as np
from keract import get_activations
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input
from keras.preprocessing.image import load_img, img_to_array
from tqdm import tqdm
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

model = VGG16(weights='imagenet')
model.compile(optimizer='adam', loss='categorical_crossentropy')

def preprocessing(input_image):
    img = load_img(input_image, target_size=(224,224))
    img = img_to_array(img)
    img = np.expand_dims(img, axis=0)
    img = preprocess_input(img)
    return img

db = '/home/rahul/new_vienna/'
with open('/home/rahul/similarity/trainset.txt','r') as f:
    im_files = eval(f.read())
files = [db+i for i in im_files]

from time import time
import matplotlib.pyplot as plt
times = []

for i in range(len(files)):
    a = time()
    im = preprocessing(files[i])
    activations = get_activations(model, im)
    times.append(time()-a)
    print(times[-1], 'seconds')
    if i % 100 == 0 and i > 0:
        plt.plot(times)
        plt.savefig('foo.png')
        print('figure saved')

foo

And it quickly becomes problematic. Oddly enough I get the same behavior using only 1 image and calling get_activations on it in the same loop as you. When I pip installed keract it also forced an install of a different keras version, the related package versions I have are tensorflow-gpu 1.13.1, keras 2.3.1, keract 2.8.4

@hbarovertwo that's weird. Could it be because of the preprocessing or the fact that the model gets compiled every single step?

Can you try with an update version of keras? I can't reproduce the problem myself... And can you provide a ZIP of your images or something that can help me reproduce the error?

@philipperemy The problem seemed to be in the activations call, I tested the times for each block in the loop and that was the only block that grew with iterations. I was only interested in the output of 3 intermediate layers so I ultimately just used a backend function to run inputs through and catch the outputs of interest. Using the same package versions as mentioned above, going this route didn't produce a similar effect and I was able to run the loop in more or less constant time.

Closing this issue for now as I found a work around and I've moved on to another project. Thanks for the help.

@hbarovertwo Ok thanks for your analysis. If others people encounter this problem, we will re-open this issue. Thanks again!