|
|
@@ -0,0 +1,565 @@
|
|
|
+{
|
|
|
+ "cells": [
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# 命名实体识别"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 1,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "0.5\n",
|
|
|
+ " precision recall f1-score support\n",
|
|
|
+ "\n",
|
|
|
+ " MISC 0.00 0.00 0.00 1\n",
|
|
|
+ " PER 1.00 1.00 1.00 1\n",
|
|
|
+ "\n",
|
|
|
+ " micro avg 0.50 0.50 0.50 2\n",
|
|
|
+ " macro avg 0.50 0.50 0.50 2\n",
|
|
|
+ "weighted avg 0.50 0.50 0.50 2\n",
|
|
|
+ "\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "from seqeval.metrics import accuracy_score\n",
|
|
|
+ "from seqeval.metrics import classification_report\n",
|
|
|
+ "from seqeval.metrics import f1_score\n",
|
|
|
+ "y_true = [['O', 'O', 'O', 'B-MISC', 'I-MISC', 'I-MISC', 'O'], ['B-PER', 'I-PER', 'O']]\n",
|
|
|
+ "y_pred = [['O', 'O', 'B-MISC', 'I-MISC', 'I-MISC', 'I-MISC', 'O'], ['B-PER', 'I-PER', 'O']]\n",
|
|
|
+ "print(f1_score(y_true, y_pred))\n",
|
|
|
+ "print(classification_report(y_true, y_pred))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 2,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stderr",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "d:\\gitcode\\.venv\\Lib\\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"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "#1导入相关包\n",
|
|
|
+ "import evaluate\n",
|
|
|
+ "from datasets import load_dataset\n",
|
|
|
+ "from transformers import AutoTokenizer, AutoModelForTokenClassification, TrainingArguments, Trainer, DataCollatorForTokenClassification"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stderr",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Generating train split: 100%|██████████| 20865/20865 [00:00<00:00, 205845.42 examples/s]\n",
|
|
|
+ "Generating validation split: 100%|██████████| 2319/2319 [00:00<00:00, 278085.34 examples/s]\n",
|
|
|
+ "Generating test split: 100%|██████████| 4637/4637 [00:00<00:00, 343925.51 examples/s]\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "#2加载数据集\n",
|
|
|
+ "# 直接使用load_dataset进行加载\n",
|
|
|
+ "ner_datasets = load_dataset(\"D:/gitcode/data/peoples-daily-ner\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 4,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "{'id': '0',\n",
|
|
|
+ " 'tokens': ['海',\n",
|
|
|
+ " '钓',\n",
|
|
|
+ " '比',\n",
|
|
|
+ " '赛',\n",
|
|
|
+ " '地',\n",
|
|
|
+ " '点',\n",
|
|
|
+ " '在',\n",
|
|
|
+ " '厦',\n",
|
|
|
+ " '门',\n",
|
|
|
+ " '与',\n",
|
|
|
+ " '金',\n",
|
|
|
+ " '门',\n",
|
|
|
+ " '之',\n",
|
|
|
+ " '间',\n",
|
|
|
+ " '的',\n",
|
|
|
+ " '海',\n",
|
|
|
+ " '域',\n",
|
|
|
+ " '。'],\n",
|
|
|
+ " 'ner_tags': [0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 5, 6, 0, 0, 0, 0, 0, 0]}"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 4,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "ner_datasets[\"train\"][0]"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 5,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "{'id': Value(dtype='string', id=None),\n",
|
|
|
+ " 'tokens': Sequence(feature=Value(dtype='string', id=None), length=-1, id=None),\n",
|
|
|
+ " 'ner_tags': Sequence(feature=ClassLabel(names=['O', 'B-PER', 'I-PER', 'B-ORG', 'I-ORG', 'B-LOC', 'I-LOC'], id=None), length=-1, id=None)}"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 5,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "ner_datasets[\"train\"].features"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 6,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "['O', 'B-PER', 'I-PER', 'B-ORG', 'I-ORG', 'B-LOC', 'I-LOC']"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 6,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "label_list = ner_datasets[\"train\"].features[\"ner_tags\"].feature.names\n",
|
|
|
+ "label_list"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 4,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "#3数据预处理\n",
|
|
|
+ "tokenizer = AutoTokenizer.from_pretrained(\"D:/gitcode/model/chinese-macbert-base\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 5,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "{'input_ids': [[101, 3862, 102], [101, 7157, 102], [101, 3683, 102], [101, 6612, 102], [101, 1765, 102], [101, 4157, 102], [101, 1762, 102], [101, 1336, 102], [101, 7305, 102], [101, 680, 102], [101, 7032, 102], [101, 7305, 102], [101, 722, 102], [101, 7313, 102], [101, 4638, 102], [101, 3862, 102], [101, 1818, 102], [101, 511, 102]], 'token_type_ids': [[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, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]]}"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 5,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "tokenizer(ner_datasets[\"train\"][0][\"tokens\"]) "
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 6,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "{'input_ids': [101, 3862, 7157, 3683, 6612, 1765, 4157, 1762, 1336, 7305, 680, 7032, 7305, 722, 7313, 4638, 3862, 1818, 511, 102], 'token_type_ids': [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, 1, 1, 1, 1, 1, 1]}"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 6,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "# 对于已经做好tokenize的数据,要指定is_split_into_words参数为True\n",
|
|
|
+ "tokenizer(ner_datasets[\"train\"][0][\"tokens\"], is_split_into_words=True) "
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "{'input_ids': [101, 10673, 12865, 12921, 8181, 8681, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1]}"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 7,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "#有可能一个英文的词,拆成几个token\n",
|
|
|
+ "#所以要对标签做一下额外的处理\n",
|
|
|
+ "res = tokenizer(\"interesting word\")\n",
|
|
|
+ "res"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 8,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "[None, 0, 0, 0, 0, 1, None]"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 8,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "#若一个单词被拆成了多个token\n",
|
|
|
+ "#如果这些token来自于同一个词,那么这些对应id是相同的\n",
|
|
|
+ "res.word_ids()"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 9,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# 借助word_ids 实现标签映射\n",
|
|
|
+ "def process_function(examples):\n",
|
|
|
+ " tokenized_exmaples = tokenizer(examples[\"tokens\"],\n",
|
|
|
+ " max_length=128, \n",
|
|
|
+ " truncation=True, \n",
|
|
|
+ " is_split_into_words=True)\n",
|
|
|
+ " #return tokenized_exmaples\n",
|
|
|
+ " labels = []\n",
|
|
|
+ " for i, label in enumerate(examples[\"ner_tags\"]):\n",
|
|
|
+ " word_ids = tokenized_exmaples.word_ids(batch_index=i)\n",
|
|
|
+ " label_ids = []\n",
|
|
|
+ " for word_id in word_ids:\n",
|
|
|
+ " if word_id is None:\n",
|
|
|
+ " #CLS SEP 不参与计算\n",
|
|
|
+ " #在cross loss 中-100不参与运算\n",
|
|
|
+ " label_ids.append(-100)\n",
|
|
|
+ " else:\n",
|
|
|
+ " label_ids.append(label[word_id])\n",
|
|
|
+ " labels.append(label_ids)\n",
|
|
|
+ " tokenized_exmaples[\"labels\"] = labels\n",
|
|
|
+ " return tokenized_exmaples"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 10,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stderr",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Map: 100%|██████████| 20865/20865 [00:02<00:00, 9362.95 examples/s] \n",
|
|
|
+ "Map: 100%|██████████| 2319/2319 [00:00<00:00, 8915.19 examples/s] \n",
|
|
|
+ "Map: 100%|██████████| 4637/4637 [00:00<00:00, 9948.85 examples/s] \n"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "DatasetDict({\n",
|
|
|
+ " train: Dataset({\n",
|
|
|
+ " features: ['id', 'tokens', 'ner_tags', 'input_ids', 'token_type_ids', 'attention_mask', 'labels'],\n",
|
|
|
+ " num_rows: 20865\n",
|
|
|
+ " })\n",
|
|
|
+ " validation: Dataset({\n",
|
|
|
+ " features: ['id', 'tokens', 'ner_tags', 'input_ids', 'token_type_ids', 'attention_mask', 'labels'],\n",
|
|
|
+ " num_rows: 2319\n",
|
|
|
+ " })\n",
|
|
|
+ " test: Dataset({\n",
|
|
|
+ " features: ['id', 'tokens', 'ner_tags', 'input_ids', 'token_type_ids', 'attention_mask', 'labels'],\n",
|
|
|
+ " num_rows: 4637\n",
|
|
|
+ " })\n",
|
|
|
+ "})"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 10,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "tokenized_datasets = ner_datasets.map(process_function, batched=True)\n",
|
|
|
+ "tokenized_datasets"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 11,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "{'id': '0', 'tokens': ['海', '钓', '比', '赛', '地', '点', '在', '厦', '门', '与', '金', '门', '之', '间', '的', '海', '域', '。'], 'ner_tags': [0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 5, 6, 0, 0, 0, 0, 0, 0], 'input_ids': [101, 3862, 7157, 3683, 6612, 1765, 4157, 1762, 1336, 7305, 680, 7032, 7305, 722, 7313, 4638, 3862, 1818, 511, 102], 'token_type_ids': [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, 1, 1, 1, 1, 1, 1], 'labels': [-100, 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 5, 6, 0, 0, 0, 0, 0, 0, -100]}\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "print(tokenized_datasets[\"train\"][0])"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stderr",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Some weights of BertForTokenClassification were not initialized from the model checkpoint at /teacher_train/model/chinese-macbert-base and are newly initialized: ['classifier.bias', 'classifier.weight']\n",
|
|
|
+ "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "#4创建模型\n",
|
|
|
+ "# 对于所有的非二分类任务,切记要指定num_labels,否则就会device错误\n",
|
|
|
+ "model = AutoModelForTokenClassification.from_pretrained(\"/teacher_train/model/chinese-macbert-base\",\n",
|
|
|
+ " num_labels=len(label_list))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 21,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "7"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 21,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "model.config.num_labels"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "#5创建评估函数\n",
|
|
|
+ "# 这里方便大家加载,替换成了本地的加载方式,无需额外下载\n",
|
|
|
+ "seqeval = evaluate.load(\"seqeval\")\n",
|
|
|
+ "seqeval"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 14,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "import numpy as np\n",
|
|
|
+ "\n",
|
|
|
+ " # predictions = [['O', 'O', 'B-MISC', 'I-MISC', 'I-MISC', 'I-MISC', 'O'], ['B-PER', 'I-PER', 'O']]\n",
|
|
|
+ " # references = [['O', 'O', 'O', 'B-MISC', 'I-MISC', 'I-MISC', 'O'], ['B-PER', 'I-PER', 'O']]\n",
|
|
|
+ "\n",
|
|
|
+ "def eval_metric(pred):\n",
|
|
|
+ " predictions, labels = pred\n",
|
|
|
+ " predictions = np.argmax(predictions, axis=-1)\n",
|
|
|
+ "\n",
|
|
|
+ " # 将id转换为原始的字符串类型的标签\n",
|
|
|
+ " true_predictions = [\n",
|
|
|
+ " [label_list[p] for p, l in zip(prediction, label) if l != -100]\n",
|
|
|
+ " for prediction, label in zip(predictions, labels) \n",
|
|
|
+ " ]\n",
|
|
|
+ "\n",
|
|
|
+ " true_labels = [\n",
|
|
|
+ " [label_list[l] for p, l in zip(prediction, label) if l != -100]\n",
|
|
|
+ " for prediction, label in zip(predictions, labels) \n",
|
|
|
+ " ]\n",
|
|
|
+ "\n",
|
|
|
+ " result = seqeval.compute(predictions=true_predictions, references=true_labels, scheme=\"IOB2\")\n",
|
|
|
+ "\n",
|
|
|
+ " return {\n",
|
|
|
+ " \"f1\": result[\"overall_f1\"]\n",
|
|
|
+ " }\n",
|
|
|
+ " "
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "args = TrainingArguments(\n",
|
|
|
+ " output_dir=\"models_for_ner\",\n",
|
|
|
+ " logging_dir=\"./logs\",\n",
|
|
|
+ " per_device_train_batch_size=64,\n",
|
|
|
+ " per_device_eval_batch_size=128,\n",
|
|
|
+ " eval_strategy=\"epoch\",\n",
|
|
|
+ " save_strategy=\"epoch\",\n",
|
|
|
+ " metric_for_best_model=\"f1\",\n",
|
|
|
+ " load_best_model_at_end=True,\n",
|
|
|
+ " logging_steps=50,\n",
|
|
|
+ " num_train_epochs=1\n",
|
|
|
+ ")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 28,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stderr",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "/tmp/ipykernel_3129756/746877450.py:9: FutureWarning: `tokenizer` is deprecated and will be removed in version 5.0.0 for `Trainer.__init__`. Use `processing_class` instead.\n",
|
|
|
+ " trainer = Trainer(\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "#7创建训练器\n",
|
|
|
+ "\"\"\"\n",
|
|
|
+ "DataCollatorForTokenClassification类适用于序列标注任务(token classification),\n",
|
|
|
+ "比如命名实体识别(NER),每个token都会对应一个预测label,\n",
|
|
|
+ "当一个序列的token比label多时,对额外的label位置添加-100处理,\n",
|
|
|
+ "使得在计算交叉熵损失时,-100位置的label损失为0不用考虑。\n",
|
|
|
+ "使得所有序列保持同一长度,同时对token多于label的场景使用-100进行填充。\n",
|
|
|
+ "\"\"\"\n",
|
|
|
+ "trainer = Trainer(\n",
|
|
|
+ " model=model,\n",
|
|
|
+ " args=args,\n",
|
|
|
+ " tokenizer=tokenizer,\n",
|
|
|
+ " train_dataset=tokenized_datasets[\"train\"],\n",
|
|
|
+ " eval_dataset=tokenized_datasets[\"validation\"],\n",
|
|
|
+ " compute_metrics=eval_metric,\n",
|
|
|
+ " data_collator=DataCollatorForTokenClassification(tokenizer=tokenizer)\n",
|
|
|
+ ")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "#8模型训练\n",
|
|
|
+ "trainer.train()"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "#9评估\n",
|
|
|
+ "trainer.evaluate(eval_dataset=tokenized_datasets[\"test\"])"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "#10模型预测\n",
|
|
|
+ "from transformers import pipeline\n",
|
|
|
+ "# 使用pipeline进行推理,要指定id2label\n",
|
|
|
+ "model.config.id2label = {idx: label for idx, label in enumerate(label_list)}\n",
|
|
|
+ "model.config"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "# 如果模型是基于GPU训练的,那么推理时要指定device\n",
|
|
|
+ "# 对于NER任务,可以指定aggregation_strategy为simple,得到具体的实体的结果,而不是token的结果\n",
|
|
|
+ "ner_pipe = pipeline(\"token-classification\", model=model, tokenizer=tokenizer, device=0, aggregation_strategy=\"simple\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": null,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": []
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "metadata": {
|
|
|
+ "kernelspec": {
|
|
|
+ "display_name": "gitcode",
|
|
|
+ "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.11.15"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "nbformat": 4,
|
|
|
+ "nbformat_minor": 2
|
|
|
+}
|