Download utils.py from ych-1114/BioBERT-CasRel-ADR-Extraction: direct link, hf CLI and curl.
- Browser
- Download file 7.7 kB
-
https://huggingface.co/ych-1114/BioBERT-CasRel-ADR-Extraction/resolve/main/utils.py
- Command line
-
hf download hf://ych-1114/BioBERT-CasRel-ADR-Extraction/utils.py
-
curl -L -o utils.py https://huggingface.co/ych-1114/BioBERT-CasRel-ADR-Extraction/resolve/main/utils.py
7.7 kB
| import torch.utils.data as data | |
| import pandas as pd | |
| import random | |
| from .config import * | |
| from .process import process_data | |
| from transformers import BertTokenizerFast | |
| #返回一个rel2id 和id2rel | |
| def get_rel(): | |
| df = pd.read_csv(REL_PATH, names=['rel', 'id']) | |
| return df['rel'].tolist(), dict(df.values) | |
| #生成长度为len,hot_pos位置为1其余位置为0的独热编码 | |
| def multihot(length, hot_pos): | |
| return [1 if i in hot_pos else 0 for i in range(length)] | |
| class Dataset(data.Dataset): | |
| def __init__(self, type='train'): | |
| super().__init__() | |
| _, self.rel2id = get_rel() | |
| # 加载文件 | |
| if type == 'train': | |
| file_path = TRAIN_PATH | |
| elif type == 'test': | |
| file_path = TEST_PATH | |
| self.lines = process_data(file_path) | |
| # 加载bert | |
| self.tokenizer = BertTokenizerFast.from_pretrained(BERT_MODEL_NAME) | |
| def __len__(self): | |
| return len(self.lines) | |
| def __getitem__(self, index): | |
| info = self.lines[index] | |
| # print(type(info)) | |
| # exit() | |
| tokenized = self.tokenizer(info['text'], return_offsets_mapping=True) | |
| info['input_ids'] = tokenized['input_ids'] | |
| info['offset_mapping'] = tokenized['offset_mapping'] | |
| return self.parse_dict(info) | |
| def get_pos_id(self, source, elem): | |
| for head_id in range(len(source)): | |
| tail_id = head_id + len(elem) | |
| if source[head_id:tail_id] == elem: | |
| return head_id, tail_id - 1 | |
| def collate_fn(self,batch): | |
| #获得最长的句子长度,便于填充pad | |
| batch.sort(key=lambda x : len(x["input_ids"]),reverse=True) | |
| max_len = len(batch[0]["input_ids"]) | |
| batch_text = { | |
| 'text': [], | |
| 'input_ids': [], | |
| 'offset_mapping': [], | |
| 'triple_list': [], | |
| } | |
| batch_mask = [] | |
| batch_sub = { | |
| 'heads_seq': [], | |
| 'tails_seq': [], | |
| } | |
| batch_sub_rnd = { | |
| 'head_seq': [], | |
| 'tail_seq': [], | |
| } | |
| batch_obj_rel = { | |
| 'heads_mx': [], | |
| 'tails_mx': [], | |
| } | |
| #对batch中的每一个item进行处理 | |
| for item in batch: | |
| input_ids = item["input_ids"] #对元素进行pad填充 | |
| item_len = len(input_ids) | |
| pad_len = max_len - item_len | |
| input_ids = input_ids + [0] * pad_len | |
| mask = [1] * item_len + [0] * pad_len | |
| # print(mask) | |
| # exit() | |
| sub_head_seq = multihot(max_len,item["sub_head_ids"]) | |
| sub_tail_seq = multihot(max_len, item["sub_tail_ids"]) | |
| # print(item["sub_head_ids"]) | |
| # print(sub_head_seq) | |
| # exit() | |
| if len(item['triple_id_list']) == 0: #如果没有三元组则continue | |
| continue | |
| sub_rnd = random.choice(item['triple_id_list'])[0] | |
| sub_rnd_head_seq = multihot(max_len, [sub_rnd[0]]) | |
| sub_rnd_tail_seq = multihot(max_len, [sub_rnd[1]]) | |
| #根据随机subject计算relations矩阵 | |
| obj_head_mx = [[0] * REL_SIZE for _ in range(max_len)] #生成两个二维全0矩阵(一个head矩阵一个tail矩阵) | |
| obj_tail_mx = [[0] * REL_SIZE for _ in range(max_len)] | |
| for triple in item["triple_id_list"]: #对全0矩阵进行填充获得obj的head和tail的rel矩阵 | |
| rel_id = triple[1] | |
| head_id, tail_id = triple[2] | |
| if triple[0] == sub_rnd: # 对于本课题可以取消这一步,因为数据集中有且仅有唯一的sub | |
| obj_head_mx[head_id][rel_id] = 1 | |
| obj_tail_mx[tail_id][rel_id] = 1 | |
| #重新组装batch,一条item压入一组信息 | |
| batch_text["text"].append(item["text"]) | |
| batch_text["input_ids"].append(input_ids) | |
| batch_text["offset_mapping"].append(item["offset_mapping"]) | |
| batch_text["triple_list"].append(item["triple_list"]) | |
| batch_mask.append(mask) | |
| batch_sub["heads_seq"].append(sub_head_seq) | |
| batch_sub["tails_seq"].append(sub_tail_seq) | |
| batch_sub_rnd["head_seq"].append(sub_rnd_head_seq) | |
| batch_sub_rnd["tail_seq"].append(sub_rnd_tail_seq) | |
| # print(sub_rnd_head_seq) | |
| # print(sub_head_seq) | |
| # exit() | |
| batch_obj_rel["heads_mx"].append(obj_head_mx) | |
| batch_obj_rel["tails_mx"].append(obj_tail_mx) | |
| return batch_mask,(batch_text,batch_sub_rnd),(batch_sub,batch_obj_rel) | |
| def parse_dict(self, info): #对dict串进行解析 | |
| text = info['text'] | |
| input_ids = info['input_ids'] #整个text的input_ids | |
| dct = { | |
| 'text': text, | |
| 'input_ids': input_ids, | |
| 'offset_mapping': info['offset_mapping'], | |
| 'sub_head_ids': [], | |
| 'sub_tail_ids': [], | |
| 'triple_list': [], | |
| 'triple_id_list': [] | |
| } | |
| for spo in info['spo_list']: | |
| subject = spo['subject'] | |
| object = spo['object'] | |
| predicate = spo['predicate'] | |
| dct['triple_list'].append((subject, predicate, object)) | |
| # 计算 subject 实体位置 | |
| tokenized = self.tokenizer(subject, add_special_tokens=False) | |
| sub_token = tokenized['input_ids'] | |
| sub_pos_id = self.get_pos_id(input_ids, sub_token) | |
| if not sub_pos_id: | |
| continue | |
| sub_head_id, sub_tail_id = sub_pos_id | |
| # 计算 object 实体位置 | |
| tokenized = self.tokenizer(object, add_special_tokens=False) | |
| obj_token = tokenized['input_ids'] | |
| obj_pos_id = self.get_pos_id(input_ids, obj_token) | |
| if not obj_pos_id: | |
| continue | |
| obj_head_id, obj_tail_id = obj_pos_id | |
| # 数据组装 | |
| dct['sub_head_ids'].append(sub_head_id) | |
| dct['sub_tail_ids'].append(sub_tail_id) | |
| dct['triple_id_list'].append(( | |
| [sub_head_id, sub_tail_id], | |
| self.rel2id[predicate], | |
| [obj_head_id, obj_tail_id], | |
| )) | |
| return dct | |
| # # 数据预处理部分已经格式化 | |
| # spo = info["spo_list"] | |
| # subject = spo['subject'] | |
| # object = spo['object'] | |
| # predicate = spo['predicate'] | |
| # dct['triple_list'].append((subject, predicate, object)) | |
| # | |
| # tokenized = self.tokenizer(subject, add_special_tokens=False) | |
| # sub_token = tokenized['input_ids'] | |
| # # print(input_ids) | |
| # # print(sub_token) | |
| # # exit() | |
| # sub_pos_id = self.get_pos_id(input_ids, sub_token) #通过编码后的 | |
| # | |
| # sub_head_id, sub_tail_id = sub_pos_id | |
| # # 计算 object 实体位置 | |
| # tokenized = self.tokenizer(object, add_special_tokens=False) | |
| # obj_token = tokenized['input_ids'] | |
| # obj_pos_id = self.get_pos_id(input_ids, obj_token) | |
| # | |
| # obj_head_id, obj_tail_id = obj_pos_id | |
| # # 数据组装 | |
| # dct['sub_head_ids'].append(sub_head_id) | |
| # dct['sub_tail_ids'].append(sub_tail_id) | |
| # | |
| # dct['triple_id_list'].append(( | |
| # [sub_head_id, sub_tail_id], | |
| # self.rel2id[predicate], | |
| # [obj_head_id, obj_tail_id], | |
| # )) | |
| # | |
| # return dct | |
| if __name__ == '__main__': | |
| dataset = Dataset() | |
| loader = data.DataLoader(dataset, shuffle=False, batch_size=2, collate_fn=dataset.collate_fn) | |
| print(next(iter(loader))) | |
| exit() |