赞
踩
这就是最后的部分,关于语言建模、多选、问答系统、文本分类、命名实体识别等任务的模型微调,这一块我也是直接看人家笔记本总结的。按照这三个部分,这个库基本就弄熟了
主要有这两种方式进行建模
- 数据加载
- from datasets import load_dataset
- datasets = load_dataset('wikitext', 'wikitext-2-raw-v1')
- #可以替换成如下的,取消注释即可,只需取消注释以下单元格,然后将路径替换为本地地址即可:
- # datasets = load_dataset("text", data_files={"train": path_to_train.txt, "validation": path_to_validation.txt}
- datasets["train"][10]
- from datasets import ClassLabel
- import random
- import pandas as pd
- from IPython.display import display, HTML
-
- def show_random_elements(dataset, num_examples=10):
- assert num_examples <= len(dataset), "Can't pick more elements than there are in the dataset."
- picks = []
- for _ in range(num_examples):
- pick = random.randint(0, len(dataset)-1)
- while pick in picks:
- pick = random.randint(0, len(dataset)-1)
- picks.append(pick)
-
- df = pd.DataFrame(dataset[picks])
- for column, typ in dataset.features.items():
- if isinstance(typ, ClassLabel):
- df[column] = df[column].transform(lambda i: typ.names[i])
- display(HTML(df.to_html()))
- show_random_elements(datasets["train"])
-
因果建模
- model_path="H:\\code\\Model\\distilgpt2\\"
- from transformers import AutoTokenizer
-
- tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=True)
- def tokenize_function(examples):
- return tokenizer(examples["text"])
- tokenized_datasets = datasets.map(tokenize_function, batched=True, num_proc=4, remove_columns=["text"])
- tokenized_datasets["train"][1]
- # block_size = tokenizer.model_max_length
- block_size = 128
- #数据预处理
- def group_texts(examples):
- # Concatenate all texts.
- concatenated_examples = {k: sum(examples[k], []) for k in examples.keys()}
- total_length = len(concatenated_examples[list(examples.keys())[0]])
- # We drop the small remainder, we could add padding if the model supported it instead of this drop, you can
- # customize this part to your needs.
- total_length = (total_length // block_size) * block_size
- # Split by chunks of max_len.
- result = {
- k: [t[i : i + block_size] for i in range(0, total_length, block_size)]
- for k, t in concatenated_examples.items()
- }
- result["labels"] = result["input_ids"].copy()
- return result
- lm_datasets = tokenized_datasets.map(
- group_texts,
- batched=True,
- batch_size=1000,
- num_proc=4,
- )
- tokenizer.decode(lm_datasets["train"][1]["input_ids"])
- from transformers import AutoModelForCausalLM
- model = AutoModelForCausalLM.from_pretrained(model_path)
- from transformers import Trainer, TrainingArguments
- training_args = TrainingArguments(
- "test-clm",
- evaluation_strategy = "epoch",
- learning_rate=2e-5,
- weight_decay=0.01,
- )
- trainer = Trainer(
- model=model,
- args=training_args,
- train_dataset=lm_datasets["train"],
- eval_dataset=lm_datasets["validation"],
- )
- trainer.train()
- import math
- eval_results = trainer.evaluate()
- print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}")
- model_path="H:\\code\\Model\\distilroberta-base\\"
- tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=True)
- tokenized_datasets = datasets.map(tokenize_function, batched=True, num_proc=4, remove_columns=["text"])
- lm_datasets = tokenized_datasets.map(
- group_texts,
- batched=True,
- batch_size=1000,
- num_proc=4,
- )
- from transformers import AutoModelForMaskedLM
- model = AutoModelForMaskedLM.from_pretrained(model_path)
- from transformers import DataCollatorForLanguageModeling
- data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm_probability=0.15)
- trainer = Trainer(
- model=model,
- args=training_args,
- train_dataset=lm_datasets["train"],
- eval_dataset=lm_datasets["validation"],
- data_collator=data_collator,
- )
- trainer.train()
- eval_results = trainer.evaluate()
- print(f"Perplexity: {math.exp(eval_results['eval_loss']):.2f}")
- model_checkpoint ="H:\\code\\Model\\bert-base-uncased\\"
- batch_size = 16
- from datasets import load_dataset, load_metric
- datasets = load_dataset("swag", "regular")
- datasets
- datasets["train"][0]
- from datasets import ClassLabel
- import random
- import pandas as pd
- from IPython.display import display, HTML
-
- def show_random_elements(dataset, num_examples=10):
- assert num_examples <= len(dataset), "Can't pick more elements than there are in the dataset."
- picks = []
- for _ in range(num_examples):
- pick = random.randint(0, len(dataset)-1)
- while pick in picks:
- pick = random.randint(0, len(dataset)-1)
- picks.append(pick)
-
- df = pd.DataFrame(dataset[picks])
- for column, typ in dataset.features.items():
- if isinstance(typ, ClassLabel):
- df[column] = df[column].transform(lambda i: typ.names[i])
- display(HTML(df.to_html()))
- show_random_elements(datasets["train"])
- def show_one(example):
- print(f"Context: {example['sent1']}")
- print(f" A - {example['sent2']} {example['ending0']}")
- print(f" B - {example['sent2']} {example['ending1']}")
- print(f" C - {example['sent2']} {example['ending2']}")
- print(f" D - {example['sent2']} {example['ending3']}")
- print(f"\nGround truth: option {['A', 'B', 'C', 'D'][example['label']]}")
- #预处理数据
- from transformers import AutoTokenizer
-
- tokenizer = AutoTokenizer.from_pretrained(model_checkpoint, use_fast=True)
- ending_names = ["ending0", "ending1", "ending2", "ending3"]
-
- def preprocess_function(examples):
- # Repeat each first sentence four times to go with the four possibilities of second sentences.
- first_sentences = [[context] * 4 for context in examples["sent1"]]
- # Grab all second sentences possible for each context.
- question_headers = examples["sent2"]
- second_sentences = [[f"{header} {examples[end][i]}" for end in ending_names] for i, header in enumerate(question_headers)]
-
- # Flatten everything
- first_sentences = sum(first_sentences, [])
- second_sentences = sum(second_sentences, [])
-
- # Tokenize
- tokenized_examples = tokenizer(first_sentences, second_sentences, truncation=True)
- # Un-flatten
- return {k: [v[i:i+4] for i in range(0, len(v), 4)] for k, v in tokenized_examples.items()}
- examples = datasets["train"][:5]
- features = preprocess_function(examples)
- print(len(features["input_ids"]), len(features["input_ids"][0]), [len(x) for x in features["input_ids"][0]])
- idx = 3
- [tokenizer.decode(features["input_ids"][idx][i]) for i in range(4)]
- show_one(datasets["train"][3])
- encoded_datasets = datasets.map(preprocess_function, batched=True)
- #微调模型
- from transformers import AutoModelForMultipleChoice, TrainingArguments, Trainer
-
- model = AutoModelForMultipleChoice.from_pretrained(model_checkpoint)
- args = TrainingArguments(
- "test-glue",
- evaluation_strategy = "epoch",
- learning_rate=5e-5,
- per_device_train_batch_size=batch_size,
- per_device_eval_batch_size=batch_size,
- num_train_epochs=3,
- weight_decay=0.01,
- )
- from dataclasses import dataclass
- from transformers.tokenization_utils_base import PreTrainedTokenizerBase, PaddingStrategy
- from typing import Optional, Union
- import torch
-
- @dataclass
- class DataCollatorForMultipleChoice:
- """
- Data collator that will dynamically pad the inputs for multiple choice received.
- """
-
- tokenizer: PreTrainedTokenizerBase
- padding: Union[bool, str, PaddingStrategy] = True
- max_length: Optional[int] = None
- pad_to_multiple_of: Optional[int] = None
-
- def __call__(self, features):
- label_name = "label" if "label" in features[0].keys() else "labels"
- labels = [feature.pop(label_name) for feature in features]
- batch_size = len(features)
- num_choices = len(features[0]["input_ids"])
- flattened_features = [[{k: v[i] for k, v in feature.items()} for i in range(num_choices)] for feature in features]
- flattened_features = sum(flattened_features, [])
-
- batch = self.tokenizer.pad(
- flattened_features,
- padding=self.padding,
- max_length=self.max_length,
- pad_to_multiple_of=self.pad_to_multiple_of,
- return_tensors="pt",
- )
-
- # Un-flatten
- batch = {k: v.view(batch_size, num_choices, -1) for k, v in batch.items()}
- # Add back labels
- batch["labels"] = torch.tensor(labels, dtype=torch.int64)
- return batch
- accepted_keys = ["input_ids", "attention_mask", "label"]
- features = [{k: v for k, v in encoded_datasets["train"][i].items() if k in accepted_keys} for i in range(10)]
- batch = DataCollatorForMultipleChoice(tokenizer)(features)
- import numpy as np
-
- def compute_metrics(eval_predictions):
- predictions, label_ids = eval_predictions
- preds = np.argmax(predictions, axis=1)
- return {"accuracy": (preds == label_ids).astype(np.float32).mean().item()}
- trainer = Trainer(
- model,
- args,
- train_dataset=encoded_datasets["train"],
- eval_dataset=encoded_datasets["validation"],
- tokenizer=tokenizer,
- data_collator=DataCollatorForMultipleChoice(tokenizer),
- compute_metrics=compute_metrics,
- )
- trainer.train()
-
问答系统
- # This flag is the difference between SQUAD v1 or 2 (if you're using another dataset, it indicates if impossible
- # answers are allowed or not).
- squad_v2 = False
- model_checkpoint="H:\\code\\Model\\distilbert-base-cased\\"
- batch_size = 16
- from datasets import load_dataset, load_metric
- datasets = load_dataset("squad_v2" if squad_v2 else "squad")
- datasets
- from datasets import ClassLabel, Sequence
- import random
- import pandas as pd
- from IPython.display import display, HTML
-
- def show_random_elements(dataset, num_examples=10):
- assert num_examples <= len(dataset), "Can't pick more elements than there are in the dataset."
- picks = []
- for _ in range(num_examples):
- pick = random.randint(0, len(dataset)-1)
- while pick in picks:
- pick = random.randint(0, len(dataset)-1)
- picks.append(pick)
-
- df = pd.DataFrame(dataset[picks])
- for column, typ in dataset.features.items():
- if isinstance(typ, ClassLabel):
- df[column] = df[column].transform(lambda i: typ.names[i])
- elif isinstance(typ, Sequence) and isinstance(typ.feature, ClassLabel):
- df[column] = df[column].transform(lambda x: [typ.feature.names[i] for i in x])
- display(HTML(df.to_html()))
- show_random_elements(datasets["train"])
- #预处理训练数据
- from transformers import AutoTokenizer
-
- tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
- import transformers
- assert isinstance(tokenizer, transformers.PreTrainedTokenizerFast)
- tokenizer("What is your name?", "My name is Sylvain.")
- max_length = 384 # The maximum length of a feature (question and context)
- doc_stride = 128 # The authorized overlap between two part of the context when splitting it is needed.
- for i, example in enumerate(datasets["train"]):
- if len(tokenizer(example["question"], example["context"])["input_ids"]) > 384:
- break
- example = datasets["train"][i]
- len(tokenizer(example["question"], example["context"])["input_ids"])
- len(tokenizer(example["question"], example["context"], max_length=max_length, truncation="only_second")["input_ids"])
- tokenized_example = tokenizer(
- example["question"],
- example["context"],
- max_length=max_length,
- truncation="only_second",
- return_overflowing_tokens=True,
- return_offsets_mapping=True,
- stride=doc_stride
- )
- print(tokenized_example["offset_mapping"][0][:100])
- first_token_id = tokenized_example["input_ids"][0][1]
- offsets = tokenized_example["offset_mapping"][0][1]
- print(tokenizer.convert_ids_to_tokens([first_token_id])[0], example["question"][offsets[0]:offsets[1]])
- sequence_ids = tokenized_example.sequence_ids()
- print(sequence_ids)
- answers = example["answers"]
- start_char = answers["answer_start"][0]
- end_char = start_char + len(answers["text"][0])
-
- # Start token index of the current span in the text.
- token_start_index = 0
- while sequence_ids[token_start_index] != 1:
- token_start_index += 1
-
- # End token index of the current span in the text.
- token_end_index = len(tokenized_example["input_ids"][0]) - 1
- while sequence_ids[token_end_index] != 1:
- token_end_index -= 1
-
- # Detect if the answer is out of the span (in which case this feature is labeled with the CLS index).
- offsets = tokenized_example["offset_mapping"][0]
- if (offsets[token_start_index][0] <= start_char and offsets[token_end_index][1] >= end_char):
- # Move the token_start_index and token_end_index to the two ends of the answer.
- # Note: we could go after the last offset if the answer is the last word (edge case).
- while token_start_index < len(offsets) and offsets[token_start_index][0] <= start_char:
- token_start_index += 1
- start_position = token_start_index - 1
- while offsets[token_end_index][1] >= end_char:
- token_end_index -= 1
- end_position = token_end_index + 1
- print(start_position, end_position)
- else:
- print("The answer is not in this feature.")
- print(tokenizer.decode(tokenized_example["input_ids"][0][start_position: end_position+1]))
- print(answers["text"][0])
- pad_on_right = tokenizer.padding_side == "right"
- def prepare_train_features(examples):
- # Tokenize our examples with truncation and padding, but keep the overflows using a stride. This results
- # in one example possible giving several features when a context is long, each of those features having a
- # context that overlaps a bit the context of the previous feature.
- tokenized_examples = tokenizer(
- examples["question" if pad_on_right else "context"],
- examples["context" if pad_on_right else "question"],
- truncation="only_second" if pad_on_right else "only_first",
- max_length=max_length,
- stride=doc_stride,
- return_overflowing_tokens=True,
- return_offsets_mapping=True,
- padding="max_length",
- )
-
- # Since one example might give us several features if it has a long context, we need a map from a feature to
- # its corresponding example. This key gives us just that.
- sample_mapping = tokenized_examples.pop("overflow_to_sample_mapping")
- # The offset mappings will give us a map from token to character position in the original context. This will
- # help us compute the start_positions and end_positions.
- offset_mapping = tokenized_examples.pop("offset_mapping")
-
- # Let's label those examples!
- tokenized_examples["start_positions"] = []
- tokenized_examples["end_positions"] = []
-
- for i, offsets in enumerate(offset_mapping):
- # We will label impossible answers with the index of the CLS token.
- input_ids = tokenized_examples["input_ids"][i]
- cls_index = input_ids.index(tokenizer.cls_token_id)
-
- # Grab the sequence corresponding to that example (to know what is the context and what is the question).
- sequence_ids = tokenized_examples.sequence_ids(i)
-
- # One example can give several spans, this is the index of the example containing this span of text.
- sample_index = sample_mapping[i]
- answers = examples["answers"][sample_index]
- # If no answers are given, set the cls_index as answer.
- if len(answers["answer_start"]) == 0:
- tokenized_examples["start_positions"].append(cls_index)
- tokenized_examples["end_positions"].append(cls_index)
- else:
- # Start/end character index of the answer in the text.
- start_char = answers["answer_start"][0]
- end_char = start_char + len(answers["text"][0])
-
- # Start token index of the current span in the text.
- token_start_index = 0
- while sequence_ids[token_start_index] != (1 if pad_on_right else 0):
- token_start_index += 1
-
- # End token index of the current span in the text.
- token_end_index = len(input_ids) - 1
- while sequence_ids[token_end_index] != (1 if pad_on_right else 0):
- token_end_index -= 1
-
- # Detect if the answer is out of the span (in which case this feature is labeled with the CLS index).
- if not (offsets[token_start_index][0] <= start_char and offsets[token_end_index][1] >= end_char):
- tokenized_examples["start_positions"].append(cls_index)
- tokenized_examples["end_positions"].append(cls_index)
- else:
- # Otherwise move the token_start_index and token_end_index to the two ends of the answer.
- # Note: we could go after the last offset if the answer is the last word (edge case).
- while token_start_index < len(offsets) and offsets[token_start_index][0] <= start_char:
- token_start_index += 1
- tokenized_examples["start_positions"].append(token_start_index - 1)
- while offsets[token_end_index][1] >= end_char:
- token_end_index -= 1
- tokenized_examples["end_positions"].append(token_end_index + 1)
-
- return tokenized_examples
- features = prepare_train_features(datasets['train'][:5])
- tokenized_datasets = datasets.map(prepare_train_features, batched=True, remove_columns=datasets["train"].column_names)
- #微调模型
- from transformers import AutoModelForQuestionAnswering, TrainingArguments, Trainer
-
- model = AutoModelForQuestionAnswering.from_pretrained(model_checkpoint)
- args = TrainingArguments(
- f"test-squad",
- evaluation_strategy = "epoch",
- learning_rate=2e-5,
- per_device_train_batch_size=batch_size,
- per_device_eval_batch_size=batch_size,
- num_train_epochs=3,
- weight_decay=0.01,
- )
- from transformers import default_data_collator
-
- data_collator = default_data_collator
- trainer = Trainer(
- model,
- args,
- train_dataset=tokenized_datasets["train"],
- eval_dataset=tokenized_datasets["validation"],
- data_collator=data_collator,
- tokenizer=tokenizer,
- )
- trainer.train()
- trainer.save_model("test-squad-trained")
- #评估
- import torch
-
- for batch in trainer.get_eval_dataloader():
- break
- batch = {k: v.to(trainer.args.device) for k, v in batch.items()}
- with torch.no_grad():
- output = trainer.model(**batch)
- output.keys()
- output.start_logits.shape, output.end_logits.shape
- output.start_logits.argmax(dim=-1), output.end_logits.argmax(dim=-1)
- n_best_size = 20
- import numpy as np
-
- start_logits = output.start_logits[0].cpu().numpy()
- end_logits = output.end_logits[0].cpu().numpy()
- # Gather the indices the best start/end logits:
- start_indexes = np.argsort(start_logits)[-1 : -n_best_size - 1 : -1].tolist()
- end_indexes = np.argsort(end_logits)[-1 : -n_best_size - 1 : -1].tolist()
- valid_answers = []
- for start_index in start_indexes:
- for end_index in end_indexes:
- if start_index <= end_index: # We need to refine that test to check the answer is inside the context
- valid_answers.append(
- {
- "score": start_logits[start_index] + end_logits[end_index],
- "text": "" # We need to find a way to get back the original substring corresponding to the answer in the context
- }
- )
- def prepare_validation_features(examples):
- # Tokenize our examples with truncation and maybe padding, but keep the overflows using a stride. This results
- # in one example possible giving several features when a context is long, each of those features having a
- # context that overlaps a bit the context of the previous feature.
- tokenized_examples = tokenizer(
- examples["question" if pad_on_right else "context"],
- examples["context" if pad_on_right else "question"],
- truncation="only_second" if pad_on_right else "only_first",
- max_length=max_length,
- stride=doc_stride,
- return_overflowing_tokens=True,
- return_offsets_mapping=True,
- padding="max_length",
- )
-
- # Since one example might give us several features if it has a long context, we need a map from a feature to
- # its corresponding example. This key gives us just that.
- sample_mapping = tokenized_examples.pop("overflow_to_sample_mapping")
-
- # We keep the example_id that gave us this feature and we will store the offset mappings.
- tokenized_examples["example_id"] = []
-
- for i in range(len(tokenized_examples["input_ids"])):
- # Grab the sequence corresponding to that example (to know what is the context and what is the question).
- sequence_ids = tokenized_examples.sequence_ids(i)
- context_index = 1 if pad_on_right else 0
-
- # One example can give several spans, this is the index of the example containing this span of text.
- sample_index = sample_mapping[i]
- tokenized_examples["example_id"].append(examples["id"][sample_index])
-
- # Set to None the offset_mapping that are not part of the context so it's easy to determine if a token
- # position is part of the context or not.
- tokenized_examples["offset_mapping"][i] = [
- (o if sequence_ids[k] == context_index else None)
- for k, o in enumerate(tokenized_examples["offset_mapping"][i])
- ]
-
- return tokenized_examples
- validation_features = datasets["validation"].map(
- prepare_validation_features,
- batched=True,
- remove_columns=datasets["validation"].column_names
- )
- raw_predictions = trainer.predict(validation_features)
- validation_features.set_format(type=validation_features.format["type"], columns=list(validation_features.features.keys()))
- max_answer_length = 30
- start_logits = output.start_logits[0].cpu().numpy()
- end_logits = output.end_logits[0].cpu().numpy()
- offset_mapping = validation_features[0]["offset_mapping"]
- # The first feature comes from the first example. For the more general case, we will need to be match the example_id to
- # an example index
- context = datasets["validation"][0]["context"]
-
- # Gather the indices the best start/end logits:
- start_indexes = np.argsort(start_logits)[-1 : -n_best_size - 1 : -1].tolist()
- end_indexes = np.argsort(end_logits)[-1 : -n_best_size - 1 : -1].tolist()
- valid_answers = []
- for start_index in start_indexes:
- for end_index in end_indexes:
- # Don't consider out-of-scope answers, either because the indices are out of bounds or correspond
- # to part of the input_ids that are not in the context.
- if (
- start_index >= len(offset_mapping)
- or end_index >= len(offset_mapping)
- or offset_mapping[start_index] is None
- or offset_mapping[end_index] is None
- ):
- continue
- # Don't consider answers with a length that is either < 0 or > max_answer_length.
- if end_index < start_index or end_index - start_index + 1 > max_answer_length:
- continue
- if start_index <= end_index: # We need to refine that test to check the answer is inside the context
- start_char = offset_mapping[start_index][0]
- end_char = offset_mapping[end_index][1]
- valid_answers.append(
- {
- "score": start_logits[start_index] + end_logits[end_index],
- "text": context[start_char: end_char]
- }
- )
-
- valid_answers = sorted(valid_answers, key=lambda x: x["score"], reverse=True)[:n_best_size]
- valid_answers
- import collections
-
- examples = datasets["validation"]
- features = validation_features
-
- example_id_to_index = {k: i for i, k in enumerate(examples["id"])}
- features_per_example = collections.defaultdict(list)
- for i, feature in enumerate(features):
- features_per_example[example_id_to_index[feature["example_id"]]].append(i)
- from tqdm.auto import tqdm
-
- def postprocess_qa_predictions(examples, features, raw_predictions, n_best_size = 20, max_answer_length = 30):
- all_start_logits, all_end_logits = raw_predictions
- # Build a map example to its corresponding features.
- example_id_to_index = {k: i for i, k in enumerate(examples["id"])}
- features_per_example = collections.defaultdict(list)
- for i, feature in enumerate(features):
- features_per_example[example_id_to_index[feature["example_id"]]].append(i)
-
- # The dictionaries we have to fill.
- predictions = collections.OrderedDict()
-
- # Logging.
- print(f"Post-processing {len(examples)} example predictions split into {len(features)} features.")
-
- # Let's loop over all the examples!
- for example_index, example in enumerate(tqdm(examples)):
- # Those are the indices of the features associated to the current example.
- feature_indices = features_per_example[example_index]
-
- min_null_score = None # Only used if squad_v2 is True.
- valid_answers = []
-
- context = example["context"]
- # Looping through all the features associated to the current example.
- for feature_index in feature_indices:
- # We grab the predictions of the model for this feature.
- start_logits = all_start_logits[feature_index]
- end_logits = all_end_logits[feature_index]
- # This is what will allow us to map some the positions in our logits to span of texts in the original
- # context.
- offset_mapping = features[feature_index]["offset_mapping"]
-
- # Update minimum null prediction.
- cls_index = features[feature_index]["input_ids"].index(tokenizer.cls_token_id)
- feature_null_score = start_logits[cls_index] + end_logits[cls_index]
- if min_null_score is None or min_null_score < feature_null_score:
- min_null_score = feature_null_score
-
- # Go through all possibilities for the `n_best_size` greater start and end logits.
- start_indexes = np.argsort(start_logits)[-1 : -n_best_size - 1 : -1].tolist()
- end_indexes = np.argsort(end_logits)[-1 : -n_best_size - 1 : -1].tolist()
- for start_index in start_indexes:
- for end_index in end_indexes:
- # Don't consider out-of-scope answers, either because the indices are out of bounds or correspond
- # to part of the input_ids that are not in the context.
- if (
- start_index >= len(offset_mapping)
- or end_index >= len(offset_mapping)
- or offset_mapping[start_index] is None
- or offset_mapping[end_index] is None
- ):
- continue
- # Don't consider answers with a length that is either < 0 or > max_answer_length.
- if end_index < start_index or end_index - start_index + 1 > max_answer_length:
- continue
-
- start_char = offset_mapping[start_index][0]
- end_char = offset_mapping[end_index][1]
- valid_answers.append(
- {
- "score": start_logits[start_index] + end_logits[end_index],
- "text": context[start_char: end_char]
- }
- )
-
- if len(valid_answers) > 0:
- best_answer = sorted(valid_answers, key=lambda x: x["score"], reverse=True)[0]
- else:
- # In the very rare edge case we have not a single non-null prediction, we create a fake prediction to avoid
- # failure.
- best_answer = {"text": "", "score": 0.0}
-
- # Let's pick our final answer: the best one or the null answer (only for squad_v2)
- if not squad_v2:
- predictions[example["id"]] = best_answer["text"]
- else:
- answer = best_answer["text"] if best_answer["score"] > min_null_score else ""
- predictions[example["id"]] = answer
-
- return predictions
- final_predictions = postprocess_qa_predictions(datasets["validation"], validation_features, raw_predictions.predictions)
- metric = load_metric("squad_v2" if squad_v2 else "squad")
- if squad_v2:
- formatted_predictions = [{"id": k, "prediction_text": v, "no_answer_probability": 0.0} for k, v in predictions.items()]
- else:
- formatted_predictions = [{"id": k, "prediction_text": v} for k, v in final_predictions.items()]
- references = [{"id": ex["id"], "answers": ex["answers"]} for ex in datasets["validation"]]
- metric.compute(predictions=formatted_predictions, references=references)
文本分类
- GLUE_TASKS = ["cola", "mnli", "mnli-mm", "mrpc", "qnli", "qqp", "rte", "sst2", "stsb", "wnli"]
- task = "cola"
- model_checkpoint="H:\\code\\Model\\distilbert-base-cased\\"
- batch_size = 16
- from datasets import load_dataset, load_metric
- actual_task = "mnli" if task == "mnli-mm" else task
- dataset = load_dataset("glue", actual_task)
- metric = load_metric('glue', actual_task)
- import datasets
- import random
- import pandas as pd
- from IPython.display import display, HTML
-
- def show_random_elements(dataset, num_examples=10):
- assert num_examples <= len(dataset), "Can't pick more elements than there are in the dataset."
- picks = []
- for _ in range(num_examples):
- pick = random.randint(0, len(dataset)-1)
- while pick in picks:
- pick = random.randint(0, len(dataset)-1)
- picks.append(pick)
-
- df = pd.DataFrame(dataset[picks])
- for column, typ in dataset.features.items():
- if isinstance(typ, datasets.ClassLabel):
- df[column] = df[column].transform(lambda i: typ.names[i])
- display(HTML(df.to_html()))
- show_random_elements(dataset["train"])
- import numpy as np
-
- fake_preds = np.random.randint(0, 2, size=(64,))
- fake_labels = np.random.randint(0, 2, size=(64,))
- metric.compute(predictions=fake_preds, references=fake_labels)
- #预处理数据
- from transformers import AutoTokenizer
-
- tokenizer = AutoTokenizer.from_pretrained(model_checkpoint, use_fast=True)
- tokenizer("Hello, this one sentence!", "And this sentence goes with it.")
- task_to_keys = {
- "cola": ("sentence", None),
- "mnli": ("premise", "hypothesis"),
- "mnli-mm": ("premise", "hypothesis"),
- "mrpc": ("sentence1", "sentence2"),
- "qnli": ("question", "sentence"),
- "qqp": ("question1", "question2"),
- "rte": ("sentence1", "sentence2"),
- "sst2": ("sentence", None),
- "stsb": ("sentence1", "sentence2"),
- "wnli": ("sentence1", "sentence2"),
- }
- sentence1_key, sentence2_key = task_to_keys[task]
- if sentence2_key is None:
- print(f"Sentence: {dataset['train'][0][sentence1_key]}")
- else:
- print(f"Sentence 1: {dataset['train'][0][sentence1_key]}")
- print(f"Sentence 2: {dataset['train'][0][sentence2_key]}")
- def preprocess_function(examples):
- if sentence2_key is None:
- return tokenizer(examples[sentence1_key], truncation=True)
- return tokenizer(examples[sentence1_key], examples[sentence2_key], truncation=True)
- preprocess_function(dataset['train'][:5])
- encoded_dataset = dataset.map(preprocess_function, batched=True)
- #微调模型
- from transformers import AutoModelForSequenceClassification, TrainingArguments, Trainer
-
- num_labels = 3 if task.startswith("mnli") else 1 if task=="stsb" else 2
- model = AutoModelForSequenceClassification.from_pretrained(model_checkpoint, num_labels=num_labels)
- metric_name = "pearson" if task == "stsb" else "matthews_correlation" if task == "cola" else "accuracy"
-
- args = TrainingArguments(
- "test-glue",
- evaluation_strategy = "epoch",
- learning_rate=2e-5,
- per_device_train_batch_size=batch_size,
- per_device_eval_batch_size=batch_size,
- num_train_epochs=5,
- weight_decay=0.01,
- load_best_model_at_end=True,
- metric_for_best_model=metric_name,
- )
- def compute_metrics(eval_pred):
- predictions, labels = eval_pred
- if task != "stsb":
- predictions = np.argmax(predictions, axis=1)
- else:
- predictions = predictions[:, 0]
- return metric.compute(predictions=predictions, references=labels)
- validation_key = "validation_mismatched" if task == "mnli-mm" else "validation_matched" if task == "mnli" else "validation"
- trainer = Trainer(
- model,
- args,
- train_dataset=encoded_dataset["train"],
- eval_dataset=encoded_dataset[validation_key],
- tokenizer=tokenizer,
- compute_metrics=compute_metrics
- )
- trainer.train()
- trainer.evaluate()
- #超参数搜索
- def model_init():
- return AutoModelForSequenceClassification.from_pretrained(model_checkpoint, num_labels=num_labels)
- trainer = Trainer(
- model_init=model_init,
- args=args,
- train_dataset=encoded_dataset["train"],
- eval_dataset=encoded_dataset[validation_key],
- tokenizer=tokenizer,
- compute_metrics=compute_metrics
- )
- best_run = trainer.hyperparameter_search(n_trials=10, direction="maximize")
- best_run
- for n, v in best_run.hyperparameters.items():
- setattr(trainer.args, n, v)
-
- trainer.train()
命名实体识别
- task = "ner" # Should be one of "ner", "pos" or "chunk"
- model_checkpoint="H:\\code\\Model\\distilbert-base-cased\\"
- batch_size = 16
- from datasets import load_dataset, load_metric
- datasets = load_dataset("conll2003")
- datasets
- label_list = datasets["train"].features[f"{task}_tags"].feature.names
- label_list
- from datasets import ClassLabel, Sequence
- import random
- import pandas as pd
- from IPython.display import display, HTML
-
- def show_random_elements(dataset, num_examples=10):
- assert num_examples <= len(dataset), "Can't pick more elements than there are in the dataset."
- picks = []
- for _ in range(num_examples):
- pick = random.randint(0, len(dataset)-1)
- while pick in picks:
- pick = random.randint(0, len(dataset)-1)
- picks.append(pick)
-
- df = pd.DataFrame(dataset[picks])
- for column, typ in dataset.features.items():
- if isinstance(typ, ClassLabel):
- df[column] = df[column].transform(lambda i: typ.names[i])
- elif isinstance(typ, Sequence) and isinstance(typ.feature, ClassLabel):
- df[column] = df[column].transform(lambda x: [typ.feature.names[i] for i in x])
- display(HTML(df.to_html()))
- show_random_elements(datasets["train"])
- #预处理数据
- from transformers import AutoTokenizer
-
- tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
- import transformers
- assert isinstance(tokenizer, transformers.PreTrainedTokenizerFast)
- tokenizer("Hello, this is one sentence!")
- example = datasets["train"][4]
- print(example["tokens"])
- tokenized_input = tokenizer(example["tokens"], is_split_into_words=True)
- tokens = tokenizer.convert_ids_to_tokens(tokenized_input["input_ids"])
- print(tokens)
- word_ids = tokenized_input.word_ids()
- aligned_labels = [-100 if i is None else example[f"{task}_tags"][i] for i in word_ids]
- print(len(aligned_labels), len(tokenized_input["input_ids"]))
- label_all_tokens = True
- def tokenize_and_align_labels(examples):
- tokenized_inputs = tokenizer(examples["tokens"], truncation=True, is_split_into_words=True)
-
- labels = []
- for i, label in enumerate(examples[f"{task}_tags"]):
- word_ids = tokenized_inputs.word_ids(batch_index=i)
- previous_word_idx = None
- label_ids = []
- for word_idx in word_ids:
- # Special tokens have a word id that is None. We set the label to -100 so they are automatically
- # ignored in the loss function.
- if word_idx is None:
- label_ids.append(-100)
- # We set the label for the first token of each word.
- elif word_idx != previous_word_idx:
- label_ids.append(label[word_idx])
- # For the other tokens in a word, we set the label to either the current label or -100, depending on
- # the label_all_tokens flag.
- else:
- label_ids.append(label[word_idx] if label_all_tokens else -100)
- previous_word_idx = word_idx
-
- labels.append(label_ids)
-
- tokenized_inputs["labels"] = labels
- return tokenized_inputs
- tokenize_and_align_labels(datasets['train'][:5])
- tokenized_datasets = datasets.map(tokenize_and_align_labels, batched=True)
- #微调模型
- from transformers import AutoModelForTokenClassification, TrainingArguments, Trainer
-
- model = AutoModelForTokenClassification.from_pretrained(model_checkpoint, num_labels=len(label_list))
- args = TrainingArguments(
- f"test-{task}",
- evaluation_strategy = "epoch",
- learning_rate=2e-5,
- per_device_train_batch_size=batch_size,
- per_device_eval_batch_size=batch_size,
- num_train_epochs=3,
- weight_decay=0.01,
- )
- from transformers import DataCollatorForTokenClassification
-
- data_collator = DataCollatorForTokenClassification(tokenizer)
- metric = load_metric("seqeval")
- labels = [label_list[i] for i in example[f"{task}_tags"]]
- metric.compute(predictions=[labels], references=[labels])
- import numpy as np
-
- def compute_metrics(p):
- predictions, labels = p
- predictions = np.argmax(predictions, axis=2)
-
- # Remove ignored index (special tokens)
- true_predictions = [
- [label_list[p] for (p, l) in zip(prediction, label) if l != -100]
- for prediction, label in zip(predictions, labels)
- ]
- true_labels = [
- [label_list[l] for (p, l) in zip(prediction, label) if l != -100]
- for prediction, label in zip(predictions, labels)
- ]
-
- results = metric.compute(predictions=true_predictions, references=true_labels)
- return {
- "precision": results["overall_precision"],
- "recall": results["overall_recall"],
- "f1": results["overall_f1"],
- "accuracy": results["overall_accuracy"],
- }
- trainer = Trainer(
- model,
- args,
- train_dataset=tokenized_datasets["train"],
- eval_dataset=tokenized_datasets["validation"],
- data_collator=data_collator,
- tokenizer=tokenizer,
- compute_metrics=compute_metrics
- )
- trainer.train()
- trainer.evaluate()
- predictions, labels, _ = trainer.predict(tokenized_datasets["validation"])
- predictions = np.argmax(predictions, axis=2)
-
- # Remove ignored index (special tokens)
- true_predictions = [
- [label_list[p] for (p, l) in zip(prediction, label) if l != -100]
- for prediction, label in zip(predictions, labels)
- ]
- true_labels = [
- [label_list[l] for (p, l) in zip(prediction, label) if l != -100]
- for prediction, label in zip(predictions, labels)
- ]
-
- results = metric.compute(predictions=true_predictions, references=true_labels)
- results
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。