From c2fa3e4db4dec142bd657101342150cccd358f7a Mon Sep 17 00:00:00 2001
From: jiahao su <85146036+xuedinge233@users.noreply.github.com>
Date: Tue, 16 Jul 2024 20:46:07 +0800
Subject: [PATCH] add doc for transformers (#35)
Add doc for transformers
---
index.rst | 7 +-
sources/transformers/fine-tune.rst | 250 ++++++++++++++++++
sources/transformers/images/downloadmodel.png | Bin 0 -> 84549 bytes
sources/transformers/index.rst | 11 +
sources/transformers/inference.rst | 183 +++++++++++++
sources/transformers/install.rst | 90 +++++++
sources/transformers/modeldownload.rst | 126 +++++++++
sources/transformers/quick_start.rst | 131 +++++++++
8 files changed, 795 insertions(+), 3 deletions(-)
create mode 100644 sources/transformers/fine-tune.rst
create mode 100644 sources/transformers/images/downloadmodel.png
create mode 100644 sources/transformers/index.rst
create mode 100644 sources/transformers/inference.rst
create mode 100644 sources/transformers/install.rst
create mode 100644 sources/transformers/modeldownload.rst
create mode 100644 sources/transformers/quick_start.rst
diff --git a/index.rst b/index.rst
index 4be6682..f3bdd87 100644
--- a/index.rst
+++ b/index.rst
@@ -20,6 +20,7 @@
sources/pytorch/index.rst
sources/llamafactory/index.rst
+ sources/transformers/index.rst
.. warning::
@@ -154,11 +155,11 @@
diff --git a/sources/transformers/fine-tune.rst b/sources/transformers/fine-tune.rst
new file mode 100644
index 0000000..e520f20
--- /dev/null
+++ b/sources/transformers/fine-tune.rst
@@ -0,0 +1,250 @@
+微调预训练模型
+==================
+
+.. note::
+
+ 阅读本篇前,请确保已按照 :doc:`安装指南 <./install>` 准备好昇腾环境及transformers!
+
+大模型微调本质是利用特定领域的数据集对已预训练的大模型进行进一步训练的过程。它旨在优化模型在特定任务上的性能,使模型能够更好地适应和完成特定领域的任务。
+本文在使用transformers库选定相关数据集和预训练模型的基础上,通过超参数调优完成对模型的微调。
+
+前置准备
+-----------------
+
+安装必要库
+<<<<<<<<<<<<<<<
+
+.. code-block:: shell
+ :linenos:
+
+ pip install transformers datasets evaluate accelerate scikit-learn
+
+加载数据集
+<<<<<<<<<<<<<<<<<<<
+
+模型训练需要使用数据集,这里使用 `Yelp Reviews dataset `_ :
+
+.. code-block:: python
+ :linenos:
+
+ from datasets import load_dataset
+
+ # load_dataset 会自动下载数据集并将其保存到本地路径中
+ dataset = load_dataset("yelp_review_full")
+ #输出数据集的第100条数据
+ dataset["train"][100]
+
+输出如下:
+
+.. code-block:: shell
+
+ {'label': 0, 'text': 'My expectations for McDonalds are t rarely high. But for one to still fail so spectacularly...that takes something special!\\n
+ The cashier took my friends\'s order, then promptly ignored me. I had to force myself in front of a cashier who opened his register to wait on the
+ person BEHIND me. I waited over five minutes for a gigantic order that included precisely one kid\'s meal. After watching two people who ordered after
+ me be handed their food, I asked where mine was. The manager started yelling at the cashiers for \\"serving off their orders\\" when they didn\'t have
+ their food. But neither cashier was anywhere near those controls, and the manager was the one serving food to customers and clearing the boards.\\nThe
+ manager was rude when giving me my order. She didn\'t make sure that I had everything ON MY RECEIPT, and never even had the decency to apologize that
+ I felt I was getting poor service.\\nI\'ve eaten at various McDonalds restaurants for over 30 years. I\'ve worked at more than one location. I expect
+ bad days, bad moods, and the occasional mistake. But I have yet to have a decent experience at this store. It will remain a place I avoid unless someone
+ in my party needs to avoid illness from low blood sugar. Perhaps I should go back to the racially biased service of Steak n Shake instead!'}
+
+
+预处理数据集
+<<<<<<<<<<<<<<<<<
+
+预处理数据集需要使用AutoTokenizer,它用来自动获取与模型匹配的分词器,分词器根据规则将文本拆分为标记,并转换为张量作为模型输入,
+下面用到了Meta-Llama-3-8B-Instruct模型,下载模型请转至 `模型获取 <./modeldownload.html>`_,以下是一个示例:
+
+.. code-block:: python
+ :linenos:
+
+ from transformers import AutoTokenizer
+
+ tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")
+ #使用分词器处理文本
+ encoded_input = tokenizer("Do not meddle in the affairs of wizards, for they are subtle and quick to anger.")
+ print(encoded_input)
+
+输出如下:
+
+.. code-block:: shell
+
+ {'input_ids': [128000, 5519, 539, 1812, 91485, 304, 279, 22747, 315, 89263, 11, 369, 814, 527, 27545, 323, 4062, 311, 19788, 13],
+ 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
+
+接着使用dataset.map方法对数据集进行预处理:
+
+.. code-block:: python
+ :linenos:
+
+ def tokenize_function(examples):
+ return tokenizer(examples["text"], padding="max_length", truncation=True)
+
+ tokenized_datasets = dataset.map(tokenize_function, batched=True)
+
+初次进行预处理需要一定时间,内容如下:
+
+.. code-block:: shell
+ :linenos:
+
+ Asking to pad to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no padding.
+ Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.
+ Map: 100%|████████████████████████████████████████████████████████████████████████| 650000/650000 [03:27<00:00, 3139.47 examples/s]
+ Map: 100%|██████████████████████████████████████████████████████████████████████████| 50000/50000 [00:15<00:00, 3156.92 examples/s]
+
+训练全部的数据集会耗费更长的时间,通常将其划分为较小的训练集和验证集,以提高训练速度:
+
+.. code-block:: python
+ :linenos:
+
+ small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
+ small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000))
+
+ # 下面是加载全训练集和验证集
+ # full_train_dataset = tokenized_datasets["train"]
+ # full_eval_dataset = tokenized_datasets["test"]
+
+训练
+------------
+
+加载模型
+<<<<<<<<<
+
+使用AutoModelForCausalLM将自动加载模型:
+
+.. code-block:: python
+ :linenos:
+
+ from transformers import AutoModelForCausalLM
+
+ model = AutoModelForCausalLM.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")
+
+超参数调优
+<<<<<<<<<<<<<<<<<<<<<
+
+超参数调优用于激活不同训练选项的标志,它定义了关于模型的更高层次的概念,例如模型复杂程度或学习能力,下边使用TrainingArguments类来加载:
+
+.. code-block:: python
+ :linenos:
+
+ from transformers import TrainingArguments
+
+ training_args = TrainingArguments(output_dir="test_trainer", eval_strategy="epoch")
+
+模型评估
+<<<<<<<<<<<<<
+
+模型评估用于衡量模型在给定数据集上的表现,包括准确率,完全匹配速率,平均并交集点等,下面是使用方式:
+
+.. code-block:: python
+ :linenos:
+
+ import
+ import sklearn
+ import evaluate
+
+ metric = evaluate.load("accuracy")
+
+ #计算预测的准确性,并将预测传递给compute
+ def compute_metrics(eval_pred):
+ logits, labels = eval_pred
+ predictions = np.argmax(logits, axis=-1)
+ return metric.compute(predictions=predictions, references=labels)
+
+
+Trainer
+<<<<<<<
+
+使用已加载的模型、训练参数、训练和测试数据集以及评估函数创建一个Trainer对象,并调用trainer.train()来微调模型:
+
+.. code-block:: python
+ :linenos:
+
+ from transformers import Trainer
+
+ trainer = Trainer(
+ model=model,
+ args=training_args,
+ train_dataset=small_train_dataset,
+ eval_dataset=small_eval_dataset,
+ compute_metrics=compute_metrics,
+ )
+
+ trainer.train()
+
+
+预训练全流程
+-------------------
+
+.. code-block:: python
+ :linenos:
+
+ import torch
+ import torch_npu
+ import numpy as np
+ import sklearn
+ import evaluate
+ from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments
+ from datasets import load_dataset
+
+ model_id = "meta-llama/Meta-Llama-3-8B-Instruct"
+ device = "npu:0" if torch.npu.is_available() else "cpu"
+
+ # 加载分词器和模型
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
+ model = AutoModelForCausalLM.from_pretrained(
+ model_id,
+ torch_dtype=torch.bfloat16,
+ device_map="auto",
+ ).to(device)
+
+ dataset = load_dataset("yelp_review_full")
+
+ #分词函数
+ def tokenize_function(examples):
+ return tokenizer(examples["text"], padding="max_length", truncation=True)
+
+ tokenized_datasets = dataset.map(tokenize_function, batched=True)
+
+ small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
+ small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(1000))
+
+ # 加载评估指标
+ metric = evaluate.load("accuracy")
+
+ # 定义评估指标的计算函数
+ def compute_metrics(eval_pred):
+ logits, labels = eval_pred
+ predictions = np.argmax(logits, axis=-1)
+ return metric.compute(predictions=predictions, references=labels)
+
+ training_args = TrainingArguments(output_dir="test_trainer", eval_strategy="epoch")
+
+ trainer = Trainer(
+ model=model,
+ args=training_args,
+ train_dataset=small_train_dataset,
+ eval_dataset=small_eval_dataset,
+ compute_metrics=compute_metrics,
+ )
+
+ trainer.train()
+
+
+训练完成后得到以下结果:
+
+.. code-block:: shell
+ :linenos:
+
+ |█████████████████████████████████| [375/375 06:21, Epoch 3/3]
+
+ ===== ============= =============== ======
+ Epoch Training Loss Validation Loss Accuracy
+ ===== ============= =============== ======
+ 1 No log 1.155628 0.499000
+ 2 No log 0.994618 0.574000
+ 3 No log 1.026123 0.590000
+ ===== ============= =============== ======
+
+ TrainOutput(global_step=375, training_loss=1.0557311197916666, metrics={'train_runtime': 384.55, 'train_samples_per_second': 7.801,
+ 'train_steps_per_second': 0.975, 'total_flos': 789354427392000.0, 'train_loss': 1.0557311197916666, 'epoch': 3.0})
diff --git a/sources/transformers/images/downloadmodel.png b/sources/transformers/images/downloadmodel.png
new file mode 100644
index 0000000000000000000000000000000000000000..e2e119f3fcb1fafe94faa4d0cc9f66399870c577
GIT binary patch
literal 84549
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