从Kaggle下载TensorFlow版BERT模型后分词报错的解决求助
问题解决思路与代码修正
核心错误原因
你遇到的NotImplementedError是因为input_text = tf.keras.layers.Input(shape=(), dtype=tf.string)创建的是符号Keras张量——它只是计算图中的占位符,没有实际数据,无法用Python的for循环迭代遍历。而HuggingFace的BertTokenizer默认处理的是Python字符串列表,不能直接作用于符号张量。
分步解决方案
1. 修正分词逻辑(兼容TensorFlow符号张量)
用tf.py_function将分词操作包装成TensorFlow兼容的计算节点,即可在Keras模型中使用符号张量作为输入:
import tensorflow as tf from transformers import BertTokenizer import kagglehub import keras import os # 下载模型 path = kagglehub.model_download("tensorflow/bert/tensorFlow2/en-wwm-uncased-l-24-h-1024-a-16") print("Path to model files:", path) # 初始化Tokenizer(用os.path.join保证跨平台路径兼容) vocab_path = os.path.join(path, "assets", "vocab.txt") encoder = BertTokenizer.from_pretrained(vocab_path) # 定义兼容TensorFlow的分词函数 def tokenize_function(texts): # 将符号张量转为Python字符串列表 texts = tf.make_ndarray(tf.make_tensor_proto(texts)).tolist() # 分词并返回Tensor格式结果 encodings = encoder(texts, padding=True, truncation=True, return_tensors="tf") return encodings["input_ids"], encodings["attention_mask"], encodings["token_type_ids"] # 构建模型输入 input_text = tf.keras.layers.Input(shape=(), dtype=tf.string, name="input_text") # 用tf.py_function包装分词操作 input_ids, attention_mask, token_type_ids = tf.py_function( func=tokenize_function, inp=[input_text], Tout=[tf.int32, tf.int32, tf.int32] ) # 为输出张量设置明确形状(Keras需要形状信息构建模型) input_ids.set_shape((None, encoder.model_max_length)) attention_mask.set_shape((None, encoder.model_max_length)) token_type_ids.set_shape((None, encoder.model_max_length)) # 加载BERT模型 model = keras.layers.TFSMLayer(path, call_endpoint='serving_default') # 调用模型获取输出 bert_output = model({"input_ids": input_ids, "attention_mask": attention_mask, "token_type_ids": token_type_ids}) # 测试模型(传入实际文本数据) test_text = tf.convert_to_tensor(["Hello, this is a test sentence."]) output = bert_output(test_text) print("BERT model output shape:", {k: v.shape for k, v in output.items()})
2. 验证模型加载正确性
若不确定TFSMLayer的call_endpoint是否匹配,可以用以下代码查看SavedModel的签名信息:
loaded_model = tf.saved_model.load(path) print("Available model signatures:", list(loaded_model.signatures.keys())) print("Input names for serving_default:", list(loaded_model.signatures["serving_default"].structured_input_signature[1].keys()))
如果输入名称与代码中的input_ids等不匹配,需要调整model()调用时的字典键名。
3. 替代方案:直接使用HuggingFace的TFBertModel
如果SavedModel加载遇到问题,推荐直接用Transformers库的TFBertModel从下载路径加载,更符合常规使用习惯:
from transformers import TFBertModel # 直接加载SavedModel格式的BERT bert_model = TFBertModel.from_pretrained(path) # 用Tokenizer处理文本后传入模型 test_encodings = encoder(["Hello, this is a test sentence."], padding=True, truncation=True, return_tensors="tf") output = bert_model(**test_encodings) print("Pooled output shape:", output.pooler_output.shape)
关于模型格式转换的补充
- 若要将.pb转为纯Keras模型,可尝试
tf.keras.models.load_model(path),但仅适用于Keras导出的SavedModel;若加载失败,说明该模型是纯TensorFlow SavedModel,建议继续使用TFSMLayer或TFBertModel加载。 - 转PyTorch模型可使用Transformers库的权重转换工具:
import torch from transformers import BertModel, convert_tf_weight_to_pt_weight # 转换TensorFlow权重为PyTorch格式 convert_tf_weight_to_pt_weight(path, "pytorch_bert_weights.bin") # 加载PyTorch模型 pt_model = BertModel.from_pretrained("bert-large-uncased-whole-word-masking", state_dict=torch.load("pytorch_bert_weights.bin"))
内容的提问来源于stack exchange,提问作者Christian Waidner
相关产品推荐
相关产品推荐

