在本地PC上运行训练好的NER模型时出错
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)
我在谷歌Colab上训练了一个模型,然后下载了这个模型,想在我的Windows电脑上加载它。
在谷歌Colab上运行得很好,即使我重启并清空终端,只要运行这段代码,就没有任何错误。
但在电脑上,我发现需要进行很多准备步骤才能加载模型,而在谷歌Colab上只需要一行代码(model = load_model("xxx/xxx"))。
我在使用TFSMLayer
时遇到了一个问题,收到以下错误信息:
-----------------------------------------
tensorflow.python.framework.errors_impl.InvalidArgumentError: 调用 TFSMLayer.call() 时遇到异常。
无法计算 __inference_signature_wrapper_1285,因为输入 #0(从零开始)预期是一个 int64 张量,但实际上是一个 float 张量 [Op:__inference_signature_wrapper_1285]
-------------------------------------------
我正在尝试加载一个使用TFSMLayer
进行推理的TensorFlow模型,但似乎TFSMLayer.call()
方法接收到的输入张量数据类型是float32
,而模型期望的是int64
。这种不一致导致了计算时的错误。
我已经尝试在将输入张量传递给加载的模型之前,使用tf.cast
将其转换为int64
,但错误依然存在。
我不确定为什么输入张量的数据类型会被转换为float32
,也不知道该如何解决这个问题。如果有任何建议或调试的方法,我将非常感激。谢谢!
1 个回答
结果发现可能是tensorflow版本的问题。我尝试在电脑上卸载tensorflow(2.16.1),然后安装和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))