From 0de3cbd31dfaedbe8d27ec504f5e6345ac9fbb30 Mon Sep 17 00:00:00 2001 From: shengdinghu Date: Mon, 18 Apr 2022 23:28:13 +0800 Subject: [PATCH] example_prompt_unify --- dist/opendelta-0.0.4-py3-none-any.whl | Bin 0 -> 76152 bytes dist/opendelta-0.0.4.tar.gz | Bin 0 -> 61237 bytes .../data_processors/__init__.py | 4 +- .../data_processors/data_collator.py | 38 +- .../data_processors/postprocessors.py | 20 +- .../examples_prompt/data_processors/tasks.py | 746 +++++++++--------- examples/examples_prompt/run_mlm.py | 522 ++++++++---- examples/examples_prompt/run_mlm.sh | 6 +- opendelta/__init__.py | 2 +- opendelta/basemodel.py | 12 +- opendelta/delta_models/lora.py | 2 - opendelta/delta_models/soft_prompt.py | 26 +- setup.py | 2 +- 13 files changed, 814 insertions(+), 566 deletions(-) create mode 100644 dist/opendelta-0.0.4-py3-none-any.whl create mode 100644 dist/opendelta-0.0.4.tar.gz diff --git a/dist/opendelta-0.0.4-py3-none-any.whl b/dist/opendelta-0.0.4-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..a31a5ff3fbeb64584a836fa62721ee9da566e2f5 GIT binary patch literal 76152 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"): +# self.max_seq_length=max_seq_length +# self.tokenizer=tokenizer +# self.num_special_tokens_to_add = len(tokenizer("")['input_ids']) +# # from IPython import embed; embed(header="Truega") +# self.truncate_method=truncate_method +# self.total_passed_sentences = 0 +# self.num_truncated_sentences = 0 +# self.mask_token_func = mask_token_func + +# if truncate_method=='tail': +# self.truncate_fct = self.truncate_from_tail +# elif truncate_method=='head': +# self.truncate_fct = self.truncate_from_head +# elif truncate_method == 'balanced': +# self.truncate_fct = self.balanced_truncate +# else: +# raise NotImplementedError + + +# def merge_wrapped_example(self, wrapped_example,): +# ''' # TODO doens't consider the situation that input has two parts +# ''' + +# wrapped_example + +# # for some dataset like SuperGLUE.COPA, the answer requires prediction an span of +# # the input. Or in generation tasks, we need to generate a piece of target_text. +# # In these case, it tokenized to the encoded_tgt_text for furture use. +# encoder_inputs = defaultdict(list) +# # from IPython import embed; embed(header="Line 67") + +# mask_count = 0 +# for piece in wrapped_example: +# if piece['text'] == "": +# encode_text = self.tokenizer.encode(self.mask_token_func(mask_count), add_special_tokens=False, return_special_tokens_mask=True ) +# mask_count += 1 +# else: +# encode_text = self.tokenizer.encode(piece['text'], add_special_tokens=False, return_special_tokens_mask=True ) +# encoder_inputs['input_ids'].append(encode_text) +# encoder_inputs['shortenable_ids'].append([piece['shortenable_ids']] * len(encode_text)) - def merge_wrapped_example(self, wrapped_example, ): - ''' # TODO doens't consider the situation that input has two parts - ''' +# encoder_inputs = self.truncate(encoder_inputs=encoder_inputs) +# encoder_inputs.pop("shortenable_ids") +# encoder_inputs = self.concate_parts(input_dict=encoder_inputs) +# decoded_inputs = self.tokenizer.decode(encoder_inputs['input_ids'], clean_up_tokenization_spaces=False) - wrapped_example, others = wrapped_example +# return decoded_inputs - # for some dataset like SuperGLUE.COPA, the answer requires prediction an span of - # the input. Or in generation tasks, we need to generate a piece of target_text. - # In these case, it tokenized to the encoded_tgt_text for furture use. + +# @staticmethod +# def balanced_truncate(input_dict: Dict, +# num_tokens_to_truncate: int=0) -> Dict: +# '''truncate the inputs with balance, number of cut tokens is proportional to the part's length. +# ''' +# shortenable_lens = [len(parts) if parts[0]==1 else 0 +# for parts in input_dict['shortenable_ids']] +# total_shortenable_len = sum(shortenable_lens) +# num_tokens_to_truncate_each_part = [part_len/total_shortenable_len*num_tokens_to_truncate +# for part_len in shortenable_lens] +# round_list(num_tokens_to_truncate_each_part, num_tokens_to_truncate) + +# truncated_example = defaultdict(list) +# for key in input_dict: +# parts = input_dict[key] +# for num_tokens_to_truncate_part, part in zip(num_tokens_to_truncate_each_part, parts): +# truncated_example[key].append(part[:len(part)-num_tokens_to_truncate_part]) +# return truncated_example + +# @staticmethod +# def truncate_from_tail(input_dict: Dict, +# num_tokens_to_truncate: int=0) -> Dict: +# r"""truncate the inputs from the rear +# """ +# truncated_example = defaultdict(list) +# shortenable_ids = input_dict['shortenable_ids'] + +# for key in input_dict: +# parts = input_dict[key] +# to_trunc = num_tokens_to_truncate +# for i, part in enumerate(parts[::-1]): +# if len(part) == 0: # to prevent some part are empty after tokenization +# continue +# if shortenable_ids[-1-i][0]==0: # ==0 means the part is not shortenable +# continue +# parts[-1-i] = part[:-to_trunc] if to_trunc Dict: +# r"""truncate the inputs from the head +# """ +# truncated_example = defaultdict(list) +# shortenable_ids = input_dict['shortenable_ids'] +# for key in input_dict: +# parts = input_dict[key] +# to_trunc = num_tokens_to_truncate +# for i, part in enumerate(parts): +# if shortenable_ids[i][0]==0: # ==0 means the part is not shortenable +# continue +# parts[i] = part[:-to_trunc] if to_trunc Dict: +# for key in input_dict: +# input_dict[key] = list(itertools.chain(*input_dict[key])) +# return input_dict + + +# def truncate(self, encoder_inputs): +# total_tokens = sum([len(part) for part in encoder_inputs['input_ids']]) +# num_specials = self.num_special_tokens_to_add +# # print("num_specials", num_specials) +# num_tokens_to_truncate = total_tokens - self.max_seq_length + num_specials +# self.total_passed_sentences+=1 +# if num_tokens_to_truncate>0: +# self.num_truncated_sentences += 1 +# if num_tokens_to_truncate > sum([len(x) for x in encoder_inputs['shortenable_ids']]): +# raise RuntimeError("num_tokens_to_truncate larger than number of shortenable tokens.") +# encoder_inputs = self.truncate_fct(input_dict=encoder_inputs, +# num_tokens_to_truncate=num_tokens_to_truncate) +# return encoder_inputs + +# def tokenizer_preprocessor(self, example): +# # source, target = example +# # from IPython import embed; embed(header="Trehre2") +# label = example['label'] +# guid = example['idx'] +# meta = dict(example) +# meta.pop("label") +# meta.pop("idx") - encoder_inputs = defaultdict(list) - for piece in wrapped_example: - encode_text = self.tokenizer.encode(piece['text'], add_special_tokens=False, return_special_tokens_mask=True ) - encoder_inputs['input_ids'].append(encode_text) - encoder_inputs['shortenable_ids'].append([piece['shortenable_ids']] * len(encode_text)) +# # from IPython import embed; embed(header="Trehre2") +# e = InputExample(**{"meta": meta, 'label': label, 'guid': guid}) - encoder_inputs = self.truncate(encoder_inputs=encoder_inputs) - encoder_inputs.pop("shortenable_ids") - encoder_inputs = self.concate_parts(input_dict=encoder_inputs) - decoded_inputs = self.tokenizer.decode(encoder_inputs['input_ids'], clean_up_tokenization_spaces=False) - - # again_encode = self.tokenizer.encode(decoded_inputs, add_special_tokens=False, return_special_tokens_mask=True) - # if len(again_encode)> self.max_seq_length - 2: - # print("length exceed!") - # print(wrapped_example) - # print(encoder_inputs['input_ids']) - # print(again_encode) - # print(decoded_inputs) - # exit() - - - - - - - # delete shortenable ids - - # encoder_inputs = self.concate_parts(input_dict=encoder_inputs) - # encoder_inputs = self.add_special_tokens(encoder_inputs=encoder_inputs) - # # create special input ids - # encoder_inputs['attention_mask'] = [1] *len(encoder_inputs['input_ids']) - # # padding - # encoder_inputs = self.padding(input_dict=encoder_inputs, max_len=self.max_seq_length, pad_id_for_inputs=self.tokenizer.pad_token_id) - - return decoded_inputs - - @staticmethod - def balanced_truncate(input_dict: Dict, - num_tokens_to_truncate: int=0) -> Dict: - '''truncate the inputs with balance, number of cut tokens is proportional to the part's length. - ''' - shortenable_lens = [len(parts) if parts[0]==1 else 0 - for parts in input_dict['shortenable_ids']] - total_shortenable_len = sum(shortenable_lens) - num_tokens_to_truncate_each_part = [part_len/total_shortenable_len*num_tokens_to_truncate - for part_len in shortenable_lens] - round_list(num_tokens_to_truncate_each_part, num_tokens_to_truncate) - - truncated_example = defaultdict(list) - for key in input_dict: - parts = input_dict[key] - for num_tokens_to_truncate_part, part in zip(num_tokens_to_truncate_each_part, parts): - truncated_example[key].append(part[:len(part)-num_tokens_to_truncate_part]) - return truncated_example - - @staticmethod - def truncate_from_tail(input_dict: Dict, - num_tokens_to_truncate: int=0) -> Dict: - r"""truncate the inputs from the rear - """ - truncated_example = defaultdict(list) - shortenable_ids = input_dict['shortenable_ids'] - - for key in input_dict: - parts = input_dict[key] - to_trunc = num_tokens_to_truncate - for i, part in enumerate(parts[::-1]): - if len(part) == 0: # to prevent some part are empty after tokenization - continue - if shortenable_ids[-1-i][0]==0: # ==0 means the part is not shortenable - continue - parts[-1-i] = part[:-to_trunc] if to_trunc Dict: - r"""truncate the inputs from the head - """ - truncated_example = defaultdict(list) - shortenable_ids = input_dict['shortenable_ids'] - for key in input_dict: - parts = input_dict[key] - to_trunc = num_tokens_to_truncate - for i, part in enumerate(parts): - if shortenable_ids[i][0]==0: # ==0 means the part is not shortenable - continue - parts[i] = part[:-to_trunc] if to_trunc Dict: - for key in input_dict: - input_dict[key] = list(itertools.chain(*input_dict[key])) - return input_dict - - # @staticmethod - # def padding(input_dict: Dict, - # max_len: int, pad_id_for_inputs: int=0, pad_id_for_others: int=0) -> None: - # for key, value in input_dict.items(): - # if (len(input_dict[key]) > max_len): - # raise ValueError(f''' - # Truncated seq length of '{key}' still greater than max length '{max_len}.' - # One possible reason is that no enough shortenable parts in template. Try add {{"shortenable": "True"}} property. - # ''') - # if 'input' in key: - # input_dict[key].extend([pad_id_for_inputs]*(max_len-len(value))) - # else: - # input_dict[key].extend([pad_id_for_others]*(max_len-len(value))) - # return input_dict - - - # def add_special_tokens(self, encoder_inputs): - # # add special tokens - # for key in encoder_inputs: - # if key == "input_ids": - # with warnings.catch_warnings(): - # warnings.simplefilter("ignore") - # encoder_inputs[key] = self.tokenizer.build_inputs_with_special_tokens( - # encoder_inputs[key]) - # return encoder_inputs - - def truncate(self, encoder_inputs): - total_tokens = sum([len(part) for part in encoder_inputs['input_ids']]) - num_specials = self.num_special_tokens_to_add - # print("num_specials", num_specials) - num_tokens_to_truncate = total_tokens - self.max_seq_length + num_specials - self.total_passed_sentences+=1 - if num_tokens_to_truncate>0: - self.num_truncated_sentences += 1 - if num_tokens_to_truncate > sum([len(x) for x in encoder_inputs['shortenable_ids']]): - raise RuntimeError("num_tokens_to_truncate larger than number of shortenable tokens.") - encoder_inputs = self.truncate_fct(input_dict=encoder_inputs, - num_tokens_to_truncate=num_tokens_to_truncate) - return encoder_inputs +# if self.predict_with_generate: +# e = self.verbalizer.wrap_one_example(e) +# example_wrapped = self.template.wrap_one_example(e) +# encoded_sentence = self.tokenizer_wrapper.merge_wrapped_example(example_wrapped) +# print(encoded_sentence) +# if self.predict_with_generate: +# # return {"source": encoded_sentence, 'target': ', 'extra_fields':[]} +# return {"source": encoded_sentence, "label": label, 'target': '', 'extra_fields':{'dataset_name':self.name}} +# else: +# return {"source": encoded_sentence, "label": label, 'target': e.target_text, 'extra_fields':{'dataset_name':self.name}} @@ -234,46 +221,23 @@ class AbstractTask(abc.ABC): "superglue-boolq", "qqp", "qnli", "superglue-record", "sst2"] large_data_without_all_splits = [] #["qqp", "qnli", "superglue-record", "sst2"] - def __init__(self, config, data_args, tokenizer, predict_with_generate, seed=42, default_max_length=1): + def __init__(self, config, data_args, seed=42, default_max_length=1): self.config = config self.seed = seed self.data_args = data_args - self.tokenizer = tokenizer - self.predict_with_generate = predict_with_generate + # self.tokenizer = tokenizer + # self.predict_with_generate = predict_with_generate self.default_max_length = default_max_length - self.truncate_method = getattr(data_args, "truncate_method", "balanced") - tid = getattr(config, "template_id", 0) - vid = getattr(config, "verbalizer_id", 0) - - self.template = ManualTemplate(tokenizer=self.tokenizer, text = self.templates_text[tid]) - self.verbalizer = ManualVerbalizer(tokenizer=self.tokenizer, classes = self.labels_list, label_words=self.verbalizers[vid]) - - # if self.predict_with_generate: - # self.reverse_verbalizer = {(int(x) for x in self.tokenizer.convert_tokens_to_ids(self.tokenizer.tokenize(self.verbalizer[label]))): label for label in self.labels_list} - # else: - # self.reverse_verbalizer = {int(self.tokenizer.convert_tokens_to_ids(self.tokenizer.tokenize(self.verbalizer[label]))[0]): label for label in self.labels_list} - - self.tokenizer_wrapper = MLMTokenizerWrapper(max_seq_length=self.data_args.max_source_length, tokenizer=self.tokenizer, truncate_method=self.truncate_method) - - generation_paradigm = getattr(config, "generation_paradigm", True) + # generation_paradigm = getattr(config, "generation_paradigm", True) # self.prompt = PromptCollections[self.name](tid, vid, generation_paradigm) - self.max_target_length = self.get_max_target_length(self.default_max_length) - def get_max_target_length(self, default_max_length): - if self.predict_with_generate: - return max([len(label) for key, label in self.verbalizer.label_words_ids.items()]) - else: - return default_max_length - def seq2seq_format(self, source, target, extra_fields={} - ): - - return {'source': ' '.join(source), - 'target': ' '.join(target), - 'task': self.name, - 'extra_fields': extra_fields - } + # def get_max_target_length(self, default_max_length): + # if self.predict_with_generate: + # return -1 + # else: + # return default_max_length def check_n_obs(self, n_obs, total_size): if n_obs is not None and n_obs > total_size: @@ -312,37 +276,9 @@ class AbstractTask(abc.ABC): else: return indices[validation_size:] - - def map_dataset(self, dataset): - # from IPython import embed; embed(header="in get target length") - return dataset.map(self.preprocessor).map(self.tokenizer_preprocessor) - def preprocessor(self, example): return example - def tokenizer_preprocessor(self, example): - # source, target = example - # from IPython import embed; embed(header="Trehre2") - label = example['label'] - guid = example['idx'] - meta = dict(example) - meta.pop("label") - meta.pop("idx") - - - - # from IPython import embed; embed(header="Trehre2") - - e = InputExample(**{"meta": meta, 'label': label, 'guid': guid}) - template_e = self.template.wrap_one_example(e) - encoded_sentence = self.tokenizer_wrapper.merge_wrapped_example(template_e) - if self.predict_with_generate: - # return {"source": encoded_sentence, 'target': ', 'extra_fields':[]} - raise NotImplementedError - else: - return {"source": encoded_sentence, "label": label, 'target': '', 'extra_fields':{'dataset_name':self.name}} - - def get(self, split, n_obs=None, split_validation_test=False): # For small datasets (n_samples < 10K) without test set, we divide validation set to # half, use one half as test set and one half as validation set. @@ -368,7 +304,7 @@ class AbstractTask(abc.ABC): # shuffles the data and samples it. if n_obs is not None: dataset = self.subsample(dataset, n_obs) - return self.map_dataset(dataset) + return dataset.map(self.preprocessor) class Squad(AbstractTask): name = "squad" @@ -387,25 +323,7 @@ class Squad(AbstractTask): return self.seq2seq_format(source, target, add_prefix) -class MRPC(AbstractTask): - name = "mrpc" - labels_list = ["0", "1"] - metric = [metrics.f1_score, metrics.accuracy] - metric_names = ["f1", "accuracy"] - split_to_data_split = {"train": "train", - "validation": "validation", - "test": "validation"} - - def load_dataset(self, split): - return datasets.load_dataset('glue', 'mrpc', split=split, script_version="master") - - # def preprocessor(self, example, add_prefix=True): - # src_texts = ["sentence1:", example['sentence1'], - # "sentence2:", example["sentence2"]] - # tgt_texts = [str(example['label'])] - # return self.seq2seq_format(src_texts, tgt_texts, add_prefix) - - +##GLUE class COLA(AbstractTask): name = "cola" labels_list = ["0", "1"] @@ -415,14 +333,19 @@ class COLA(AbstractTask): "validation": "validation", "test": "validation"} - def load_dataset(self, split): - return datasets.load_dataset('glue', 'cola', - split=split, script_version="master") + templates_text = {"0": """sentence: {"meta": 'sentence', "shortenable":True} Are there any error in the sentence? {"mask"}""", + } - # def preprocessor(self, example, add_prefix=True): - # src_texts = ["sentence:", example['sentence']] - # tgt_texts = [str(example['label'])] - # return self.seq2seq_format(src_texts, tgt_texts, add_prefix) + verbalizers = { + "0":{ "0": "yes", "1": "no"} + } + + def load_dataset(self, split): + if self.data_args.datasets_load_from_disk: + return datasets.load_from_disk(f"{self.data_args.datasets_saved_path}/glue.cola")[split] + else: + return datasets.load_dataset('glue', 'cola', + split=split, script_version="master") class SST2(AbstractTask): @@ -434,38 +357,50 @@ class SST2(AbstractTask): "validation": "validation", "test": "validation"} - verbalizers = [ - - ] + verbalizers = { + "0":{"0":"negative","1":"positive"} + } + + templates_text = { + "0":"""The sentiment of sentence: "{"meta":"sentence", "shortenable":True} is {"mask"}.""" + } def load_dataset(self, split): - return datasets.load_dataset('glue', 'sst2', - split=split, script_version="master") - - def preprocessor(self, example, add_prefix=True): - src_texts = ["sentence:", example['sentence']] - tgt_texts = [str(example['label'])] - return self.seq2seq_format(src_texts, tgt_texts, add_prefix) + if self.data_args.datasets_load_from_disk: + return datasets.load_from_disk(f"{self.data_args.datasets_saved_path}/glue.sst2")[split] + else: + return datasets.load_dataset('glue', 'sst2', + split=split, script_version="master") -class STSB(AbstractTask): - name = "stsb" - labels_list = [str(np.round(label, decimals=1)) for label in np.arange(0, 5.2, 0.2)] - metric = [metrics.pearson_corrcoef, metrics.spearman_corrcoef] - metric_names = ["pearson", "spearmanr"] + +class MRPC(AbstractTask): + name = "mrpc" + labels_list = ["0", "1"] + metric = [metrics.f1_score, metrics.accuracy] + metric_names = ["f1", "accuracy"] split_to_data_split = {"train": "train", "validation": "validation", "test": "validation"} - def load_dataset(self, split): - return datasets.load_dataset('glue', 'stsb', - split=split, script_version="master") - def preprocessor(self, example, add_prefix=True): - src_texts = ["sentence1:", example['sentence1'], - "sentence2:", example["sentence2"]] - tgt_texts = [str(round_stsb_target(example['label']))] - return self.seq2seq_format(src_texts, tgt_texts, add_prefix) + templates_text = { + "0": """sentence1: {"meta": 'sentence1', "shortenable":True}. sentence2: {"meta":"sentence2", "shortenable":True}. Are sentence1 and sentence2 equivalent? {"mask"}.""", + } + + verbalizers = { + "0":{"0": "no","1": "yes"} + } + + + + + def load_dataset(self, split): + if self.data_args.datasets_load_from_disk: + return datasets.load_from_disk(f"{self.data_args.datasets_saved_path}/glue.mrpc")[split] + else: + return datasets.load_dataset('glue', 'mrpc', split=split, script_version="master") + class QQP(AbstractTask): @@ -477,14 +412,46 @@ class QQP(AbstractTask): "validation": "validation", "test": "validation"} + templates_text = {"0": + """question1: {"meta": 'question1', "shortenable":True}. question2: {"meta": 'question2', "shortenable":True} Are question1 and question2 equivalent? {"mask"}.""" + } + + verbalizers = { + "0":{"0": "no","1": "yes"} + } + + def load_dataset(self, split): - return datasets.load_dataset('glue', 'qqp', + if self.data_args.datasets_load_from_disk: + return datasets.load_from_disk(f"{self.data_args.datasets_saved_path}/glue.qqp")[split] + else: + return datasets.load_dataset('glue', 'qqp', + split=split, script_version="master") + + + +class STSB(AbstractTask): + name = "stsb" + labels_list = [str(np.round(label, decimals=1)) for label in np.arange(0, 5.2, 0.2)] + metric = [metrics.pearson_corrcoef, metrics.spearman_corrcoef] + metric_names = ["pearson", "spearmanr"] + split_to_data_split = {"train": "train", + "validation": "validation", + "test": "validation"} + + + verbalizers = { + "" + } + + def load_dataset(self, split): + return datasets.load_dataset('glue', 'stsb', split=split, script_version="master") def preprocessor(self, example, add_prefix=True): - src_texts = ["question1:", example['question1'], - "question2:", example["question2"]] - tgt_texts = [str(example['label'])] + src_texts = ["sentence1:", example['sentence1'], + "sentence2:", example["sentence2"]] + tgt_texts = [str(round_stsb_target(example['label']))] return self.seq2seq_format(src_texts, tgt_texts, add_prefix) @@ -498,14 +465,29 @@ class MNLI(AbstractTask): metric_names = ["accuracy"] - def load_dataset(self, split): - return datasets.load_dataset('glue', 'mnli', split=split, script_version="master") + templates_text = { + "0":"""premise: {"meta": 'premise', "shortenable":True}. hypothesis: {"meta": 'hypothesis', "shortenable":True} Does the premise entails the hypothesis? {"mask"}.""", + } - def preprocessor(self, example, add_prefix=True): - src_texts = ["premise:", example['premise'], - "hypothesis", example["hypothesis"]] - tgt_texts = [str(example['label'])] - return self.seq2seq_format(src_texts, tgt_texts, add_prefix) + verbalizers = { + "0":{ + "0": "yes", + "1": "neutral", + "2": "no", + } + } + + def load_dataset(self, split): + if self.data_args.datasets_load_from_disk: + return datasets.load_from_disk(f"{self.data_args.datasets_saved_path}/glue.mnli")[split] + else: + return datasets.load_dataset('glue', 'mnli', split=split, script_version="master") + + # def preprocessor(self, example, add_prefix=True): + # src_texts = ["premise:", example['premise'], + # "hypothesis", example["hypothesis"]] + # tgt_texts = [str(example['label'])] + # return self.seq2seq_format(src_texts, tgt_texts, add_prefix) class QNLI(AbstractTask): @@ -517,14 +499,33 @@ class QNLI(AbstractTask): "validation": "validation", "test": "validation"} - def load_dataset(self, split): - return datasets.load_dataset('glue', 'qnli', split=split, script_version="master") + templates_text = { + "0": """premise: {"meta": 'sentence', "shortenable":True}. hypothesis: {"meta": 'question', "shortenable":True}"""+ + """Does the premise entails the hypothesis? {"mask"}.""", + } - def preprocessor(self, example, add_prefix=True): - src_texts = ["question:", example['question'], - "sentence:", example["sentence"]] - tgt_texts = [str(example['label'])] - return self.seq2seq_format(src_texts, tgt_texts, add_prefix) + verbalizers = { + "0":{ + "0": "yes", + "1": "no", + } + } + + + def load_dataset(self, split): + if self.data_args.datasets_load_from_disk: + return datasets.load_from_disk(f"{self.data_args.datasets_saved_path}/glue.qnli")[split] + else: + return datasets.load_dataset('glue', 'qnli', split=split, script_version="master") + + # def load_dataset(self, split): + # return datasets.load_dataset('glue', 'qnli', split=split, script_version="master") + + # def preprocessor(self, example, add_prefix=True): + # src_texts = ["question:", example['question'], + # "sentence:", example["sentence"]] + # tgt_texts = [str(example['label'])] + # return self.seq2seq_format(src_texts, tgt_texts, add_prefix) #Tested class RTE(AbstractTask): @@ -537,15 +538,15 @@ class RTE(AbstractTask): "test": "validation"} - templates_text = [ - """sentence1: {"meta": 'sentence1', "shortenable":True}. sentence2:,"""+ - """{"meta":"sentence2", "shortenable":True}. The answer was {"mask"}.""", - ] + templates_text = { + "0": """sentence1: {"meta": 'sentence1', "shortenable":True} sentence2: {"meta":"sentence2", "shortenable":True} The answer was {"mask"}.""", + } - verbalizers = [{ - "0": "yes", + verbalizers = { + "0":{"0": "yes", "1": "no" - }] + } + } def load_dataset(self, split): if self.data_args.datasets_load_from_disk: @@ -555,38 +556,6 @@ class RTE(AbstractTask): split=split, script_version="master") -#Tested -class SuperGLUEBoolQ(AbstractTask): - name="superglue-boolq" - labels_list = ['0', '1'] - metric = [metrics.accuracy] - metric_names = ["accuracy"] - split_to_data_split = {"train": "train", - "validation": "validation", - "test": "validation"} - - verbalizers = [ - { - "0": "no", - "1": "yes" - }, - ] - mlmhead_verbalizers = { - "0": "no", - "1": "yes" - } - templates_text = [ - """hypothesis: {"meta": "question", "shortenable":True} premise: {"meta":"passage", "shortenable":True} The answer was {"mask"}.""" - ] - - def load_dataset(self, split): - if self.data_args.datasets_load_from_disk: - return datasets.load_from_disk(f"{self.data_args.datasets_saved_path}/super_glue.boolq")[split] - else: - return datasets.load_dataset('super_glue', 'boolq', split=split, script_version="master") - - - class WNLI(AbstractTask): name = "wnli" @@ -597,13 +566,13 @@ class WNLI(AbstractTask): "validation": "validation", "test": "validation"} - verbalizers = [{ - "0": "True", - "1": "False", - }] - templates_text = [ - """{"meta": 'sentence1',"shortenable":True} Does it mean the following: "{"meta":'sentence2'}"? {"mask"}.""" - ] + verbalizers = { + "0":{"0": "True", + "1": "False", + } + } + templates_text = {"0": """{"meta": 'sentence1',"shortenable":True} Does it mean the following: "{"meta":'sentence2'}"? {"mask"}.""" + } def load_dataset(self, split): @@ -613,6 +582,34 @@ class WNLI(AbstractTask): return datasets.load_dataset('glue', 'wnli', split=split, script_version="master") +#SuperGLUE +class SuperGLUEBoolQ(AbstractTask): + name="superglue-boolq" + labels_list = ['0', '1'] + metric = [metrics.accuracy] + metric_names = ["accuracy"] + split_to_data_split = {"train": "train", + "validation": "validation", + "test": "validation"} + + verbalizers = { + "0": { + "0": "no", + "1": "yes" + }, + } + + templates_text = { + "0": """hypothesis: {"meta": "question", "shortenable":True} premise: {"meta":"passage", "shortenable":True} The answer was {"mask"}.""" + } + + def load_dataset(self, split): + if self.data_args.datasets_load_from_disk: + return datasets.load_from_disk(f"{self.data_args.datasets_saved_path}/super_glue.boolq")[split] + else: + return datasets.load_dataset('super_glue', 'boolq', split=split, script_version="master") + + # class SuperGLUECB(AbstractTask): name = "superglue-cb" @@ -623,14 +620,15 @@ class SuperGLUECB(AbstractTask): metric = [metrics.mean_multiclass_f1(num_classes=3), metrics.accuracy] metric_names = ["f1_multiclass", "accuracy"] - verbalizers = [{ - "0": "yes", - "1": "no", - "2": "maybe" - }] - templates_text = [ - """hypothesis: {"meta": 'hypothesis',"shortenable":True} premise: {"meta":'premise', "shortenable":True} The answer was {"mask"}.""" - ] + verbalizers = { + "0":{"0": "yes", + "1": "no", + "2": "maybe" + } + } + templates_text = { + "0": """hypothesis: {"meta": 'hypothesis',"shortenable":True} premise: {"meta":'premise', "shortenable":True} The answer was {"mask"}.""" + } def load_dataset(self, split): if self.data_args.datasets_load_from_disk: @@ -648,13 +646,15 @@ class SuperGLUECOPA(AbstractTask): metric = [metrics.accuracy] metric_names = ["accuracy"] - verbalizers = [{ - "0": "1", - "1": "2", - }] - templates_text = [ - """choice1: {"meta":"choice1"} choice2: {"meta":"choice2"} premise: {"meta":"premise", "shortenable":True} The {"meta":"question"} answer was choice{"mask"}.""" - ] + verbalizers = { + "0":{ + "0": "1", + "1": "2", + } + } + templates_text = { + "0": """choice1: {"meta":"choice1"} choice2: {"meta":"choice2"} premise: {"meta":"premise", "shortenable":True} The {"meta":"question"} answer was choice{"mask"}.""" + } def load_dataset(self, split): if self.data_args.datasets_load_from_disk: @@ -673,19 +673,16 @@ class SuperGLUEMultiRC(AbstractTask): metrics.accuracy] metric_names = ["f1", "em"] - # generation_verbalizers = [{ - # "0": "no", - # "1": "yes", - # }, - # ] - verbalizers = [{ + verbalizers = { + "0": { "0": "no", "1": "yes", - }] - templates_text = [ - """question: {"meta":"question", "shortenable":False} answer: {"meta":"answer", "shortenable":False, "post_processing": lambda x:x+"."} paragraph: {"meta":"paragraph", "shortenable":True} The answer was {"mask"}.""" - ] + } + } + templates_text = { + "0": """question: {"meta":"question", "shortenable":False} answer: {"meta":"answer", "shortenable":False, "post_processing": lambda x:x+"."} paragraph: {"meta":"paragraph", "shortenable":True} The answer was {"mask"}.""" + } def load_dataset(self, split): @@ -720,15 +717,16 @@ class SuperGLUEWIC(AbstractTask): metric = [metrics.accuracy] metric_names = ["accuracy"] - verbalizers = [{ + verbalizers = { + "0": { "0": "No", "1": "Yes", - }] + } + } - templates_text = [ - """sentence1: {"meta":"sentence1"} sentence2: {"meta":"sentence2", "shortenable": True} word: {"meta":"word"} {"mask"}. - """ - ] + templates_text = { + "0": """sentence1: {"meta":"sentence1"} sentence2: {"meta":"sentence2", "shortenable": True} word: {"meta":"word"} {"mask"}.""" + } def load_dataset(self, split): if self.data_args.datasets_load_from_disk: @@ -786,7 +784,7 @@ class SuperGLUEWIC(AbstractTask): # text = self._mark_span(text, example['span2_text'], span2_index, '#') # src_texts = ["text:", text] # tgt_texts = [str(example["label"])] -# return self.seq2seq_format(src_texts, tgt_texts, add_prefix) +# return self.fseq2seq_format(src_texts, tgt_texts, add_prefix) class SuperGLUERecord(AbstractTask): @@ -875,9 +873,9 @@ TASK_MAPPING = OrderedDict( class AutoTask: @classmethod - def get(self, task, config, data_args, tokenizer,predict_with_generate, seed=42): + def get(self, task, config, data_args, seed=42): if task in TASK_MAPPING: - return TASK_MAPPING[task](config, data_args, tokenizer,predict_with_generate, seed) + return TASK_MAPPING[task](config, data_args, seed) raise ValueError( "Unrecognized task {} for AutoTask Model: {}.\n" "Task name should be one of {}.".format( diff --git a/examples/examples_prompt/run_mlm.py b/examples/examples_prompt/run_mlm.py index 139c432..cfc00e7 100644 --- a/examples/examples_prompt/run_mlm.py +++ b/examples/examples_prompt/run_mlm.py @@ -34,6 +34,7 @@ from transformers import ( AutoModelForMaskedLM, AutoModelForSeq2SeqLM, AutoTokenizer, + DataCollatorForSeq2Seq, HfArgumentParser, MBartTokenizer, default_data_collator, @@ -41,8 +42,8 @@ from transformers import ( ) from transformers.trainer_utils import is_main_process, get_last_checkpoint # from ..seq2seq.utils import get_adapter_config -from examples_prompt.data_processors import AutoTask, TaskDataCollatorForSeq2Seq, AutoPostProcessor, data_collator -from examples_prompt.seq2seq_trainer import Seq2SeqTrainer +from examples_prompt.data_processors import AutoTask #, #TaskDataCollatorForSeq2Seq, AutoPostProcessor, data_collator +from transformers import Seq2SeqTrainer # from training_args import AdapterTrainingArguments from examples_prompt.trainers.trainer_utils import save_training_config from dataclasses import dataclass, field @@ -56,7 +57,8 @@ import json import numpy as np logger = logging.getLogger(__name__) - +import os +os.environ["TOKENIZERS_PARALLELISM"] = "false" TASK_TO_METRICS = {"mrpc": ["accuracy", "f1"], "cola": ['matthews_correlation'], @@ -109,7 +111,6 @@ class RemainArgHfArgumentParser(HfArgumentParser): def main(): - # See all possible arguments in src/transformers/training_args.py # or by passing the --help flag to this script. # We now keep distinct sets of args, for a cleaner separation of concerns. @@ -202,21 +203,26 @@ def main(): use_auth_token=True if model_args.use_auth_token else None, ) - model = AutoModelForMaskedLM.from_pretrained( + if training_args.predict_with_generate: + model = AutoModelForSeq2SeqLM.from_pretrained( model_args.model_name_or_path, from_tf=bool(".ckpt" in model_args.model_name_or_path), config=config, cache_dir=model_args.cache_dir, revision=model_args.model_revision, use_auth_token=True if model_args.use_auth_token else None, - ) - model.resize_token_embeddings(len(tokenizer)) + ) + else: + model = AutoModelForMaskedLM.from_pretrained( + model_args.model_name_or_path, + from_tf=bool(".ckpt" in model_args.model_name_or_path), + config=config, + cache_dir=model_args.cache_dir, + revision=model_args.model_revision, + use_auth_token=True if model_args.use_auth_token else None, + ) + model.resize_token_embeddings(len(tokenizer)) - from openprompt.prompts import ManualTemplate - from openprompt.plms import MLMTokenizerWrapper - template = ManualTemplate(tokenizer, text="""sentence1: {"meta": 'premise'}, sentence2:,"""+ - """{"meta":"hypothesis", "shortenable":True}, The answer was {"mask"} .""") - tokenizer_wrapper = MLMTokenizerWrapper(max_seq_length=data_args.max_source_length, tokenizer=tokenizer, truncate_method='tail') @@ -248,49 +254,185 @@ def main(): # Temporarily set max_target_length for training. #max_target_length = data_args.max_target_length - padding = "max_length" if data_args.pad_to_max_length else False - - def preprocess_function(examples, **kwargs): - # max_target_length += 1 - tokenizer = kwargs['tokenizer'] - data_args = kwargs['data_args'] - print("max_length", data_args.max_source_length) - model_inputs = tokenizer(examples['source'], max_length=data_args.max_source_length, - padding="max_length", truncation=True) - - # mask_position = [(id, input_id.index(tokenizer.mask_token_id)) for id, input_id in enumerate(model_inputs.input_ids)]# [[-100 if i != tokenizer.mask_token_id else tokenizer.convert_tokens_to_ids(target) for i in input_id] for input_id, target in zip(model_inputs.input_ids, examples['target'])] - # model_inputs["mask_position"] = mask_position - model_inputs["extra_fields"] = examples['extra_fields'] - # from IPython import embed; embed(header="Therer") - return model_inputs column_names = ['source', 'target', 'label', 'extra_fields'] performance_metrics = {} + + + + def get_prompts(task, tokenizer, predict_with_generate, template_id="0", verbalizer_id="0"): + # tid = getattr(config, "template_id", "0") + # vid = getattr(config, "verbalizer_id", "0") + from openpromptu.prompts import GenerationVerbalizer, ManualVerbalizer + from openpromptu.prompts import ManualTemplate + template = ManualTemplate(text = task.templates_text[template_id]) + if predict_with_generate: + verbalizer = GenerationVerbalizer(tokenizer=tokenizer, classes = task.labels_list, label_words=task.verbalizers[verbalizer_id]) + else: + verbalizer = ManualVerbalizer(tokenizer=tokenizer, classes = task.labels_list, label_words=task.verbalizers[verbalizer_id]) + # max_target_length = self.get_max_target_length(self.default_max_length) + + from openpromptu import TokenizerWrapper + tokenizer_wrapper = TokenizerWrapper(max_seq_length=data_args.max_source_length, tokenizer=tokenizer, truncate_method="balanced", mask_token_func=mask_token_func) + return template, verbalizer, tokenizer_wrapper + + + from openpromptu.data_utils import InputExample + + max_target_length = 32 + + if os.path.basename(model_args.model_name_or_path).startswith("t5"): + mask_token_func = lambda i: tokenizer.additional_special_tokens[i] + def preprocess_function(raw_example, **kwargs): + # max_target_length += 1 + tokenizer = kwargs['tokenizer'] + data_args = kwargs['data_args'] + template = kwargs['template'] + verbalizer = kwargs['verbalizer'] + tokenizer_wrapper = kwargs['tokenizer_wrapper'] + split = kwargs['split'] + # extra_fileds = example['extra_fields'] + + example = InputExample(**raw_example) + + # from collections import namedtuple + # example['tgt_text'] = "" + # example = namedtuple("ObjectName", example.keys())(*example.values()) + try: + example = verbalizer.wrap_one_example(example) + example, other = template.wrap_one_example(example) + input_sentence = tokenizer_wrapper.merge_wrapped_example(example) + model_inputs = tokenizer(input_sentence, max_length=256, + padding="max_length", truncation=True) + except: + from IPython import embed; embed(header="Therer") + + + # if split == "train": + with tokenizer.as_target_tokenizer(): + label = tokenizer(other['tgt_text']).input_ids + # label = [l if l != tokenizer.pad_token_id else -100 for l in label] + + # from IPython import embed; embed(header="Therer") + model_inputs["labels"] = label + # else: + # # from IPython import embed; embed(header="Therer") + # model_inputs["tgt_text"] = other['tgt_text'] + # model_inputs['labels'] = None # model_inputs["extra_fields"] = extra_fileds + # from IPython import embed; embed(header="Therer2") + return model_inputs + + def compute_metrics(eval_preds, tokenizer, dataset_name, eval_metric): + # from IPython import embed; embed(header="In compute metrics") + preds, labels = eval_preds + decoded_preds = tokenizer.batch_decode(preds, skip_special_tokens=True) + decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True) + # post_processor = .get(data_args.dataset_name[0], tokenizer, + # data_args.ignore_pad_token_for_loss) + # decoded_preds, decoded_labels = post_processor.process(preds, labels, data_info) + result = {} + for metric in eval_metric: + result.update(metric(decoded_preds, decoded_labels)) + + average_metric = sum(result.values())/len(result) + result.update({"average_metrics":average_metric}) + return result + + + + elif os.path.basename(model_args.model_name_or_path).startswith("roberta") \ + or os.path.basename(model_args.model_name_or_path).startswith("bert"): + mask_token_func = lambda i: tokenizer.mask_token + def preprocess_function(raw_example, **kwargs): + # max_target_length += 1 + + # from IPython import embed; embed(header="Therer") + tokenizer = kwargs['tokenizer'] + + data_args = kwargs['data_args'] + template = kwargs['template'] + verbalizer = kwargs['verbalizer'] + tokenizer_wrapper = kwargs['tokenizer_wrapper'] + + example = InputExample(**raw_example) + + # from collections import namedtuple + # example['tgt_text'] = "" + # example = namedtuple("ObjectName", example.keys())(*example.values()) + # try: + # example = verbalizer.wrap_one_example(example) + example, other = template.wrap_one_example(example) + input_sentence = tokenizer_wrapper.merge_wrapped_example(example) + model_inputs = tokenizer(input_sentence, max_length=256, + padding="max_length", truncation=True) + + + + # print("max_length", data_args.max_source_length) + # model_inputs = tokenizer(examples['source'], max_length=data_args.max_source_length, + # padding="max_length", truncation=True) + + # mask_position = [(id, input_id.index(tokenizer.mask_token_id)) for id, input_id in enumerate(model_inputs.input_ids)]# [[-100 if i != tokenizer.mask_token_id else tokenizer.convert_tokens_to_ids(target) for i in input_id] for input_id, target in zip(model_inputs.input_ids, examples['target'])] + # model_inputs["mask_position"] = mask_position + # model_inputs["extra_fields"] = examples['extra_fields'] + # from IPython import embed; embed(header="Therer") + return model_inputs + + def compute_metrics(eval_preds, dataset_name): + # from IPython import embed; embed(header="In compute metrics") + + preds, labels = eval_preds.predictions, eval_preds.label_ids + + preds = np.argmax(preds, axis=-1) + + result = {} + average_metrics = [] + for metric in eval_metric: + metric_item = metric(preds, labels) + metric_value = list(metric_item.values()) + result.update(metric_item) + average_metrics.extend(metric_value) + print("average:",average_metrics) + average_metric = sum(average_metrics)/len(average_metrics) + result.update({"average_metrics":average_metric}) + return result + + + + + if training_args.do_train: train_task = AutoTask.get(data_args.task_name, data_args.dataset_config_name, data_args=data_args, - tokenizer=tokenizer, - predict_with_generate=training_args.predict_with_generate, + # tokenizer=tokenizer, + # predict_with_generate=training_args.predict_with_generate, seed=data_args.data_seed) train_dataset = train_task.get(split='train', split_validation_test=training_args.split_validation_test, n_obs=data_args.max_train_samples) + template, verbalizer, tokenizer_wrapper = get_prompts(train_task, tokenizer, training_args.predict_with_generate) + + train_dataset = train_dataset.map( - functools.partial(preprocess_function, - data_args=data_args, - tokenizer=tokenizer), - batched=True, + functools.partial(preprocess_function, + data_args=data_args, + tokenizer=tokenizer, + template=template, + verbalizer=verbalizer, + tokenizer_wrapper=tokenizer_wrapper, + split="train"), + batched=False, num_proc=data_args.preprocessing_num_workers, remove_columns=[x for x in train_dataset.features if x not in ("label",)], # if train_dataset != "superglue-record" else column_names+["answers"], load_from_cache_file=not data_args.overwrite_cache, @@ -298,6 +440,8 @@ def main(): + + eval_splits_names = [] if training_args.do_eval: @@ -306,87 +450,49 @@ def main(): eval_splits_names.append("test") eval_splits = {} for split_name in eval_splits_names: - _tasks = {dataset_name: AutoTask.get(dataset_name, - dataset_config_name, - data_args=data_args, - tokenizer=tokenizer, - predict_with_generate=training_args.predict_with_generate, - seed=data_args.data_seed) - for dataset_name, dataset_config_name\ - in zip(getattr(data_args,f"{split_name}_dataset_name"), getattr(data_args, f"{split_name}_dataset_config_name"))} + eval_task = AutoTask.get(data_args.task_name, + data_args.dataset_config_name, + data_args=data_args, + # tokenizer=tokenizer, + # predict_with_generate=training_args.predict_with_generate, + seed=data_args.data_seed) + # for dataset_name, dataset_config_name\ + # in zip(getattr(data_args,f"{split_name}_dataset_name"), getattr(data_args, f"{split_name}_dataset_config_name"))} - _datasets = {dataset_name: task.get(split=split_name, - split_validation_test=training_args.split_validation_test, - n_obs=data_args.max_train_samples) - for dataset_name, task in _tasks.items() - } + eval_dataset = eval_task.get(split=split_name, + split_validation_test=training_args.split_validation_test, + n_obs=data_args.max_train_samples) - _datasets = {dataset_name: d.map( - functools.partial(preprocess_function, - data_args=data_args, - tokenizer=tokenizer), - batched=True, + + + template, _verbalizer, tokenizer_wrapper = get_prompts(eval_task, tokenizer, training_args.predict_with_generate) + + eval_dataset = eval_dataset.map( + functools.partial(preprocess_function, + data_args=data_args, + tokenizer=tokenizer, + template=template, + verbalizer=_verbalizer, + tokenizer_wrapper=tokenizer_wrapper, + split=split_name), + batched=False, num_proc=data_args.preprocessing_num_workers, - remove_columns=[x for x in d.features if x not in ("label",)], # if train_dataset != "superglue-record" else column_names+["answers"], + remove_columns=[x for x in eval_dataset.features if x not in ("label",)], # if train_dataset != "superglue-record" else column_names+["answers"], load_from_cache_file=not data_args.overwrite_cache, ) - for dataset_name, d in _datasets.items() - } - eval_splits[split_name] = _datasets + + eval_splits[split_name] = eval_dataset if split_name == "test": - eval_metrics = {dataset_name:task.metric for dataset_name, task in _tasks.items()} - verbalizers = {dataset_name:task.verbalizer for dataset_name, task in _tasks.items()} + eval_metric = eval_task.metric + verbalizer = _verbalizer - # Metric, we assume we have only one training task. - # eval_metrics = [task.metric for task in - # for dataset_name, dataset_config_name in zip(data_args.dataset_name, data_args.dataset_config_name)][0] - - # Extracts the extra information needed to evaluate on each dataset. - # These information are only used in the compute_metrics. - # We will assume that the test/eval dataloader does not change the order of - # the data. - # data_info = {"eval": eval_datasets[data_args.eval_dataset_name[0]]['extra_fields'], - # "test": test_datasets[data_args.test_dataset_name[0]]['extra_fields'], - # "train": train_dataset['extra_fields']} - def compute_metrics(eval_preds, dataset_name): - - preds, labels = eval_preds.predictions, eval_preds.label_ids - - preds = np.argmax(preds, axis=-1) - - result = {} - average_metrics = [] - for metric in eval_metrics[dataset_name]: - metric_item = metric(preds, labels) - metric_value = list(metric_item.values()) - result.update(metric_item) - average_metrics.extend(metric_value) - print("average:",average_metrics) - average_metric = sum(average_metrics)/len(average_metrics) - result.update({"average_metrics":average_metric}) - return result - - # from IPython import embed; embed(header="isseq2seq") - # Initialize our Trainer - # if training_args.is_seq2seq == True: - # trainer = Seq2SeqTrainer( - # model=model, - # args=training_args, - # delta_args=delta_args, - # train_dataset=splits['train'] if training_args.do_train else None, - # eval_dataset=list(splits['validation'].values())[0] if training_args.do_eval else None, - # data_info = data_info, - # tokenizer=tokenizer, - # data_collator=data_collator, - # compute_metrics=compute_metrics if training_args.predict_with_generate else None, - # evaluation_metrics = TASK_TO_METRICS[data_args.dataset_name[0]], - # ) - # else: class MLMTrainer(Trainer): - _verbalizers = verbalizers + def __init__(self, verbalizer=None, **kwargs): + super().__init__(**kwargs) + self.verbalizer=verbalizer # def training_step(self, model, inputs): # from IPython import embed; embed(header="in trainstep") @@ -394,7 +500,7 @@ def main(): def compute_loss(self, model, inputs, return_outputs=False): labels = inputs.pop('labels') - extra_fields = inputs.pop("extra_fields") + # extra_fields = inputs.pop("extra_fields") outputs = model(**inputs) logits = outputs.get("logits") input_ids = inputs['input_ids'] @@ -402,20 +508,8 @@ def main(): # from IPython import embed; embed(header="382") - verbalizer = self._verbalizers[extra_fields[0]['dataset_name']].cuda() + verbalizer = self.verbalizer.cuda() logits_at_mask = logits[torch.where(input_ids == verbalizer.tokenizer.mask_token_id)] - - # colidx = torch.where(input_ids == verbalizer.tokenizer.mask_token_id)[0].cpu() - # print(colidx) - # missing = set([i for i in range(input_ids.size(0))]) - set(colidx.numpy()) - # print(missing) - # if len(missing) > 0: - # print("missing") - # missing = list(missing)[0] - # input_ids_missing = input_ids[missing] - # print(input_ids_missing) - # missing_tokens = verbalizer.tokenizer.convert_ids_to_tokens(input_ids_missing) - # print(missing_tokens) label_logits = verbalizer.process_logits(logits_at_mask) loss_fct = torch.nn.CrossEntropyLoss() # from IPython import embed; embed(header="In compute loss") @@ -423,21 +517,136 @@ def main(): outputs.logits = label_logits return (loss, outputs) if return_outputs else loss + + class MySeq2SeqTrainer(Seq2SeqTrainer): + def compute_loss(self, model, inputs, return_outputs=False): + # from IPython import embed; embed(header="agag") + + intlabel = inputs.pop('label') + # extra_fields = inputs.pop("extra_fields") + outputs = model(**inputs) + # logits = outputs.get("logits") + # input_ids = inputs['input_ids'] + + + + # # from IPython import embed; embed(header="382") + # verbalizer = self._verbalizers.cuda() + # logits_at_mask = logits[torch.where(input_ids == verbalizer.tokenizer.mask_token_id)] + # label_logits = verbalizer.process_logits(logits_at_mask) + # loss_fct = torch.nn.CrossEntropyLoss() + # # from IPython import embed; embed(header="In compute loss") + # loss = loss_fct(label_logits, labels) + # outputs.logits = label_logits + if return_outputs: + return (outputs.loss, outputs) + else: + return outputs.loss + + + # def evaluate( + # self, + # eval_dataset: Optional[Dict[str, Dataset]] = None, + # ignore_keys: Optional[List[str]] = None, + # metric_key_prefix: str = "eval", + # max_length: Optional[int] = None, + # num_beams: Optional[int] = None, + # ) -> Dict[str, float]: + # # TODO: this also needs to be set per dataset + # self._max_length = max_length + # self._num_beams = num_beams + # return super().evaluate(eval_dataset, ignore_keys=ignore_keys, metric_key_prefix=metric_key_prefix) + + + def prediction_step( + self, + model, #nn.Module, + inputs, #Dict[str, Union[torch.Tensor, Any]], + prediction_loss_only, #: bool, + ignore_keys, #: Optional[List[str]] = None, + ): #-> Tuple[Optional[float], Optional[torch.Tensor], Optional[torch.Tensor]]: + """ + Perform an evaluation step on :obj:`model` using obj:`inputs`. + + Subclass and override to inject custom behavior. + + Args: + model (:obj:`nn.Module`): + The model to evaluate. + inputs (:obj:`Dict[str, Union[torch.Tensor, Any]]`): + The inputs and targets of the model. + + The dictionary will be unpacked before being fed to the model. Most models expect the targets under the + argument :obj:`labels`. Check your model's documentation for all accepted arguments. + prediction_loss_only (:obj:`bool`): + Whether or not to return the loss only. + + Return: + Tuple[Optional[float], Optional[torch.Tensor], Optional[torch.Tensor]]: A tuple with the loss, logits and + labels (each being optional). + """ + if not self.args.predict_with_generate or prediction_loss_only: + return super().prediction_step( + model, inputs, prediction_loss_only=prediction_loss_only, ignore_keys=ignore_keys + ) + + + has_labels = "labels" in inputs + inputs = self._prepare_inputs(inputs) + intlabel = inputs.pop('label') + gen_kwargs = { + "max_length": 10, # self._max_length if s is not None else self.model.config.max_length, + "num_beams": 1 #self._num_beams if self._num_beams is not None else self.model.config.num_beams, + } + generated_tokens = self.model.generate( + inputs["input_ids"], + attention_mask=inputs["attention_mask"], + **gen_kwargs, + ) + # in case the batch is shorter than max length, the output should be padded + if generated_tokens.shape[-1] < gen_kwargs["max_length"]: + generated_tokens = self._pad_tensors_to_max_len(generated_tokens, gen_kwargs["max_length"]) + + with torch.no_grad(): + + outputs = model(**inputs) + if has_labels: + if self.label_smoother is not None: + loss = self.label_smoother(outputs, inputs["labels"]).mean().detach() + else: + loss = (outputs["loss"] if isinstance(outputs, dict) else outputs[0]).mean().detach() + else: + loss = None + + if self.args.prediction_loss_only: + return (loss, None, None) + + labels = inputs["labels"] + if labels.shape[-1] < gen_kwargs["max_length"]: + labels = self._pad_tensors_to_max_len(labels, gen_kwargs["max_length"]) + + # from IPython import embed; embed(header="In seqseqtrainer") + return (loss, generated_tokens, labels) + + + + + # def prediction_step(self, model, inputs, prediction_loss_only, ignore_keys): # aa = super().prediction_step(model, inputs, prediction_loss_only, ignore_keys) # # from IPython import embed; embed() # return aa - from transformers.data.data_collator import torch_default_data_collator , DataCollatorMixin - class DataCollatorWithExtraFields(DataCollatorMixin): - return_tensors: str = "pt" - def torch_call(self, features): - print(len(features)) - extra_fields = [f.pop('extra_fields') for f in features] - batch = torch_default_data_collator(features) - batch['extra_fields'] =extra_fields - print(batch['input_ids'].size()) - print(batch['labels'].size()) - return batch + # from transformers.data.data_collator import torch_default_data_collator , DataCollatorMixin + # class DataCollatorWithExtraFields(DataCollatorMixin): + # return_tensors: str = "pt" + # def torch_call(self, features): + # # print(len(features)) + # # extra_fields = [f.pop('extra_fields') for f in features] + # batch = torch_default_data_collator(features) + # batch['extra_fields'] =extra_fields + # # print(batch['input_ids'].size()) + # # print(batch['labels'].size()) + # return batch # from transformers.data.data_collator import DefaultDataCollator @@ -455,15 +664,29 @@ def main(): training_args.remove_unused_columns = False - trainer = MLMTrainer( - model=model, - args=training_args, - train_dataset=train_dataset if training_args.do_train else None, - eval_dataset=eval_splits['eval'][data_args.task_name] if training_args.do_eval else None, - compute_metrics=functools.partial(compute_metrics, dataset_name=data_args.task_name), - # tokenizer=tokenizer, - data_collator=DataCollatorWithExtraFields(), - ) + if os.path.basename(model_args.model_name_or_path).startswith("roberta") or \ + os.path.basename(model_args.model_name_or_path).startswith("bert"): + trainer = MLMTrainer( + model=model, + args=training_args, + train_dataset=train_dataset if training_args.do_train else None, + eval_dataset=eval_splits['eval'] if training_args.do_eval else None, + compute_metrics=functools.partial(compute_metrics, dataset_name=data_args.task_name), + tokenizer=tokenizer, + # data_collator=DataCollatorWithExtraFields(), + verbalizer=verbalizer, + ) + elif os.path.basename(model_args.model_name_or_path).startswith("t5"): + trainer = MySeq2SeqTrainer( + model=model, + args=training_args, + train_dataset=train_dataset if training_args.do_train else None, + eval_dataset=eval_splits['eval'] if training_args.do_eval else None, + compute_metrics=functools.partial(compute_metrics, tokenizer=tokenizer, dataset_name=data_args.task_name, eval_metric=eval_metric), + tokenizer=tokenizer, + data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer), + ) + # Saves training config. @@ -522,24 +745,23 @@ def main(): if training_args.do_eval: logger.info("*** Evaluate ***") - for dataset_name, eval_dataset in eval_splits['eval'].items(): - metrics = trainer.evaluate(eval_dataset=eval_dataset, - ) - trainer.log_metrics(f"{dataset_name}_eval", metrics) - trainer.save_metrics(f"{dataset_name}_eval", metrics) - all_results['evaluate'][dataset_name] = metrics + + metrics = trainer.evaluate(eval_dataset=eval_splits['eval'], + ) + trainer.log_metrics(f"{data_args.task_name}_eval", metrics) + trainer.save_metrics(f"{data_args.task_name}_eval", metrics) + all_results['evaluate'][data_args.task_name] = metrics # Test all_results['test'] = {} if training_args.do_test: logger.info("*** Test ***") - for dataset_name, test_dataset in eval_splits['test'].items(): - metrics = trainer.evaluate(eval_dataset=test_dataset, - metric_key_prefix="test" - ) - trainer.log_metrics(f"{dataset_name}_test", metrics) - trainer.save_metrics(f"{dataset_name}_test", metrics) - all_results['test'][dataset_name] = metrics + metrics = trainer.evaluate(eval_dataset=eval_splits['test'], + metric_key_prefix="test" + ) + trainer.log_metrics(f"{data_args.task_name}_test", metrics) + trainer.save_metrics(f"{data_args.task_name}_test", metrics) + all_results['test'][data_args.task_name] = metrics # repo_name = create_hub_repo_name(root="DeltaHub", # dataset=data_args.task_name, diff --git a/examples/examples_prompt/run_mlm.sh b/examples/examples_prompt/run_mlm.sh index 8f22f53..0836f20 100644 --- a/examples/examples_prompt/run_mlm.sh +++ b/examples/examples_prompt/run_mlm.sh @@ -1,7 +1,7 @@ -cd configs/ -python config_gen.py --job $3 + +python configs/config_gen.py --job $3 echo "Regenerate config" -cd ../ + files=(cola mnli mrpc qnli qqp rte sst2 stsb superglue-boolq superglue-cb superglue-copa superglue-multirc superglue-record superglue-wic superglue-wsc.fixed) for ((i=$1; i<=$2; i++)) do diff --git a/opendelta/__init__.py b/opendelta/__init__.py index 90aa410..38b4ffd 100644 --- a/opendelta/__init__.py +++ b/opendelta/__init__.py @@ -1,5 +1,5 @@ -__version__ = "0.0.1" +__version__ = "0.0.4" class GlobalSetting: def __init__(self): diff --git a/opendelta/basemodel.py b/opendelta/basemodel.py index ae6d504..8abfc8a 100644 --- a/opendelta/basemodel.py +++ b/opendelta/basemodel.py @@ -728,6 +728,9 @@ class DeltaBase(nn.Module, SaveLoadMixin): elif _delta_info['method'] == "insert_sequential": self.insert_sequential_module(module=submodule, _delta_info=_delta_info) + elif _delta_info['method'] == "insert_parallel": + self.insert_parallel_module(module=submodule, + _delta_info=_delta_info) else: raise NotImplementedError @@ -765,7 +768,13 @@ class DeltaBase(nn.Module, SaveLoadMixin): submodule.forward = submodule.forward.__wrapped__ delattr(submodule, _delta_info["delta_name"]) else: - raise AttributeError("submodule {}'s forward has no attribute __wrapped__. It'ss not a wrapped function.".format(name)) + raise AttributeError("submodule {}'s forward has no attribute __wrapped__. It's not a wrapped function.".format(name)) + elif _delta_info['method'] == "insert_parallel": + if hasattr(submodule.forward, "__wrapped__"): + submodule.forward = submodule.forward.__wrapped__ + delattr(submodule, _delta_info["delta_name"]) + else: + raise AttributeError("submodule {}'s forward has no attribute __wrapped__. It's not a wrapped function.".format(name)) else: raise NotImplementedError @@ -776,4 +785,3 @@ class DeltaBase(nn.Module, SaveLoadMixin): except AttributeError: pass - diff --git a/opendelta/delta_models/lora.py b/opendelta/delta_models/lora.py index 16fef6e..60bcee2 100644 --- a/opendelta/delta_models/lora.py +++ b/opendelta/delta_models/lora.py @@ -28,7 +28,6 @@ class LowRankLinear(nn.Module): self.r = r self.lora_alpha = lora_alpha self.lora_dropout = lora_dropout - self.lin = nn.Linear(in_features, out_features) # if lora_dropout > 0.: self.lora_dropout = nn.Dropout(p=lora_dropout) else: @@ -37,7 +36,6 @@ class LowRankLinear(nn.Module): self.lora_A = nn.Parameter(weight.new_zeros((r, in_features))) self.lora_B = nn.Parameter(weight.new_zeros((out_features, r))) self.scaling = self.lora_alpha / self.r - self.lin.reset_parameters() # nn.init.kaiming_uniform_(self.lora_A, a=math.sqrt(5)) nn.init.zeros_(self.lora_B) diff --git a/opendelta/delta_models/soft_prompt.py b/opendelta/delta_models/soft_prompt.py index a43c851..b60f7fd 100644 --- a/opendelta/delta_models/soft_prompt.py +++ b/opendelta/delta_models/soft_prompt.py @@ -1,3 +1,4 @@ +from examples_prompt.metrics.metrics import exact_match from opendelta.utils.signature import get_arg_names, get_arg_names_inside_func from opendelta.utils.name_based_addressing import * from opendelta.utils.cuda import get_device @@ -47,6 +48,7 @@ class SoftPromptLayer(nn.Module): soft_token_num: int = 100, raw_embedding: Optional[torch.Tensor] = None, init_range: Optional[float] = 0.5, + other_expand_ids: Optional[Dict] = {"attention_mask":1, "token_type_ids":0}, token_init = False, pad_id = 0, device: Optional[str]=None, @@ -59,10 +61,13 @@ class SoftPromptLayer(nn.Module): self.pad_id = pad_id self.token_init = token_init self.device = device + self.other_expand_ids = other_expand_ids assert self.num_tokens>0 self.instantiate(raw_embedding(torch.tensor([0])).shape[-1]) + self.all_pseudo_tokens = {} + def pre_forward(self, *args, **kwargs): # if attention_mask is passed as PLM's input, modify it here if 'encoder_outputs' in kwargs and kwargs['encoder_outputs'] is not None: @@ -100,8 +105,19 @@ class SoftPromptLayer(nn.Module): inputs_embeds = torch.cat([soft_embeds, inputs_embeds], 1) kwargs['inputs_embeds'] = inputs_embeds - am = kwargs['attention_mask'] - am.data = torch.cat([torch.ones((*am.shape[:-1], inputs_embeds.shape[-2]-am.shape[-1]), dtype = am.dtype,device=am.device), am], dim=-1) + for expand_key in self.other_expand_ids: + if expand_key in kwargs: + real_tokens = kwargs[expand_key] + if expand_key in self.all_pseudo_tokens: + pseudo_tokens = self.all_pseudo_tokens[expand_key].to(real_tokens.device) + else: + pseudo_tokens_value = self.other_expand_ids[expand_key] + pseudo_tokens = torch.ones( + (*real_tokens.shape[:-1], inputs_embeds.shape[-2]-real_tokens.shape[-1]), + dtype = real_tokens.dtype, + device=real_tokens.device) * pseudo_tokens_value + self.all_pseudo_tokens[expand_key] = pseudo_tokens + real_tokens.data = torch.cat([pseudo_tokens, real_tokens], dim=-1) return args, kwargs @@ -136,6 +152,10 @@ class SoftPromptModel(DeltaBase): soft_token_num (:obj:`int`, *optional*): num of new tokens to add in the front of the input. init_range (:obj:`float`, *optional*): If initialize new tokens randomly, the random range of uniform distribution. token_init (:obj:`bool`, *optional*, default to :obj:`True`): Whether to initialize the new tokens with tokens of the plm + other_expand_ids (:obj:`dict`, *optional*, default to `{"attention_mask":1, "token_type_ids":0}`) The name of + other tokens and its default value that expand along with the input sequence. For example, when + you prepend 100 tokens to the input_ids, the attention_mask should be extended, and the token_type_ids should + be extended as well. modified_modules (:obj:`List[str]`): For prefix tuning, the it must refer to an attention layer (Currently, only the implemented ones) unfrozen_modules (:obj:`List[str]`, *optional*, default to :obj:`None`): The modules that should be unfrozen @@ -151,6 +171,7 @@ class SoftPromptModel(DeltaBase): soft_token_num=100, init_range = 0.5, token_init=True, + other_expand_ids={"attention_mask":1, "token_type_ids":0}, modified_modules: Optional[List[str]] = None, exclude_modules: Optional[List[str]] = None, unfrozen_modules: Optional[List[str]] = None, @@ -202,6 +223,7 @@ class SoftPromptModel(DeltaBase): soft_prompt_layer = SoftPromptLayer( soft_token_num = self.soft_token_num, raw_embedding = self.raw_embedding, + other_expand_ids = self.other_expand_ids, token_init = self.token_init, init_range = self.init_range, device = module_device, diff --git a/setup.py b/setup.py index 0fd267c..3d04729 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ print(requires) with open('README.md', 'r') as f: setuptools.setup( name = 'opendelta', - version = '0.0.3', + version = '0.0.4', description = "An open source framework for delta learning (parameter efficient learning).", long_description=open("README.md", "r", encoding="utf-8").read(), long_description_content_type="text/markdown",