tnblog
首页
视频
资源
登录

HugginFace 使用训练工具(学习笔记)

5260人阅读 2023/10/25 14:57 总访问:3256080 评论:0 收藏:0 手机
分类: HuggingFace

HugginFace 使用训练工具(学习笔记)

训练工具介绍


HuggingFace提供了巨大的模型库,但我们往往还需要对特定的数据集进行二次训练,这个过程也叫做迁移学习。
这里我们以情感分类的任务作为例子。

使用训练工具


再此之前,我安装的框架环境版本如下:

  1. %pip install -q transformers==4.18 datasets==2.4.0 torchtext

准备数据集

加载编码工具


首先加载一个编码工具,由于编码工具和模型往往是成对使用的,所以这里使用hfl/rbt3编码工具,因为要再训练的模型是hfl/rbt3模型,代码如下:

  1. from transformers import AutoTokenizer
  2. tokenizer = AutoTokenizer.from_pretrained('hfl/rbt3')
  3. tokenizer


加载了编码工具后,简单的测试一下:

  1. tokenizer.batch_encode_plus(
  2. ['明月装饰了你的窗子', '你装饰了别人的梦'],
  3. truncation=True,
  4. )

准备数据集


加载数据集,使用该数据集再来训练模型,代码如下:

  1. from datasets import load_dataset
  2. dataset = load_dataset("lansinuote/ChnSentiCorp")
  3. #缩小数据规模,便于测试 shuffle 打乱顺序
  4. dataset['train'] = dataset['train'].shuffle().select(range(2000))
  5. dataset['test'] = dataset['test'].shuffle().select(range(100))
  6. dataset


这段代码对数据进行了采样,一是便于测试,二是模拟再训练集的体量较小的情况,以验证即使是小的数据集,也能通过迁移学习得到一个较好的训练结果。运行结果如下:


可见训练集的数量仅有2000条,测试集的数量有100条。
现在的数据集还是文本数据,使用编码工具把这些抽象的文字编码成计算机善于处理的数字,代码如下:

  1. #第6章/编码
  2. def f(data):
  3. return tokenizer.batch_encode_plus(data['text'], truncation=True)
  4. dataset = dataset.map(f,
  5. batched=True,
  6. batch_size=1000,
  7. num_proc=4,
  8. remove_columns=['text'])
  9. dataset
参数 描述
batch 为True表明使用批处理来处理数据,而不是一条一条地处理。
batch_size 为1000表明每个批次有1000条数据
num_proc 为4表明使用4个线程进行操作。
remove_columns 这里表示映射结束后删除text字段


我们可以看到原来的text已经被删除了,但多了input_ids(编码)、token_type_idsattention_mask字段,这些字段是编码工具编码的结果,折合前面观察到的编码器试算的结果一致。
接下来,我们将句子抄过超过512长度的句子过滤掉。

  1. def f(data):
  2. return [len(i) <= 512 for i in data['input_ids']]
  3. dataset = dataset.filter(f, batched=True, batch_size=1000, num_proc=4)
  4. dataset


可以看到数据集中的有部分数据被移除。

定义模型和训练工具

加载预训练模型


数据集准备好了,现在就可以加载要再训练的模型了,代码如下:

  1. from transformers import AutoModelForSequenceClassification
  2. model = AutoModelForSequenceClassification.from_pretrained('hfl/rbt3',
  3. num_labels=2)
  4. #统计模型参数量
  5. sum([i.nelement() for i in model.parameters()]) / 10000


hfl/rb3是一个基于中文文本数据训练的BERT的模型,在代码的最后一行记录该模型的参数,大概3800万个。


加载了模型之后,对模型进行试算一下:

  1. import torch
  2. #模拟一批数据
  3. data = {
  4. 'input_ids': torch.ones(4, 10, dtype=torch.long),
  5. 'token_type_ids': torch.ones(4, 10, dtype=torch.long),
  6. 'attention_mask': torch.ones(4, 10, dtype=torch.long),
  7. 'labels': torch.ones(4, dtype=torch.long)
  8. }
  9. #模型试算
  10. out = model(**data)
  11. out['loss'], out['logits'].shape


模型的输出包括两部分,一部分是loss,另外一部分是logits。(这里就是模拟没仍和意义)

定义评价函数


为了便于在训练过程中观察模型的性能,需要定义一个评价指标函数。
这里我们缇娜家正确率的指标函数:

  1. from datasets import load_metric
  2. metric = load_metric('accuracy')


由于模型计算的输出和评价指标要求的还是有差别,所以需要定义一个转换函数,把模型计算的输出转换成评价指标可以计算的数据类型,这个函数就是在训练过程中真正要用到的评价函数,代码如下:

  1. import numpy as np
  2. from transformers.trainer_utils import EvalPrediction
  3. def compute_metrics(eval_pred):
  4. logits, labels = eval_pred
  5. # 最大值的索引
  6. logits = logits.argmax(axis=1)
  7. return {'accuracy': (logits == labels).sum() / len(labels)}
  8. #return metric.compute(predictions=logits, references=labels)
  9. #模拟输出
  10. eval_pred = EvalPrediction(
  11. predictions=np.array([[0, 1], [2, 3], [4, 5], [6, 7]]),
  12. label_ids=np.array([1, 1, 0, 1]),
  13. )
  14. compute_metrics(eval_pred)


这段代码中,不仅定义了评价函数,还对该函数进行了试算,运行结果如下:

定义训练超参数


在开始训练之前,需要定义好超参数,HuggingFace使用TrainingArguments对象来封装超参数,代码如下:

  1. from transformers import TrainingArguments
  2. #定义训练参数
  3. args = TrainingArguments(
  4. #定义临时数据保存路径
  5. output_dir='./output_dir',
  6. #定义测试执行的策略,可取值no、epoch、steps
  7. evaluation_strategy='steps',
  8. #定义每隔多少个step执行一次测试
  9. eval_steps=30,
  10. #定义模型保存策略,可取值no、epoch、steps
  11. save_strategy='steps',
  12. #定义每隔多少个step保存一次
  13. save_steps=30,
  14. #定义共训练几个轮次
  15. num_train_epochs=1,
  16. #定义学习率
  17. learning_rate=1e-4,
  18. #加入参数权重衰减,防止过拟合
  19. weight_decay=1e-2,
  20. #定义测试和训练时的批次大小
  21. per_device_eval_batch_size=16,
  22. per_device_train_batch_size=16,
  23. #定义是否要使用gpu训练
  24. no_cuda=False,
  25. )


TrainingArguments对象中可以封装的超参数有很多,
更多请参考:https://huggingface.co/docs/transformers/main/en/main_classes/trainer#transformers.TrainingArguments

定义训练器


完成了上面的准备工作,现在可以定义训练器,代码如下:

  1. from transformers import Trainer
  2. from transformers.data.data_collator import DataCollatorWithPadding
  3. #定义训练器
  4. trainer = Trainer(
  5. model=model,
  6. args=args,
  7. train_dataset=dataset['train'],
  8. eval_dataset=dataset['test'],
  9. compute_metrics=compute_metrics,
  10. data_collator=DataCollatorWithPadding(tokenizer),
  11. )


定义训练器时需要传递要训练的模型、超参数对象、训练和验证数据集、评价函数,以及数据整理函数。

数据整理函数


DataCollatorWithPadding对象能把批次中长短不一的句子补充成统一的长度,模型期待的数据类型也是矩阵,所以经过数据处理之后,数据即被整理成模型可以计算的矩阵格式。例子如下:

  1. data_collator = DataCollatorWithPadding(tokenizer)
  2. #获取一批数据
  3. data = dataset['train'][:5]
  4. #输出这些句子的长度
  5. for i in data['input_ids']:
  6. print(len(i))
  7. #调用数据整理函数
  8. data = data_collator(data)
  9. #查看整理后的数据
  10. for k, v in data.items():
  11. print(k, v.shape)


我们可以通过下面的代码查看句子时怎么被补长的。

  1. tokenizer.decode(data['input_ids'][0])


可以看到,数据整理函数时通过对句子的尾部补充PAD来对句子补长的。

训练和测试

训练模型


在开始训练之前,不妨直接对模型进行一次测试,先定下训练前的基准,在训练结束后再对比这里得到的基准,以验证训练的有效性,代码如下:

  1. trainer.evaluate()


在模型训练之前只有48%的正确率。
接下里我们对模型进行训练:

  1. trainer.train()


从该日志中的Total optimization steps = 124可知,本次有124个训练,由于定超参数时定了每个steps执行一次测试,并保存模型参数,所以当训练结束时,期待4次测试结果,并有4个保存的参数模型。

列名 描述
Step 表示测试执行的时的steps
Training Loss 表示训练loss,在本次任务中未记录。
Validation Loss 表示验证集上测试得出的loss
Accuracy 表示在验证集上测试得出的正确率,最后得到的正确率为85%


这个正确率其实不算太理想,待会我还会通过v100开启GPU进行训练测试一下。
我们可以在output_dir文件夹中找到4个模型文件夹,这是对应步数保存的检查点。


如果在某个训练过程中由于各种原因导致导致训练中断,或者希望从某个检查点重新训练模型,则可以使用训练器的train()函数的resume_from_checkpoint参数设定检查点,从该检查点重新训练,代码如下:

  1. trainer.train(resume_from_checkpoint='./output_dir/checkpoint-90')


它会跳过前面的90个训练后面的34个,会覆盖掉checkpoint-120文件夹。


在训练结束后,不妨再执行一次测试,以测试模型的性能,代码如下:

  1. trainer.evaluate()


可以看到模型最终的性能正确率为86%

模型的保存和加载


训练得到满意的模型后,可以动手将该模型的参数保存到磁盘上,以备以后需要时加载,代码如下:

  1. #手动保存模型参数
  2. trainer.save_model(output_dir='./output_dir/save_model')


加载模型参数的方法如下:

  1. #手动加载模型参数
  2. import torch
  3. model.load_state_dict(torch.load('./output_dir/save_model/pytorch_model.bin'))

使用模型预测


最后介绍使用模型进行预测的方法,代码如下:

  1. # 将模型设置为评估模式
  2. model.eval()
  3. # 这个循环通过评估数据加载器获取一个数据批次,然后立即退出循环。
  4. for i, data in enumerate(trainer.get_eval_dataloader()):
  5. break
  6. # 这段代码将示例数据批次中的所有张量数据移动到 CUDA 设备(通常是 GPU),以便在 GPU 上进行推断。
  7. for k, v in data.items():
  8. data[k] = v.to('cuda')
  9. # 数据批次传递给模型以获取模型的输出。
  10. out = model(**data)
  11. # 计算模型输出中每个样本的预测标签。
  12. out = out['logits'].argmax(dim=1)
  13. # 将输入的标记(tokens)转换回文本。然后,打印真实标签和模型的预测标签。
  14. for i in range(16):
  15. print(tokenizer.decode(data['input_ids'][i], skip_special_tokens=True))
  16. print('label=', data['labels'][i].item())
  17. print('predict=', out[i].item())


在这段代码中,首先把模型切换到运行模式,然后从测试数据集中获取一个批次的数据用于预测,之后把这批数据输入模型进行计算,得出的结果即为模型预测的结果,最后输出前4句的结果,并与真实的label进行比较,运行结果如下:

其他

使用V100跑


超参数该的GPU选项钩上。

  1. no_cuda=False


训练前,只有49%的正确率:


训练后,只花了12秒就训练完了,但正确率很低还是87%,我们通过更改轮次多训练几次:


改了一下配置重新训练了一下这次感觉要乐观很多,92%

  1. from transformers import TrainingArguments
  2. #定义训练参数
  3. args = TrainingArguments(
  4. #定义临时数据保存路径
  5. output_dir='./outputxxxp_dir',
  6. #定义测试执行的策略,可取值no、epoch、steps
  7. evaluation_strategy='steps',
  8. #定义每隔多少个step执行一次测试
  9. eval_steps=30,
  10. #定义模型保存策略,可取值no、epoch、steps
  11. save_strategy='steps',
  12. #定义每隔多少个step保存一次
  13. save_steps=30,
  14. #定义共训练几个轮次
  15. num_train_epochs=20,
  16. #定义学习率
  17. learning_rate=3e-4,
  18. #加入参数权重衰减,防止过拟合
  19. weight_decay=1e-3,
  20. #定义测试和训练时的批次大小
  21. per_device_eval_batch_size=32,
  22. per_device_train_batch_size=32,
  23. #定义是否要使用gpu训练
  24. no_cuda=False,
  25. )


但是请看我跑之前的和跑之后的GPU用量。。。。


欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

评价

HugginFace 初探

HugginFace 初探[TOC] 安装环境python环境是3.6。import sys sys.version 安装torch,简单起见,避免环境问题,并且计...

HugginFace 使用编码工具(学习笔记)

HugginFace 使用编码工具(学习笔记)[TOC] 安装环境# 我这里的python是3.11 %pip install -q transformers==4.18 datasets...

HugginFace 使用数据集(学习笔记)

HugginFace 使用数据集(学习笔记)[TOC] 数据集工具介绍HuggingFace 提供了统一的数据集处理工具,让不同的数据集通过统一...

HugginFace 使用评价指标工具(学习笔记)

HugginFace 使用评价指标工具(学习笔记)[TOC] 评价指标工具介绍在训练和测试一个模型时往往需要计算不同的评价指标,如正...

HugginFace 使用管道工具(学习笔记)

HugginFace 使用管道工具(学习笔记)[TOC] 管道工具介绍HuggingFace 有一个巨大的模型库,其中一些是已经非常成熟的经典模...

HugginFace 中文情感分类(学习笔记)

HugginFace 中文情感分类(学习笔记)[TOC] 数据集介绍本章使用的是lansinuote/ChnSentiCorp数据集,这是一个情感分类数据集...

HugginFace 中文填空(学习笔记)

HugginFace 中文填空(学习笔记)[TOC] 数据集介绍本章使用的仍然是情感分类数据集,每条包括一句购物评价一集以及是不是好...

HugginFace 中文数据关系推断(学习笔记)

HugginFace 中文数据关系推断(学习笔记)[TOC] 实现代码安装包加载的环境可以通过如下命令进行安装。%pip install -q trans...

HugginFace 中文命名实体识别(学习笔记)

HugginFace 中文命名实体识别(学习笔记)[TOC] 任务简介简单来说就是的识别人名、机构名、地名。数据集的介绍本章所使用的...

常用的很厉害的工具

图片压缩相对图片无损放大来说是小kiss。下面是非常非常帅气的图片无损放大http://bigjpg.com/图片压缩https://www.upyun.c...

一些有用的资源分享(工具+电子书)

工具类图片相关工具TinyPNG:https://tinypng.com/ 免费的在线图片压缩工具,压缩率高,无损画质,直接拖拽使用,很方便。p...

开发自己的代码生成工具

在一个项目中其实有很多代码都是重复的,几乎每个基础模块的代码都有增删改查的功能,而这些功能都是大同小异,如果这些功...

windoes 强力下载工具Internet Download Manager

大家好,我是刘小贱,今天呢我给大家推荐一款Windows系统上的下载神器:Internet Download Manager ,这款软件通过在浏览器上...

net core使用jwt 三: 使用过滤器实现通用token验证Token验证工具

net core使用jwt二 : 验证前台传递的tokenhttp://www.tnblog.net/aojiancc2/article/details/2845过滤器实现通用token验证...

oralce plsql打开执行sql的工具

如果不小心关闭了,要打开执行sql的工具栏如下箭头的地方右键即可
这一世以无限游戏为使命!
排名
2
文章
620
粉丝
44
评论
93
docker中Sware集群与service
尘叶心繁 : 想学呀!我教你呀
一个bug让程序员走上法庭 索赔金额达400亿日元
叼着奶瓶逛酒吧 : 所以说做程序员也要懂点法律知识
.net core 塑形资源
剑轩 : 收藏收藏
映射AutoMapper
剑轩 : 好是好,这个对效率影响大不大哇,效率高不高
ASP.NET Core 服务注册生命周期
剑轩 : http://www.tnblog.net/aojiancc2/article/details/167
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术