TFX Evaluator problem with a keras multioutput model - python

I am using a very simple keras model in TFX, to solve a regression problem.
It seems that TFX wants that you use a keras model with named outputs, so I made:
output = {key: tf.keras.layers.Dense(1, name = key)(x)
for key in _transformed_names(_LABEL_KEYS)}
model(inputs, outputs)
I don't understand how the evaluator maps the label names of my dataset with the output names of my model.
In my code I set up the label_keys and prediction_keys argument in tfma.ModelSpec with a list of form :
[["model output name", "Label key in my Dataset"]]
It seems that the proto message is created correctly, but when I run the Evaluator I get the following error:
ValueError: unable to prepare labels and predictions because the labels and/or predictions are dicts with unrecognized keys. If a multi-output keras model (or estimator) was used check that an output_name was provided. If an estimator was used check that common prediction keys were provided (e.g. logistic, probabilities, etc)
If I try to provide a single label key and a single prediction key using the label_key and prediction_key arguments I get the following error:
TypeError: update_state() takes from 2 to 3 positional arguments but 4 were given [while running 'ExtractEvaluateAndWriteResults/ExtractAndEvaluate/EvaluateMetricsAndPlots/ComputeMetricsAndPlots()/ComputePerSlice/ComputeUnsampledMetrics/CombinePerSliceKey/WindowIntoDiscarding']
I have tried in all possible ways but nothing.
Is there a way to use a model with no named outputs (an Dense output layer with more than one node) ? Or a way to solve this problem ?
P.S. Is there a Tutorials of a TFX pipeline with a multiple outputs keras model ?
Thanks.

in eval_config,setting
options=Options(include_default_metrics=BoolValue(value=False))
e.g:
eval_config = tfma.EvalConfig(
model_specs = [...],
slicing_specs=[tfma.SlicingSpec(),...],
metrics_specs=[...],
options=Options(include_default_metrics=BoolValue(value=False))
)
evaluator = Evaluator(
...
eval_config=eval_config
)

Related

Extract weights of a tflite model directly on an android studio variable

I'm having some difficulties writing an extract_weights and an initialize function for a tf.Module model that i later convert to tflite.
The idea is that, i want to use this model for on device training.
The project architecture is as it follows:
-first i create a transfer learning model that will later be used for training
-then i upload this model in my android application where i train it using the tflite.Interpreter
-the model will be trained federated using a flower server
The problem that i have at the moment is that flower needs to colect from each device the weights as ByteBuffers after each training loop, but i don't seem to understand how i could save them in my android application.
These are the methods that i wrote
#tf.function
def extract_weights(self):
"""
Extracts the traininable weights of the head model as a list of numpy arrays.
Paramaters:
Returns:
Map of extracted weights and biases.
"""
tmp_dict = {}
tensor_names = [weight.name for weight in self.head_model.weights]
tensors_to_save = [weight.read_value() for weight in self.head_model.weights]
for index, layer in enumerate(tensors_to_save):
tmp_dict[tensor_names[index]] = layer
return tmp_dict
#tf.function(input_signature=[SIGNATURE_DICT])
def initialize_weights(self, weights):
"""
Initializes weights of the head model.
Paramaters:
weights : Tensors used for initialization.
Returns:
NONE
"""
tensor_names = [weight.name for weight in self.head_model.weights]
for i, tensor in enumerate(self.head_model.weights):
tensor.assign(weights[tensor_names[i]])
To notice that when i instantiate a TransferLearningModel(my model class that implements tf.Module) object and call these to functions i got no problems but when i try to convert them to tflite i get this error:
ValueError: Got a non-Tensor value<tf.Operation 'StatefulPartitionedCall' type=StatefulPartitionedCall>for key 'output_0' in the output of the function __inference_initialize_weights_8582 used to generate the SavedModel signature 'initialize'. Outputs for functions used as signatures must be a ValueError: Got a non-Tensor value<tf.Operation 'StatefulPartitionedCall' type=StatefulPartitionedCall> for key 'output_0' in the output of the function __inference_initialize_weights_8582 used to generate the SavedModel signature 'initialize'. Outputs for functions used as signatures must be a single Tensor, a sequence of Tensors, or a dictionary from string to Tensor.
I understand the error but i don t get why i have to return something when simply initializing the weights of my model.

Accessing training data during tensorflow graph execution

