Error when I trying to run a trained ner model on local pc

35 Views Asked by At

import re
import pickle
import keras
import tensorflow as tf
from keras.models import Sequential
from keras.layers import TFSMLayer
import numpy as np

class CustomNonPaddingTokenLoss(keras.losses.Loss):
    def __init__(self, reduction=tf.keras.losses.Reduction.AUTO, name="custom_ner_loss"):
        super().__init__(reduction=reduction, name=name)

    def call(self, y_true, y_pred):
        loss_fn = keras.losses.SparseCategoricalCrossentropy(
            from_logits=False, reduction=self.reduction
        )
        loss = loss_fn(y_true, y_pred)
        mask = tf.cast((y_true > 0), dtype=tf.float32)
        loss = loss * mask
        return tf.reduce_sum(loss) / tf.reduce_sum(mask)

def map_record_to_training_data(record):
    record = tf.strings.split(record, sep="\t")
    length = tf.strings.to_number(record[0], out_type=tf.int32)
    tokens = record[1 : length + 1]
    tags = record[length + 1 :]
    tags = tf.strings.to_number(tags, out_type=tf.int64)
    tags += 1
    return tokens, tags

def lookup(tokens):
    # Load the list from the file
    with open('./resources/vocabulary.pkl', 'rb') as f:
        loaded_list = pickle.load(f)
    # The StringLookup class will convert tokens to token IDs
    lookup_layer = keras.layers.StringLookup(vocabulary=loaded_list)

    # No need to lowercase Vietnamese characters
    return lookup_layer(tokens)

def format_datatype(data):
    tokens =  [re.sub(r'[;,]', '', d) for d in data.split(' ')]
    #default is 0, since is for prediction
    ner_tags = [0 for d in data.split(' ')]

    #tab to separate
    string_input = str(len(tokens))+ "\t"+ "\t".join(tokens)+ "\t"+ "\t".join(map(str, ner_tags))
    string_input = tf.data.Dataset.from_tensor_slices([string_input])

    
    finalize_input = (string_input.map(map_record_to_training_data)
                      .map(lambda x, y: (lookup(x),  y))
                      .padded_batch(1)
                      )

    return finalize_input

def prediction(data):
    # Register the custom loss function with TensorFlow
    tf.keras.utils.get_custom_objects()['CustomNonPaddingTokenLoss'] = CustomNonPaddingTokenLoss
    loaded_model = Sequential()
    loaded_model.add(TFSMLayer("./resources/ner_model", call_endpoint='serving_default'))


    all_predicted_tag_ids = []
    
    for x, _ in data:
        print("Input Tensor Info:")
        print("Data Type:", x.dtype)
        print("Shape:", x.shape)
        x = tf.cast(x, tf.int64)
        output = loaded_model(x, training=False)
        predictions = np.argmax(output, axis=-1)
        predictions = np.reshape(predictions, [-1])
        all_predicted_tag_ids.append(predictions)

    all_predicted_tag_ids = np.concatenate(all_predicted_tag_ids)

    ner_labels = ["[PAD]", "N", "M", "other"]
    mapping =  dict(zip(range(len(ner_labels)), ner_labels))
    predicted_tags = [mapping[tag] for tag in all_predicted_tag_ids]

    return predicted_tags

sample_input = "Hello world, my name is John, I live in New York, my birthday is 10/02/1990."

result = prediction(format_datatype(sample_input))
print(result)

I trained the model on google colab, and download the model and try to load in on my window pc. *It work fine on google colab, even when I restart and clear the terminal and just run this block of code, there are no error at all. When I move to pc, I found that I need to load the model with a lot of pre-step, unlike on google colab just a (model = load_model("xxx/xxx"))

I am encountering an issue while using the TFSMLayer in TensorFlow, where I receive the following error message

-----------------------------------------

tensorflow.python.framework.errors_impl.InvalidArgumentError: Exception encountered when calling TFSMLayer.call().

cannot compute __inference_signature_wrapper_1285 as input #0(zero-based) was expected to be a int64 tensor but is a float tensor [Op:__inference_signature_wrapper_1285]

-------------------------------------------

I'm trying to load a TensorFlow model that uses the TFSMLayer for inference, but it seems that the input tensor received by the TFSMLayer.call() method is of data type float32, while the model expects int64. This inconsistency leads to an error during computation.

I have already attempted to cast the input tensor to int64 using tf.cast before passing it to the loaded model, but the error persists.

I'm uncertain why the input tensor's data type is being converted to float32, and how to resolve this issue. Any insights or suggestions on how to debug and resolve this problem would be greatly appreciated. Thank you!

1

There are 1 best solutions below

0
Yin Jie On

Turns out it might be tensorflow version issue. I try to uninstall tensorflow on pc (2.16.1) and install the same version as google colab (2.15.0) and the original code run smoothly.

import re
import pickle
import keras
import tensorflow as tf
import numpy as np
print(tf.__version__)
class CustomNonPaddingTokenLoss(keras.losses.Loss):
    def __init__(self, reduction=tf.keras.losses.Reduction.AUTO, name="custom_ner_loss"):
        super().__init__(reduction=reduction, name=name)

    def call(self, y_true, y_pred):
        loss_fn = keras.losses.SparseCategoricalCrossentropy(
            from_logits=False, reduction=self.reduction
        )
        loss = loss_fn(y_true, y_pred)
        mask = tf.cast((y_true > 0), dtype=tf.float32)
        loss = loss * mask
        return tf.reduce_sum(loss) / tf.reduce_sum(mask)

def map_record_to_training_data(record):
    record = tf.strings.split(record, sep="\t")
    length = tf.strings.to_number(record[0], out_type=tf.int32)
    tokens = record[1 : length + 1]
    tags = record[length + 1 :]
    tags = tf.strings.to_number(tags, out_type=tf.int64)
    tags += 1
    return tokens, tags

def lookup(tokens):
    # Load the list from the file
    with open('./resources/vocabulary.pkl', 'rb') as f:
        loaded_list = pickle.load(f)
    # The StringLookup class will convert tokens to token IDs
    lookup_layer = keras.layers.StringLookup(vocabulary=loaded_list)

    # No need to lowercase Vietnamese characters
    return lookup_layer(tokens)

def format_datatype(data):
    tokens =  [re.sub(r'[;,]', '', d) for d in data.split(' ')]
    #default is 0, since is for prediction
    ner_tags = [0 for d in data.split(' ')]

    #tab to separate
    string_input = str(len(tokens))+ "\t"+ "\t".join(tokens)+ "\t"+ "\t".join(map(str, ner_tags))
    string_input = tf.data.Dataset.from_tensor_slices([string_input])

    
    finalize_input = (string_input.map(map_record_to_training_data)
                      .map(lambda x, y: (lookup(x),  y))
                      .padded_batch(1)
                      )

    return finalize_input

def prediction(data):
    # Register the custom loss function with TensorFlow
    tf.keras.utils.get_custom_objects()['CustomNonPaddingTokenLoss'] = CustomNonPaddingTokenLoss
    
    loaded_model = tf.keras.models.load_model("./resources/ner_model")

    all_predicted_tag_ids = []
    
    for x, _ in data:
        print("Input Tensor Info:")
        print("Data Type:", x.dtype)
        print("Shape:", x.shape)
        x = tf.cast(x, tf.int64)
        output = loaded_model(x, training=False)
        predictions = np.argmax(output, axis=-1)
        predictions = np.reshape(predictions, [-1])
        all_predicted_tag_ids.append(predictions)

    all_predicted_tag_ids = np.concatenate(all_predicted_tag_ids)

    ner_labels = ["[PAD]", "N", "M", "other"]
    mapping =  dict(zip(range(len(ner_labels)), ner_labels))
    predicted_tags = [mapping[tag] for tag in all_predicted_tag_ids]

    return predicted_tags

sample_input = ""Hello world, my name is John, I live in New York, my birthday is 10/02/1990."

result = prediction(format_datatype(sample_input))
print(result)
print(len(result))