Multiprocessing with Keras - multithreading

I'm stuck with the following error while I'm trying to parallelize training process over multiple cores. Any help, please?
or is there any other way to do it?
from sklearn import datasets
X, y = datasets.make_classification(n_samples=1000, n_features=20,
n_informative=2, n_redundant=10,
random_state=42)
def train(x):
import tensorflow as tf
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras import backend as K
config = tf.ConfigProto(intra_op_parallelism_threads=1,
inter_op_parallelism_threads=1,
allow_soft_placement=True)
session = tf.Session(config=config)
K.set_session(session)
model = Sequential()
model.add(Dense(units=64, input_dim=20))
model.add(Activation('relu'))
model.add(Dense(units=1))
model.add(Activation('softmax'))
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit(X, y, epochs=5, batch_size=32)
K.clear_session()
return x
import multiprocessing
ls = [1,2,3]
pool = multiprocessing.Pool()
results = pool.map(train, ls)
pool.close()
pool.terminate()
Using TensorFlow backend. Using TensorFlow backend. Using TensorFlow
backend. Epoch 1/5 Exception in thread Thread-9: Traceback (most
recent call last): File "/usr/lib/python2.7/threading.py", line 801,
in __bootstrap_inner self.run() File
"/usr/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs) File
"/usr/lib/python2.7/multiprocessing/pool.py", line 389, in
_handle_results task = get() TypeError: ('init() takes exactly 4 arguments (1 given)', , ())

Related

TypeError: 'list' object is not an iterator - Tensorflow Custom Metric Callback

Running into an issue trying to get a custom metric callback to work with Tensorflow. I've created a minimal working example below to help troubleshoot. I'm running:
Windows 10
Python 3.6
scikit-learn==0.23.2
pandas==0.25.3
numpy==1.18.5
tensorflow==2.3.0
Using the breast cancer binary dataset, I'm trying to invoke the custom metric that was shown as a solution here, but running into the above error, probably because I'm not using it right.
This code...
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_score, recall_score, f1_score
import pandas as pd
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import Callback
# Get binary classification dataset
data = load_breast_cancer(as_frame=True)
print(data)
df = data['data']
df['target'] = data['target']
# Train Test split
train, test = train_test_split(data, test_size = 0.10, shuffle=False)
# Define features and labels
x_train = train.iloc[:, :-1]
y_train = train.iloc[:, -1]
x_test = test.iloc[:, :-1]
y_test = test.iloc[:, -1]
# https://github.com/keras-team/keras/issues/10472#issuecomment-472543538
class Metrics(Callback):
def __init__(self, val_data, batch_size=20):
super().__init__()
self.validation_data = val_data
self.batch_size = batch_size
def on_train_begin(self, logs={}):
# print(self.validation_data)
self.val_f1s = []
self.val_recalls = []
self.val_precisions = []
def on_epoch_end(self, epoch, logs={}):
batches = len(self.validation_data)
total = batches * self.batch_size
val_pred = np.zeros((total,1))
val_true = np.zeros((total))
for batch in range(batches):
xVal, yVal = next(self.validation_data)
val_pred[batch * self.batch_size : (batch+1) * self.batch_size] = np.asarray(self.model.predict(xVal)).round()
val_true[batch * self.batch_size : (batch+1) * self.batch_size] = yVal
val_pred = np.squeeze(val_pred)
_val_f1 = f1_score(val_true, val_pred)
_val_precision = precision_score(val_true, val_pred)
_val_recall = recall_score(val_true, val_pred)
self.val_f1s.append(_val_f1)
self.val_recalls.append(_val_recall)
self.val_precisions.append(_val_precision)
return
# Define a function that creates a basic model
def make_deep_learning_classifier():
model = Sequential()
model.add(Dense(64, activation='relu', input_dim=x_train.shape[1], kernel_initializer='normal'))
model.add(Dense(32, activation='relu', input_dim=x_train.shape[1], kernel_initializer='normal'))
model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer=Adam(), metrics=['accuracy'])
return model
# Get our model
model = make_deep_learning_classifier()
print(model.summary())
# Define some params
batch_size = 32
# Call our custom callback
callback = [Metrics(val_data=[x_test, y_test], batch_size=batch_size)] # < Issue here?
# Start training
model.fit(x_train, y_train, epochs=1000, batch_size=batch_size, verbose=1, callbacks=callback, validation_data=(x_test, y_test))
print(Metrics.val_precisions) # < Issue here?
...produces this traceback...
File "test.py", line 91, in <module>
model.fit(x_train, y_train, epochs=1000, batch_size=batch_size, verbose=1, callbacks=callback, validation_data=(x_test, y_test))
File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training.py", line 108, in _method_wrapper
return method(self, *args, **kwargs)
File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1137, in fit
callbacks.on_epoch_end(epoch, epoch_logs)
File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\callbacks.py", line 416, in on_epoch_end
callback.on_epoch_end(epoch, numpy_logs)
File "test.py", line 54, in on_epoch_end
xVal, yVal = next(self.validation_data)
TypeError: 'list' object is not an iterator
When I change val_data=[x_test, y_test] to val_data=(x_test, y_test) in the callback variable, I get...
TypeError: 'tuple' object is not an iterator
The user who proposed this callback solution mentions something about generators, but I'm not sure how those work. Just trying to define my own custom metric for Tensorflow/Keras. I won't be using this exact callback, but once I get this one running, I can modify it to my own. Just providing it as an example that seemed to work in that GitHub post that I hope someone will be able to point out what I'm doing wrong.
Thanks!
UPDATE
Using the solution below, I try to properly call my iterator function on my val_data by using
iter_val_data = iter(self.validation_data)
for batch in range(batches):
xVal, yVal = next(iter_val_data)
But then I get a too many values to unpack error, so I change it to:
iter_val_data = iter(self.validation_data)
for batch in range(batches):
xVal = next(iter_val_data)
yVal = next(iter_val_data)
Then I get the error:
Traceback (most recent call last):
File "test.py", line 89, in <module>
model.fit(x_train, y_train, epochs=1000, batch_size=batch_size, verbose=1, callbacks=callback, validation_data=(x_test, y_test))
File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training.py", line 108, in _method_wrapper
return method(self, *args, **kwargs)
File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1137, in fit
callbacks.on_epoch_end(epoch, epoch_logs)
File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\tensorflow\python\keras\callbacks.py", line 416, in on_epoch_end
callback.on_epoch_end(epoch, numpy_logs)
File "test.py", line 53, in on_epoch_end
val_pred[batch * self.batch_size : (batch+1) * self.batch_size] = np.asarray(self.model.predict(xVal)).round()
ValueError: could not broadcast input array from shape (57,1) into shape (32,1)
Ideas from here? Try and run the code in the same environment as described above if you can. Thanks!
As you see here and as your error messages states, you need to use next() with an iterator. You call next() on the list, how should next() know, which element is coming next? For that you need an iterator, that saves that state. So this should fix your issue:
iter_val_data = iter(self.validation_data)
for batch in range(batches):
xVal, yVal = next(iter_val_data)

