SPO主谓宾,S的P是O,这样描述,S就是头实体,O就是尾实体
把所以的关系列出来,那么关系里面是实体的关系,所以一定存在头实体和尾实体,没个文字的分类,肯定是属于哪个实体的分类,而实体的类别存在与关系的类别中,一个关系就是两个实体,所有的关系X2,就是这个字所能够分成的所属实体的类别。
尾实体可能存在多种类别,所以用@做区分
实际的数据标注,把所有的头实体类别,关系类别,尾实体类别都做好标注,相应的实际示例实体也抽取出来。类别是示例的抽象,示例是类别的具体,类似于程序里面类的实例化。
实际的关系列表里面有两个类别是I和O,这两个关系类别没有所谓的尾实体或者头实体,只是针对一个字符的实体标注,所以要排除乘以1,实际公式 num_classes=(len(label_map) - 2) * 2 + 2)
from paddlenlp.transformers import RobertaForTokenClassification, RobertaTokenizer
model = RobertaForTokenClassification.from_pretrained(
"roberta-wwm-ext-large",
num_classes=(len(label_map) - 2) * 2 + 2)
tokenizer = RobertaTokenizer.from_pretrained("roberta-wwm-ext-large")
根据对应的object的类型,对应的关系也要增加
labels = outside_label + labels + outside_label
tok_to_orig_start_index = [-1] + tok_to_orig_start_index + [-1]
tok_to_orig_end_index = [-1] + tok_to_orig_end_index + [-1]
if seq_len < max_length:
tokens = tokens + ["[PAD]"] * (max_length - seq_len - 2)
labels = labels + outside_label * (max_length - len(labels))
tok_to_orig_start_index = tok_to_orig_start_index + [-1] * (
max_length - len(tok_to_orig_start_index))
tok_to_orig_end_index = tok_to_orig_end_index + [-1] * (
max_length - len(tok_to_orig_end_index))
token_ids = tokenizer.convert_tokens_to_ids(tokens)
return InputFeature(
input_ids=np.array(token_ids),
seq_len=np.array(seq_len),
tok_to_orig_start_index=np.array(tok_to_orig_start_index),
tok_to_orig_end_index=np.array(tok_to_orig_end_index),
labels=np.array(labels), )
构造多标签样本id