返回模型
说明文档
模型卡片:植物名称 BERT NER(PEFT/LoRA 微调版)
模型描述
本模型是基于 google-bert/bert-base-cased 微调的版本,专门用于识别常见和学名植物名称的命名实体识别(NER)。它采用**参数高效微调(PEFT)**方法,具体使用 **LoRA(低秩适应)**来修改基础模型的注意力层(query 和 value)以完成此任务。目标是识别文本中对应植物名称的片段,并根据 IOB2 标注方案将其分类为常见名(PLANT_COMMON)或学名(PLANT_SCI)。
- 开发者: [您的姓名/组织 - 请填写]
- 模型类型: BERT(
bert-base-cased)使用 PEFT/LoRA 进行词元分类(NER)微调 - 语言: 主要为英语(基于
bert-base-cased和可能的训练数据) - 许可证: 基础模型(
bert-base-cased)使用 Apache 2.0。微调后的适配器权重继承此许可证,除非另有说明 - 微调自模型:
google-bert/bert-base-cased
预期用途与局限性
预期用途
本模型用于识别和分类英文文本中的植物名称(常见名和学名)。潜在应用包括:
- 从植物学文本、研究论文或园艺文章中提取植物名称
- 构建数据库中植物提及信息的结构化数据
- 协助基于包含的植物名称进行文档索引或搜索
- 为需要植物实体知识的下游任务预处理文本
局限性
- 领域特定性: 模型在与训练数据相似的文本(关于植物的生成模板)上可能表现最佳。在显著不同的领域(例如,高度非正式的文本、复杂的生物通路描述,除非包含类似数据)上性能可能会下降
- IOB2 方案: 模型严格遵守 IOB2 标注方案(
B-TAG、I-TAG、O)。它识别命名实体片段的开头(B-)和内部(I-)词元 - 特定标签: 仅训练识别
PLANT_COMMON和PLANT_SCI。它将所有其他词元标记为O(外部)。除非明确训练,否则无法识别其他实体类型(例如,地点、人物、化学物质) - 歧义性: 可能在歧义词汇上表现不佳,即某个词在一种语境下是植物名称,而在另一种语境下不是(例如,"Rose" 作为名称 vs. 作为花朵)
- 新名称: 在训练期间未见过(或与见过的名称差异很大)的植物名称上性能可能较低
- 上下文依赖性: 像大多数 NER 模型一样,其准确性在很大程度上取决于周围的上下文。简短、孤立的提及可能更难正确分类
- 大小写敏感性: 基于
bert-base-cased,模型区分大小写,这可能有利于区分学名,但可能影响不一致书写的常见名
如何使用(使用 Transformers 和 PEFT)
此模型需要先加载基础 BERT 模型,然后应用训练好的 LoRA 适配器。
from transformers import AutoModelForTokenClassification, AutoTokenizer, AutoConfig
from peft import PeftModel
import torch
# --- 配置 ---
BASE_MODEL_NAME = "google-bert/bert-base-cased"
# --- *** 指向包含保存适配器的目录 *** ---
# 例如,您的 BEST_MODEL_DIR 或 CHECKPOINT_DIR
ADAPTER_PATH = "/kaggle/working/bert_ner_peft_gpu_best_v4"
# --- ************************************************************** ---
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 1. 加载分词器(从适配器路径或基础模型)
try:
tokenizer = AutoTokenizer.from_pretrained(ADAPTER_PATH)
except Exception:
print(f"警告:在 {ADAPTER_PATH} 中未找到分词器,从 {BASE_MODEL_NAME} 加载")
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL_NAME)
# 2. 加载基础模型(确保配置与训练匹配)
# 需要训练时的标签映射来正确加载配置
label_list = ["O", "B-PLANT_COMMON", "I-PLANT_COMMON", "B-PLANT_SCI", "I-PLANT_SCI"]
label_map = {label: i for i, label in enumerate(label_list)}
id_to_label = {i: label for i, label in enumerate(label_list)}
num_labels = len(label_list)
config = AutoConfig.from_pretrained(
BASE_MODEL_NAME,
num_labels=num_labels,
id2label=id_to_label,
label2id=label_map
)
base_model = AutoModelForTokenClassification.from_pretrained(
BASE_MODEL_NAME,
config=config,
ignore_mismatched_sizes=True # 如果头层已初始化,这很重要
)
# 如有必要调整嵌入大小(如果在训练期间添加了填充词元)
if len(tokenizer) != base_model.get_input_embeddings().weight.shape[0]:
print(f"将模型嵌入调整为 {len(tokenizer)}")
base_model.resize_token_embeddings(len(tokenizer))
# 3. 加载 PEFT 模型(应用适配器)
model = PeftModel.from_pretrained(base_model, ADAPTER_PATH)
model.to(DEVICE)
model.eval()
print("PEFT 模型已加载,可进行推理。")
# --- 推理示例 ---
text = "The Pineapple Guava (Feijoa sellowiana) is different from Ananas comosus."
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True).to(DEVICE)
with torch.no_grad():
logits = model(**inputs).logits
predictions = torch.argmax(logits, dim=2)
predicted_token_class_ids = predictions[0].cpu().numpy()
# 将 ID 映射回标签,与词元对齐
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0].cpu().numpy())
word_ids = inputs.word_ids() # 仅适用于快速分词器
aligned_labels = []
previous_word_idx = None
for i, token in enumerate(tokens):
if token in [tokenizer.cls_token, tokenizer.sep_token, tokenizer.pad_token]:
continue # 跳过特殊词元
word_idx = word_ids[i]
if word_idx != previous_word_idx: # 只取每个词的第一个词元
label_id = predicted_token_class_ids[i]
label_str = id_to_label.get(label_id, "O")
aligned_labels.append(label_str)
previous_word_idx = word_idx
original_words = text.split() # 简单分割用于演示,可能需要更好的分词对齐
# 演示用的粗略对齐:假设 aligned_labels 与原始词长度匹配
print("文本:", text)
print("预测标签(近似对齐):")
for word, label in zip(original_words[:len(aligned_labels)], aligned_labels):
if label != "O": print(f"- {word}: {label}")
使用合并后的模型
如果您使用了合并脚本,可以直接加载完整模型:
from transformers import AutoModelForTokenClassification, AutoTokenizer
import torch
# --- *** 指向包含合并模型的目录 *** ---
MERGED_MODEL_PATH = "/kaggle/working/bert_ner_peft_gpu_merged"
# --- ************************************************************** ---
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
tokenizer = AutoTokenizer.from_pretrained(MERGED_MODEL_PATH)
model = AutoModelForTokenClassification.from_pretrained(MERGED_MODEL_PATH)
model.to(DEVICE)
model.eval()
print("合并模型已加载,可进行推理。")
# --- 推理示例(同上) ---
使用 ONNX 模型
import onnxruntime as ort
import numpy as np
import os
from transformers import AutoTokenizer, AutoConfig
# --- *** 指向包含 ONNX 模型的目录 *** ---
ONNX_MODEL_DIR = "/kaggle/working/bert_ner_onnx"
# --- ************************************************************** ---
# 加载分词器
tokenizer = AutoTokenizer.from_pretrained(ONNX_MODEL_DIR)
# 加载 ONNX 模型并创建会话
model_path = os.path.join(ONNX_MODEL_DIR, "model.onnx")
ort_session = ort.InferenceSession(model_path, providers=['CPUExecutionProvider']) # 或 ['CUDAExecutionProvider'](如果可用)
# 加载 id_to_label 映射(解码所需)
# 您可能需要从保存的 config.json 加载或重新定义
# 示例:从目录重新加载配置
config = AutoConfig.from_pretrained(ONNX_MODEL_DIR)
id_to_label = config.id2label
# --- 推理示例 ---
text = "The Pineapple Guava (Feijoa sellowiana) is different from Ananas comosus."
inputs = tokenizer(text, return_tensors="np") # 使用 numpy 以适配 ONNX 运行时
# 为 ONNX 会话准备输入
ort_inputs = {k: v for k, v in inputs.items()}
# 运行推理
ort_outputs = ort_session.run(None, ort_inputs)
logits = ort_outputs[0] # 通常是第一个输出
predictions = np.argmax(logits, axis=-1)
predicted_token_class_ids = predictions[0]
# 将 ID 映射回标签(对齐逻辑与 PyTorch 版本类似)
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])
# 注意:获取 word_ids 可能需要来自快速分词器的原始 'encoding' 对象
# 您可能需要使用 return_offsets_mapping=True 重新分词并手动对齐
# 为简单起见,让我们只打印原始词元标签:
print("文本:", text)
print("预测标签(每个词元):")
for token, label_id in zip(tokens, predicted_token_class_ids):
if token not in [tokenizer.cls_token, tokenizer.sep_token, tokenizer.pad_token]:
print(f"- {token}: {id_to_label.get(label_id, 'O')}")
训练数据
该模型是在从专注于常见和学名植物名称的模板生成的数据集上微调的。数据格式为 CoNLL 风格(每行一个词元和标签,用 TAB 分隔,句子之间用空行分隔)。
数据划分: 90% 训练,10% 验证(使用 sklearn.model_selection.train_test_split,random_state=42)。
训练过程
预处理
- 分词器: 来自 google-bert/bert-base-cased 的 BertTokenizerFast
- 填充: 填充/截断至 max_length=128
- 标签对齐: 标准 IOB2 方案。标签与每个词的第一个词元对齐。特殊词元和后续子词词元被分配 ignore_index(-100)
训练
- 框架: PyTorch 配合 transformers 和 peft
- 环境: GPU(根据设置可能是 Kaggle P100/T4/V100)
- 精度: Float32(启用了 AMP,但由于早期调试脚本以 FP32 运行)
- 优化器: AdamW
- 学习率: 2e-5,带线性预热(10% 步数)和衰减
- 批次大小: 4(每设备)
- 轮数: 训练最多 3 轮,带早停(基于验证 F1,patience=3)
- PEFT 配置: LoRA(r=8, alpha=16, dropout=0.1, target_modules=["query", "value"])
- 梯度裁剪: 最大范数 = 1.0
评估结果
使用 seqeval 库进行评估,采用 IOB2 方案和严格匹配。跟踪的主要指标是微平均 F1 分数。
环境影响
- 硬件: 在 Nvidia P100 GPU 上训练
- 计算: [如果已知,请估计训练时间,例如,在单个 T4 GPU 上约 X 小时]。如果已知计算详情,可以使用机器学习影响计算器等工具估算碳排放。
免责声明
该模型是从基础模型微调而来,继承了其能力和偏见。性能在很大程度上取决于目标文本与训练数据之间的相似性。请务必针对您的具体用例进行充分评估。
Dudeman523/NER-Bert-Based-Cased-PlantNames-Onnx
作者 Dudeman523
↓ 1
♥ 0
创建时间: 2025-04-17 19:04:34+00:00
更新时间: 2025-04-25 13:12:49+00:00
在 Hugging Face 上查看文件 (8)
.gitattributes
README.md
config.json
onnx/model_quantized.onnx
ONNX
special_tokens_map.json
tokenizer.json
tokenizer_config.json
vocab.txt