"The CPU implementation of FusedBatchNorm only supports NHWC tensor format for now."

I am trying to recreate a model and re-produce its published results. I use TF 2.0 and the model I think was coded with Theano backend. The model came from this repo in github, for context.
I also do not use tensorflow-gpu as it is not compatible with my hardware setup.
Anyway, at first I've encountered a lot of error trying to load its weights or even the model. When I realized the save/load functions are just messed up, I moved on to trying to just load and train the model. Since I use Tensorflow, I modified the code to use the 'channels_last' format, or NHWC, as the error says so.
Here's my import list:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from tensorflow import keras
import cv2
import os
import pathlib
import shutil
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
The modified model:
def createModel():
model = keras.models.Sequential()
model.add(keras.layers.Lambda(norm_input, input_shape=(28,28,1), output_shape=(28,28,1)))
model.add(keras.layers.Conv2D(32, (3,3)))
model.add(keras.layers.LeakyReLU())
model.add(keras.layers.BatchNormalization(axis=1))
model.add(keras.layers.Conv2D(32, (3,3)))
model.add(keras.layers.LeakyReLU())
model.add(keras.layers.MaxPooling2D())
model.add(keras.layers.BatchNormalization(axis=1))
model.add(keras.layers.Conv2D(64, (3,3)))
model.add(keras.layers.LeakyReLU())
model.add(keras.layers.BatchNormalization(axis=1))
model.add(keras.layers.Conv2D(64, (3,3)))
model.add(keras.layers.LeakyReLU())
model.add(keras.layers.MaxPooling2D())
model.add(keras.layers.Flatten())
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Dense(512))
model.add(keras.layers.LeakyReLU())
model.add(keras.layers.BatchNormalization())
model.add(keras.layers.Dropout(0.3))
model.add(keras.layers.Dense(10, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
return model
How I loaded and preprocessed the MNIST dataset:
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
test_labels = y_test
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
x_train = x_train.astype(np.float32)
x_test = x_test.astype(np.float32)
x_train /= 255
x_test /= 255
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)
The ImageDataGenerator:
gen = keras.preprocessing.image.ImageDataGenerator(
rotation_range=12,
width_shift_range=0.1,
shear_range=0.3,
height_shift_range=0.1,
zoom_range=0.1,
data_format='channels_last')
And lastly, the function to train the models:
def fit_model(m):
m.fit_generator(batches, steps_per_epoch=steps_per_epoch, epochs=1, verbose=0,
validation_data=test_batches, validation_steps=validation_steps)
m.optimizer.lr = 0.1
m.fit_generator(batches, steps_per_epoch=steps_per_epoch, epochs=4, verbose=0,
validation_data=test_batches, validation_steps=validation_steps)
m.optimizer.lr = 0.01
m.fit_generator(batches, steps_per_epoch=steps_per_epoch, epochs=12, verbose=0,
validation_data=test_batches, validation_steps=validation_steps)
m.optimizer.lr = 0.001
m.fit_generator(batches, steps_per_epoch=steps_per_epoch, epochs=18, verbose=0,
validation_data=test_batches, validation_steps=validation_steps)
return m
The last code snippet is where the error points to, but I don't know what exactly broke there that's related to the image format. Specifically, it points at the third line, or the line that starts with the validation_data=....
The full error is:
Component function execution failed: Internal: The CPU implementation of FusedBatchNorm only supports NHWC tensor format for now.
[[{{node batch_normalization_v2/cond/then/_0/FusedBatchNorm}}]]
And traceback:
Traceback (most recent call last):
File "model3.py", line 113, in <module>
m = fit_model(createModel())
File "model3.py", line 52, in fit_model
validation_data=test_batches, validation_steps=validation_steps)
File "/home/ren/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 1515, in fit_generator
steps_name='steps_per_epoch')
File "/home/ren/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_generator.py", line 257, in model_iteration
batch_outs = batch_function(*batch_data)
File "/home/ren/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 1259, in train_on_batch
outputs = self._fit_function(ins) # pylint: disable=not-callable
File "/home/ren/.local/lib/python3.6/site-packages/tensorflow/python/keras/backend.py", line 3217, in __call__
outputs = self._graph_fn(*converted_inputs)
File "/home/ren/.local/lib/python3.6/site-packages/tensorflow/python/eager/function.py", line 558, in __call__
return self._call_flat(args)
File "/home/ren/.local/lib/python3.6/site-packages/tensorflow/python/eager/function.py", line 627, in _call_flat
outputs = self._inference_function.call(ctx, args)
File "/home/ren/.local/lib/python3.6/site-packages/tensorflow/python/eager/function.py", line 415, in call
ctx=ctx)
File "/home/ren/.local/lib/python3.6/site-packages/tensorflow/python/eager/execute.py", line 66, in quick_execute
six.raise_from(core._status_to_exception(e.code, message), None)
File "<string>", line 3, in raise_from
tensorflow.python.framework.errors_impl.InternalError: The CPU implementation of FusedBatchNorm only supports NHWC tensor format for now.
[[{{node batch_normalization_v2/cond/then/_0/FusedBatchNorm}}]] [Op:__inference_keras_scratch_graph_3602]
I'd expect it to be fixed when I added the line tf.keras.backend.set_image_data_format('channels_last') at the top of my code. I also even put the same argument in the ImageDataGenerator mentioned earlier for good measure. So I honestly don't have any idea what I've missed or where I went wrong.
DISCLAIMER
I am only a novice in this area, and have only based this answer on what I've read in the docs. I have no full understanding of the possible repercussions and its extent to the model; at worst, it may affect its performance and accuracy. At best, this solution can be considered only a makeshift patch to suppress the error, at least until someone else confirms it as otherwise. Any confirmations, clarifications, suggestions, and alternate solutions are always welcome.
From Keras documentation on BatchNormalization:
axis: Integer, the axis that should be normalized (typically the features axis). For instance, after a Conv2D layer with data_format="channels_first", set axis=1 in BatchNormalization.
Since I use channels_last or NHWC as image format, simply equating axis to -1 in the parameter fixed it. To be clear:
keras.layers.BatchNormalization(axis=-1)
Fixed my problem.
if you want to operate Batch Normalization on the first axis this little trick override the error:
replace: model.add(keras.layers.BatchNormalization(axis=1))
with:
model.add(keras.layers.Permute((2, 3, 1)))
model.add(keras.layers.BatchNormalization(axis=-1))
model.add(keras.layers.Permute((3, 1, 2)))