I'd like to use pre-trained sentence embeddings in my tensorflow graph execution model. The embeddings are available dynamically from a function call, which takes in an array of sentences and outputs an array of sentence embeddings. This function uses a pre-trained pytorch model so has to remain separate from the tensorflow model I'm training:
def get_pretrained_embeddings(sentences):
return pretrained_pytorch_model.encode(sentences)
My tensorflow model looks like this:
class SentenceModel(tf.keras.Model):
def __init__(self):
super().__init__()
def call(self, sentences):
embedding_layer = tf.keras.layers.Embedding(
10_000,
256,
embeddings_initializer=tf.keras.initializers.Constant(get_pretrained_embeddings(sentences)),
trainable=False,
)
sentence_text_embedding = tf.keras.Sequential([
embedding_layer,
tf.keras.layers.GlobalAveragePooling1D(),
])
return sentence_text_embedding,
But when I try to train this model using
cached_train = train.shuffle(100_000).batch(1024)
model.fit(cached_train)
my embeddings_initializer call gets the error:
OperatorNotAllowedInGraphError: iterating over `tf.Tensor` is not allowed: AutoGraph did convert this function. This might indicate you are trying to use an unsupported feature.
I assume this is because tensorflow is trying to compile the graph using symbolic data. How can I get my external function, which relies on the current training data batch, to work with tensorflow's graph training?
Tensorflow compiles models to an execution graph before performing the actual training process. The obvious side-effect that clues us into this is if we have a regular Python print() statement in e.g. our call() method, it will only get executed once as Tensorflow runs through your code to construct the execution graph, which it will later convert to native code.
The other side effect of this is that cannot use anything that isn't a tensor of some description when training. By 'tensor' here, all of the following can be considered a tensor:
The input value of your call() method (obviously)
A tf.Sequential
A tf.keras.Model/tf.keras.layers.Layer subclass
A SparseTensor
A tf.constant()
....probably more I haven't listed here.
To this end, you would need to convert your PyTorch model to a Tensorflow one to be able to reference it in a subclass of tf.keras.Model/tf.keras.layers.Layer.
As a side note, if you do find you need to iterate a tensor, you should just be able to iterate it on the 1st dimension (i.e. the batch size) like so:
for part in some_tensor:
pass
If you want to iterate on some other dimension, I recommend doing a tf.unstack(some_tensor, axis=AXIS_NUMBER_HERE) first and iterate over the result thereof.

How do i specify to a model what to take as input of a custom loss function?

I'm having issues in understanding/implementing a custom loss function in my model.
I have a keras model which is composed by 3 sub models as you can see here in the model architecture,
Now, I'd like to use the outputs of model and model_2 in my custom loss function.
I understand that in the loss function definition I can write:
def custom_mse(y_true, y_pred):
*calculate stuff*
return loss
But how do I tell the model to take its 2 outputs as inputs of the loss function?
Maybe, and i hope so, it's super trivial but I didn't find anything online, if you could help me it'd be fantastic.
Thanks in advance
Context:
model and model_2 are the same pretrained model, a binary classifier, which predicts the interaction between 2 inputs (of image-like type).
model_1 is a generative model which will edit one of the inputs.
Therefore:
complete_model = Model(inputs=[input_1, input_2], outputs=[out_model, out_model2])
opt = *an optimizer*
complete_model.compile(loss=custom_mse,
??????,
optimizer = opt,
metrics=['whatever'])
The main goal is to compare the prediction with the edited input against the one with the un-edited input, therefore the model will outputs the 2 interactions, which i need to use in the loss function.
EDIT:
Thank you Andrey for the solution,
Now however i can't manage to implement together the 2 loss functions, namely the one with add_loss(func) and a classic binary_crossentropy in model.complie(loss='binary_crossentropy', ...).
Can I maybe add an add_loss specifying model_2.output and the label? If yes do you know how?
They work by themselves but not together, when i try to run the code they raise
ValueError: Shapes must be equal rank, but are 0 and 4 From merging shape 0 with other shapes. for '{{node AddN}} = AddN[N=2, T=DT_FLOAT](binary_crossentropy/weighted_loss/value, complete_model/generator/tf_op_layer_SquaredDifference_3/SquaredDifference_3)' with input shapes: [], [?,500,400,1].
You can add loss with compile() only for standard loss function signature (y_true, y_pred). You can not use it because your signature is something like (y_true, (y_pred1, y_pred2)). Use add_loss() API instead. See here: https://keras.io/api/losses/

Keras : ValueError: `y` argument is not supported when using `keras.utils.Sequence` as input

I wanted to do a simple classification task but when I try to run it, I am getting this error:
`ValueError: `y` argument is not supported when using `keras.utils.Sequence` as input.`
Use the keyword validation_data. If you pass your validation dataset without the keyword, Keras thinks validation_dataset is your labels.
model.fit(train_dataset, validation_data=validation_dataset, batch_size=32, epochs=1)
Let's imagine that you want to predict if it's a Dog or a Cat picture, you have two labels Dog and Cat. Now when it comes to CNN dataset the way most of peoples structure it (which is what is expecting image_generator.flow_from_directory) looks like this :
Train/
.........Cat/
...............Image1.jpg
...............Image2.jpg
.........Dog/
...............Image3.jpg
...............Image4.jpg
Same for your label directory.
Btw your directory Label should be renamed validation ( it's not really important but it makes more sense)

Neural Network classifier in python

Here I developed a neural network classifier to solve the titanic problem.
from sknn.mlp import Classifier, Layer
nn = Classifier(
layers=[
Layer("Maxout", units=100, pieces=2),
Layer("Softmax")],
learning_rate=0.001,
n_iter=25)
nn.fit(X_train, y_train)
I got this error, I have tried a lot to fix it but nothing works with me.
Please, help me
TypeError: init() got an unexpected keyword argument 'pieces'
The signature of Layer does not define any argument called pieces. To create two layers with same parameters, you'll have to define the Layer object twice:
layers=[
Layer("Sigmoid", units=100),
Layer("Sigmoid", units=100),
Layer("Softmax", units=1)] # The units parameter is not optional
More so, "Maxout" does not look like a Layer type. Not sure of where you found that.
Specifically, options are Rectifier, Sigmoid, Tanh, and ExpLin
for non-linear layers and Linear or Softmax for output layers

Categories

Resources