From 9aad49a188d757373d9f862026c2e8d5fcc60315 Mon Sep 17 00:00:00 2001 From: cuiluyuan Date: Thu, 18 Dec 2025 15:09:39 +0800 Subject: [PATCH 1/2] add bert, gpt and prompt --- .../01.BERT/bert_emotect_finetune.ipynb | 936 ++++------ .../01.BERT/bert_introduction.ipynb | 224 +-- .../02.GPT/gpt_imdb_finetune.ipynb | 793 ++++---- .../chatglm4_simple_inference.ipynb | 390 ---- .../07.LLaMA2/llama_finetune_inference.ipynb | 1638 ----------------- .../07.LLaMA2/llama_inference_debug.py | 42 - .../roberta_sequence_classification.ipynb | 633 ++++--- .../Chapter2/pretrain.md | 2 +- 8 files changed, 1168 insertions(+), 3490 deletions(-) delete mode 100644 01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/04.ChatGLM/chatglm4_simple_inference.ipynb delete mode 100644 01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/07.LLaMA2/llama_finetune_inference.ipynb delete mode 100644 01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/07.LLaMA2/llama_inference_debug.py diff --git a/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/01.BERT/bert_emotect_finetune.ipynb b/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/01.BERT/bert_emotect_finetune.ipynb index 6ceed46..e271533 100644 --- a/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/01.BERT/bert_emotect_finetune.ipynb +++ b/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/01.BERT/bert_emotect_finetune.ipynb @@ -4,159 +4,61 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 环境配置" + "# 基于 MindSpore 的 BERT 模型实现对话情绪识别\n", + "\n", + "## 案例介绍\n", + "\n", + "该案例以一个文本情感分类任务为例子来说明BERT模型的整个应用过程。\n", + "\n", + "## 模型简介\n", + "\n", + "BERT全称是来自变换器的双向编码器表征量(Bidirectional Encoder Representations from Transformers),它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模型例如问答、命名实体识别、自然语言推理、文本分类等在许多自然语言处理任务中发挥着重要作用。模型是基于Transformer中的Encoder并加上双向的结构,因此一定要熟练掌握Transformer的Encoder的结构。\n", + "\n", + "BERT模型的主要创新点都在pre-train方法上,即用了Masked Language Model和Next Sentence Prediction两种方法分别捕捉词语和句子级别的representation。\n", + "\n", + "在用Masked Language Model方法训练BERT的时候,随机把语料库中15%的单词做Mask操作。对于这15%的单词做Mask操作分为三种情况:80%的单词直接用[Mask]替换、10%的单词直接替换成另一个新的单词、10%的单词保持不变。\n", + "\n", + "因为涉及到Question Answering (QA) 和 Natural Language Inference (NLI)之类的任务,增加了Next Sentence Prediction预训练任务,目的是让模型理解两个句子之间的联系。与Masked Language Model任务相比,Next Sentence Prediction更简单些,训练的输入是句子A和B,B有一半的几率是A的下一句,输入这两个句子,BERT模型预测B是不是A的下一句。\n", + "\n", + "BERT预训练之后,会保存它的Embedding table和12层Transformer权重(BERT-BASE)或24层Transformer权重(BERT-LARGE)。使用预训练好的BERT模型可以对下游任务进行Fine-tuning,比如:文本分类、相似度判断、阅读理解等。\n", + "\n", + "对话情绪识别(Emotion Detection,简称EmoTect),专注于识别智能对话场景中用户的情绪,针对智能对话场景中的用户文本,自动判断该文本的情绪类别并给出相应的置信度,情绪类型分为积极、消极、中性。 对话情绪识别适用于聊天、客服等多个场景,能够帮助企业更好地把握对话质量、改善产品的用户交互体验,也能分析客服服务质量、降低人工质检成本。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "安装MindSpore框架和MindNLP套件" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n", - "Collecting mindspore==2.5.0\n", - " Using cached https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.5.0/MindSpore/unified/aarch64/mindspore-2.5.0-cp39-cp39-linux_aarch64.whl (345.0 MB)\n", - "Requirement already satisfied: pip in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (25.1)\n", - "\u001b[31mERROR: Could not find a version that satisfies the requirement install (from versions: none)\u001b[0m\u001b[31m\n", - "\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n", - "\u001b[31mERROR: No matching distribution found for install\u001b[0m\u001b[31m\n", - "\u001b[0m" - ] - } - ], - "source": [ - "!pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.5.0/MindSpore/unified/aarch64/mindspore-2.5.0-cp39-cp39-linux_aarch64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple" + "## 环境配置\n", + "\n", + "本案例的运行环境为:\n", + "\n", + "| Python | MindSpore | MindSpore NLP |\n", + "| :----- | :-------- | :------------ |\n", + "| 3.10 | 2.7.0 | 0.5.1 |\n", + "\n", + "如果你在如[昇思大模型平台](https://xihe.mindspore.cn/training-projects)、[华为云ModelArts](https://www.huaweicloud.com/product/modelarts.html)、[启智社区](https://openi.pcl.ac.cn/)等算力平台的Jupyter在线编程环境中运行本案例,可取消如下代码的注释,进行依赖库安装:" ] }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://repo.huaweicloud.com/repository/pypi/simple/\n", - "Requirement already satisfied: mindnlp==0.4.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (0.4.0)\n", - "Requirement already satisfied: mindspore>=2.2.14 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.5.0)\n", - "Requirement already satisfied: tqdm in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (4.67.1)\n", - "Requirement already satisfied: requests in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.32.3)\n", - "Requirement already satisfied: datasets in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (3.6.0)\n", - "Requirement already satisfied: evaluate in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.4.3)\n", - "Requirement already satisfied: tokenizers==0.19.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.19.1)\n", - "Requirement already satisfied: safetensors in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.3)\n", - "Requirement already satisfied: sentencepiece in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.2.0)\n", - "Requirement already satisfied: regex in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2024.11.6)\n", - "Requirement already satisfied: addict in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.4.0)\n", - "Requirement already satisfied: ml-dtypes in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.1)\n", - "Requirement already satisfied: pyctcdecode in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.0)\n", - "Requirement already satisfied: jieba in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.42.1)\n", - "Requirement already satisfied: pytest==7.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (7.2.0)\n", - "Requirement already satisfied: pillow>=10.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (11.2.1)\n", - "Requirement already satisfied: attrs>=19.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (25.3.0)\n", - "Requirement already satisfied: iniconfig in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (2.1.0)\n", - "Requirement already satisfied: packaging in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (24.2)\n", - "Requirement already satisfied: pluggy<2.0,>=0.12 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (1.5.0)\n", - "Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (1.2.0)\n", - "Requirement already satisfied: tomli>=1.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (2.2.1)\n", - "Requirement already satisfied: huggingface-hub<1.0,>=0.16.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from tokenizers==0.19.1->mindnlp==0.4.0) (0.32.3)\n", - "Requirement already satisfied: filelock in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (3.18.0)\n", - "Requirement already satisfied: fsspec>=2023.5.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (2025.3.0)\n", - "Requirement already satisfied: pyyaml>=5.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (6.0.2)\n", - "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (4.12.2)\n", - "Requirement already satisfied: hf-xet<2.0.0,>=1.1.2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (1.1.2)\n", - "Requirement already satisfied: numpy<2.0.0,>=1.20.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.26.4)\n", - "Requirement already satisfied: protobuf>=3.13.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (6.30.2)\n", - "Requirement already satisfied: asttokens>=2.0.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (3.0.0)\n", - "Requirement already satisfied: scipy>=1.5.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.13.1)\n", - "Requirement already satisfied: psutil>=5.6.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (5.9.0)\n", - "Requirement already satisfied: astunparse>=1.6.3 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.6.3)\n", - "Requirement already satisfied: dill>=0.3.7 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (0.3.8)\n", - "Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore>=2.2.14->mindnlp==0.4.0) (0.45.1)\n", - "Requirement already satisfied: six<2.0,>=1.6.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore>=2.2.14->mindnlp==0.4.0) (1.17.0)\n", - "Requirement already satisfied: pyarrow>=15.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (20.0.0)\n", - "Requirement already satisfied: pandas in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (2.2.3)\n", - "Requirement already satisfied: xxhash in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (3.5.0)\n", - "Requirement already satisfied: multiprocess<0.70.17 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (0.70.16)\n", - "Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (3.12.7)\n", - "Requirement already satisfied: aiohappyeyeballs>=2.5.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (2.6.1)\n", - "Requirement already satisfied: aiosignal>=1.1.2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.3.2)\n", - "Requirement already satisfied: async-timeout<6.0,>=4.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (5.0.1)\n", - "Requirement already satisfied: frozenlist>=1.1.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.6.0)\n", - "Requirement already satisfied: multidict<7.0,>=4.5 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (6.4.4)\n", - "Requirement already satisfied: propcache>=0.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (0.3.1)\n", - "Requirement already satisfied: yarl<2.0,>=1.17.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.20.0)\n", - "Requirement already satisfied: idna>=2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from yarl<2.0,>=1.17.0->aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (3.10)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (3.4.1)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (2.4.0)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (2025.4.26)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2025.2)\n", - "Requirement already satisfied: tzdata>=2022.7 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2025.2)\n", - "Requirement already satisfied: pygtrie<3.0,>=2.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pyctcdecode->mindnlp==0.4.0) (2.5.0)\n", - "Requirement already satisfied: hypothesis<7,>=6.14 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pyctcdecode->mindnlp==0.4.0) (6.133.2)\n", - "Requirement already satisfied: sortedcontainers<3.0.0,>=2.1.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from hypothesis<7,>=6.14->pyctcdecode->mindnlp==0.4.0) (2.4.0)\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n" - ] - } - ], - "source": [ - "!pip install mindnlp==0.4.0" - ] - }, - { - "cell_type": "markdown", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "#### 注:MindNLP whl包下载链接为:[MindNLP](https://repo.mindspore.cn/mindspore-lab/mindnlp/newest/any/)" + "# !pip install mindspore==2.7.0 mindnlp==0.5.1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "# 基于 MindSpore 实现 BERT 对话情绪识别\n", - "\n", - "\n", - "## 模型简介\n", - "\n", - "BERT全称是来自变换器的双向编码器表征量(Bidirectional Encoder Representations from Transformers),它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模型例如问答、命名实体识别、自然语言推理、文本分类等在许多自然语言处理任务中发挥着重要作用。模型是基于Transformer中的Encoder并加上双向的结构,因此一定要熟练掌握Transformer的Encoder的结构。\n", - "\n", - "BERT模型的主要创新点都在pre-train方法上,即用了Masked Language Model和Next Sentence Prediction两种方法分别捕捉词语和句子级别的representation。\n", - "\n", - "在用Masked Language Model方法训练BERT的时候,随机把语料库中15%的单词做Mask操作。对于这15%的单词做Mask操作分为三种情况:80%的单词直接用[Mask]替换、10%的单词直接替换成另一个新的单词、10%的单词保持不变。\n", - "\n", - "因为涉及到Question Answering (QA) 和 Natural Language Inference (NLI)之类的任务,增加了Next Sentence Prediction预训练任务,目的是让模型理解两个句子之间的联系。与Masked Language Model任务相比,Next Sentence Prediction更简单些,训练的输入是句子A和B,B有一半的几率是A的下一句,输入这两个句子,BERT模型预测B是不是A的下一句。\n", - "\n", - "BERT预训练之后,会保存它的Embedding table和12层Transformer权重(BERT-BASE)或24层Transformer权重(BERT-LARGE)。使用预训练好的BERT模型可以对下游任务进行Fine-tuning,比如:文本分类、相似度判断、阅读理解等。\n", - "\n", - "对话情绪识别(Emotion Detection,简称EmoTect),专注于识别智能对话场景中用户的情绪,针对智能对话场景中的用户文本,自动判断该文本的情绪类别并给出相应的置信度,情绪类型分为积极、消极、中性。 对话情绪识别适用于聊天、客服等多个场景,能够帮助企业更好地把握对话质量、改善产品的用户交互体验,也能分析客服服务质量、降低人工质检成本。\n", - "\n", - "下面以一个文本情感分类任务为例子来说明BERT模型的整个应用过程。" + "其他场景可参考[MindSpore安装指南](https://www.mindspore.cn/install)与[MindSpore NLP安装指南](https://github.com/mindspore-lab/mindnlp?tab=readme-ov-file#installation)进行环境搭建。" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "tags": [] }, @@ -165,62 +67,29 @@ "name": "stderr", "output_type": "stream", "text": [ - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", " setattr(self, word, getattr(machar, word).flat[0])\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", " return self._float_to_str(self.smallest_subnormal)\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", " setattr(self, word, getattr(machar, word).flat[0])\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", " return self._float_to_str(self.smallest_subnormal)\n", - "Building prefix dict from the default dictionary ...\n", - "Loading model from cache /tmp/jieba.cache\n", - "Loading model cost 0.908 seconds.\n", - "Prefix dict has been built successfully.\n" + "/usr/local/python3.10.14/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "Modular Diffusers is currently an experimental feature under active development. The API is subject to breaking changes in future releases.\n", + "[WARNING] ME(3859:281473418565184,MainProcess):2025-11-25-13:56:29.950.000 [mindspore/context.py:1412] For 'context.set_context', the parameter 'pynative_synchronize' will be deprecated and removed in a future version. Please use the api mindspore.runtime.launch_blocking() instead.\n" ] } ], "source": [ "import os\n", - "\n", + "import mindnlp\n", "import mindspore\n", - "from mindspore.dataset import text, GeneratorDataset, transforms\n", + "from datasets import Dataset\n", "from mindspore import nn, context\n", "\n", - "from mindnlp.engine.trainer import Trainer" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# prepare dataset\n", - "class SentimentDataset:\n", - " \"\"\"Sentiment Dataset\"\"\"\n", - "\n", - " def __init__(self, path):\n", - " self.path = path\n", - " self._labels, self._text_a = [], []\n", - " self._load()\n", - "\n", - " def _load(self):\n", - " with open(self.path, \"r\", encoding=\"utf-8\") as f:\n", - " dataset = f.read()\n", - " lines = dataset.split(\"\\n\")\n", - " for line in lines[1:-1]:\n", - " label, text_a = line.split(\"\\t\")\n", - " self._labels.append(int(label))\n", - " self._text_a.append(text_a)\n", - "\n", - " def __getitem__(self, index):\n", - " return self._labels[index], self._text_a[index]\n", - "\n", - " def __len__(self):\n", - " return len(self._labels)" + "mindspore.set_context(pynative_synchronize=True)" ] }, { @@ -244,7 +113,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "tags": [] }, @@ -253,16 +122,16 @@ "name": "stdout", "output_type": "stream", "text": [ - "--2025-06-03 16:26:40-- https://baidu-nlp.bj.bcebos.com/emotion_detection-dataset-1.0.0.tar.gz\n", - "正在解析主机 baidu-nlp.bj.bcebos.com (baidu-nlp.bj.bcebos.com)... 36.110.192.178, 2409:8c04:1001:1203:0:ff:b0bb:4f27\n", - "正在连接 baidu-nlp.bj.bcebos.com (baidu-nlp.bj.bcebos.com)|36.110.192.178|:443... 已连接。\n", - "已发出 HTTP 请求,正在等待回应... 200 OK\n", - "长度:1710581 (1.6M) [application/x-gzip]\n", - "正在保存至: “emotion_detection.tar.gz”\n", + "--2025-11-25 13:56:41-- https://baidu-nlp.bj.bcebos.com/emotion_detection-dataset-1.0.0.tar.gz\n", + "Resolving proxy-notebook.modelarts.com (proxy-notebook.modelarts.com)... 192.168.0.33\n", + "Connecting to proxy-notebook.modelarts.com (proxy-notebook.modelarts.com)|192.168.0.33|:8083... connected.\n", + "Proxy request sent, awaiting response... 200 OK\n", + "Length: 1710581 (1.6M) [application/x-gzip]\n", + "Saving to: ‘emotion_detection.tar.gz’\n", "\n", - "emotion_detection.t 100%[===================>] 1.63M 7.02MB/s 用时 0.2s \n", + "emotion_detection.t 100%[===================>] 1.63M 986KB/s in 1.7s \n", "\n", - "2025-06-03 16:26:41 (7.02 MB/s) - 已保存 “emotion_detection.tar.gz” [1710581/1710581])\n", + "2025-11-25 13:56:43 (986 KB/s) - ‘emotion_detection.tar.gz’ saved [1710581/1710581]\n", "\n", "data/\n", "data/test.tsv\n", @@ -285,168 +154,77 @@ "source": [ "### 数据加载和数据预处理\n", "\n", - "新建 process_dataset 函数用于数据加载和数据预处理,具体内容可见下面代码注释。" + "具体内容可见下面代码注释。" ] }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "tags": [] - }, + "execution_count": null, + "metadata": {}, "outputs": [], "source": [ - "import numpy as np\n", - "\n", - "def process_dataset(source, tokenizer, max_seq_len=64, batch_size=32, shuffle=True):\n", - " is_ascend = mindspore.get_context('device_target') == 'Ascend'\n", - "\n", - " column_names = [\"label\", \"text_a\"]\n", - " \n", - " dataset = GeneratorDataset(source, column_names=column_names, shuffle=shuffle)\n", - " # transforms\n", - " type_cast_op = transforms.TypeCast(mindspore.int32)\n", - " def tokenize_and_pad(text):\n", - " if is_ascend:\n", - " tokenized = tokenizer(text, padding='max_length', truncation=True, max_length=max_seq_len)\n", - " else:\n", - " tokenized = tokenizer(text)\n", - " return tokenized['input_ids'], tokenized['attention_mask']\n", - " # map dataset\n", - " dataset = dataset.map(operations=tokenize_and_pad, input_columns=\"text_a\", output_columns=['input_ids', 'attention_mask'])\n", - " dataset = dataset.map(operations=[type_cast_op], input_columns=\"label\", output_columns='labels')\n", - " # batch dataset\n", - " if is_ascend:\n", - " dataset = dataset.batch(batch_size)\n", - " else:\n", - " dataset = dataset.padded_batch(batch_size, pad_info={'input_ids': (None, tokenizer.pad_token_id),\n", - " 'attention_mask': (None, 0)})\n", - "\n", - " return dataset" + "# 准备数据集(假设数据格式:标签\\t文本)\n", + "def load_dataset(path):\n", + " labels, texts = [], []\n", + " with open(path, 'r', encoding='utf-8') as f:\n", + " for line in f.readlines()[1:]: # 跳过标题行\n", + " if line.strip():\n", + " label, text = line.strip().split('\\t')\n", + " labels.append(int(label))\n", + " texts.append(text)\n", + " return {'label': labels, 'text': texts}\n" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "昇腾NPU环境下暂不支持动态Shape,数据预处理部分采用静态Shape处理:" + "# 加载数据\n", + "train_data = load_dataset(\"data/train.tsv\")\n", + "val_data = load_dataset(\"data/dev.tsv\")\n", + "test_data = load_dataset(\"data/test.tsv\")\n", + "\n", + "# 转换为Hugging Face数据集格式\n", + "train_dataset = Dataset.from_dict(train_data)\n", + "val_dataset = Dataset.from_dict(val_data)\n", + "test_dataset = Dataset.from_dict(test_data)" ] }, { "cell_type": "code", - "execution_count": 7, - "metadata": { - "tags": [] - }, + "execution_count": null, + "metadata": {}, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "70d7820ca2334d3ba52d2b57e7a23918", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0.00/49.0 [00:00\n", + "数据集列名: ['input_ids', 'attention_mask', 'labels']\n", + "数据集特征: {'input_ids': List(Value('int32')), 'attention_mask': List(Value('int8')), 'labels': Value('int32')}\n", + "数据集长度: 9655\n", + "\n", + "前3个样本:\n", + "样本 0: {'input_ids': [101, 872, 4638, 4495, 3189, 1762, 8043, 3299, 8043, 3189, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'labels': 1}\n", + "样本 1: {'input_ids': [101, 1420, 6432, 872, 3221, 671, 702, 3265, 4511, 8024, 3221, 1408, 8043, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'labels': 1}\n", + "样本 2: {'input_ids': [101, 872, 2823, 5756, 4638, 1416, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'labels': 1}\n" ] } ], "source": [ - "%env HF_ENDPOINT=https://hf-mirror.com" + "# 查看数据集信息\n", + "print(\"数据集信息:\")\n", + "print(f\"数据集类型: {type(tokenized_train)}\")\n", + "print(f\"数据集列名: {tokenized_train.column_names}\")\n", + "print(f\"数据集特征: {tokenized_train.features}\")\n", + "print(f\"数据集长度: {len(tokenized_train)}\")\n", + "\n", + "# 查看前3个样本\n", + "print(\"\\n前3个样本:\")\n", + "for i in range(min(3, len(tokenized_train))):\n", + " print(f\"样本 {i}: {tokenized_train[i]}\")" ] }, { @@ -530,38 +356,22 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "tags": [] }, "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "15fc8f5f71ab4c5ea26e9e6b9e5f0743", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0.00/392M [00:00\n", + " \n", + " \n", + " [151/151 02:51, Epoch 1/1]\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
EpochTraining LossValidation LossAccuracy
1No log0.2168330.917593