How to fix AttributeError: 'NoneType' object has no attribute '_inbound_nodes' that comes while creating lstm model using manhattan distance?

I am trying to create a neural net model that return the similarity score of two sentences using manhattan LSTM (e.g.https://medium.com/mlreview/implementing-malstm-on-kaggles-quora-question-pairs-competition-8b31b0b16a07 ). I have used quora-questions pairs dataset and generated their embeddings using google-bert. Now, i want to create a LSTM model like the above examples and use it but i am getting the following error:
Using TensorFlow backend.
(100000, 1, 768)
(100000, 1, 768)
(100000,)
(100000, 100)
Traceback (most recent call last):
File "train_model_manhattan.py", line 151, in <module>
model = Model(inputs=[inp1,inp2], outputs=[malstm_distance])
File "/home/manishp/anaconda3/envs/bert_env/lib/python3.6/site-packages/keras/legacy/interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "/home/manishp/anaconda3/envs/bert_env/lib/python3.6/site-packages/keras/engine/network.py", line 93, in __init__
self._init_graph_network(*args, **kwargs)
File "/home/manishp/anaconda3/envs/bert_env/lib/python3.6/site-packages/keras/engine/network.py", line 231, in _init_graph_network
self.inputs, self.outputs)
File "/home/manishp/anaconda3/envs/bert_env/lib/python3.6/site-packages/keras/engine/network.py", line 1366, in _map_graph_network
tensor_index=tensor_index)
File "/home/manishp/anaconda3/envs/bert_env/lib/python3.6/site-packages/keras/engine/network.py", line 1353, in build_map
node_index, tensor_index)
File "/home/manishp/anaconda3/envs/bert_env/lib/python3.6/site-packages/keras/engine/network.py", line 1353, in build_map
node_index, tensor_index)
File "/home/manishp/anaconda3/envs/bert_env/lib/python3.6/site-packages/keras/engine/network.py", line 1325, in build_map
node = layer._inbound_nodes[node_index]
AttributeError: 'NoneType' object has no attribute '_inbound_nodes'
Here is what I have already tried. Note that embeddings returned has shape(768) i.e. is a vector of size 768 like this [1.2e+05 2.7e-01 7.8 .... 8.9]
print(np.shape(train_vec1)) => (100000, 1, 768)
print(np.shape(train_vec2)) => (100000, 1, 768)
print(np.shape(train_label))
#################################################
def exponent_neg_manhattan_distance(left, right):
return np.exp(-np.sum(np.abs(left-right), axis=1, keepdims=True))
def manhattan_distance(left, right):
''' Helper function for the similarity estimate of the LSTMs outputs'''
print(np.shape(left))
return K.sum(K.abs(left - right), axis=1, keepdims=True)
#################################################
import keras
from keras.layers import Input, LSTM, Dense
from keras.models import Model
inp1= Input(shape=(768,))
inp2= Input(shape=(768,))
x = keras.layers.concatenate([inp1, inp2],axis=-1)
x = Dense(1024, activation='relu')(x)
x = Dropout(0.5) (x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5) (x)
x = Dense(64, activation='relu')(x)
out=Dense(1)(x)
# Since this is a siamese network, both sides share the same LSTM
shared_lstm = LSTM(100)
left_output = shared_lstm(train_vec1_tensor)
right_output = shared_lstm(train_vec2_tensor)
# Calculates the distance as defined by the MaLSTM model
malstm_distance = Lambda(function=lambda x: manhattan_distance(x[0], x[1]),output_shape=lambda x: (x[0][0], 1))([left_output, right_output])
#######################
Getting error when code flow reaches the following line
#######################
model = Model(inputs=[inp1,inp2], outputs=[malstm_distance])
This is my entire code
import os
data_file='quora_duplicate_questions.tsv'
# 0 means dont load, 1 means fetch from file
LOAD_ENCODING_FROM_FILE=1
encoding_data_file_quest1='encoding_quest1'
encoding_data_file_quest2='encoding_quest2'
encoding_data_file_label='quest_label'
#################################################
import numpy as np
import pandas as pd
import tensorflow as tf
import re
from bert_serving.client import BertClient
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
import numpy as np
import pickle
from keras import models
from keras import layers
from keras import optimizers
from keras.layers import Dropout
from keras import backend as K
from keras.layers import Lambda
#################################################
maxlen = 125 # We will cut reviews after 125 words
# The next step is to tranform all sentences to fixed length encoding using bert embeddings
# [0.1 0.4 0.4] [0.9 0.6 0.1] 2.4
# [0.4 0.1 0.3] [0.5 0.6 0.1] 1.0
# Save the encodings in a file
if LOAD_ENCODING_FROM_FILE == 1:
with open(encoding_data_file_quest1, "rb") as fp:
vec1=pickle.load(fp)
with open(encoding_data_file_quest2, "rb") as fp:
vec2=pickle.load(fp)
with open(encoding_data_file_label, "rb") as fp:
label=pickle.load(fp)
train_vec1 = np.asarray(vec1, np.float32)
train_vec2 = np.asarray(vec2, np.float32)
train_vec1 = train_vec1.reshape((100000,1,768))
train_vec2 = train_vec2.reshape((100000,1,768))
train_vec1_tensor = K.cast(train_vec1,dtype='float32')
train_vec2_tensor = K.cast(train_vec2,dtype='float32')
train_label = np.asarray(label,np.float32)
print(np.shape(train_vec1))
print(np.shape(train_vec2))
print(np.shape(train_label))
#################################################
def exponent_neg_manhattan_distance(left, right):
return np.exp(-np.sum(np.abs(left-right), axis=1, keepdims=True))
def manhattan_distance(left, right):
''' Helper function for the similarity estimate of the LSTMs outputs'''
print(np.shape(left))
return K.sum(K.abs(left - right), axis=1, keepdims=True)
#################################################
import keras
from keras.layers import Input, LSTM, Dense
from keras.models import Model
inp1= Input(shape=(768,))
inp2= Input(shape=(768,))
x = keras.layers.concatenate([inp1, inp2],axis=-1)
x = Dense(1024, activation='relu')(x)
x = Dropout(0.5) (x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5) (x)
x = Dense(64, activation='relu')(x)
out=Dense(1)(x)
# Since this is a siamese network, both sides share the same LSTM
shared_lstm = LSTM(100)
left_output = shared_lstm(train_vec1_tensor)
right_output = shared_lstm(train_vec2_tensor)
# Calculates the distance as defined by the MaLSTM model
malstm_distance = Lambda(function=lambda x: manhattan_distance(x[0], x[1]),output_shape=lambda x: (x[0][0], 1))([left_output, right_output])
#######################
Getting error when code flow reaches the following line
#######################
model = Model(inputs=[inp1,inp2], outputs=[malstm_distance])
model.summary()
optimizer = optimizers.Adadelta(clipnorm=gradient_clipping_norm)
model.compile(optimizer,
loss='mean_squared_error',
metrics=['accuracy'])
history=model.fit([train_vec1, train_vec2], train_label,
epochs=30,batch_size=200,
validation_split=0.2)
I want the model to take two embeddings, calculate the manhattan distance of the embeddings and return the distance.
left_output and right_output are obtained from the LSTM layer. The inputs are fed to the Input layer and through a series of Dense layers. However, note that there is no connection anywhere between the set of Dense layers and the LSTM. The Model expects the output from the LSTM layer which is not possible. This line keras.layers.concatenate should use the outputs from the shared_lstm rather than using the outputs of input layers directly. Like this
keras.layers.concatenate([left_output, right_output],axis=-1)
Only, then this can be a Siamese network.

Saving Keras model fails after renaming layers

I have a problem with renaming layers. Below is the simplest example illustrating the problem:
from keras.layers import Dense, Conv2D, Flatten, Input
from keras.models import Model
inputs = Input(shape=(784,))
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)
# This creates a model that includes
# the Input layer and three Dense layers
model = Model(inputs=inputs, outputs=predictions)
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
print(model.summary())
for i, layer in enumerate(model.layers):
layer.name = 'layer' + str(i)
print(model.summary())
model.save('temp')
It fails with the message:
Traceback (most recent call last):
File "scripts/save_load.py", line 24, in <module>
model.save('temp')
File "/lib/python3.6/site-packages/keras/engine/topology.py", line 2416, in save
save_model(self, filepath, overwrite)
File "/lib/python3.6/site-packages/keras/models.py", line 101, in save_model
'config': model.get_config()
File "/lib/python3.6/site-packages/keras/engine/topology.py", line 2281, in get_config
new_node_index = node_conversion_map[node_key]
KeyError: 'layer0_ib-0'
What am I doing wrong?
I know I can pass names to the layer constructor, it seems not to fail in this case, but is there any chance to improve my solution?

What should the generator passed to predict_generator() return?

I am calling Keras predict_generator() like:
bottleneck_features_train = model.predict_generator(train_gen, len(telemetry))
where train_gen() is defined like
def train_gen():
# ...
yield (X, y)
and X is a numpy array with shape (48, 299, 299, 3), y is a numpy array with shape (48,)
I get the error below. What should I do instead?
Otherwise, a link to a working example would help. Only examples I have found are for Keras 1 or using ImageDataGenerator.flow().
I am running Keras 2.0.2.
Here the error:
Traceback (most recent call last):
File "/home/fanta/workspace/CarND-Behavioral-Cloning-P3/cache.py", line 143, in <module>
tf.app.run()
File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/platform/app.py", line 44, in run
_sys.exit(main(_sys.argv[:1] + flags_passthrough))
File "/home/fanta/workspace/CarND-Behavioral-Cloning-P3/cache.py", line 138, in main
bottleneck_features_train = model.predict_generator(train_gen, len(telemetry))
File "/usr/local/lib/python3.5/dist-packages/keras/legacy/interfaces.py", line 88, in wrapper
return func(*args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 2094, in predict_generator
outs = self.predict_on_batch(x)
File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 1677, in predict_on_batch
self._feed_input_shapes)
File "/usr/local/lib/python3.5/dist-packages/keras/engine/training.py", line 100, in _standardize_input_data
'Found: array with shape ' + str(data.shape))
ValueError: The model expects 0 input arrays, but only received one array. Found: array with shape (48, 299, 299, 3)
Process finished with exit code 1
===== UPDATE =====
The issue is not related to the generator. Here below a short program to reproduce it. Note that if you switch the network from inception to vgg, it works fine.
from keras.applications.inception_v3 import InceptionV3
from keras.applications.vgg16 import VGG16
from keras.layers import Input, AveragePooling2D
from keras.models import Model
from keras.datasets import cifar10
from scipy.misc import imresize
import pickle
import tensorflow as tf
import keras.backend as K
import numpy as np
network='inception' # Must be 'inception' or 'vgg'
dataset='cifar10'
batch_size=64
if network == 'vgg':
size = (224, 224)
elif network == 'inception':
size = (299, 299)
else:
assert False, "network must be either 'inception' or 'vgg'"
def create_model():
input_tensor = Input(shape=(size[0], size[1], 3))
if network == 'inception':
model = InceptionV3(input_tensor=input_tensor, include_top=False)
x = model.output
x = AveragePooling2D((8, 8), strides=(8, 8))(x)
model = Model(model.input, x)
elif network == 'vgg':
model = VGG16(input_tensor=input_tensor, include_top=False)
x = model.output
x = AveragePooling2D((7, 7))(x)
model = Model(model.input, x)
else:
assert False
return model
def main():
# Download and load cifar10 dataset
(X_train, y_train), (_, _) = cifar10.load_data()
# Reduce the dataset to the first 1000 entries, to save memory and computation time
X_train = X_train[0:1000]
y_train = y_train[0:1000]
# Resize dataset images to comply with expected input image size
X_train = [imresize(image, size) for image in X_train]
X_train = np.array(X_train)
# File name where to save bottlenecked features
train_output_file = "{}_{}_{}.p".format(network, dataset, 'bottleneck_features_train')
print("Saving to", train_output_file)
with tf.Session() as sess:
K.set_session(sess)
K.set_learning_phase(1)
model = create_model()
# We skip pre-processing and bottleneck the features
bottleneck_features_train = model.predict(X_train, batch_size=batch_size, verbose=1)
data = {'features': bottleneck_features_train, 'labels': y_train}
pickle.dump(data, open(train_output_file, 'wb'))
if __name__ == '__main__':
main()
At prediction step your generator should only yield the input and not the targets. So only the X, not the y.
Does that help?

Resources