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)
我在 google colab 上训练了模型,然后下载模型并尝试加载到我的窗口电脑上。 *它在谷歌colab上工作正常,即使我重新启动并清除终端并运行这段代码,也没有任何错误。 当我转移到 PC 时,我发现我需要通过很多预先步骤来加载模型,这与 google colab 上的只是 (model = load_model("xxx/xxx"))
我在 TensorFlow 中使用
TFSMLayer
时遇到问题,收到以下错误消息
---------------------------------------------------------
tensorflow.python.framework.errors_impl.InvalidArgumentError:调用 TFSMLayer.call() 时遇到异常。
无法计算 __inference_signature_wrapper_1285,因为输入 #0(从零开始)预计是 int64 张量,但实际上是浮点张量 [Op:__inference_signature_wrapper_1285]
--------------------------------------------------------
我正在尝试加载一个使用
TFSMLayer
进行推理的 TensorFlow 模型,但似乎 TFSMLayer.call()
方法接收到的输入张量的数据类型为 float32
,而模型期待int64
。这种不一致会导致计算过程中出现错误。
在将输入张量传递给加载的模型之前,我已经尝试使用
int64
将输入张量转换为 tf.cast
,但错误仍然存在。
我不确定为什么输入张量的数据类型被转换为
float32
,以及如何解决这个问题。任何有关如何调试和解决此问题的见解或建议将不胜感激。谢谢!
原来可能是tensorflow版本问题。 我尝试在pc(2.16.1)上卸载tensorflow并安装与google colab(2.15.0)相同的版本,原始代码运行顺利。
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))