" + ], "text/plain": [ - " 0%| | 0/34 [00:00" ] }, "metadata": {}, "output_type": "display_data" }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 0.056950367987155914, 'eval_accuracy': 0.9861111111111112, 'eval_runtime': 1.5702, 'eval_samples_per_second': 21.653, 'eval_steps_per_second': 21.653, 'epoch': 4.0}\n", - "{'loss': 0.0568, 'learning_rate': 1.456953642384106e-06, 'epoch': 4.64}\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/34 [00:00=2.2.14 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.4.1)\n", - "Requirement already satisfied: tqdm in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (4.67.1)\n", - "Requirement already satisfied: requests in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.32.3)\n", - "Requirement already satisfied: datasets in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (3.6.0)\n", - "Requirement already satisfied: evaluate in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.4.3)\n", - "Requirement already satisfied: tokenizers==0.19.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.19.1)\n", - "Requirement already satisfied: safetensors in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.3)\n", - "Requirement already satisfied: sentencepiece in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.2.0)\n", - "Requirement already satisfied: regex in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2024.11.6)\n", - "Requirement already satisfied: addict in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.4.0)\n", - "Requirement already satisfied: ml-dtypes in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.1)\n", - "Requirement already satisfied: pyctcdecode in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.0)\n", - "Requirement already satisfied: jieba in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.42.1)\n", - "Requirement already satisfied: pytest==7.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (7.2.0)\n", - "Requirement already satisfied: pillow>=10.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (11.2.1)\n", - "Requirement already satisfied: attrs>=19.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (25.3.0)\n", - "Requirement already satisfied: iniconfig in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (2.1.0)\n", - "Requirement already satisfied: packaging in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (24.2)\n", - "Requirement already satisfied: pluggy<2.0,>=0.12 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (1.5.0)\n", - "Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (1.2.0)\n", - "Requirement already satisfied: tomli>=1.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (2.2.1)\n", - "Requirement already satisfied: huggingface-hub<1.0,>=0.16.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from tokenizers==0.19.1->mindnlp==0.4.0) (0.31.1)\n", - "Requirement already satisfied: filelock in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (3.18.0)\n", - "Requirement already satisfied: fsspec>=2023.5.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (2025.3.0)\n", - "Requirement already satisfied: pyyaml>=5.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (6.0.2)\n", - "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (4.12.2)\n", - "Requirement already satisfied: hf-xet<2.0.0,>=1.1.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (1.1.0)\n", - "Requirement already satisfied: numpy<2.0.0,>=1.20.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.26.4)\n", - "Requirement already satisfied: protobuf>=3.13.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (6.30.2)\n", - "Requirement already satisfied: asttokens>=2.0.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (3.0.0)\n", - "Requirement already satisfied: scipy>=1.5.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.13.1)\n", - "Requirement already satisfied: psutil>=5.6.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (5.9.0)\n", - "Requirement already satisfied: astunparse>=1.6.3 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.6.3)\n", - "Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore>=2.2.14->mindnlp==0.4.0) (0.45.1)\n", - "Requirement already satisfied: six<2.0,>=1.6.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore>=2.2.14->mindnlp==0.4.0) (1.17.0)\n", - "Requirement already satisfied: pyarrow>=15.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (20.0.0)\n", - "Requirement already satisfied: dill<0.3.9,>=0.3.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (0.3.8)\n", - "Requirement already satisfied: pandas in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (2.2.3)\n", - "Requirement already satisfied: xxhash in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (3.5.0)\n", - "Requirement already satisfied: multiprocess<0.70.17 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (0.70.16)\n", - "Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (3.11.18)\n", - "Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (2.6.1)\n", - "Requirement already satisfied: aiosignal>=1.1.2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.3.2)\n", - "Requirement already satisfied: async-timeout<6.0,>=4.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (5.0.1)\n", - "Requirement already satisfied: frozenlist>=1.1.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.6.0)\n", - "Requirement already satisfied: multidict<7.0,>=4.5 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (6.4.3)\n", - "Requirement already satisfied: propcache>=0.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (0.3.1)\n", - "Requirement already satisfied: yarl<2.0,>=1.17.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.20.0)\n", - "Requirement already satisfied: idna>=2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from yarl<2.0,>=1.17.0->aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (3.10)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (3.4.1)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (2.4.0)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (2025.4.26)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2025.2)\n", - "Requirement already satisfied: tzdata>=2022.7 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2025.2)\n", - "Requirement already satisfied: pygtrie<3.0,>=2.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pyctcdecode->mindnlp==0.4.0) (2.5.0)\n", - "Requirement already satisfied: hypothesis<7,>=6.14 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pyctcdecode->mindnlp==0.4.0) (6.131.15)\n", - "Requirement already satisfied: sortedcontainers<3.0.0,>=2.1.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from hypothesis<7,>=6.14->pyctcdecode->mindnlp==0.4.0) (2.4.0)\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n", - "Looking in indexes: https://repo.huaweicloud.com/repository/pypi/simple/\n", - "Requirement already satisfied: pytesseract in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (0.3.13)\n", - "Requirement already satisfied: packaging>=21.3 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytesseract) (24.2)\n", - "Requirement already satisfied: Pillow>=8.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytesseract) (11.2.1)\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n" + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", + " setattr(self, word, getattr(machar, word).flat[0])\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", + " return self._float_to_str(self.smallest_subnormal)\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", + " setattr(self, word, getattr(machar, word).flat[0])\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", + " return self._float_to_str(self.smallest_subnormal)\n", + "[WARNING] ME(64329:281473217238592,MainProcess):2025-11-25-16:57:21.881.000 [mindspore/context.py:1412] For 'context.set_context', the parameter 'pynative_synchronize' will be deprecated and removed in a future version. Please use the api mindspore.runtime.launch_blocking() instead.\n" ] } ], "source": [ - "# install mindnlp\n", - "!pip install mindnlp==0.4.0\n", - "!pip install pytesseract" + "import mindspore\n", + "mindspore.set_context(pynative_synchronize=True) #开启同步设置,方便后续问题定位" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "0ad0c6f0", "metadata": {}, "outputs": [ @@ -295,69 +267,11 @@ "name": "stderr", "output_type": "stream", "text": [ - "[WARNING] GE_ADPT(6108,ffffab724020,python):2025-05-13-12:28:08.673.160 [mindspore/ccsrc/utils/dlopen_macro.h:163] DlsymAscend] Dynamically load symbol aclmdlBundleGetModelId failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so: undefined symbol: aclmdlBundleGetModelId\n", - "[WARNING] GE_ADPT(6108,ffffab724020,python):2025-05-13-12:28:08.673.218 [mindspore/ccsrc/utils/dlopen_macro.h:163] DlsymAscend] Dynamically load symbol aclmdlBundleLoadFromMem failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so: undefined symbol: aclmdlBundleLoadFromMem\n", - "[WARNING] GE_ADPT(6108,ffffab724020,python):2025-05-13-12:28:08.673.244 [mindspore/ccsrc/utils/dlopen_macro.h:163] DlsymAscend] Dynamically load symbol aclmdlBundleUnload failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so: undefined symbol: aclmdlBundleUnload\n", - "[WARNING] GE_ADPT(6108,ffffab724020,python):2025-05-13-12:28:08.673.383 [mindspore/ccsrc/utils/dlopen_macro.h:163] DlsymAscend] Dynamically load symbol aclrtGetMemUceInfo failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so: undefined symbol: aclrtGetMemUceInfo\n", - "[WARNING] GE_ADPT(6108,ffffab724020,python):2025-05-13-12:28:08.673.408 [mindspore/ccsrc/utils/dlopen_macro.h:163] DlsymAscend] Dynamically load symbol aclrtDeviceTaskAbort failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so: undefined symbol: aclrtDeviceTaskAbort\n", - "[WARNING] GE_ADPT(6108,ffffab724020,python):2025-05-13-12:28:08.673.431 [mindspore/ccsrc/utils/dlopen_macro.h:163] DlsymAscend] Dynamically load symbol aclrtMemUceRepair failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so: undefined symbol: aclrtMemUceRepair\n", - "[WARNING] GE_ADPT(6108,ffffab724020,python):2025-05-13-12:28:08.674.937 [mindspore/ccsrc/utils/dlopen_macro.h:163] DlsymAscend] Dynamically load symbol acltdtCleanChannel failed, result = /usr/local/Ascend/ascend-toolkit/latest/lib64/libacl_tdt_channel.so: undefined symbol: acltdtCleanChannel\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", - " setattr(self, word, getattr(machar, word).flat[0])\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", - " return self._float_to_str(self.smallest_subnormal)\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", - " setattr(self, word, getattr(machar, word).flat[0])\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", - " return self._float_to_str(self.smallest_subnormal)\n", - "Building prefix dict from the default dictionary ...\n", - "Loading model from cache /tmp/jieba.cache\n", - "Loading model cost 1.042 seconds.\n", - "Prefix dict has been built successfully.\n" + "/usr/local/python3.10.14/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "Modular Diffusers is currently an experimental feature under active development. The API is subject to breaking changes in future releases.\n" ] }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6421e22f124345fe924aa445c22403a2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "0.00B [00:00, ?B/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "30735811eedd4f2ea525d38c702c177f", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "0.00B [00:00, ?B/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2e931b32674045c599aeb89a2088f180", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0.00/334 [00:00 \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n", - "\u001b[31mERROR: No matching distribution found for install\u001b[0m\u001b[31m\n", - "\u001b[0m" - ] - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "!pip install pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.5.0/MindSpore/unified/aarch64/mindspore-2.5.0-cp39-cp39-linux_aarch64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple" + "## 环境配置\n", + "\n", + "本案例的运行环境为:\n", + "\n", + "| Python | MindSpore | MindSpore NLP |\n", + "| :----- | :-------- | :------------ |\n", + "| 3.10 | 2.7.0 | 0.5.1 |\n", + "\n", + "如果你在如[昇思大模型平台](https://xihe.mindspore.cn/training-projects)、[华为云ModelArts](https://www.huaweicloud.com/product/modelarts.html)、[启智社区](https://openi.pcl.ac.cn/)等算力平台的Jupyter在线编程环境中运行本案例,可取消如下代码的注释,进行依赖库安装:" ] }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://repo.huaweicloud.com/repository/pypi/simple/\n", - "Requirement already satisfied: mindnlp==0.4.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (0.4.0)\n", - "Requirement already satisfied: mindspore>=2.2.14 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.4.1)\n", - "Requirement already satisfied: tqdm in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (4.67.1)\n", - "Requirement already satisfied: requests in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.32.3)\n", - "Requirement already satisfied: datasets in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (3.6.0)\n", - "Requirement already satisfied: evaluate in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.4.3)\n", - "Requirement already satisfied: tokenizers==0.19.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.19.1)\n", - "Requirement already satisfied: safetensors in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.3)\n", - "Requirement already satisfied: sentencepiece in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.2.0)\n", - "Requirement already satisfied: regex in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2024.11.6)\n", - "Requirement already satisfied: addict in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.4.0)\n", - "Requirement already satisfied: ml-dtypes in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.1)\n", - "Requirement already satisfied: pyctcdecode in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.0)\n", - "Requirement already satisfied: jieba in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.42.1)\n", - "Requirement already satisfied: pytest==7.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (7.2.0)\n", - "Requirement already satisfied: pillow>=10.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindnlp==0.4.0) (11.1.0)\n", - "Requirement already satisfied: attrs>=19.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (25.3.0)\n", - "Requirement already satisfied: iniconfig in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (2.1.0)\n", - "Requirement already satisfied: packaging in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (24.2)\n", - "Requirement already satisfied: pluggy<2.0,>=0.12 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (1.5.0)\n", - "Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (1.2.0)\n", - "Requirement already satisfied: tomli>=1.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (2.2.1)\n", - "Requirement already satisfied: huggingface-hub<1.0,>=0.16.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from tokenizers==0.19.1->mindnlp==0.4.0) (0.32.3)\n", - "Requirement already satisfied: numpy<2.0.0,>=1.20.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.26.4)\n", - "Requirement already satisfied: protobuf>=3.13.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (6.30.2)\n", - "Requirement already satisfied: asttokens>=2.0.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (2.0.5)\n", - "Requirement already satisfied: scipy>=1.5.4 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.13.1)\n", - "Requirement already satisfied: psutil>=5.6.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (5.9.0)\n", - "Requirement already satisfied: astunparse>=1.6.3 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.6.3)\n", - "Requirement already satisfied: filelock in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (3.18.0)\n", - "Requirement already satisfied: pyarrow>=15.0.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (20.0.0)\n", - "Requirement already satisfied: dill<0.3.9,>=0.3.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (0.3.8)\n", - "Requirement already satisfied: pandas in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (2.2.3)\n", - "Requirement already satisfied: xxhash in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (3.5.0)\n", - "Requirement already satisfied: multiprocess<0.70.17 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (0.70.16)\n", - "Requirement already satisfied: fsspec<=2025.3.0,>=2023.1.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (2025.3.0)\n", - "Requirement already satisfied: pyyaml>=5.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (6.0.2)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (3.4.1)\n", - "Requirement already satisfied: idna<4,>=2.5 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (3.10)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (2.3.0)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (2025.1.31)\n", - "Requirement already satisfied: pygtrie<3.0,>=2.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pyctcdecode->mindnlp==0.4.0) (2.5.0)\n", - "Requirement already satisfied: hypothesis<7,>=6.14 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pyctcdecode->mindnlp==0.4.0) (6.133.2)\n", - "Requirement already satisfied: six in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from asttokens>=2.0.4->mindspore>=2.2.14->mindnlp==0.4.0) (1.16.0)\n", - "Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore>=2.2.14->mindnlp==0.4.0) (0.45.1)\n", - "Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (3.12.7)\n", - "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (4.12.2)\n", - "Requirement already satisfied: hf-xet<2.0.0,>=1.1.2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (1.1.2)\n", - "Requirement already satisfied: sortedcontainers<3.0.0,>=2.1.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from hypothesis<7,>=6.14->pyctcdecode->mindnlp==0.4.0) (2.4.0)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2025.2)\n", - "Requirement already satisfied: tzdata>=2022.7 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2025.2)\n", - "Requirement already satisfied: aiohappyeyeballs>=2.5.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (2.6.1)\n", - "Requirement already satisfied: aiosignal>=1.1.2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.3.2)\n", - "Requirement already satisfied: async-timeout<6.0,>=4.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (5.0.1)\n", - "Requirement already satisfied: frozenlist>=1.1.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.6.0)\n", - "Requirement already satisfied: multidict<7.0,>=4.5 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (6.4.4)\n", - "Requirement already satisfied: propcache>=0.2.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (0.3.1)\n", - "Requirement already satisfied: yarl<2.0,>=1.17.0 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets->mindnlp==0.4.0) (1.20.0)\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "!pip install mindnlp==0.4.0" + "# !pip install mindspore==2.7.0 mindnlp==0.5.1" ] }, { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://repo.huaweicloud.com/repository/pypi/simple/\n", - "Requirement already satisfied: jieba in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (0.42.1)\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.1.1\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n" - ] - } - ], + "cell_type": "markdown", + "metadata": {}, "source": [ - "!pip install jieba" + "其他场景可参考[MindSpore安装指南](https://www.mindspore.cn/install)与[MindSpore NLP安装指南](https://github.com/mindspore-lab/mindnlp?tab=readme-ov-file#installation)进行环境搭建。" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 安装依赖" ] }, { "cell_type": "code", - "execution_count": 4, - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "env: HF_ENDPOINT=https://hf-mirror.com\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ - "%env HF_ENDPOINT=https://hf-mirror.com" + "!pip install jieba" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "tags": [] }, @@ -170,128 +79,165 @@ "name": "stderr", "output_type": "stream", "text": [ - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:02.546.745 [mindspore/run_check/_check_version.py:329] MindSpore version 2.4.1 and Ascend AI software package (Ascend Data Center Solution)version 7.6 does not match, the version of software package expect one of ['7.3', '7.5']. Please refer to the match info on: https://www.mindspore.cn/install\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", " setattr(self, word, getattr(machar, word).flat[0])\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", " return self._float_to_str(self.smallest_subnormal)\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", " setattr(self, word, getattr(machar, word).flat[0])\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", " return self._float_to_str(self.smallest_subnormal)\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:04.810.368 [mindspore/run_check/_check_version.py:347] MindSpore version 2.4.1 and \"te\" wheel package version 7.6 does not match. For details, refer to the installation guidelines: https://www.mindspore.cn/install\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:04.812.087 [mindspore/run_check/_check_version.py:354] MindSpore version 2.4.1 and \"hccl\" wheel package version 7.6 does not match. For details, refer to the installation guidelines: https://www.mindspore.cn/install\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:04.812.731 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 3\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:05.814.363 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 2\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:06.816.061 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 1\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:09.473.235 [mindspore/run_check/_check_version.py:329] MindSpore version 2.4.1 and Ascend AI software package (Ascend Data Center Solution)version 7.6 does not match, the version of software package expect one of ['7.3', '7.5']. Please refer to the match info on: https://www.mindspore.cn/install\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:09.474.964 [mindspore/run_check/_check_version.py:347] MindSpore version 2.4.1 and \"te\" wheel package version 7.6 does not match. For details, refer to the installation guidelines: https://www.mindspore.cn/install\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:09.475.567 [mindspore/run_check/_check_version.py:354] MindSpore version 2.4.1 and \"hccl\" wheel package version 7.6 does not match. For details, refer to the installation guidelines: https://www.mindspore.cn/install\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:09.476.234 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 3\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:10.477.850 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 2\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:11.478.869 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 1\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:12.480.761 [mindspore/run_check/_check_version.py:329] MindSpore version 2.4.1 and Ascend AI software package (Ascend Data Center Solution)version 7.6 does not match, the version of software package expect one of ['7.3', '7.5']. Please refer to the match info on: https://www.mindspore.cn/install\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:12.482.175 [mindspore/run_check/_check_version.py:347] MindSpore version 2.4.1 and \"te\" wheel package version 7.6 does not match. For details, refer to the installation guidelines: https://www.mindspore.cn/install\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:12.482.802 [mindspore/run_check/_check_version.py:354] MindSpore version 2.4.1 and \"hccl\" wheel package version 7.6 does not match. For details, refer to the installation guidelines: https://www.mindspore.cn/install\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:12.483.400 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 3\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:13.485.045 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 2\n", - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:14.486.640 [mindspore/run_check/_check_version.py:368] Please pay attention to the above warning, countdown: 1\n", - "Building prefix dict from the default dictionary ...\n", - "Loading model from cache /tmp/jieba.cache\n", - "Loading model cost 1.075 seconds.\n", - "Prefix dict has been built successfully.\n" + "/usr/local/python3.10.14/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "Modular Diffusers is currently an experimental feature under active development. The API is subject to breaking changes in future releases.\n", + "[WARNING] ME(13257:281473667298880,MainProcess):2025-11-25-14:35:28.604.000 [mindspore/context.py:1412] For 'context.set_context', the parameter 'device_target' will be deprecated and removed in a future version. Please use the api mindspore.set_device() instead.\n", + "[WARNING] ME(13257:281473667298880,MainProcess):2025-11-25-14:35:28.606.000 [mindspore/context.py:1412] For 'context.set_context', the parameter 'device_id' will be deprecated and removed in a future version. Please use the api mindspore.set_device() instead.\n" ] } ], "source": [ "import os\n", - "\n", + "import mindnlp\n", "import mindspore\n", "from mindspore.dataset import text, GeneratorDataset, transforms\n", "from mindspore import nn\n", - "mindspore.set_context(device_target='Ascend', device_id=0)\n", "\n", - "from mindnlp.dataset import load_dataset\n", + "from datasets import load_dataset\n", "\n", - "from mindnlp.engine.trainer import Trainer" + "from transformers import Trainer" ] }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "tags": [] - }, - "outputs": [], + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[WARNING] ME(13257:281473667298880,MainProcess):2025-11-25-14:35:30.889.000 [mindspore/context.py:1412] For 'context.set_context', the parameter 'pynative_synchronize' will be deprecated and removed in a future version. Please use the api mindspore.runtime.launch_blocking() instead.\n" + ] + } + ], + "source": [ + "mindspore.set_context(pynative_synchronize=True) #开启同步设置,方便后续定位" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "imdb_ds = load_dataset('imdb', split=['train', 'test'])\n", - "imdb_train = imdb_ds['train']\n", - "imdb_test = imdb_ds['test']\n", - "# 为加快运行速度只选取一部分训练\n", - "imdb_train, _ = imdb_train.split([0.1, 0.9])\n", - "imdb_test, _ = imdb_test.split([0.1, 0.9])" + "## 数据加载与预处理\n", + "\n", + "### 数据集加载" ] }, { "cell_type": "code", - "execution_count": 7, - "metadata": { - "tags": [] - }, + "execution_count": 5, + "metadata": {}, "outputs": [ { - "data": { - "text/plain": [ - "2500" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" + "name": "stderr", + "output_type": "stream", + "text": [ + "Generating train split: 100%|██████████| 25000/25000 [00:00<00:00, 141645.48 examples/s]\n", + "Generating test split: 100%|██████████| 25000/25000 [00:00<00:00, 143740.58 examples/s]\n", + "Generating unsupervised split: 100%|██████████| 50000/50000 [00:00<00:00, 153439.56 examples/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "采样后训练集大小: 2500\n", + "采样后测试集大小: 2500\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] } ], "source": [ - "imdb_train.get_dataset_size()" + "# 在加载时直接采样10%的数据\n", + "imdb_ds = load_dataset('imdb', split=['train[:10%]', 'test[:10%]'])\n", + "imdb_train = imdb_ds[0] # 10%的训练数据\n", + "imdb_test = imdb_ds[1] # 10%的测试数据\n", + "\n", + "print(f\"采样后训练集大小: {len(imdb_train)}\")\n", + "print(f\"采样后测试集大小: {len(imdb_test)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 数据预处理" ] }, { "cell_type": "code", - "execution_count": 8, - "metadata": { - "tags": [] - }, + "execution_count": 6, + "metadata": {}, "outputs": [], "source": [ - "import numpy as np\n", + "from datasets import Dataset\n", + "from torch.utils.data import DataLoader\n", + "from transformers import AutoTokenizer, DataCollatorWithPadding\n", "\n", "def process_dataset(dataset, tokenizer, max_seq_len=512, batch_size=4, shuffle=False):\n", - " is_ascend = mindspore.get_context('device_target') == 'Ascend'\n", - " def tokenize(text):\n", - " if is_ascend:\n", - " tokenized = tokenizer(text, padding='max_length', truncation=True, max_length=max_seq_len)\n", - " else:\n", - " tokenized = tokenizer(text, truncation=True, max_length=max_seq_len)\n", - " return tokenized['input_ids'], tokenized['attention_mask']\n", - "\n", + " \n", + " def tokenize_function(examples):\n", + " return tokenizer(\n", + " examples['text'],\n", + " truncation=True,\n", + " max_length=max_seq_len,\n", + " return_tensors=None\n", + " )\n", + " \n", + " # 如果 shuffle 为 True,先打乱数据集\n", " if shuffle:\n", - " dataset = dataset.shuffle(batch_size)\n", - "\n", - " # map dataset\n", - " dataset = dataset.map(operations=[tokenize], input_columns=\"text\", output_columns=['input_ids', 'attention_mask'])\n", - " dataset = dataset.map(operations=transforms.TypeCast(mindspore.int32), input_columns=\"label\", output_columns=\"labels\")\n", - " # batch dataset\n", - " if is_ascend:\n", - " dataset = dataset.batch(batch_size)\n", - " else:\n", - " dataset = dataset.padded_batch(batch_size, pad_info={'input_ids': (None, tokenizer.pad_token_id),\n", - " 'attention_mask': (None, 0)})\n", - "\n", - " return dataset" + " dataset = dataset.shuffle(seed=42)\n", + " \n", + " # 应用 tokenize 函数\n", + " dataset = dataset.map(\n", + " tokenize_function,\n", + " batched=True,\n", + " remove_columns=['text']\n", + " )\n", + " \n", + " # 重命名标签列\n", + " if 'label' in dataset.column_names:\n", + " dataset = dataset.rename_column('label', 'labels')\n", + " \n", + " # 设置格式\n", + " dataset.set_format(type='torch')\n", + " \n", + " # 使用 DataCollatorWithPadding 处理所有 padding\n", + " data_collator = DataCollatorWithPadding(\n", + " tokenizer=tokenizer,\n", + " padding='longest' # 动态 padding\n", + " )\n", + " \n", + " dataloader = DataLoader(\n", + " dataset,\n", + " batch_size=batch_size,\n", + " shuffle=shuffle,\n", + " collate_fn=data_collator,\n", + " drop_last=False\n", + " )\n", + " \n", + " return dataloader" ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "metadata": { "tags": [] }, @@ -300,14 +246,12 @@ "name": "stderr", "output_type": "stream", "text": [ - "ftfy or spacy is not installed using BERT BasicTokenizer instead of SpaCy & ftfy.\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/mindnlp/transformers/tokenization_utils_base.py:1526: FutureWarning: `clean_up_tokenization_spaces` was not set. It will be set to `True` by default. This behavior will be depracted, and will be then set to `False` by default. \n", - " warnings.warn(\n" + "ftfy or spacy is not installed using BERT BasicTokenizer instead of SpaCy & ftfy.\n" ] } ], "source": [ - "from mindnlp.transformers import OpenAIGPTTokenizer\n", + "from transformers import OpenAIGPTTokenizer\n", "# tokenizer\n", "gpt_tokenizer = OpenAIGPTTokenizer.from_pretrained('openai-gpt')\n", "\n", @@ -322,67 +266,147 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": { - "tags": [] - }, + "execution_count": 8, + "metadata": {}, "outputs": [ { - "name": "stderr", + "name": "stdout", "output_type": "stream", "text": [ - "[WARNING] ME(250:281472944873504,MainProcess):2025-06-03-14:44:51.758.363 [mindspore/dataset/engine/datasets.py:2534] Dataset is shuffled before split.\n" + "训练集大小: 1750\n", + "验证集大小: 750\n" ] } ], "source": [ "# split train dataset into train and valid datasets\n", - "imdb_train, imdb_val = imdb_train.split([0.7, 0.3])" + "dataset_split = imdb_train.train_test_split(test_size=0.3, seed=42)\n", + "imdb_train = dataset_split['train']\n", + "imdb_val = dataset_split['test']\n", + "\n", + "print(f\"训练集大小: {len(imdb_train)}\")\n", + "print(f\"验证集大小: {len(imdb_val)}\")" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Map: 100%|██████████| 1750/1750 [00:15<00:00, 111.91 examples/s]\n", + "Map: 100%|██████████| 750/750 [00:07<00:00, 104.21 examples/s]\n", + "Map: 100%|██████████| 2500/2500 [00:21<00:00, 113.66 examples/s]\n" + ] + } + ], "source": [ "dataset_train = process_dataset(imdb_train, gpt_tokenizer, shuffle=True)\n", "dataset_val = process_dataset(imdb_val, gpt_tokenizer)\n", "dataset_test = process_dataset(imdb_test, gpt_tokenizer)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 查看数据信息" + ] + }, { "cell_type": "code", - "execution_count": 12, - "metadata": { - "tags": [] - }, + "execution_count": 10, + "metadata": {}, "outputs": [ { - "data": { - "text/plain": [ - "[Tensor(shape=[4, 512], dtype=Int64, value=\n", - " [[ 500, 246, 1322 ... 40480, 40480, 40480],\n", - " [ 1473, 980, 246 ... 40480, 40480, 40480],\n", - " [39516, 498, 481 ... 40480, 40480, 40480],\n", - " [ 616, 544, 808 ... 40480, 40480, 40480]]),\n", - " Tensor(shape=[4, 512], dtype=Int64, value=\n", - " [[1, 1, 1 ... 0, 0, 0],\n", - " [1, 1, 1 ... 0, 0, 0],\n", - " [1, 1, 1 ... 0, 0, 0],\n", - " [1, 1, 1 ... 0, 0, 0]]),\n", - " Tensor(shape=[4], dtype=Int32, value= [1, 1, 0, 0])]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "检查训练数据:\n", + "[MS_ALLOC_CONF]Runtime config: enable_vmm:True vmm_align_size:2MB\n", + "Batch 0:\n", + " Input IDs shape: mindtorch.Size([4, 268])\n", + " Attention mask shape: mindtorch.Size([4, 268])\n", + " Labels: [0 0 0 0]\n", + "Batch 1:\n", + " Input IDs shape: mindtorch.Size([4, 512])\n", + " Attention mask shape: mindtorch.Size([4, 512])\n", + " Labels: [0 0 0 0]\n", + "Batch 2:\n", + " Input IDs shape: mindtorch.Size([4, 512])\n", + " Attention mask shape: mindtorch.Size([4, 512])\n", + " Labels: [0 0 0 0]\n" + ] } ], "source": [ - "next(dataset_train.create_tuple_iterator())" + "# 检查数据\n", + "print(\"检查训练数据:\")\n", + "for i, batch in enumerate(dataset_train):\n", + " print(f\"Batch {i}:\")\n", + " print(f\" Input IDs shape: {batch['input_ids'].shape}\")\n", + " print(f\" Attention mask shape: {batch['attention_mask'].shape}\")\n", + " print(f\" Labels: {batch['labels']}\")\n", + " if i >= 2: # 只看前3个batch\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 现有的 process_dataset 函数返回 DataLoader,可以这样提取 Dataset\n", + "def extract_dataset_from_dataloader(dataloader):\n", + " \"\"\"从 DataLoader 中提取原始的 Dataset\"\"\"\n", + " return dataloader.dataset\n", + "\n", + "# 使用示例\n", + "dataset_train = extract_dataset_from_dataloader(dataset_train)\n", + "dataset_val = extract_dataset_from_dataloader(dataset_val)\n", + "dataset_test = extract_dataset_from_dataloader(dataset_test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 加载评估指标" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Looking in indexes: http://pip.modelarts.private.com:8888/repository/pypi/simple\n", + "Collecting scikit-learn\n", + " Downloading http://pip.modelarts.private.com:8888/repository/pypi/packages/scikit-learn/1.7.2/scikit_learn-1.7.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (9.5 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m9.5/9.5 MB\u001b[0m \u001b[31m133.8 MB/s\u001b[0m \u001b[33m0:00:00\u001b[0m\n", + "\u001b[?25hRequirement already satisfied: numpy>=1.22.0 in /usr/local/python3.10.14/lib/python3.10/site-packages (from scikit-learn) (1.26.4)\n", + "Requirement already satisfied: scipy>=1.8.0 in /usr/local/python3.10.14/lib/python3.10/site-packages (from scikit-learn) (1.10.1)\n", + "Collecting joblib>=1.2.0 (from scikit-learn)\n", + " Downloading http://pip.modelarts.private.com:8888/repository/pypi/packages/joblib/1.5.2/joblib-1.5.2-py3-none-any.whl (308 kB)\n", + "Collecting threadpoolctl>=3.1.0 (from scikit-learn)\n", + " Downloading http://pip.modelarts.private.com:8888/repository/pypi/packages/threadpoolctl/3.6.0/threadpoolctl-3.6.0-py3-none-any.whl (18 kB)\n", + "Installing collected packages: threadpoolctl, joblib, scikit-learn\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3/3\u001b[0m [scikit-learn][0m [scikit-learn]\n", + "\u001b[1A\u001b[2KSuccessfully installed joblib-1.5.2 scikit-learn-1.7.2 threadpoolctl-3.6.0\n" + ] + } + ], + "source": [ + "!pip install scikit-learn # 安装依赖" ] }, { @@ -395,7 +419,7 @@ "source": [ "import evaluate\n", "import numpy as np\n", - "from mindnlp.engine.utils import EvalPrediction\n", + "from transformers import EvalPrediction\n", "\n", "metric = evaluate.load(\"accuracy\")\n", "\n", @@ -405,59 +429,54 @@ " return metric.compute(predictions=predictions, references=labels)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 模型加载" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from transformers import OpenAIGPTForSequenceClassification, TrainingArguments\n", + "\n", + "\n", + "model = OpenAIGPTForSequenceClassification.from_pretrained('openai-gpt', num_labels=2)\n", + "model.config.pad_token_id = gpt_tokenizer.pad_token_id\n", + "model.resize_token_embeddings(model.config.vocab_size + 3)" + ] + }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "tags": [] }, "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "94d1b9d8276a4040a27030d34c8d44e2", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0.00/457M [00:00 type is zero.\n", - " setattr(self, word, getattr(machar, word).flat[0])\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", - " return self._float_to_str(self.smallest_subnormal)\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", - " setattr(self, word, getattr(machar, word).flat[0])\n", - "/home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", - " return self._float_to_str(self.smallest_subnormal)\n", - "Building prefix dict from the default dictionary ...\n", - "Dumping model to file cache /tmp/jieba.cache\n", - "Loading model cost 1.022 seconds.\n", - "Prefix dict has been built successfully.\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ef6c147f60104856b73d7926b515b038", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0.00/6.01k [00:00 此为在线运行平台配置python3.9的指南,如在其他环境平台运行案例,请根据实际情况修改如下代码" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "第一步:设置python版本为3.9.0" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%%capture captured_output\n", - "!/home/ma-user/anaconda3/bin/conda create -n python-3.9.0 python=3.9.0 -y --override-channels --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main\n", - "!/home/ma-user/anaconda3/envs/python-3.9.0/bin/pip install ipykernel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "import os\n", - "\n", - "data = {\n", - " \"display_name\": \"python-3.9.0\",\n", - " \"env\": {\n", - " \"PATH\": \"/home/ma-user/anaconda3/envs/python-3.9.0/bin:/home/ma-user/anaconda3/envs/python-3.7.10/bin:/modelarts/authoring/notebook-conda/bin:/opt/conda/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/ma-user/modelarts/ma-cli/bin:/home/ma-user/modelarts/ma-cli/bin\"\n", - " },\n", - " \"language\": \"python\",\n", - " \"argv\": [\n", - " \"/home/ma-user/anaconda3/envs/python-3.9.0/bin/python\",\n", - " \"-m\",\n", - " \"ipykernel\",\n", - " \"-f\",\n", - " \"{connection_file}\"\n", - " ]\n", - "}\n", - "\n", - "if not os.path.exists(\"/home/ma-user/anaconda3/share/jupyter/kernels/python-3.9.0/\"):\n", - " os.mkdir(\"/home/ma-user/anaconda3/share/jupyter/kernels/python-3.9.0/\")\n", - "\n", - "with open('/home/ma-user/anaconda3/share/jupyter/kernels/python-3.9.0/kernel.json', 'w') as f:\n", - " json.dump(data, f, indent=4)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### 注:以上代码运行完成后,需要重新设置kernel为python-3.9.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "

" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "第二步:安装MindSpore框架和MindNLP套件" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "mindspore官网提供了不同的mindspore版本,可以根据自己的操作系统和Python版本,安装不同版本的mindspore\n", - "\n", - "\n", - "https://www.mindspore.cn/install" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://mirrors.aliyun.com/pypi/simple/\n", - "Collecting mindspore==2.5.0\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/23/22/dff0f1bef6c0846a97271ae5d39ca187914f39562f9e3f6787041dea1a97/mindspore-2.5.0-cp39-cp39-manylinux1_x86_64.whl (958.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m958.4/958.4 MB\u001b[0m \u001b[31m9.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:03\u001b[0m\n", - "\u001b[?25hCollecting numpy<2.0.0,>=1.20.0 (from mindspore==2.5.0)\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/54/30/c2a907b9443cf42b90c17ad10c1e8fa801975f01cb9764f3f8eb8aea638b/numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (18.2 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m18.2/18.2 MB\u001b[0m \u001b[31m16.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hCollecting protobuf>=3.13.0 (from mindspore==2.5.0)\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/28/50/1925de813499546bc8ab3ae857e3ec84efe7d2f19b34529d0c7c3d02d11d/protobuf-6.30.2-cp39-abi3-manylinux2014_x86_64.whl (316 kB)\n", - "Requirement already satisfied: asttokens>=2.0.4 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore==2.5.0) (3.0.0)\n", - "Collecting pillow>=6.2.0 (from mindspore==2.5.0)\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/f6/46/0bd0ca03d9d1164a7fa33d285ef6d1c438e963d0c8770e4c5b3737ef5abe/pillow-11.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.4/4.4 MB\u001b[0m \u001b[31m14.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hCollecting scipy>=1.5.4 (from mindspore==2.5.0)\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/35/f5/d0ad1a96f80962ba65e2ce1de6a1e59edecd1f0a7b55990ed208848012e0/scipy-1.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (38.6 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m38.6/38.6 MB\u001b[0m \u001b[31m16.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: packaging>=20.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore==2.5.0) (24.2)\n", - "Requirement already satisfied: psutil>=5.6.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore==2.5.0) (5.9.1)\n", - "Collecting astunparse>=1.6.3 (from mindspore==2.5.0)\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/2b/03/13dde6512ad7b4557eb792fbcf0c653af6076b81e5941d36ec61f7ce6028/astunparse-1.6.3-py2.py3-none-any.whl (12 kB)\n", - "Collecting safetensors>=0.4.0 (from mindspore==2.5.0)\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/a6/f8/dae3421624fcc87a89d42e1898a798bc7ff72c61f38973a65d60df8f124c/safetensors-0.5.3-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (471 kB)\n", - "Collecting dill>=0.3.7 (from mindspore==2.5.0)\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl (119 kB)\n", - "Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore==2.5.0) (0.45.1)\n", - "Requirement already satisfied: six<2.0,>=1.6.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore==2.5.0) (1.17.0)\n", - "Installing collected packages: safetensors, protobuf, pillow, numpy, dill, astunparse, scipy, mindspore\n", - "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n", - "auto-tune 0.1.0 requires te, which is not installed.\n", - "schedule-search 0.0.1 requires absl-py, which is not installed.\u001b[0m\u001b[31m\n", - "\u001b[0mSuccessfully installed astunparse-1.6.3 dill-0.3.9 mindspore-2.5.0 numpy-1.26.4 pillow-11.1.0 protobuf-6.30.2 safetensors-0.5.3 scipy-1.13.1\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.5.0/MindSpore/unified/x86_64/mindspore-2.5.0-cp39-cp39-linux_x86_64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "注意,这里如果通过pip安装mindnlp的话,需要参考链接对mindnlp/core/nn/modules/module.py进行Files changed所示的修改,确保loss正确下降,链接教程:https://github.com/mindspore-lab/mindnlp/pull/2007/files\n", - "可以通过git clone下载最新的mindnlp,然后将下载的最新的mindnlp版本替换到你环境中安装mindnlp的位置,一般是/home/user/miniconda3/envs/yourenv/lib/python3.9/site-packages" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://mirrors.aliyun.com/pypi/simple\n", - "Collecting mindnlp==0.4.0\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/0f/a8/5a072852d28a51417b5e330b32e6ae5f26b491ef01a15ba968e77f785e69/mindnlp-0.4.0-py3-none-any.whl (8.4 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m8.4/8.4 MB\u001b[0m \u001b[31m4.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m0m\n", - "\u001b[?25hRequirement already satisfied: mindspore>=2.2.14 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.5.0)\n", - "Requirement already satisfied: tqdm in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (4.67.1)\n", - "Requirement already satisfied: requests in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.32.3)\n", - "Requirement already satisfied: datasets in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (3.5.0)\n", - "Requirement already satisfied: evaluate in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.4.3)\n", - "Requirement already satisfied: tokenizers==0.19.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.19.1)\n", - "Requirement already satisfied: safetensors in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.3)\n", - "Requirement already satisfied: sentencepiece in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.2.0)\n", - "Requirement already satisfied: regex in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (2024.11.6)\n", - "Requirement already satisfied: addict in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (2.4.0)\n", - "Requirement already satisfied: ml-dtypes in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.1)\n", - "Requirement already satisfied: pyctcdecode in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (0.5.0)\n", - "Collecting jieba (from mindnlp==0.4.0)\n", - " Downloading https://mirrors.aliyun.com/pypi/packages/c6/cb/18eeb235f833b726522d7ebed54f2278ce28ba9438e3135ab0278d9792a2/jieba-0.42.1.tar.gz (19.2 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m19.2/19.2 MB\u001b[0m \u001b[31m15.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25h Preparing metadata (setup.py) ... \u001b[?25ldone\n", - "\u001b[?25hRequirement already satisfied: pytest==7.2.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (7.2.0)\n", - "Requirement already satisfied: pillow>=10.0.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindnlp==0.4.0) (11.1.0)\n", - "Requirement already satisfied: attrs>=19.2.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (24.3.0)\n", - "Requirement already satisfied: iniconfig in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (2.1.0)\n", - "Requirement already satisfied: packaging in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (24.2)\n", - "Requirement already satisfied: pluggy<2.0,>=0.12 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (1.5.0)\n", - "Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (1.2.2)\n", - "Requirement already satisfied: tomli>=1.0.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pytest==7.2.0->mindnlp==0.4.0) (2.0.1)\n", - "Requirement already satisfied: huggingface-hub<1.0,>=0.16.4 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from tokenizers==0.19.1->mindnlp==0.4.0) (0.30.2)\n", - "Requirement already satisfied: numpy<2.0.0,>=1.20.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.26.4)\n", - "Requirement already satisfied: protobuf>=3.13.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (6.30.2)\n", - "Requirement already satisfied: asttokens>=2.0.4 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (3.0.0)\n", - "Requirement already satisfied: scipy>=1.5.4 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.13.1)\n", - "Requirement already satisfied: psutil>=5.6.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (5.9.1)\n", - "Requirement already satisfied: astunparse>=1.6.3 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (1.6.3)\n", - "Requirement already satisfied: dill>=0.3.7 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from mindspore>=2.2.14->mindnlp==0.4.0) (0.3.8)\n", - "Requirement already satisfied: filelock in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (3.18.0)\n", - "Requirement already satisfied: pyarrow>=15.0.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (19.0.1)\n", - "Requirement already satisfied: pandas in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (2.2.3)\n", - "Requirement already satisfied: xxhash in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (3.5.0)\n", - "Requirement already satisfied: multiprocess<0.70.17 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (0.70.16)\n", - "Requirement already satisfied: fsspec<=2024.12.0,>=2023.1.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from fsspec[http]<=2024.12.0,>=2023.1.0->datasets->mindnlp==0.4.0) (2024.12.0)\n", - "Requirement already satisfied: aiohttp in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (3.11.16)\n", - "Requirement already satisfied: pyyaml>=5.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from datasets->mindnlp==0.4.0) (6.0.2)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (3.3.2)\n", - "Requirement already satisfied: idna<4,>=2.5 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (3.7)\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (2.3.0)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from requests->mindnlp==0.4.0) (2025.1.31)\n", - "Requirement already satisfied: pygtrie<3.0,>=2.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pyctcdecode->mindnlp==0.4.0) (2.5.0)\n", - "Requirement already satisfied: hypothesis<7,>=6.14 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pyctcdecode->mindnlp==0.4.0) (6.130.13)\n", - "Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore>=2.2.14->mindnlp==0.4.0) (0.45.1)\n", - "Requirement already satisfied: six<2.0,>=1.6.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore>=2.2.14->mindnlp==0.4.0) (1.17.0)\n", - "Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp==0.4.0) (2.6.1)\n", - "Requirement already satisfied: aiosignal>=1.1.2 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp==0.4.0) (1.3.2)\n", - "Requirement already satisfied: async-timeout<6.0,>=4.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp==0.4.0) (5.0.1)\n", - "Requirement already satisfied: frozenlist>=1.1.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp==0.4.0) (1.5.0)\n", - "Requirement already satisfied: multidict<7.0,>=4.5 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp==0.4.0) (6.4.2)\n", - "Requirement already satisfied: propcache>=0.2.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp==0.4.0) (0.3.1)\n", - "Requirement already satisfied: yarl<2.0,>=1.17.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from aiohttp->datasets->mindnlp==0.4.0) (1.19.0)\n", - "Requirement already satisfied: typing-extensions>=3.7.4.3 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers==0.19.1->mindnlp==0.4.0) (4.13.1)\n", - "Requirement already satisfied: sortedcontainers<3.0.0,>=2.1.0 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from hypothesis<7,>=6.14->pyctcdecode->mindnlp==0.4.0) (2.4.0)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2.9.0.post0)\n", - "Requirement already satisfied: pytz>=2020.1 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2025.2)\n", - "Requirement already satisfied: tzdata>=2022.7 in /home/jiangna1/miniconda3/envs/llama39/lib/python3.9/site-packages (from pandas->datasets->mindnlp==0.4.0) (2025.2)\n", - "Building wheels for collected packages: jieba\n", - " Building wheel for jieba (setup.py) ... \u001b[?25ldone\n", - "\u001b[?25h Created wheel for jieba: filename=jieba-0.42.1-py3-none-any.whl size=19314508 sha256=30064bba508d12a9c2c545bdec7e271f61d5a83e9fdd53298a82e74659e1fd26\n", - " Stored in directory: /home/jiangna1/.cache/pip/wheels/95/ef/7c/d8b3108835edfa15487417c5bddff166482b195d8090117ac5\n", - "Successfully built jieba\n", - "Installing collected packages: jieba, mindnlp\n", - "Successfully installed jieba-0.42.1 mindnlp-0.4.0\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install mindnlp==0.4.0 -i https://mirrors.aliyun.com/pypi/simple\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## LLaMA微调推理全流程" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# LLaMA介绍" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "LLaMA(Large Language Model Meta AI)是由Meta(前Facebook)推出的一系列开源大规模语言模型,意味着大模型应用进入了“免费时代”,初创公司也能够以低廉的价格来创建类似ChatGPT这样的聊天机器人。 LLaMA 专注于自然语言处理任务,其结构基于Transformer架构,但是进行了改进,比如引入更高效的注意力机制和更紧凑的模型设计,例如使用SwiGLU激活函数 使用RoPE位置编码等。\n", - "\n", - "LLaMA的模型参数规模设计更为精细,以更少的参数实现了与更大模型相当的性能。例如,LLaMA-7B模型的性能可以与175B参数规模的GPT-3媲美。模型在推理过程中采用了多查询注意力(Multi-Query Attention, MQA)机制,改进了传统多头注意力的查询方式,将多个注意力头的查询统一为单个查询头,从而显著减少了推理时间和显存需求,提升了效率。适用于文本生成、问答、翻译等任务。例如,在文本生成任务中,LLaMA可以生成高质量的文章段落,其轻量化设计降低了硬件需求,使研究者和开发者更容易使用高性能的语言模型。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "导入必要的包" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "import numpy as np\n", - "import mindspore as ms\n", - "import mindspore.dataset as ds" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[WARNING] ME(52617:140460371482432,MainProcess):2025-04-11-09:21:14.572.566 [mindspore/context.py:1335] For 'context.set_context', the parameter 'device_target' will be deprecated and removed in a future version. Please use the api mindspore.set_device() instead.\n" - ] - } - ], - "source": [ - "#将模式设置为动态图模式(PYNATIVE_MODE),并指定设备目标为Ascend芯片\n", - "ms.set_context(mode=ms.PYNATIVE_MODE, device_target=\"Ascend\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "#指定模型路径\n", - "base_model_path = \"/home/jiangna1/.mindnlp/model/hfl/chinese-llama-2-1.3b\" #中文模型,这里我提前下载到了本地减少下载时间\n", - "# base_model_path = \"NousResearch/Hermes-3-Llama-3.2-3B\" #英文模型\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 数据集\n", - "\n", - "这里提供两份用于微调的数据集,分别用于中文模型和英文模型,其中中文模型为hfl/chinese-llama-2-1.3b,参数量为1.3B,英文模型为NousResearch/Hermes-3-Llama-3.2-3B,参数量为3.2B,用户可以根据自己的配置或期望训练时长自行选择。\n", - "\n", - "数据来源皆为hugging face公开用于微调的数据集,其中中文数据集来源为弱智吧,数据格式为:\n", - "\n", - " {\"instruction\": \"只剩一个心脏了还能活吗?\",\n", - "\n", - " \"output\": \"能,人本来就只有一个心脏。\"},\n", - "\n", - " {\"instruction\": \"爸爸再婚,我是不是就有了个新娘?\",\n", - "\n", - " \"output\": \"不是的,你有了一个继母。\\\"新娘\\\"是指新婚的女方,而你爸爸再婚,他的新婚妻子对你来说是继母。\"}\n", - "\n", - "\n", - "英文数据来源为Alpaca,数据格式为:\n", - "\n", - " {\"instruction\": \"Give three tips for staying healthy.\",\n", - "\n", - " \"input\": \"\",\n", - "\n", - " \"output\": \"1.Eat a balanced diet and make sure to include plenty of fruits and vegetables. \\n2. Exercise regularly to keep your body active and strong. \\n3. Get enough sleep and maintain a consistent sleep schedule.\"},\n", - "\n", - " {\"instruction\": \"What are the three primary colors?\",\n", - "\n", - " \"input\": \"\",\n", - "\n", - " \"output\": \"The three primary colors are red, blue, and yellow.\"}\n", - "\n", - "\n", - "以下教程同时包括包括中文和英文模型的微调教程为例,其中英文模型微调效果更好,但因为时间关系,本模型展示主要以小规模的中文为例,可以自行根据自己的需求修改数据来源和模型。\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 数据加载和数据预处理" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "新建 tokenize_function 函数用于数据预处理,具体内容可见下面代码注释。" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "def tokenize_function(example, tokenizer):\n", - " instruction = example.get(\"instruction\", \"\")\n", - " input_text = example.get(\"input\", \"\")\n", - " output = example.get(\"output\", \"\")\n", - " # prompt\n", - " if input_text:\n", - " prompt = f\"User: {instruction} {input_text}\\nAssistant: {output}\"\n", - " else:\n", - " prompt = f\"User: {instruction}\\nAssistant: {output}\"\n", - " \n", - " # Tokenize\n", - " tokenized = tokenizer(prompt, padding=\"max_length\", truncation=True, max_length=512)\n", - " input_ids = np.array(tokenized[\"input_ids\"], dtype=np.int32)\n", - "\n", - " # Handle label\n", - " pad_token_id = tokenizer.pad_token_id\n", - " labels = np.array(\n", - " [-100 if token_id == pad_token_id else token_id for token_id in input_ids], dtype=np.int32\n", - " )\n", - " return input_ids, labels\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "数据来源如下,为了避免网络问题,建议先下载到本地\n", - "\n", - "https://huggingface.co/datasets/LooksJuicy/ruozhiba" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# data_path = \"/home/jiangna1/mindnlp_llama_all/alpaca_data.json\" #英文数据集\n", - "data_path = \"/home/jiangna1/mindnlp_llama_all/chinese_data.json\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "查看数据具体内容,该数据只包括instruction和output两列" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[{'instruction': '只剩一个心脏了还能活吗?', 'output': '能,人本来就只有一个心脏。'}, {'instruction': '爸爸再婚,我是不是就有了个新娘?', 'output': '不是的,你有了一个继母。\"新娘\"是指新婚的女方,而你爸爸再婚,他的新婚妻子对你来说是继母。'}, {'instruction': '樟脑丸是我吃过最难吃的硬糖有奇怪的味道怎么还有人买', 'output': '樟脑丸并不是硬糖,而是一种常见的驱虫药,不能食用。虽然它的味道可能不太好,但是由于其有效的驱虫效果,所以仍然有很多人会购买。'}]\n" - ] - } - ], - "source": [ - "with open(data_path, 'r', encoding='utf-8') as f:\n", - " data = json.load(f)\n", - "print(data[:3])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "从指定路径加载预训练的分词器,该分词器能将输入文本分割成模型可处理的词元。接着,将填充标记设置为结束标记,这样在处理不同长度的文本序列时,用结束标记来填充额外位置,避免引入额外特殊标记,减少模型学习负担。最后,设置填充方向为右侧,使文本在右侧添加填充标记达到统一长度,维持文本原始顺序。" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 29871, 2056]" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from mindnlp.transformers import AutoTokenizer\n", - "\n", - "tokenizer = AutoTokenizer.from_pretrained(base_model_path)\n", - "tokenizer.pad_token = tokenizer.eos_token\n", - "tokenizer.pad_token_id = tokenizer.eos_token_id\n", - "tokenizer.padding_side = \"right\"\n", - "tokenizer.encode(' ;')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "将数据分为训练集和验证集" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "def data_generator(dataset, tokenizer):\n", - " for item in dataset:\n", - " yield tokenize_function(item, tokenizer)\n", - " \n", - "split_ratio = 0.9\n", - "split_index = int(len(data) * split_ratio)\n", - "train_data, val_data = data[:split_index], data[split_index:]\n", - "\n", - "train_dataset = ds.GeneratorDataset(\n", - " source=lambda: data_generator(train_data, tokenizer), \n", - " column_names=[\"input_ids\", \"labels\"]\n", - ")\n", - "\n", - "eval_dataset = ds.GeneratorDataset(\n", - " source=lambda: data_generator(val_data, tokenizer), \n", - " column_names=[\"input_ids\", \"labels\"]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "查看处理后的数据,tokenizer 将输入的文本(prompt)拆分为词片段(tokens),然后将每个词片段映射为对应的 token ID。" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[MS_ALLOC_CONF]Runtime config: enable_vmm:True vmm_align_size:2MB\n", - "Sample 0: Input IDs: [ 1 4911 29901 29871 47133 32002 37755 30743 33302 31704]\n", - "Sample 0: Labels: [ 1 4911 29901 29871 47133 32002 37755 30743 33302 31704]\n", - "\n", - "Sample 1: Input IDs: [ 1 4911 29901 29871 33594 31733 33364 30214 30672 32308]\n", - "Sample 1: Labels: [ 1 4911 29901 29871 33594 31733 33364 30214 30672 32308]\n", - "\n", - "Sample 2: Input IDs: [ 1 4911 29901 29871 47019 33027 31818 34030 39950 44345]\n", - "Sample 2: Labels: [ 1 4911 29901 29871 47019 33027 31818 34030 39950 44345]\n", - "\n", - "Sample 3: Input IDs: [ 1 4911 29901 29871 34214 30698 30429 36310 32658 30743]\n", - "Sample 3: Labels: [ 1 4911 29901 29871 34214 30698 30429 36310 32658 30743]\n", - "\n", - "Sample 4: Input IDs: [ 1 4911 29901 32581 34822 31639 2882 6530 30883 30210]\n", - "Sample 4: Labels: [ 1 4911 29901 32581 34822 31639 2882 6530 30883 30210]\n", - "\n" - ] - } - ], - "source": [ - "for i, sample in enumerate(train_dataset.create_dict_iterator()):\n", - " if i >= 5:\n", - " break\n", - " print(f\"Sample {i}: Input IDs: {sample['input_ids'][:10]}\") \n", - " print(f\"Sample {i}: Labels: {sample['labels'][:10]}\\n\") " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## lora指令微调" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "指定微调结果输出路径" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# 指定输出路径\n", - "peft_output_dir = \"/home/jiangna1/mindnlp_llama_all/pert_model_Chinese\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "加载基座模型\n" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "LlamaForCausalLM has generative capabilities, as `prepare_inputs_for_generation` is explicitly overwritten. However, it doesn't directly inherit from `GenerationMixin`.`PreTrainedModel` will NOT inherit from `GenerationMixin`, and this model will lose the ability to call `generate` and other related functions.\n", - " - If you are the owner of the model architecture code, please modify your model class such that it inherits from `GenerationMixin` (after `PreTrainedModel`, otherwise you'll get an exception).\n", - " - If you are not the owner of the model architecture class, please contact the model code owner to update it.\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jiangna1/miniconda3/envs/ms39/lib/python3.9/site-packages/mindnlp/transformers/generation/configuration_utils.py:557: UserWarning: `do_sample` is set to `False`. However, `temperature` is set to `0.2` -- this flag is only used in sample-based generation modes. You should set `do_sample=True` or unset `temperature`. This was detected when initializing the generation config instance, which means the corresponding file may hold incorrect parameterization and should be fixed.\n", - " warnings.warn(\n", - "/home/jiangna1/miniconda3/envs/ms39/lib/python3.9/site-packages/mindnlp/transformers/generation/configuration_utils.py:562: UserWarning: `do_sample` is set to `False`. However, `top_p` is set to `0.9` -- this flag is only used in sample-based generation modes. You should set `do_sample=True` or unset `top_p`. This was detected when initializing the generation config instance, which means the corresponding file may hold incorrect parameterization and should be fixed.\n", - " warnings.warn(\n", - "/home/jiangna1/miniconda3/envs/ms39/lib/python3.9/site-packages/mindnlp/transformers/generation/configuration_utils.py:557: UserWarning: `do_sample` is set to `False`. However, `temperature` is set to `0.2` -- this flag is only used in sample-based generation modes. You should set `do_sample=True` or unset `temperature`.\n", - " warnings.warn(\n", - "/home/jiangna1/miniconda3/envs/ms39/lib/python3.9/site-packages/mindnlp/transformers/generation/configuration_utils.py:562: UserWarning: `do_sample` is set to `False`. However, `top_p` is set to `0.9` -- this flag is only used in sample-based generation modes. You should set `do_sample=True` or unset `top_p`.\n", - " warnings.warn(\n" - ] - } - ], - "source": [ - "from mindnlp.transformers import AutoModelForCausalLM, GenerationConfig\n", - "\n", - "ms_base_model = AutoModelForCausalLM.from_pretrained(base_model_path, ms_dtype=ms.float16)\n", - "ms_base_model.generation_config = GenerationConfig.from_pretrained(base_model_path)\n", - "ms_base_model.generation_config.pad_token_id = ms_base_model.generation_config.eos_token_id\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "#修改精度,会使训练变慢,但是训练loss下降效果会变好\n", - "for name, param in ms_base_model.parameters_and_names():\n", - " param.set_dtype(ms.float32) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "这部分代码的主要作用是创建一个 LoRA的配置对象 ms_config,大语言模型进行微调时,LoRA 是一种高效的参数微调方法,通过在预训练模型的基础上添加低秩矩阵来减少需要训练的参数数量,从而提高微调效率。" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from mindnlp.peft import LoraConfig, TaskType, get_peft_model, PeftModel\n", - "\n", - "ms_config = LoraConfig(\n", - " task_type=TaskType.CAUSAL_LM,#微调任务的类型\n", - " #指定需要应用 LoRA 调整的目标模块\n", - " # target_modules=[\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\", \"gate_proj\", \"up_proj\", \"down_proj\"],\n", - " target_modules = [\"q_proj\", \"k_proj\", \"v_proj\", \"o_proj\"],\n", - " inference_mode=False, \n", - " r=8, \n", - " lora_alpha=32, \n", - " lora_dropout=0.1 \n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "基于给定的基础模型和 LoRA 配置创建一个可进行参数高效微调的模型。" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "ms_model = get_peft_model(ms_base_model, ms_config)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "训练参数的设置" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "from mindnlp.engine import TrainingArguments, Trainer\n", - "\n", - "num_train_epochs = 70\n", - "fp16 = True\n", - "overwrite_output_dir = True\n", - "per_device_train_batch_size = 16\n", - "per_device_eval_batch_size = 32\n", - "gradient_accumulation_steps = 16\n", - "gradient_checkpointing = True\n", - "evaluation_strategy = \"steps\"\n", - "learning_rate = 1e-5\n", - "lr_scheduler_type = \"cosine\" \n", - "weight_decay = 0.01\n", - "warmup_ratio = 0.1\n", - "max_grad_norm = 0.3\n", - "group_by_length = False \n", - "auto_find_batch_size = False\n", - "save_steps = 50 \n", - "logging_strategy = \"steps\"\n", - "logging_steps = 150 \n", - "load_best_model_at_end = True \n", - "packing = False\n", - "save_total_limit = 3\n", - "neftune_noise_alpha = 5 \n", - "eval_steps = 10\n", - "\n", - "training_arguments = TrainingArguments(\n", - " output_dir=peft_output_dir,\n", - " overwrite_output_dir=overwrite_output_dir,\n", - " num_train_epochs=num_train_epochs,\n", - " load_best_model_at_end=load_best_model_at_end,\n", - " per_device_train_batch_size=per_device_train_batch_size,\n", - " per_device_eval_batch_size=per_device_eval_batch_size,\n", - " evaluation_strategy=evaluation_strategy,\n", - " eval_steps=eval_steps,\n", - " max_grad_norm=max_grad_norm,\n", - " auto_find_batch_size=auto_find_batch_size,\n", - " save_total_limit=save_total_limit,\n", - " gradient_accumulation_steps=gradient_accumulation_steps,\n", - " save_steps=save_steps,\n", - " logging_strategy=logging_strategy,\n", - " logging_steps=logging_steps,\n", - " learning_rate=learning_rate,\n", - " weight_decay=weight_decay,\n", - " fp16=fp16,\n", - " warmup_ratio=warmup_ratio,\n", - " group_by_length=group_by_length,\n", - " lr_scheduler_type=lr_scheduler_type\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "初始化训练器" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "trainer = Trainer(\n", - " model=ms_model,\n", - " train_dataset=train_dataset,\n", - " eval_dataset=eval_dataset,\n", - " args=training_arguments\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "开始训练" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 0%| | 1/350 [00:19<1:51:45, 19.21s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "." - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 3%|▎ | 10/350 [02:02<1:04:58, 11.47s/it]We detected that you are passing `past_key_values` as a tuple and this is deprecated. Please use an appropriate `Cache` class\n", - " \n", - " 3%|▎ | 10/350 [02:05<1:04:58, 11.47s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.853940486907959, 'eval_runtime': 2.8532, 'eval_samples_per_second': 1.752, 'eval_steps_per_second': 0.35, 'epoch': 1.88}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 6%|▌ | 20/350 [04:00<1:02:29, 11.36s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.840895891189575, 'eval_runtime': 2.3863, 'eval_samples_per_second': 2.095, 'eval_steps_per_second': 0.419, 'epoch': 3.76}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 9%|▊ | 30/350 [05:54<1:00:27, 11.33s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.8152430057525635, 'eval_runtime': 2.3786, 'eval_samples_per_second': 2.102, 'eval_steps_per_second': 0.42, 'epoch': 5.65}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 11%|█▏ | 40/350 [07:49<58:26, 11.31s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.772057294845581, 'eval_runtime': 2.3891, 'eval_samples_per_second': 2.093, 'eval_steps_per_second': 0.419, 'epoch': 7.53}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 14%|█▍ | 50/350 [09:44<56:29, 11.30s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.7203030586242676, 'eval_runtime': 2.3927, 'eval_samples_per_second': 2.09, 'eval_steps_per_second': 0.418, 'epoch': 9.41}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 17%|█▋ | 60/350 [11:48<54:53, 11.36s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.6663565635681152, 'eval_runtime': 2.3972, 'eval_samples_per_second': 2.086, 'eval_steps_per_second': 0.417, 'epoch': 11.29}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 20%|██ | 70/350 [13:43<52:18, 11.21s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.6159634590148926, 'eval_runtime': 2.3981, 'eval_samples_per_second': 2.085, 'eval_steps_per_second': 0.417, 'epoch': 13.18}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 23%|██▎ | 80/350 [15:38<50:19, 11.18s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.565094470977783, 'eval_runtime': 2.3789, 'eval_samples_per_second': 2.102, 'eval_steps_per_second': 0.42, 'epoch': 15.06}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 26%|██▌ | 90/350 [17:33<49:11, 11.35s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.5170516967773438, 'eval_runtime': 2.3956, 'eval_samples_per_second': 2.087, 'eval_steps_per_second': 0.417, 'epoch': 16.94}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 29%|██▊ | 100/350 [19:28<47:17, 11.35s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.4649040699005127, 'eval_runtime': 2.3707, 'eval_samples_per_second': 2.109, 'eval_steps_per_second': 0.422, 'epoch': 18.82}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 31%|███▏ | 110/350 [21:30<45:42, 11.43s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.407757520675659, 'eval_runtime': 2.3942, 'eval_samples_per_second': 2.088, 'eval_steps_per_second': 0.418, 'epoch': 20.71}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 34%|███▍ | 120/350 [23:25<43:28, 11.34s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.343446969985962, 'eval_runtime': 2.3932, 'eval_samples_per_second': 2.089, 'eval_steps_per_second': 0.418, 'epoch': 22.59}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 37%|███▋ | 130/350 [25:20<41:29, 11.31s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.267294406890869, 'eval_runtime': 2.3965, 'eval_samples_per_second': 2.086, 'eval_steps_per_second': 0.417, 'epoch': 24.47}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 40%|████ | 140/350 [27:15<39:26, 11.27s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.219864845275879, 'eval_runtime': 2.3872, 'eval_samples_per_second': 2.094, 'eval_steps_per_second': 0.419, 'epoch': 26.35}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 43%|████▎ | 150/350 [29:08<37:32, 11.26s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'loss': 3.5504, 'learning_rate': 7.056435515653059e-06, 'epoch': 28.24}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "." - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 43%|████▎ | 150/350 [29:10<37:32, 11.26s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.1902430057525635, 'eval_runtime': 2.5486, 'eval_samples_per_second': 1.962, 'eval_steps_per_second': 0.392, 'epoch': 28.24}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 46%|████▌ | 160/350 [31:12<35:42, 11.28s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.161935329437256, 'eval_runtime': 2.391, 'eval_samples_per_second': 2.091, 'eval_steps_per_second': 0.418, 'epoch': 30.12}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 49%|████▊ | 170/350 [33:07<33:32, 11.18s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.138967752456665, 'eval_runtime': 2.3927, 'eval_samples_per_second': 2.09, 'eval_steps_per_second': 0.418, 'epoch': 32.0}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 51%|█████▏ | 180/350 [35:03<32:11, 11.36s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.122406482696533, 'eval_runtime': 2.3994, 'eval_samples_per_second': 2.084, 'eval_steps_per_second': 0.417, 'epoch': 33.88}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 54%|█████▍ | 190/350 [36:58<30:17, 11.36s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.106480836868286, 'eval_runtime': 2.3919, 'eval_samples_per_second': 2.09, 'eval_steps_per_second': 0.418, 'epoch': 35.76}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 57%|█████▋ | 200/350 [38:53<28:21, 11.35s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0940558910369873, 'eval_runtime': 2.397, 'eval_samples_per_second': 2.086, 'eval_steps_per_second': 0.417, 'epoch': 37.65}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 60%|██████ | 210/350 [40:56<26:40, 11.43s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.082423686981201, 'eval_runtime': 2.3797, 'eval_samples_per_second': 2.101, 'eval_steps_per_second': 0.42, 'epoch': 39.53}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 63%|██████▎ | 220/350 [42:51<24:30, 11.31s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0746374130249023, 'eval_runtime': 2.405, 'eval_samples_per_second': 2.079, 'eval_steps_per_second': 0.416, 'epoch': 41.41}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 66%|██████▌ | 230/350 [44:46<22:31, 11.26s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0679070949554443, 'eval_runtime': 2.3952, 'eval_samples_per_second': 2.088, 'eval_steps_per_second': 0.418, 'epoch': 43.29}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 69%|██████▊ | 240/350 [46:41<20:33, 11.21s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.060976266860962, 'eval_runtime': 2.3947, 'eval_samples_per_second': 2.088, 'eval_steps_per_second': 0.418, 'epoch': 45.18}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 71%|███████▏ | 250/350 [48:36<18:39, 11.19s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0542078018188477, 'eval_runtime': 2.3973, 'eval_samples_per_second': 2.086, 'eval_steps_per_second': 0.417, 'epoch': 47.06}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 74%|███████▍ | 260/350 [50:39<17:09, 11.44s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.049464702606201, 'eval_runtime': 2.3926, 'eval_samples_per_second': 2.09, 'eval_steps_per_second': 0.418, 'epoch': 48.94}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 77%|███████▋ | 270/350 [52:34<15:09, 11.37s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.047043561935425, 'eval_runtime': 2.3877, 'eval_samples_per_second': 2.094, 'eval_steps_per_second': 0.419, 'epoch': 50.82}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 80%|████████ | 280/350 [54:29<13:14, 11.34s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0444722175598145, 'eval_runtime': 2.3917, 'eval_samples_per_second': 2.091, 'eval_steps_per_second': 0.418, 'epoch': 52.71}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 83%|████████▎ | 290/350 [56:24<11:20, 11.34s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0422093868255615, 'eval_runtime': 2.3938, 'eval_samples_per_second': 2.089, 'eval_steps_per_second': 0.418, 'epoch': 54.59}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " 86%|████████▌ | 300/350 [58:17<09:25, 11.31s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'loss': 3.0383, 'learning_rate': 6.088921331488568e-07, 'epoch': 56.47}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 86%|████████▌ | 300/350 [58:19<09:25, 11.31s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0407938957214355, 'eval_runtime': 2.3837, 'eval_samples_per_second': 2.098, 'eval_steps_per_second': 0.42, 'epoch': 56.47}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 89%|████████▊ | 310/350 [1:00:22<07:34, 11.37s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0404062271118164, 'eval_runtime': 2.3948, 'eval_samples_per_second': 2.088, 'eval_steps_per_second': 0.418, 'epoch': 58.35}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 91%|█████████▏| 320/350 [1:02:17<05:38, 11.27s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0399832725524902, 'eval_runtime': 2.3929, 'eval_samples_per_second': 2.089, 'eval_steps_per_second': 0.418, 'epoch': 60.24}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 94%|█████████▍| 330/350 [1:04:12<03:43, 11.20s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.039731740951538, 'eval_runtime': 2.3855, 'eval_samples_per_second': 2.096, 'eval_steps_per_second': 0.419, 'epoch': 62.12}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - " 97%|█████████▋| 340/350 [1:06:07<01:51, 11.19s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.0396060943603516, 'eval_runtime': 2.3904, 'eval_samples_per_second': 2.092, 'eval_steps_per_second': 0.418, 'epoch': 64.0}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \n", - "100%|██████████| 350/350 [1:08:03<00:00, 11.35s/it]" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'eval_loss': 3.039623260498047, 'eval_runtime': 2.3877, 'eval_samples_per_second': 2.094, 'eval_steps_per_second': 0.419, 'epoch': 65.88}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "The intermediate checkpoints of PEFT may not be saved correctly, consider using a custom callback to save adapter_model.bin in corresponding saving folders. Check some examples here: https://github.com/huggingface/peft/issues/96\n", - "100%|██████████| 350/350 [1:08:12<00:00, 11.69s/it]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'train_runtime': 4092.112, 'train_samples_per_second': 23.264, 'train_steps_per_second': 0.086, 'train_loss': 3.2515819876534597, 'epoch': 65.88}\n" - ] - } - ], - "source": [ - "trainer.train()\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for name, param in trainer.model.parameters_and_names():\n", - " param.set_dtype(ms.float16)\n", - "trainer.model.save_pretrained(peft_output_dir)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "最后存储还是存储为 16 位浮点数,保存训练后的 LoRA 模型保存到指定的输出目录" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 推理" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "注意,lora微调后保存的并不是完整的参数,在推理时,需要将保存的 LoRA 参数加载到原预训练模型中,合并后得到完整的模型,然后进行推理。" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "使用PeftModel进行配置和参数合并,最后将模型设置为评估模式,进行推理任务。" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "model merge succeeded\n" - ] - }, - { - "data": { - "text/plain": [ - "LlamaForCausalLM(\n", - " (model): LlamaModel(\n", - " (embed_tokens): Embedding(55296, 4096, padding_idx=0)\n", - " (layers): ModuleList(\n", - " (0-3): 4 x LlamaDecoderLayer(\n", - " (self_attn): LlamaAttention(\n", - " (q_proj): lora.Linear(\n", - " (base_layer): Linear (4096 -> 4096)\n", - " (lora_dropout): ModuleDict(\n", - " (default): Dropout(p=0.1, inplace=False)\n", - " )\n", - " (lora_A): ModuleDict(\n", - " (default): Linear (4096 -> 8)\n", - " )\n", - " (lora_B): ModuleDict(\n", - " (default): Linear (8 -> 4096)\n", - " )\n", - " (lora_embedding_A): ParameterDict()\n", - " (lora_embedding_B): ParameterDict()\n", - " (lora_magnitude_vector): ModuleDict()\n", - " )\n", - " (k_proj): lora.Linear(\n", - " (base_layer): Linear (4096 -> 4096)\n", - " (lora_dropout): ModuleDict(\n", - " (default): Dropout(p=0.1, inplace=False)\n", - " )\n", - " (lora_A): ModuleDict(\n", - " (default): Linear (4096 -> 8)\n", - " )\n", - " (lora_B): ModuleDict(\n", - " (default): Linear (8 -> 4096)\n", - " )\n", - " (lora_embedding_A): ParameterDict()\n", - " (lora_embedding_B): ParameterDict()\n", - " (lora_magnitude_vector): ModuleDict()\n", - " )\n", - " (v_proj): lora.Linear(\n", - " (base_layer): Linear (4096 -> 4096)\n", - " (lora_dropout): ModuleDict(\n", - " (default): Dropout(p=0.1, inplace=False)\n", - " )\n", - " (lora_A): ModuleDict(\n", - " (default): Linear (4096 -> 8)\n", - " )\n", - " (lora_B): ModuleDict(\n", - " (default): Linear (8 -> 4096)\n", - " )\n", - " (lora_embedding_A): ParameterDict()\n", - " (lora_embedding_B): ParameterDict()\n", - " (lora_magnitude_vector): ModuleDict()\n", - " )\n", - " (o_proj): lora.Linear(\n", - " (base_layer): Linear (4096 -> 4096)\n", - " (lora_dropout): ModuleDict(\n", - " (default): Dropout(p=0.1, inplace=False)\n", - " )\n", - " (lora_A): ModuleDict(\n", - " (default): Linear (4096 -> 8)\n", - " )\n", - " (lora_B): ModuleDict(\n", - " (default): Linear (8 -> 4096)\n", - " )\n", - " (lora_embedding_A): ParameterDict()\n", - " (lora_embedding_B): ParameterDict()\n", - " (lora_magnitude_vector): ModuleDict()\n", - " )\n", - " (rotary_emb): LlamaRotaryEmbedding()\n", - " )\n", - " (mlp): LlamaMLP(\n", - " (gate_proj): Linear (4096 -> 11008)\n", - " (up_proj): Linear (4096 -> 11008)\n", - " (down_proj): Linear (11008 -> 4096)\n", - " (act_fn): SiLU()\n", - " )\n", - " (input_layernorm): LlamaRMSNorm((4096,), eps=1e-05)\n", - " (post_attention_layernorm): LlamaRMSNorm((4096,), eps=1e-05)\n", - " )\n", - " )\n", - " (norm): LlamaRMSNorm((4096,), eps=1e-05)\n", - " (rotary_emb): LlamaRotaryEmbedding()\n", - " )\n", - " (lm_head): Linear (4096 -> 55296)\n", - ")" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#将 LoRA微调后的参数加载到预训练模型中\n", - "from mindnlp.peft import PeftModel\n", - "model = PeftModel.from_pretrained(ms_base_model, peft_output_dir)\n", - "model = model.merge_and_unload()\n", - "print('model merge succeeded')\n", - "model.eval()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "定义一个函数,用于根据用户输入的问题生成相应的回答" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [], - "source": [ - "import mindspore as ms\n", - "\n", - "def generate_response(question, model, tokenizer, max_length=256):\n", - " prompt = f\"以下是用户和助手之间的问答。\\n问:{question}\\n答:\"\n", - " inputs = tokenizer(prompt, return_tensors=\"ms\", padding=True, truncation=True, max_length=512)\n", - " output_ids = model.generate(\n", - " **inputs,\n", - " do_sample=False,\n", - " # temperature=0.7,\n", - " # top_p=0.9,\n", - " repetition_penalty=1.2,\n", - " no_repeat_ngram_size=3,\n", - " max_length=max_length,\n", - " eos_token_id=tokenizer.eos_token_id\n", - " )\n", - "\n", - " response = tokenizer.decode(output_ids[0], skip_special_tokens=True)\n", - " response = response.split(\"Answer:\")[-1].strip()\n", - " return response\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "一个实例" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jiangna1/miniconda3/envs/ms39/lib/python3.9/site-packages/mindnlp/transformers/generation/configuration_utils.py:557: UserWarning: `do_sample` is set to `False`. However, `temperature` is set to `0.2` -- this flag is only used in sample-based generation modes. You should set `do_sample=True` or unset `temperature`.\n", - " warnings.warn(\n", - "/home/jiangna1/miniconda3/envs/ms39/lib/python3.9/site-packages/mindnlp/transformers/generation/configuration_utils.py:562: UserWarning: `do_sample` is set to `False`. However, `top_p` is set to `0.9` -- this flag is only used in sample-based generation modes. You should set `do_sample=True` or unset `top_p`.\n", - " warnings.warn(\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User: 如何保持清醒?\n", - "LLAMA: 以下是用户和助手之间的问答。\n", - "问:如何保持清醒?\n", - "答:在你睡觉的时候,你的大脑会一直处于兴奋状态中;当你醒来时,它就会继续工作了。所以如果你的睡眠时间很短的话,你就不会感到太疲劳或昏沉。你可以通过使用一些药物来帮助恢复精力、提高警觉度以及降低血压等方法使自己进入深度睡眠的状态。此外,你还可以通过服用维生素B6片剂或者吃富含蛋白质的食物等方式让自己重新振作起来。\n" - ] - } - ], - "source": [ - "question = \"如何保持清醒?\"\n", - "response = generate_response(question, model, tokenizer)\n", - "\n", - "print(f\"User: {question}\")\n", - "print(f\"LLAMA: {response}\")" - ] - } - ], - "metadata": { - "AIGalleryInfo": { - "item_id": "5443b528-0dd5-4909-ac4f-1c9cf839e2aa" - }, - "flavorInfo": { - "architecture": "X86_64", - "category": "GPU" - }, - "imageInfo": { - "id": "e1a07296-22a8-4f05-8bc8-e936c8e54202", - "name": "mindspore1.7.0-cuda10.1-py3.7-ubuntu18.04" - }, - "kernelspec": { - "display_name": "ms39", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/07.LLaMA2/llama_inference_debug.py b/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/07.LLaMA2/llama_inference_debug.py deleted file mode 100644 index 4b7d81a..0000000 --- a/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/07.LLaMA2/llama_inference_debug.py +++ /dev/null @@ -1,42 +0,0 @@ -import sys -import os -# Add current directory to Python path for local module imports -sys.path.insert(0, os.path.abspath(".")) -from ms_mindnlp.transformers.models.llama.modeling_llama import LlamaModel -from ms_mindnlp.transformers.models.llama.configuration_llama import LlamaConfig -import mindspore as ms -from mindspore import dtype, ops -import debugpy - -debugpy.listen(("0.0.0.0", 5678)) -print("Waiting for debugger to attach...") - -debugpy.wait_for_client() -print("Debugger is attached.") - -# import inspect -# llama_config_file_path = inspect.getfile(LlamaConfig) -# print(f"{llama_config_file_path}") - -ms.set_context(mode=ms.PYNATIVE_MODE) - -def run(): - """Main execution function for LLaMA model inference demo""" - config = LlamaConfig( - vocab_size=32000, # Tokenizer vocabulary size - hidden_size=4096, # Hidden layer dimension - intermediate_size=11008, # FFN layer inner dimension - num_hidden_layers=2, # Number of transformer blocks - num_attention_heads=32, # Parallel attention heads - num_key_value_heads=2, # KV heads for grouped-query attention - max_position_embeddings=2048, # Maximum sequence length - ) - model = LlamaModel(config=config) - # Generate random input tensor: (batch_size=2, seq_length=16) - input_ids = ops.randint(0, config.vocab_size, (2, 16), dtype=dtype.int32) - output = model(input_ids=input_ids) - print("inference") - print(output) - -if __name__ == "__main__": - run() \ No newline at end of file diff --git a/01.LLM_Theory_Course/02.Technical_Topic_Introduction/01.Prompt_Tuning/roberta_sequence_classification.ipynb b/01.LLM_Theory_Course/02.Technical_Topic_Introduction/01.Prompt_Tuning/roberta_sequence_classification.ipynb index 75c4c9e..5ccd5c5 100644 --- a/01.LLM_Theory_Course/02.Technical_Topic_Introduction/01.Prompt_Tuning/roberta_sequence_classification.ipynb +++ b/01.LLM_Theory_Course/02.Technical_Topic_Introduction/01.Prompt_Tuning/roberta_sequence_classification.ipynb @@ -5,74 +5,51 @@ "id": "7a2ac91c", "metadata": {}, "source": [ - "# 基于MindNLP的Roberta模型Prompt Tuning" + "# 基于MindNLP的RoBERTa模型Prompt Tuning\n", + "\n", + "## 案例介绍\n", + "\n", + "本案例对roberta-large模型基于GLUE基准数据集进行prompt tuning。\n", + "\n", + "## 模型介绍\n", + "\n", + "RoBERTa 的全称是 Robustly optimized BERT approach,可以理解为“经过更精细优化的 BERT 模型”。它由 Facebook AI(现 Meta AI)在 2019 年发布,是对 Google 的 BERT 模型的一次重大改进和重新设计。\n", + "\n", + "其核心思想是:BERT 的原始设计很好,但训练不充分、配置可以优化。通过一系列改进,RoBERTa 在多个自然语言理解基准测试上超越了 BERT,成为了当时最强大的预训练模型之一。" ] }, { "cell_type": "markdown", - "id": "324424c6", + "id": "de06584a", "metadata": {}, "source": [ - "安装mindspore, mindnlp及其他依赖" + "## 环境配置\n", + "\n", + "本案例的运行环境为:\n", + "\n", + "| Python | MindSpore | MindSpore NLP |\n", + "| :----- | :-------- | :------------ |\n", + "| 3.10 | 2.7.0 | 0.5.1 |\n", + "\n", + "如果你在如[昇思大模型平台](https://xihe.mindspore.cn/training-projects)、[华为云ModelArts](https://www.huaweicloud.com/product/modelarts.html)、[启智社区](https://openi.pcl.ac.cn/)等算力平台的Jupyter在线编程环境中运行本案例,可取消如下代码的注释,进行依赖库安装:" ] }, { "cell_type": "code", - "execution_count": 1, - "id": "cd3f2df1-da30-4009-8b33-80df52be80c7", + "execution_count": null, + "id": "7e3693f7", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n", - "Collecting mindspore==2.4.1\n", - " Downloading https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.4.1/MindSpore/unified/aarch64/mindspore-2.4.1-cp39-cp39-linux_aarch64.whl (335.5 MB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m335.5/335.5 MB\u001b[0m \u001b[31m6.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: numpy<2.0.0,>=1.20.0 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from mindspore==2.4.1) (1.26.1)\n", - "Requirement already satisfied: protobuf>=3.13.0 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from mindspore==2.4.1) (3.20.3)\n", - "Requirement already satisfied: asttokens>=2.0.4 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from mindspore==2.4.1) (2.4.1)\n", - "Requirement already satisfied: pillow>=6.2.0 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from mindspore==2.4.1) (9.0.1)\n", - "Requirement already satisfied: scipy>=1.5.4 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from mindspore==2.4.1) (1.11.3)\n", - "Requirement already satisfied: packaging>=20.0 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from mindspore==2.4.1) (23.2)\n", - "Requirement already satisfied: psutil>=5.6.1 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from mindspore==2.4.1) (5.9.5)\n", - "Requirement already satisfied: astunparse>=1.6.3 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from mindspore==2.4.1) (1.6.3)\n", - "Collecting safetensors>=0.4.0 (from mindspore==2.4.1)\n", - " Downloading https://pypi.tuna.tsinghua.edu.cn/packages/08/94/7760694760f1e5001bd62c93155b8b7ccb652d1f4d0161d1e72b5bf9581a/safetensors-0.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (442 kB)\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m442.4/442.4 kB\u001b[0m \u001b[31m39.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: six>=1.12.0 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from asttokens>=2.0.4->mindspore==2.4.1) (1.16.0)\n", - "Requirement already satisfied: wheel<1.0,>=0.23.0 in /home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages (from astunparse>=1.6.3->mindspore==2.4.1) (0.41.2)\n", - "\u001b[33mDEPRECATION: moxing-framework 2.1.16.2ae09d45 has a non-standard version number. pip 24.0 will enforce this behaviour change. A possible replacement is to upgrade to a newer version of moxing-framework or contact the author to suggest that they release a version with a conforming version number. Discussion can be found at https://github.com/pypa/pip/issues/12063\u001b[0m\u001b[33m\n", - "\u001b[0mInstalling collected packages: safetensors, mindspore\n", - " Attempting uninstall: mindspore\n", - " Found existing installation: mindspore 2.3.0\n", - " Uninstalling mindspore-2.3.0:\n", - " Successfully uninstalled mindspore-2.3.0\n", - "Successfully installed mindspore-2.4.1 safetensors-0.4.5\n" - ] - } - ], + "outputs": [], "source": [ - "!pip install https://ms-release.obs.cn-north-4.myhuaweicloud.com/2.4.1/MindSpore/unified/aarch64/mindspore-2.4.1-cp39-cp39-linux_aarch64.whl --trusted-host ms-release.obs.cn-north-4.myhuaweicloud.com -i https://pypi.tuna.tsinghua.edu.cn/simple" + "# !pip install mindspore==2.7.0 mindnlp==0.5.1" ] }, { - "cell_type": "code", - "execution_count": 14, - "id": "d8b0ba09", + "cell_type": "markdown", + "id": "82f37bbc", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "env: HF_ENDPOINT=https://hf-mirror.com\n" - ] - } - ], "source": [ - "%env HF_ENDPOINT=https://hf-mirror.com" + "其他场景可参考[MindSpore安装指南](https://www.mindspore.cn/install)与[MindSpore NLP安装指南](https://github.com/mindspore-lab/mindnlp?tab=readme-ov-file#installation)进行环境搭建。" ] }, { @@ -80,30 +57,49 @@ "id": "5b0e977f", "metadata": {}, "source": [ - "## 模型与数据集加载\n", + "## 数据加载与预处理\n", "\n", - "本案例对roberta-large模型基于GLUE基准数据集进行prompt tuning。" + "### 数据集加载" ] }, { "cell_type": "code", - "execution_count": 15, - "id": "ef577ba3", + "execution_count": 2, + "id": "01011a29-c30f-49f0-9daf-86d1150d1115", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", + " setattr(self, word, getattr(machar, word).flat[0])\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", + " return self._float_to_str(self.smallest_subnormal)\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:549: UserWarning: The value of the smallest subnormal for type is zero.\n", + " setattr(self, word, getattr(machar, word).flat[0])\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for type is zero.\n", + " return self._float_to_str(self.smallest_subnormal)\n", + "/usr/local/python3.10.14/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "Modular Diffusers is currently an experimental feature under active development. The API is subject to breaking changes in future releases.\n" + ] + } + ], "source": [ "import argparse\n", "import os\n", "\n", + "import mindnlp\n", "import mindspore\n", - "from mindnlp.core.optim import AdamW\n", + "import mindnlp\n", "from tqdm import tqdm\n", "import evaluate\n", - "from mindnlp.dataset import load_dataset\n", - "from mindnlp.engine import set_seed\n", - "from mindnlp.transformers import AutoModelForSequenceClassification, AutoTokenizer\n", - "from mindnlp.common.optimization import get_linear_schedule_with_warmup\n", - "from mindnlp.peft import (\n", + "from datasets import load_dataset\n", + "\n", + "from transformers import AutoModelForSequenceClassification, AutoTokenizer\n", + "from transformers import get_linear_schedule_with_warmup\n", + "from peft import (\n", " get_peft_config,\n", " get_peft_model,\n", " get_peft_model_state_dict,\n", @@ -115,17 +111,34 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, + "id": "5c1b6b37-9f55-42fb-b076-715dc1c72f8a", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[WARNING] ME(67332:281473403209280,MainProcess):2025-11-25-17:06:03.983.000 [mindspore/context.py:1412] For 'context.set_context', the parameter 'pynative_synchronize' will be deprecated and removed in a future version. Please use the api mindspore.runtime.launch_blocking() instead.\n" + ] + } + ], + "source": [ + "mindspore.set_context(pynative_synchronize=True) #开启同步,方便定位" + ] + }, + { + "cell_type": "code", + "execution_count": null, "id": "af061f0b", "metadata": {}, "outputs": [], "source": [ "batch_size = 32\n", - "model_name_or_path = \"AI-ModelScope/roberta-large\"\n", + "model_name_or_path = \"FacebookAI/roberta-large\"\n", "task = \"mrpc\"\n", "peft_type = PeftType.PROMPT_TUNING\n", - "# num_epochs = 20\n", - "num_epochs = 5" + "num_epochs = 1" ] }, { @@ -138,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 5, "id": "4e9663be", "metadata": {}, "outputs": [], @@ -159,19 +172,10 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "871ebbae", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/ma-user/anaconda3/envs/MindSpore/lib/python3.9/site-packages/mindnlp/transformers/tokenization_utils_base.py:1526: FutureWarning: `clean_up_tokenization_spaces` was not set. It will be set to `True` by default. This behavior will be depracted, and will be then set to `False` by default. \n", - " warnings.warn(\n" - ] - } - ], + "outputs": [], "source": [ "# load tokenizer\n", "if any(k in model_name_or_path for k in (\"gpt\", \"opt\", \"bloom\")):\n", @@ -179,14 +183,35 @@ "else:\n", " padding_side = \"right\"\n", "\n", - "tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, padding_side=padding_side, mirror=\"modelscope\")\n", + "tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, padding_side=padding_side)\n", "if getattr(tokenizer, \"pad_token_id\") is None:\n", " tokenizer.pad_token_id = tokenizer.eos_token_id" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 7, + "id": "f969c17b-48a9-45d6-90c3-852b105e9f86", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('right', 1)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tokenizer.padding_side, tokenizer.pad_token_id" + ] + }, + { + "cell_type": "code", + "execution_count": 8, "id": "79ef5257", "metadata": {}, "outputs": [ @@ -194,101 +219,230 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'sentence1': Tensor(shape=[], dtype=String, value= 'Amrozi accused his brother , whom he called \" the witness \" , of deliberately distorting his evidence .'), 'sentence2': Tensor(shape=[], dtype=String, value= 'Referring to him as only \" the witness \" , Amrozi accused his brother of deliberately distorting his evidence .'), 'label': Tensor(shape=[], dtype=Int64, value= 1), 'idx': Tensor(shape=[], dtype=Int64, value= 0)}\n" + "DatasetDict({\n", + " train: Dataset({\n", + " features: ['sentence1', 'sentence2', 'label', 'idx'],\n", + " num_rows: 3668\n", + " })\n", + " validation: Dataset({\n", + " features: ['sentence1', 'sentence2', 'label', 'idx'],\n", + " num_rows: 408\n", + " })\n", + " test: Dataset({\n", + " features: ['sentence1', 'sentence2', 'label', 'idx'],\n", + " num_rows: 1725\n", + " })\n", + "})\n", + "{'sentence1': 'Amrozi accused his brother , whom he called \" the witness \" , of deliberately distorting his evidence .', 'sentence2': 'Referring to him as only \" the witness \" , Amrozi accused his brother of deliberately distorting his evidence .', 'label': Tensor(shape=[], dtype=Int64, value= 1), 'idx': Tensor(shape=[], dtype=Int64, value= 0)}\n" ] } ], "source": [ "datasets = load_dataset(\"glue\", task)\n", - "print(next(datasets['train'].create_dict_iterator()))" + "\n", + "# 查看数据集的划分\n", + "print(datasets) \n", + "train_dataset = datasets['train']\n", + "\n", + "# Set the dataset format for PyTorch\n", + "train_dataset.set_format(type='torch')\n", + "\n", + "# Simply iterate directly\n", + "print(train_dataset[0])" + ] + }, + { + "cell_type": "markdown", + "id": "19163e58", + "metadata": {}, + "source": [ + "### 数据集处理" ] }, { "cell_type": "code", - "execution_count": 20, - "id": "151943cb", + "execution_count": 12, + "id": "c27365a4-a79b-42ee-a666-3a46cf066f38", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Map: 100%|██████████| 3668/3668 [00:00<00:00, 11107.72 examples/s]\n", + "Map: 100%|██████████| 408/408 [00:00<00:00, 10199.22 examples/s]\n" + ] + } + ], "source": [ - "from mindnlp.dataset import BaseMapFunction\n", - "\n", - "class MapFunc(BaseMapFunction):\n", - " def __call__(self, sentence1, sentence2, label, idx):\n", - " outputs = tokenizer(sentence1, sentence2, truncation=True, max_length=None)\n", - " return outputs['input_ids'], outputs['attention_mask'], label\n", - "\n", + "from torch.utils.data import DataLoader\n", + "from transformers import DataCollatorWithPadding\n", "\n", "def get_dataset(dataset, tokenizer):\n", - " input_colums=['sentence1', 'sentence2', 'label', 'idx']\n", - " output_columns=['input_ids', 'attention_mask', 'labels']\n", - " dataset = dataset.map(MapFunc(input_colums, output_columns),\n", - " input_colums, output_columns)\n", - " dataset = dataset.padded_batch(batch_size, pad_info={'input_ids': (None, tokenizer.pad_token_id),\n", - " 'attention_mask': (None, 0)})\n", + " def tokenize_function(examples):\n", + " return tokenizer(\n", + " examples['sentence1'],\n", + " examples['sentence2'],\n", + " truncation=True,\n", + " max_length=None,\n", + " )\n", + " \n", + " # 应用tokenize函数\n", + " dataset = dataset.map(\n", + " tokenize_function,\n", + " batched=True,\n", + " remove_columns=['sentence1', 'sentence2', 'idx']\n", + " )\n", + " \n", " return dataset\n", "\n", + "# 处理数据集\n", "train_dataset = get_dataset(datasets['train'], tokenizer)\n", - "eval_dataset = get_dataset(datasets['validation'], tokenizer)" + "eval_dataset = get_dataset(datasets['validation'], tokenizer)\n", + "\n", + "# 创建数据整理器\n", + "data_collator = DataCollatorWithPadding(tokenizer=tokenizer)\n", + "\n", + "# 创建DataLoader\n", + "train_dataloader = DataLoader(\n", + " train_dataset, \n", + " batch_size=batch_size, \n", + " collate_fn=data_collator,\n", + " shuffle=True\n", + ")\n", + "\n", + "eval_dataloader = DataLoader(\n", + " eval_dataset, \n", + " batch_size=batch_size, \n", + " collate_fn=data_collator\n", + ")" ] }, { "cell_type": "code", - "execution_count": 21, - "id": "a99c4ab6", + "execution_count": 13, + "id": "2ac57266-cd84-440b-b38a-2d6eacb287c3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "train_dataloader" + ] + }, + { + "cell_type": "markdown", + "id": "dd8a28a5", + "metadata": {}, + "source": [ + "### 查看数据集信息" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "79340ca2-a167-4987-ad37-d079ac1ea69e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MS_ALLOC_CONF]Runtime config: enable_vmm:True vmm_align_size:2MB\n", + "输入ID: mindtorch.Size([32, 75])\n", + "注意力掩码: mindtorch.Size([32, 75])\n", + "标签: mindtorch.Size([32])\n" + ] + } + ], + "source": [ + "# 获取一个批次\n", + "batch = next(iter(train_dataloader))\n", + "\n", + "print(\"输入ID:\", batch['input_ids'].shape)\n", + "print(\"注意力掩码:\", batch['attention_mask'].shape)\n", + "if 'labels' in batch:\n", + " print(\"标签:\", batch['labels'].shape)" + ] + }, + { + "cell_type": "markdown", + "id": "f6ef16ca", + "metadata": {}, + "source": [ + "## 加载评估指标" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9ccecda-1637-420c-aaac-c9c25ef69c81", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n", - "Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n", - "Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n", - "Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n", - "Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n", - "Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n", - "Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n" + "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n", + "To disable this warning, you can either:\n", + "\t- Avoid using `tokenizers` before the fork if possible\n", + "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "{'input_ids': Tensor(shape=[32, 70], dtype=Int64, value=\n", - "[[ 0, 10127, 1001 ... 1, 1, 1],\n", - " [ 0, 975, 26802 ... 1, 1, 1],\n", - " [ 0, 1213, 56 ... 1, 1, 1],\n", - " ...\n", - " [ 0, 133, 1154 ... 1, 1, 1],\n", - " [ 0, 12667, 8423 ... 1, 1, 1],\n", - " [ 0, 32478, 1033 ... 1, 1, 1]]), 'attention_mask': Tensor(shape=[32, 70], dtype=Int64, value=\n", - "[[1, 1, 1 ... 0, 0, 0],\n", - " [1, 1, 1 ... 0, 0, 0],\n", - " [1, 1, 1 ... 0, 0, 0],\n", - " ...\n", - " [1, 1, 1 ... 0, 0, 0],\n", - " [1, 1, 1 ... 0, 0, 0],\n", - " [1, 1, 1 ... 0, 0, 0]]), 'labels': Tensor(shape=[32], dtype=Int64, value= [1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, \n", - " 1, 1, 0, 0, 1, 1, 1, 0])}\n" + "Looking in indexes: http://pip.modelarts.private.com:8888/repository/pypi/simple\n", + "Requirement already satisfied: scikit-learn in /usr/local/python3.10.14/lib/python3.10/site-packages (1.7.2)\n", + "Requirement already satisfied: numpy>=1.22.0 in /usr/local/python3.10.14/lib/python3.10/site-packages (from scikit-learn) (1.26.4)\n", + "Requirement already satisfied: scipy>=1.8.0 in /usr/local/python3.10.14/lib/python3.10/site-packages (from scikit-learn) (1.10.1)\n", + "Requirement already satisfied: joblib>=1.2.0 in /usr/local/python3.10.14/lib/python3.10/site-packages (from scikit-learn) (1.5.2)\n", + "Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/python3.10.14/lib/python3.10/site-packages (from scikit-learn) (3.6.0)\n" ] } ], "source": [ - "print(next(train_dataset.create_dict_iterator()))" + "!pip install scikit-learn #安装依赖" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 16, "id": "9dc17398", "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Downloading builder script: 5.75kB [00:00, 6.29MB/s]\n" + ] + } + ], "source": [ "metric = evaluate.load(\"glue\", task)" ] }, + { + "cell_type": "markdown", + "id": "e0d29ec3", + "metadata": {}, + "source": [ + "## 模型加载" + ] + }, { "cell_type": "markdown", "id": "9034b5b2", @@ -308,7 +462,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 17, "id": "f929a616", "metadata": {}, "outputs": [ @@ -316,7 +470,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Some weights of RobertaForSequenceClassification were not initialized from the model checkpoint at AI-ModelScope/roberta-large and are newly initialized: ['classifier.dense.bias', 'classifier.dense.weight', 'classifier.out_proj.bias', 'classifier.out_proj.weight']\n", + "Some weights of RobertaForSequenceClassification were not initialized from the model checkpoint at FacebookAI/roberta-large and are newly initialized: ['classifier.dense.bias', 'classifier.dense.weight', 'classifier.out_proj.bias', 'classifier.out_proj.weight']\n", "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n" ] }, @@ -324,13 +478,13 @@ "name": "stdout", "output_type": "stream", "text": [ - "trainable params: 1,061,890 || all params: 356,423,684 || trainable%: 0.2979291353713745\n" + "trainable params: 1,061,890 || all params: 356,423,684 || trainable%: 0.2979\n" ] } ], "source": [ "# load model\n", - "model = AutoModelForSequenceClassification.from_pretrained(model_name_or_path, return_dict=True, mirror=\"modelscope\")\n", + "model = AutoModelForSequenceClassification.from_pretrained(model_name_or_path, return_dict=True)\n", "model = get_peft_model(model, peft_config)\n", "# print number of trainable parameters\n", "model.print_trainable_parameters()" @@ -354,12 +508,13 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 20, "id": "3c7ee704", "metadata": {}, "outputs": [], "source": [ - "optimizer = AdamW(params=model.trainable_params(), lr=lr)\n", + "import torch\n", + "optimizer = torch.optim.Adam(params=model.parameters(), lr=lr)\n", "\n", "# Instantiate scheduler\n", "lr_scheduler = get_linear_schedule_with_warmup(\n", @@ -379,44 +534,49 @@ }, { "cell_type": "code", - "execution_count": 25, - "id": "a0d2bff6", + "execution_count": 21, + "id": "222dece5-672c-4301-a26c-2c4e5fd3bf40", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "base_model.classifier.modules_to_save.default.dense.weight: mindtorch.Size([1024, 1024])\n", + "base_model.classifier.modules_to_save.default.dense.bias: mindtorch.Size([1024])\n", + "base_model.classifier.modules_to_save.default.out_proj.weight: mindtorch.Size([2, 1024])\n", + "base_model.classifier.modules_to_save.default.out_proj.bias: mindtorch.Size([2])\n", + "prompt_encoder.default.embedding.weight: mindtorch.Size([10, 1024])\n" + ] + } + ], + "source": [ + "for name, param in model.named_parameters():\n", + " if param.requires_grad:\n", + " print(f\"{name}: {param.shape}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5db89ce-d3da-4f34-a9dd-0d805858ec1e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(Tensor(shape=[1024, 1024], dtype=Float32, value=\n", - " [[-1.36615150e-02, 4.08777148e-02, 2.55590724e-03 ... 3.47721018e-02, 9.83245391e-03, 3.02866008e-02],\n", - " [-1.82124749e-02, -1.49800153e-02, -7.02886097e-03 ... 2.07055025e-02, 3.45048914e-03, -3.01328991e-02],\n", - " [-6.06489694e-03, 6.34483900e-03, 1.55880465e-03 ... 3.41698825e-02, -7.40761030e-03, 3.69770750e-02],\n", - " ...\n", - " [-4.91964221e-02, 1.94903351e-02, 2.51724524e-03 ... 3.08064763e-02, -7.55657675e-04, -8.02899338e-03],\n", - " [-2.02472787e-03, -2.46642623e-02, -7.02362158e-04 ... 2.86021479e-03, 8.27849377e-03, 9.28967725e-03],\n", - " [-2.06481982e-02, 2.20393538e-02, 3.17191752e-03 ... -2.68367468e-03, -4.67487238e-02, 9.09192720e-04]]),\n", - " Tensor(shape=[1024], dtype=Float32, value= [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00 ... 0.00000000e+00, 0.00000000e+00, 0.00000000e+00]),\n", - " Tensor(shape=[2, 1024], dtype=Float32, value=\n", - " [[ 8.87530856e-03, 2.81313114e-04, 3.74777764e-02 ... -2.02168617e-02, 4.23110556e-03, -3.84111144e-02],\n", - " [ 3.84113006e-03, -1.38288038e-02, 1.98907983e-02 ... -3.23316827e-02, -3.48059200e-02, 7.11114611e-04]]),\n", - " Tensor(shape=[2], dtype=Float32, value= [ 0.00000000e+00, 0.00000000e+00]),\n", - " Tensor(shape=[10, 1024], dtype=Float32, value=\n", - " [[-1.75136819e-01, 6.45715892e-02, 1.14947283e+00 ... 8.42640877e-01, 6.34459913e-01, 9.26455021e-01],\n", - " [ 7.65107423e-02, 5.32130003e-01, -2.12189722e+00 ... 1.34316778e+00, 4.83163930e-02, -2.11086214e-01],\n", - " [-7.30758488e-01, -8.77783835e-01, -5.94429135e-01 ... -2.58468151e-01, -2.85294857e-02, -2.18536639e+00],\n", - " ...\n", - " [ 4.13678169e-01, -1.15315497e+00, 8.49422574e-01 ... 2.54201055e-01, -1.30300558e+00, 2.13208008e+00],\n", - " [ 5.60092032e-01, -8.55898261e-01, -7.30682373e-01 ... -1.04416716e+00, -1.10600793e+00, 4.29843873e-01],\n", - " [-1.94377673e+00, 4.45314497e-02, -4.56895113e-01 ... 1.88079858e+00, -6.05825901e-01, -3.19380850e-01]]))" + "device(type=npu, index=0)" ] }, - "execution_count": 25, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# print name of trainable parameters\n", - "model.trainable_params()" + "model.npu() #模型移动到npu侧\n", + "device = model.device # 获取模型所在的设备\n", + "device" ] }, { @@ -434,117 +594,70 @@ }, { "cell_type": "code", - "execution_count": 26, - "id": "0667ebea", + "execution_count": 32, + "id": "28c9818a-5225-4b05-a69c-3b490fd70d47", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "100%|██████████| 115/115 [00:26<00:00, 4.38it/s]\n", - "100%|██████████| 13/13 [00:01<00:00, 7.83it/s]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "epoch 0: {'accuracy': 0.6985294117647058, 'f1': 0.8183161004431314}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 115/115 [00:26<00:00, 4.42it/s]\n", - "100%|██████████| 13/13 [00:01<00:00, 7.78it/s]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "epoch 1: {'accuracy': 0.7009803921568627, 'f1': 0.8195266272189349}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 115/115 [00:26<00:00, 4.38it/s]\n", - "100%|██████████| 13/13 [00:01<00:00, 7.76it/s]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "epoch 2: {'accuracy': 0.7083333333333334, 'f1': 0.8231797919762258}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 115/115 [00:26<00:00, 4.39it/s]\n", - "100%|██████████| 13/13 [00:01<00:00, 8.15it/s]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "epoch 3: {'accuracy': 0.7009803921568627, 'f1': 0.8195266272189349}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "100%|██████████| 115/115 [00:27<00:00, 4.21it/s]\n", - "100%|██████████| 13/13 [00:01<00:00, 8.02it/s]" + "100%|██████████| 115/115 [00:26<00:00, 4.31it/s]\n", + "100%|██████████| 13/13 [00:02<00:00, 5.26it/s]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "epoch 4: {'accuracy': 0.7009803921568627, 'f1': 0.8195266272189349}\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\n" + "epoch 0: {'accuracy': 0.6838235294117647, 'f1': 0.8122270742358079}\n" ] } ], "source": [ - "from mindnlp.core import value_and_grad\n", - "def forward_fn(**batch):\n", - " outputs = model(**batch)\n", - " loss = outputs.loss\n", - " return loss\n", - "\n", - "grad_fn = value_and_grad(forward_fn, tuple(model.parameters()))\n", + "import mindtorch\n", "\n", "for epoch in range(num_epochs):\n", - " model.set_train()\n", - " train_total_size = train_dataset.get_dataset_size()\n", - " for step, batch in enumerate(tqdm(train_dataset.create_dict_iterator(), total=train_total_size)):\n", - " optimizer.zero_grad()\n", - " loss = grad_fn(**batch)\n", + " # 训练阶段\n", + " model.train()\n", + " train_total_size = len(train_dataloader)\n", + " for step, batch in enumerate(tqdm(train_dataloader, total=train_total_size)):\n", + " \n", + " # 将batch中的所有张量移动到模型所在的设备\n", + " batch_on_device = {}\n", + " for key, value in batch.items():\n", + " if mindtorch.is_tensor(value):\n", + " batch_on_device[key] = value.to(device)\n", + " else:\n", + " batch_on_device[key] = value\n", + " \n", + " # 手动清零梯度,避免调用optimizer.zero_grad()\n", + " for param in model.parameters():\n", + " if param.grad is not None:\n", + " param.grad = None \n", + " \n", + " outputs = model(**batch_on_device)\n", + " loss = outputs.loss\n", + " loss.backward()\n", " optimizer.step()\n", " lr_scheduler.step()\n", "\n", - " model.set_train(False)\n", - " eval_total_size = eval_dataset.get_dataset_size()\n", - " for step, batch in enumerate(tqdm(eval_dataset.create_dict_iterator(), total=eval_total_size)):\n", - " outputs = model(**batch)\n", - " predictions = outputs.logits.argmax(axis=-1)\n", - " predictions, references = predictions, batch[\"labels\"]\n", + " # 评估阶段\n", + " model.eval()\n", + " eval_total_size = len(eval_dataloader)\n", + " for step, batch in enumerate(tqdm(eval_dataloader, total=eval_total_size)): \n", + " # 将batch中的所有张量移动到模型所在的设备\n", + " batch_on_device = {}\n", + " for key, value in batch.items():\n", + " if mindtorch.is_tensor(value):\n", + " batch_on_device[key] = value.to(device)\n", + " else:\n", + " batch_on_device[key] = value\n", + " with torch.no_grad():\n", + " outputs = model(**batch_on_device)\n", + " \n", + " predictions = outputs.logits.argmax(dim=-1)\n", + " predictions, references = predictions.asnumpy(), batch[\"labels\"].asnumpy()\n", " metric.add_batch(\n", " predictions=predictions,\n", " references=references,\n", @@ -553,22 +666,6 @@ " eval_metric = metric.compute()\n", " print(f\"epoch {epoch}:\", eval_metric)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4de28f75", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7cb41077-b027-4c0f-87ed-380cd816d2f4", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -584,9 +681,9 @@ "name": "mindspore1.7.0-cuda10.1-py3.7-ubuntu18.04" }, "kernelspec": { - "display_name": "MindSpore", + "display_name": "Python 3.10", "language": "python", - "name": "mindspore" + "name": "py310" }, "language_info": { "codemirror_mode": { @@ -598,7 +695,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.10" + "version": "3.10.14" }, "vscode": { "interpreter": { diff --git a/03.MindSpore_Compatible_Training_Course/Chapter2/pretrain.md b/03.MindSpore_Compatible_Training_Course/Chapter2/pretrain.md index 405fd26..f50e06d 100644 --- a/03.MindSpore_Compatible_Training_Course/Chapter2/pretrain.md +++ b/03.MindSpore_Compatible_Training_Course/Chapter2/pretrain.md @@ -117,7 +117,7 @@ INFO:root:Done! mkdir dataset cd dataset/ -wget https://hf-mirror.com/datasets/tatsu-lab/alpaca/blob/main/data/train-00000-of-00001-a09b74b3ef9c3b56.parquet +wget https://modelscope.cn/datasets/angelala00/tatsu-lab-alpaca/resolve/master/train-00000-of-00001-a09b74b3ef9c3b56.parquet cd .. ``` From c523607354c2775a26d2599034fb5c2b5f0dd238 Mon Sep 17 00:00:00 2001 From: cuiluyuan Date: Fri, 19 Dec 2025 10:09:14 +0800 Subject: [PATCH 2/2] delete bert_pretain --- .../01.BERT/bert_pretrain.ipynb | 68 ------------------- 1 file changed, 68 deletions(-) delete mode 100644 01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/01.BERT/bert_pretrain.ipynb diff --git a/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/01.BERT/bert_pretrain.ipynb b/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/01.BERT/bert_pretrain.ipynb deleted file mode 100644 index 860c363..0000000 --- a/01.LLM_Theory_Course/01.Industry_Model_Introduction/01.Classic_Model_Technical_Analysis/01.BERT/bert_pretrain.ipynb +++ /dev/null @@ -1,68 +0,0 @@ -{ - "cells": [ - { - "attachments": { - "image.png": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABbIAAAKwCAIAAADC6B5fAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAFsqADAAQAAAABAAACsAAAAACtU0ddAABAAElEQVR4AeydB5gUxdaGp3tm87ILu+QcJSsgSlBJiooBMWC85hxRr+HHeM1evV5zvuYMigoqYsAIioCCYCDnDJvzzkz/32zv9vZU98zO7KSema+ffaC6+lTVqbd6t2rOnDolKYpi40UCJEACJEACJEACJEACJEACJEACJEACyUdATr4us8ckQAIkQAIkQAIkQAIkQAIkQAIkQAIk4CFAswjfAxIgARIgARIgARIgARIgARIgARIggSQlQLNIkg48u00CJEACJEACJEACJEACJEACJEACJECzCN8BEiABEiABEiABEiABEiABEiABEiCBJCVAs0iSDjy7TQIkQAIkQAIkQAIkQAIkQAIkQAIkQLMI3wESIAESIAESIAESIAESIAESIAESIIEkJUCzSJIOPLtNAiRAAiRAAiRAAiRAAiRAAiRAAiRAswjfARIgARIgARIgARIgARIgARIgARIggSQlQLNIkg48u00CJEACJEACJEACJEACJEACJEACJECzCN8BEiABEiABEiABEiABEiABEiABEiCBJCVAs0iSDjy7TQIkQAIkQAIkQAIkQAIkQAIkQAIkQLMI3wESIAESIAESIAESIAESIAESIAESIIEkJUCzSJIOPLtNAiRAAiRAAiRAAiRAAiRAAiRAAiRAswjfARIgARIgARIgARIgARIgARIgARIggSQlQLNIkg48u00CJEACJEACJEACJEACJEACJEACJECzCN8BEiABEiABEiABEiABEiABEiABEiCBJCVAs0iSDjy7TQIkQAIkQAIkQAIkQAIkQAIkQAIkQLMI3wESIAESIAESIAESIAESIAESIAESIIEkJUCzSJIOPLtNAiRAAiRAAiRAAiRAAiRAAiRAAiRAswjfARIgARIgARIgARIgARIgARIgARIggSQlQLNIkg48u00CJEACJEACJEACJEACJEACJEACJECzCN8BEiABEiABEiABEiABEiABEiABEiCBJCVAs0iSDjy7TQIkQAIkQAIkQAIkQAIkQAIkQAIkQLMI3wESIAESIAESIAESIAESIAESIAESIIEkJUCzSJIOPLtNAiRAAiRAAiRAAiRAAiRAAiRAAiRAswjfARIgARIgARIgARIgARIgARIgARIggSQlQLNIkg48u00CJEACJEACJEACJEACJEACJEACJECzCN8BEiABEiABEiABEiABEiABEiABEiCBJCVAs0iSDjy7TQIkQAIkQAIkQAIkQAIkQAIkQAIk4CACErA+gWnTpi1ZsiRAPe12e15eXuvWrTt37nzEEUeMHDnS4eB7HiC8ZBRbvXr1559/vmLFil27dpWVleXn57dv33706NETJ07EW5SMRNhnEiABEiCBJCbARVcSD35Uu15UVFReXq41mZqa2qZNG+2WCRKIMgFJUZQoN8nmSCBYArBufP3118GWUuVzc3OvvPLKm266CYnm1cBSiUrgyy+/vPnmm3/77TfTDsqyfPLJJ99///29e/c2FWAmCZAACZAACSQeAS66Em9Mrdmj4cOHL126VNNt1KhRCxcu1G6ZIIEoE+AmmigDZ3PRJlBcXIxPtj179oRHQLTbZntWJVBbW3vWWWcdeeSRvmwiUNztds+cOXPAgAHPPPOMVftBvUiABEiABEjAQgS46LLQYFhblT/++ENvE7G2stQuKQjQLJIUw8xOFhQUHHfccW+88QZRkEBVVdWJJ5749ttvB4ICBhR4Gz3wwAOBCFOGBEiABEiABEiAiy6+A00SePXVV5uUoQAJRJMAzSLRpM22YknA5XJdddVVO3fujKUSbNsCBG699dZPP/00KEVuueWWTz75JKgiFCYBEiABEiCBpCXARVfSDn0gHf/qq6+effbZQCQpQwJRI0CzSNRQs6HYEygpKUEsidjrQQ1iRwCxex9//HHT9jMzM/v37y9JkunTyy+/HO+P6SNmkgAJkAAJkAAJCAS46BKA8FYl8OGHH8KDWx9slWRIwAoEaBaxwihQh+YQOOGEExAwWH/hq4k9e/b89ddfL7744rhx40wrxT6an376yfQRM5OBwPXXX4/3ROhpv3795s+fD6ffP//8c/fu3S+99FJ6erogs3Xr1oceekjI5C0JkAAJkAAJJAMBLrqSYZQj2kfsSp49ezaC2U+dOrW6ujqibbFyEmgGAZpFmgGNRSxKAEeH4ERVfMS96KKLvvnmG9MPsTCj4EOvRTtAtSJMYNWq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Kh98sJLfGFpVyslVn8tjxtr27lXTnn9TUurzjzrKpjllpDSsRlJT9Y3aGrY6ojZ9vtS7d32F7dp75e+/v5ovde/uld+wcVXq398rv3M9HHnYMEW/V7ShI/Ihhyhd60/k8dScmanWLx8+wVba4G6DLDWErSTpK7dpsVozM73yO3VSK+G/JEACJEACJEACFiHQsBCxiDpUgwRIgARIgARIIBACdof97vr4IF7i+fmm+VLPnub5Q4fahw71qqHuRho33j5uvDFfnnKiDT+GSz73PEOeJ8N+zTTz/NvF2FgesawsUyVtiFdq1lmYOczzR46yjxxlbFc+6mgbfgyXfOppNvwYLvniSwx5ngz7jTeb5CNUkpmStrw883yTKphFAiRAAiRAAiTQSAA7dBpvIpmiWSSSdFk3CZAACZAACZAACViSwIwZMyypF5UiARIgARIggWgTsJBZRJueteMtTj3VE8XdeOHsAEUNb2Z81pCDswOMxwc0PKz//4G6S8gUbj/55BMhx3i7adMmY6Y+Jycnp0mFD4GnblOduqzu0tdsTD9ddxnz9Tnff/+9/tY0XahF7zN9bLN17ty5SYUnTZrUpMxNdZePRuqz36i7/MssW7bMvwCeuhCJ0O81YMCAJhU+re7yW43t3rrLv8zHH3/sXwBP169f718mKyurSYVHjhzZpMzFdZf/tp6ou/zLfPPNN/4F8HSv3p3eTLpDhw5NKnzkkUc2KfPPusushca8V+uuxnuz1NKlS82yvfJqGqJOeuXqbvr27dukwqecckqTMnfVXbqKTZKzZs0yyfXOWtNwSoh3duNdenp6k8ocdNBBTcpcUHc11muWerTuMnvSmPfVV1813vhI7dq1y8eT+uy2bds2qfDhhx/epMz999/vvyE+JYG4IIDZLC70pJIkQAIkQAIkEGkCUpPrv0hroNVv9JCxjm6akkyQAAmQAAmQAAmQQAIQ4LorAQaRXSABEiCBxCYQtanKQt4iiT2i7B0JkAAJkAAJkAAJkAAJkAAJkAAJkECABKLmoktvkQBHhGIkQAIkQAIkQAIkkDgEovYVXOIgY09IgARIgAQSlICcoP1it0iABEiABEiABEiABEiABEiABEiABEigCQLcRNMEID4mARIgARIgARIggcQjcNVVVyVep9gjEiABEiABEmgGAQuZRTg9N2P8WIQESIAESCDKBC688EKhxZdeeknI4S0JWJ/Ak08+aX0lqSEJkAAJkAAJRIGAhWKLRKG3bIIESIAESIAEQiTAiAwhAmRxEiABEiABEiABErAUAQt5i1iKC5UhARIgARIgARIgARIgARIgARIgARKIFYGouejSWyRWQ8x2SYAESCBeCezs2TVeVQ+H3h02bBGq2dGji5DDWxIgARIgARIgARIIL4H26zeHt0Lr1xY1F12eRGP9l4EakgAJkAAJkAAJkAAJkAAJkAAJJDWBJP9eKqJjz000EcXLykmABEgg0QhwSk60EWV/kpXAvwuLha7f3CpXyOEtCZAACZAACSQDAQuZRW6//XaB+D333CPk8JYESIAESIAEYkvg9XatY6sAWyeBsBB4rKhEqIdmEQEIb0mABEiABJKEgIVii0Rt41CSDC27SQIkQAKRIKD3FknCPa6RQMo6SSAmBLjuigl2NkoCJEACwRJI5qVX1KYqC3mLBPt+UJ4ESIAESIAESIAESIAESIAESIAESCAhCcyZMyc6/aJZJDqc2QoJkAAJkAAJkAAJkAAJkAAJkAAJkECgBI477rhARUOT40k0ofFjaRIgARIgARIgARIgARIgARIgARIggbglQG+RuB06Kk4CJEACJEACJEACzSXw/PPPN7coy5EACZAACZBAQhGwkFmE03NCvVnsDAmQAAkkKIGDDz5Y6Nkvv/wi5PCWBKxP4JJLLrG+ktSQBEiABEiABKJAwEIn0USht2yCBEiABEggRALJHA5dRRe1oOghjhSLkwAJkAAJkAAJJAABLr2iMIgW8haJQm/ZBAmQAAmQAAmQAAmQAAmQAAmQAAmQgPUJRM1Fl2YR678M1JAESIAESIAESIAESIAESIAESIAEkovA4sWLo9NhnkQTHc5shQRIgARIgARIgARIgARIgARIgARIwHIE6C1iuSGhQiRAAiRAAiRAAiQQaQJTpkwRmvjoo4+EHN6SAAmQAAmQQDIQsJBZhNNzMrxw7CMJkAAJxDuBjRs3xnsXqD8JgMDHH39MDiRAAiRAAiRAAiBgIbMIp2e+kSRAAiRAAtYn0K1bN+srSQ1JgARIgARIgARIgAQCJGAhs0iAGlOMBEiABEiABEiABEiABEiABEiABEggsQlEzUWXZpHEfpHYOxIgARIgARIgARIgARIgARIgARKIPwJRc9HlSTTx93JQYxIg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+/bta2pLqVUe3SLUTg0qhgggAohAZBBAbg6M+9ChQwML4FNEwBQIeOcDam1tNYXmqCQigAggAtGHALhCRnRePpOGLFq0KPpMpsoiijbRID1TtTJQGZ8IYCSnT1iwEhHQFQFKwjh1tRE7RwSMR8D720hMHmz8LOCIQRHAV6+gEKEAIqAHApS8fRlGVRRFi7S1tekxo9gnIoAIIAKIACKACCACiAAigAggAogAIoAImAsBw0J0KXKLmGuGUFtEABFABBABRAARQAQQAUQAEUAEEAFEIGwE1qxZE3Zb74ZpaWnFxcXe9eatKSkpMUZ5dIsYgzOOggggAoiACRBAbjbBJKGKiAAigAggAogAIhAtCNx8880amjJx4sR//etfGnYYO12hWyR25hotRQQQAUQgCALIzUEAwseIQBQhkJKSEkXWoCmIACKACCACiED4CFDkFkF6Dn8asSUigAggAoiAUQj8/PPPiqFOOOEERQ3eIgL0I9DU1ES/kqghIoAIIALRjUBWVpa3gc3Nze3t7VAPCUfhfEBvAX816enp/h5hfWAEKHKLID0Hnip8igggAoiA3gggN6tB+MQTT1SI4fkdCkDwFhFABBABRAARQATUIPDRRx95i+3bt++6666DT8fwgjFv3rxLLrnEWwZrtEWAIreItoZhb4gAIoAIIAKhIoDcHCpiKI8IIAKIACKACCACiIC2CBQVFT366KN/+9vfbDbbf//734SEBHCOaDuEWXozLESX4HdcZlkTqCcNCKxYsYIGNVAHRMBgBLZu3eriZhj3hhtuMJibp02bZrC9gYeDiFaFADKpAhC8RQQQAURAKwTw1UsrJLEf0yHw66+/3nLLLYIgwIvHrbfeeuaZZxppAiVvX4a9dLFGgotjIQKIACKACJgRgVGjRj3wwAMs66SMp5566tNPPzWjFagzIoAIIAKIACKACCACpkCgpqbmvffeA58IaAvfvjz22GPffPONKTQ3qZK4icakE4dqIwKIACJgHALe3BwfHz9r1izjNMCREAFEQGsE9u7dq+hy0KBBihq8RQQQAUQAETAegU8++eSZZ55paWmRhgb/CHxBBW9f3gnOJBks9AQBitwiSM89mUhsiwggAoiATgggNyuAPe+88xQ1eIsImBGBwYMHK9TG7WAKQPAWEUAEEAGDETh8+PAjjzyybt06adz+/fuPHj0a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+vJEbyAAAiAAAiAAAiAAAiAAAiAAAiAAAhFDQBuwbRDFv/zyS9fIdoPoBjVAAARAAARAAARAINIJ0LtWpE8B+oMACIAACICALgQM6hbRZW7oBARAAARAAARAAARAwC0B/P7kFgsqQQAEQAAEYpAAFtHE4E3HlEEABEAABEAABEAABEAABEAABEAABOwEDBQtQruueLknrnsHuApr9g5wFaC9A7yPQk0mTJjQrMx9DYdr/+qaTxsOdY1redOmTa6V6hpK59OsMv37929WZlrDoe7Ztfx0w+Far66ZP3+++tRtuaCgwG29UpmWltaswqeffnqzMjc0HEq3bguvNxxuLymVv/32m1L2VCgtLfV0Sa5v3759swqPGzeuWZm7Gw7vY33ccHiXWb9+vXcBuiqKoneZPn36NKvwxQ2H936eaDi8y3zzzTfeBejqnj17vMskJyc3q/App5zSrMy1DYf3sV5tOLzLLF261LsAXS0uLvYu06ZNm2YVPuecc5qVuaPh8D7WfxsO7zJr1671LkBXrVard5mePXs2q/DkyZOblXm04fA+li/LBHbt2uW9k4SEhGaV8d4DroIACIAACIAACIAACBiWQPPfug2rOhQDARAAARAAARAAARAAARAAARAAARAAgUAIYBFNIPTQFgRAAARAAARAAARAAARAAARAAARAIIIJwC0SwTcPqoMACIAACIAACIAACIAACIAACIAACARCAG6RQOihLQiAAAiAAAiAAAiAAAiAAAiAAAiAQAQTgFskgm8eVAcBEAABEAABEAABEAABEAABEAABEAiEANwigdBDWxAAARAAARAAARAAARAAARAAARAAgQgmALdIBN88qA4CIAACIAACIAACIAACIAACIAACIBAIAbhFAqGHtiAAAiAAAiAAAiAAAiAAAiAAAiAAAhFMAG6RCL55UB0EQAAEQAAEQAAEQAAEQAAEQAAEQCAQAnCLBEIPbUEABEAABEAABEAABEAABEAABEAABCKYANwiEXzzoDoIgAAIgAAIgAAIgAAIgAAIgAAIgEAgBOAWCYQe2oIACIAACIAACIAACIAACIAACIAACEQwAbhFIvjmQXUQAAEQAAEQAAEQAAEQAAEQAAEQAIFACMAtEgg9tAUBEAABEAABEAABEAABEAABEAABEIhgAnCLRPDNg+ogAAIgAAIgAAIgAAIgAAIgAAIgAAKBEIBbJBB6aAsCIAACIAACIAACIAACIAACIAACIBDBBOAWieCbB9VBAARAAARAAARAAARAAARAAARAAAQCIQC3SCD00BYEQAAEQAAEQAAEQAAEQAAEQAAEQCCCCcAtEsE3D6qDAAiAAAiAAAiAAAiAAAiAAAiAAAgEQgBukUDooS0IgAAIgAAIgAAIgAAIgAAIgAAIgEAEE4BbJIJvHlQHARAAARAAARAAARAAARAAARAAARAIhADcIoHQQ1sQAAEQAAEQAAEQAAEQAAEQAAEQAIEIJgC3SATfPKgOAiAAAiAAAiAAAiAAAiAAAiAAAiAQCAG4RQKhh7YgAAIgAAIgAAIgAAIgAAIgAAIgAAIRTABukQi+eVAdBEAABEAABEAABEAABEAABEAABEAgEAJwiwRCD21BAARAAARAAARAAARAAARAAARAAAQimMD/A4pDdVbRtjUVAAAAAElFTkSuQmCC" - } - }, - "cell_type": "markdown", - "id": "da7c69f9", - "metadata": {}, - "source": [ - "### DataParallel\n", - "\n", - "![image.png](attachment:image.png)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "48000382", - "metadata": {}, - "outputs": [], - "source": [ - "mean = _get_gradients_mean()\n", - "degree = _get_device_num()\n", - "grad_reducer = nn.DistributedGradReducer(optimizer.parameters, mean, degree)\n", - "\n", - "def train_step(input_ids, input_mask, masked_lm_ids, masked_lm_positions, masked_lm_weights, \\\n", - " next_sentence_label, segment_ids):\n", - " status = init_register()\n", - " input_ids = ops.depend(input_ids, status)\n", - " (total_loss, masked_lm_loss, next_sentence_loss), grads = grad_fn(input_ids, input_mask, segment_ids, \\\n", - " masked_lm_ids, masked_lm_positions, masked_lm_weights, next_sentence_label)\n", - " grads = clip_by_global_norm(grads, clip_norm=1.0)\n", - " grads = grad_reducer(grads)\n", - " status = all_finite(grads, status)\n", - " if status:\n", - " total_loss = loss_scaler.unscale(total_loss)\n", - " grads = loss_scaler.unscale(grads)\n", - " total_loss = ops.depend(total_loss, optimizer(grads))\n", - " total_loss = ops.depend(total_loss, loss_scaler.adjust(status))\n", - " return total_loss, masked_lm_loss, next_sentence_loss, status" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.5" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -}