I have some tensorflow model which I need to export in a saved model. Below is the simplified code of the model, which I am trying to export.
import tensorflow as tf
def foo(x):
return tf.reduce_sum(x)
inputs = tf.keras.layers.Input(shape=(128,128,3))
y = tf.keras.layers.Conv2D(filters=32, kernel_size=3, padding='SAME')(inputs)
y = tf.keras.layers.ReLU()(y)
outputs = tf.map_fn(foo, y, dtype=(tf.float32))
model = tf.keras.models.Model(inputs=inputs, outputs=outputs)
model.save('./export', save_format='tf')
but while exporting the model I am getting the following error.
/Users/bruce/.venv/bin/python /Users/bruce/test_project/mymodel/test.py
Traceback (most recent call last):
File "/Users/bruce/test_project/mymodel/test.py", line 12, in <module>
outputs = tf.map_fn(foo, y, dtype=(tf.float32))
File "/Users/bruce/.venv/lib/python3.6/site-packages/tensorflow_core/python/ops/map_fn.py", line 228, in map_fn
for elem in elems_flat]
File "/Users/bruce/.venv/lib/python3.6/site-packages/tensorflow_core/python/ops/map_fn.py", line 228, in <listcomp>
for elem in elems_flat]
File "/Users/bruce/.venv/lib/python3.6/site-packages/tensorflow_core/python/ops/tensor_array_ops.py", line 1078, in __init__
name=name)
File "/Users/bruce/.venv/lib/python3.6/site-packages/tensorflow_core/python/ops/tensor_array_ops.py", line 716, in __init__
self._tensor_array = [None for _ in range(size)]
TypeError: 'Tensor' object cannot be interpreted as an integer
I cannot remove the part tf.map_fn which is doing some essential processing which I need in the saved model while deploying it.
You need to use a custom layer:
class MyMapLayer(tf.keras.layers.Layer):
def __init__(*args, **kwargs)
super().__init__(*args, **kwargs)
def foo(self, x):
return tf.reduce_sum(x)
def call(self, inputs, **kwargs):
return tf.map_fn(self.foo, inputs, dtype=(tf.float32))
Then, in your model:
inputs = tf.keras.layers.Input(shape=(128,128,3))
y = tf.keras.layers.Conv2D(filters=32, kernel_size=3, padding='SAME')(inputs)
y = tf.keras.layers.ReLU()(y)
outputs = MyMapLayer()(y)
model = tf.keras.models.Model(inputs=inputs, outputs=outputs)
Related
I am building a model with a custom attention layer as implemented in Tensorflow's nmt tutorial. I used the same layer code with a few changes which I found as suggestions in order to solve my problem.
The problem is that I cannot load the model from file after I save it when I have this custom layer. This is the layer class:
class BahdanauAttention(layers.Layer):
def __init__(self, output_dim=30, **kwargs):
super(BahdanauAttention, self).__init__(**kwargs)
self.W1 = tf.keras.layers.Dense(output_dim)
self.W2 = tf.keras.layers.Dense(output_dim)
self.V = tf.keras.layers.Dense(1)
def call(self, inputs, **kwargs):
query = inputs[0]
values = inputs[1]
query_with_time_axis = tf.expand_dims(query, 1)
score = self.V(tf.nn.tanh(
self.W1(query_with_time_axis) + self.W2(values)))
attention_weights = tf.nn.softmax(score, axis=1)
context_vector = attention_weights * values
context_vector = tf.reduce_sum(context_vector, axis=1)
return context_vector, attention_weights
def get_config(self):
config = super(BahdanauAttention, self).get_config()
config.update({
'W1': self.W1,
'W2': self.W2,
'V': self.V,
})
return config
I am saving the model with keras' ModelCheckpoint callback:
path = os.path.join(self.dir, 'model_{}'.format(self.timestamp))
callbacks.append(ModelCheckpoint(path, save_best_only=True, monitor='val_loss', mode='min'))
Later, I am loading the model like so:
self.model = load_model(path, custom_objects={'BahdanauAttention': BahdanauAttention, 'custom_loss': self.custom_loss})
This is the error message I am getting:
raise TypeError(error_message, kwarg)
TypeError: ('Keyword argument not understood:', 'W1')
and full traceback:
Traceback (most recent call last):
File "models/lstm.py", line 49, in load_model
'dollar_mape_loss': self.dollar_mape_loss})
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/saving/save.py", line 187, in load_model
return saved_model_load.load(filepath, compile, options)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 121, in load
path, options=options, loader_cls=KerasObjectLoader)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/saved_model/load.py", line 633, in load_internal
ckpt_options)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 194, in __init__
super(KerasObjectLoader, self).__init__(*args, **kwargs)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/saved_model/load.py", line 130, in __init__
self._load_all()
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 215, in _load_all
self._layer_nodes = self._load_layers()
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 315, in _load_layers
layers[node_id] = self._load_layer(proto.user_object, node_id)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 341, in _load_layer
obj, setter = self._revive_from_config(proto.identifier, metadata, node_id)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 359, in _revive_from_config
self._revive_layer_from_config(metadata, node_id))
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 417, in _revive_layer_from_config
generic_utils.serialize_keras_class_and_config(class_name, config))
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/layers/serialization.py", line 175, in deserialize
printable_module_name='layer')
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/utils/generic_utils.py", line 360, in deserialize_keras_object
return cls.from_config(cls_config)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py", line 697, in from_config
return cls(**config)
File "models/lstm.py", line 310, in __init__
super(BahdanauAttention, self).__init__(**kwargs)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/training/tracking/base.py", line 457, in _method_wrapper
result = method(self, *args, **kwargs)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py", line 318, in __init__
generic_utils.validate_kwargs(kwargs, allowed_kwargs)
File "venv/m/lib/python3.7/site-packages/tensorflow/python/keras/utils/generic_utils.py", line 778, in validate_kwargs
raise TypeError(error_message, kwarg)
TypeError: ('Keyword argument not understood:', 'W1')
Similar questions suggest that the code is using different versions of Keras and TensorFlow. I am only using TensorFlow's Keras. These are the imports
from tensorflow.keras.models import load_model
from tensorflow.keras.callbacks import EarlyStopping, CSVLogger, ModelCheckpoint
from tensorflow.keras import layers
Following keras' documentation on custom layers, They recommend that any weights should not be initialized in __init__() but in build(). This way the weights do not need to be added to the config and the error will be resolved.
This is the updated custom layer class:
class BahdanauAttention(tf.keras.layers.Layer):
def __init__(self, units=30, **kwargs):
super(BahdanauAttention, self).__init__(**kwargs)
self.units = units
def build(self, input_shape):
self.W1 = tf.keras.layers.Dense(self.units)
self.W2 = tf.keras.layers.Dense(self.units)
self.V = tf.keras.layers.Dense(1)
def call(self, inputs, **kwargs):
query = inputs[0]
values = inputs[1]
query_with_time_axis = tf.expand_dims(query, 1)
score = self.V(tf.nn.tanh(
self.W1(query_with_time_axis) + self.W2(values)))
attention_weights = tf.nn.softmax(score, axis=1)
context_vector = attention_weights * values
context_vector = tf.reduce_sum(context_vector, axis=1)
return context_vector, attention_weights
def get_config(self):
config = super(BahdanauAttention, self).get_config()
config.update({
'units': self.units,
})
return config
I also have this problem.
I've tried a lot of methods and found that this method can be used.
first,build model
model = TextAttBiRNN(maxlen, max_features, embedding_dims).get_model()
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
second, load weights:
I solved the problem with this:
model_file = "/content/drive/My Drive/dga/output_data/model_lstm_att_test_v6.h5"
model.load_weights(model_file)
then,we will find the modle can be use.
in this way,I avoided the previous questions.
I am loading a pretrained attention model in Keras using load_model() .
My Attention class is defined as below.
# attention class
from keras.engine.topology import Layer
from keras import initializers, regularizers, constraints
from keras import backend as K
class Attention(Layer):
def __init__(self, step_dim, w_regularizer=None, b_regularizer=None,
w_constraint=None, b_constraint=None, bias=True, **kwargs):
self.supports_masking = True
# weight initializer
self.init = initializers.get('glorot_uniform')
self.w_regularizer = regularizers.get(w_regularizer)
self.b_regularizer = regularizers.get(b_regularizer)
self.w_constraint = constraints.get(w_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.step_dim = step_dim
self.features_dim = 0
super(Attention, self).__init__(**kwargs)
def build(self, input_shape):
assert len(input_shape) == 3
self.w = self.add_weight(shape=(input_shape[-1],),
initializer=self.init, name='{}_w'.format(self.name),
regularizer=self.w_regularizer,
constraint=self.w_constraint)
self.features_dim = input_shape[-1]
if self.bias:
self.b = self.add_weight(shape=(input_shape[1],),
initializer='zero', name='{}_b'.format(self.name),
regularizer=self.b_regularizer,
constraint=self.b_constraint)
else:
self.b = None
self.built = True
def compute_mask(self, input, input_mask=None):
return None
def call(self, x, mask=None):
features_dim = self.features_dim
step_dim = self.step_dim
eij = K.reshape(K.dot(K.reshape(x, (-1, features_dim)),
K.reshape(self.w, (features_dim, 1))), (-1, step_dim))
if self.bias:
eij += self.b
eij = K.tanh(eij)
a = K.exp(eij)
if mask is not None:
a *= K.cast(mask, K.floatx())
a /= K.cast(K.sum(a, axis=1, keepdims=True) + K.epsilon(), K.floatx())
a = K.expand_dims(a)
weighted_input = x * a
return K.sum(weighted_input, axis=1)
def compute_output_shape(self, input_shape):
return input_shape[0], self.features_dim
def get_config(self):
config = {
'step_dim': self.step_dim,
'w_regularizer': self.w_regularizer,
'w_constraint': self.w_constraint,
'b_regularizer': self.b_regularizer,
'b_constraint': self.b_constraint,
'bias': self.bias
}
base_config = super(Attention, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
The model is called in test_loadmod.py as
from attention import Attention
from keras.models import load_model
model = load_model('attention_wo_cval.h5', custom_objects={'Attention': Attention})
print(model)
The custom Attention model is made available using load_model() and custom_objects is passed into it as described here.
However it doesnt seem to find the step_dim attribute. Throws up the below error. Any idea how to get this going ? Thanks for your time and help.
Error while loading
TypeError: __init__() missing 1 required positional argument: 'step_dim'
File "test_loadmod.py", line 4, in <module>
model = load_model('attention_wo_cval.h5', custom_objects={'Attention': Attention})
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\engine\saving.py", line 492, in load_wrapper
return load_function(*args, **kwargs)
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\engine\saving.py", line 584, in load_model
model = _deserialize_model(h5dict, custom_objects, compile)
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\engine\saving.py", line 274, in _deserialize_model
model = model_from_config(model_config, custom_objects=custom_objects)
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\engine\saving.py", line 627, in model_from_config
return deserialize(config, custom_objects=custom_objects)
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\layers\__init__.py", line 165, in deserialize
return deserialize_keras_object(config,
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\utils\generic_utils.py", line 144, in deserialize_keras_object
return cls.from_config(
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\engine\network.py", line 1056, in from_config
process_layer(layer_data)
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\engine\network.py", line 1041, in process_layer
layer = deserialize_layer(layer_data,
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\layers\__init__.py", line 165, in deserialize
return deserialize_keras_object(config,
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\utils\generic_utils.py", line 149, in deserialize_keras_object
return cls.from_config(config['config'])
File "C:\Users\RV\AppData\Local\Programs\Python\Python38\lib\site-packages\keras\engine\base_layer.py", line 1179, in from_config
return cls(**config)
TypeError: __init__() missing 1 required positional argument: 'step_dim'
The get_config method is the right solution, but you have to pay attention to save the model when this method is updated.
So:
First add the get_config method
Save the model (with this method)
Load the method
I am trying to apply shap.deepexplainer to explain the model output.
My model class is as follows:
class MyModel(tf.keras.Model):
def __init__(self,
input_dim,
emb_dim=128,
alpha_hidden_dim_size=128,
beta_hidden_dim_size=128,
keep_prob_emb=0.25,
keep_prob_context=0.25,
num_class=1):
super(MyModel, self).__init__()
self.embedding = layers.Dense(emb_dim,
use_bias=False,
input_shape=(input_dim, ))
self.emb_drp = layers.Dropout(keep_prob_emb)
self.enroll = layers.Dense(emb_dim, activation='tanh')
self.gru_alpha = layers.Bidirectional(
layers.LSTM(alpha_hidden_dim_size, return_sequences=True))
self.gru_beta = layers.Bidirectional(
layers.LSTM(beta_hidden_dim_size, return_sequences=True))
self.alpha = layers.Dense(1)
self.beta = layers.Dense(emb_dim, activation='tanh')
self.context_drp = layers.Dropout(keep_prob_context)
self.out = layers.Dense(num_class)
def call(self, visits, enroll, lengths, **kwargs):
max_len = lengths[tf.argmax(lengths)]
visits = visits[:, :max_len]
emb = self.embedding(visits)
emb = self.emb_drp(emb, training=kwargs.get('training', False))
enroll = self.enroll(enroll)
mask = tf.sequence_mask(lengths)
h_a = self.gru_alpha(emb, mask=mask)
h_b = self.gru_beta(emb, mask=mask)
preAlpha = self.alpha(h_a)
preAlpha = tf.keras.backend.squeeze(preAlpha, axis=2)
mask_norm = (1 - tf.cast(mask, tf.float32)) * NEG_INF
alpha = tf.nn.softmax(preAlpha + mask_norm, axis=1)
beta = self.beta(h_b)
c_t = tf.math.reduce_sum(alpha[:, :, None] * beta * emb, axis=1)
c_t = layers.add([c_t, enroll])
c_t = self.context_drp(c_t, training=kwargs.get('training', False))
preY = self.out(c_t)
return preY, alpha, beta
When I applied my model as:
model = MyModel(**flags)
And the model is successfully loaded:
print(model)
<__main__.MyModel object at 0x7f51db414400>
Then I am trying to use the
background = X.loc[10:20]
e = shap.DeepExplainer((model.layers[0].input, model.layers[-1].output), background)
but then it gives me the error:
AttributeError: Layer dense is not connected, no input to return.
Traceback (most recent call last): File
"/home/ANANT/codes/test/env/lib/python3.6/site-packages/tensorflow/python/keras/engine/base_layer.py",line
1808, in input' is not connected, no input to return.')
And also the model.layers[-1].output can not give proper output neither:
AttributeError: Layer dense_4 has no inbound nodes. Traceback (most
recent call last): File
"/home/ANANT/test/env/lib/python3.6/site-packages/tensorflow/python/keras/engine/base_layer.py",
line 1827, in output raise AttributeError('Layer ' + self.name + ' has
no inbound nodes.')
My package versions are: keras==2.3.1, tensorflow==1.15.3, shap==0.35.0
I stuck at this question for a few days, tried shap.KernelExplainer as well, and it gives me a different error:
shap.KernelExplainer(model, df_fis, link="logit")
And the error is as follows:
TypeError: call() missing 2 required positional arguments: 'enroll'
and 'lengths' Traceback (most recent call last): File
"/home/ANANT/test/env/lib/python3.6/site-packages/shap/explainers/kernel.py",
line 97, in __init__model_null = match_model_to_data(self.model,
self.data) File
"/home/ANANT/test/env/lib/python3.6/site-packages/shap/common.py",
line 89, in match_model_to_dataout_val = model.f(data.data) File
"/home/ANANT/test/env/lib/python3.6/site-packages/tensorflow/python/keras/engine/base_layer.py",
line 968, in __call__outputs = self.call(cast_inputs, *args, **kwargs)
Please help, thanks in advance!
I think you missed the softmax part
Pytorch version
self.softmax = LogSoftmax(dim=1)
Keras version
layers.Dense(num_classes, activation="softmax")
Add the above line at the end of your __init__ method, see if it works
I am trying to use Pytorch grouped Conv2d operator on very large images (10k x 10k pixels). I am getting an RuntimeError: offset is too big error when trying to apply a grouped convolution in the network. Anyone knows how to circumvent this?
Code for reproducibility:
import torch
import torch.nn as nn
import pdb
def create_img(size, batch_size=1, channels=3):
return torch.FloatTensor(batch_size, channels, size, size).uniform_(-1, 1)
class TestModel(nn.Module):
def __init__(self):
super(TestModel, self).__init__()
self.conv1 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=(3,3), stride=(1,1), groups=64, bias=False)
def forward(self, x):
out = self.conv1(x)
return out
if __name__ == '__main__':
model = TestModel()
data = create_img(5002, channels=64)
out = model(data)
pdb.set_trace()
and the error:
Traceback (most recent call last):
File "test.py", line 26, in <module>
out = model(data)
File ".../pipenv/lib/python3.6/site-packages/torch/nn/modules/module.py", line 489, in __call__
result = self.forward(*input, **kwargs)
File "test.py", line 17, in forward
out = self.conv1(x)
File ".../pipenv/lib/python3.6/site-packages/torch/nn/modules/module.py", line 489, in __call__
result = self.forward(*input, **kwargs)
File ".../pipenv/lib/python3.6/site-packages/torch/nn/modules/conv.py", line 320, in forward
self.padding, self.dilation, self.groups)
RuntimeError: offset is too big
I am using Python 3.6 and Pytorch 1.0.0. Strange thing is, this works with smaller images. Change the images size from 5002 to 502, for example.
Solved by updating Pytorch to 1.3.0
I wanted to test my network on a toy data set - a few examples with two imbalanced classes (0 and 1). Unfortunately, there are problems when using the class_weight parameter to improve the balance. It looks like I forget something.
import tensorflow as tf
from tensorflow.python.keras.layers import Dense, Dropout
from tensorflow.python.keras.applications.xception import Xception, preprocess_input
from tensorflow.python.keras.models import Model
from tensorflow.python.keras.optimizers import Adam
# parsing images from TFRecords
def parse_function(proto):
example = {'image_raw': tf.FixedLenFeature([], tf.string), 'label': tf.FixedLenFeature([], tf.int64)}
parsed_example = tf.parse_single_example(proto, example)
image = tf.decode_raw(parsed_example['image_raw'], tf.uint8)
image = tf.reshape(image, [HEIGHT, WIDTH, DEPTH])
image = preprocess_input(tf.cast(image, tf.float32))
return image, parsed_example['label']
def get_data(filepath, schuffle_size=32, batch_size=8, prefetch=1, repeat=None, num_parallel_calls=1):
dataset = tf.data.TFRecordDataset(filepath)
if schuffle_size != 0:
dataset = dataset.shuffle(schuffle_size)
dataset = dataset.repeat(repeat)
dataset = dataset.map(parse_function, num_parallel_calls=num_parallel_calls)
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(prefetch)
iterator = dataset.make_one_shot_iterator()
return iterator
def build_model(number_of_neurons_in_dense_layer, dropout, learning_rate):
base_model = Xception(weights='imagenet', include_top=False, pooling='avg', input_shape=(HEIGHT, WIDTH, 3))
for layer in base_model.layers:
layer.trainable = True
x = base_model.output
x = Dropout(dropout)(x)
x = Dense(number_of_neurons_in_dense_layer, activation='relu')(x)
x = Dropout(dropout)(x)
logits = Dense(NUMBER_OF_CLASSES, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=logits)
model.compile(optimizer=Adam(lr=learning_rate), loss='sparse_categorical_crossentropy', metrics=['categorical_accuracy'])
return model
global NUMBER_OF_CLASSES, HEIGHT, WIDTH, DEPTH
NUMBER_OF_CLASSES = 2
...
CLASS_WEIGHTS = {
0: 1,
1: 7
}
model = build_model(64, 0.4, 0.001)
train = get_data(..., 8, 2, num_parallel_calls=8)
val = get_data(...., 0, 4, num_parallel_calls=8)
model.fit(train, validation_data=val, epochs=3,steps_per_epoch=8//2,
validation_steps=8//4, shuffle=False,
class_weight=CLASS_WEIGHTS)
I am getting the following errors
Original exception was:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py", line 51, in _wrapfunc
return getattr(obj, method)(*args, **kwds)
AttributeError: 'Tensor' object has no attribute 'reshape'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/usr/model.py", line 147, in main
class_weight=CLASS_WEIGHTS)
File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py", line 776, in fit
shuffle=shuffle)
File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py", line 2432, in _standardize_user_data
feed_sample_weight_modes)
File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py", line 2431, in <listcomp>
for (ref, sw, cw, mode) in zip(y, sample_weights, class_weights,
File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_utils.py", line 758, in standardize_weights
y_classes = np.reshape(y, y.shape[0])
File "/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py", line 279, in reshape
return _wrapfunc(a, 'reshape', newshape, order=order)
File "/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py", line 61, in _wrapfunc
return _wrapit(obj, method, *args, **kwds)
File "/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py", line 41, in _wrapit
result = getattr(asarray(obj), method)(*args, **kwds)
TypeError: __index__ returned non-int (type NoneType)
Without the class_weight parameter, the fit function works correctly.
Just for a future reference:
I ran into this error to and was able to resolve it by passing an array instead of a dictionary.
e.g.
CLASS_WEIGHTS = np.array([1,7])
instead of:
CLASS_WEIGHTS = {
0: 1,
1: 7
}