首页 > 其他分享 >HuggingFace情感分析任务微调

HuggingFace情感分析任务微调

时间:2024-10-31 10:47:20浏览次数:8  
标签:log No 微调 HuggingFace dataset 情感 PAD import data

官方教程地址:https://huggingface.co/learn/nlp-course/zh-CN/chapter3/1?fw=pt

部分内容参考:

李福林, & 计算机技术. (2023). HuggingFace 自然语言处理详解: 基于 BERT 中文模型的任务实战. 清华大学出版社.

HuggingFace将AI项目研发分为四个步骤,准备数据集、定义模型、训练、测试,在此大方向下可以细化成几个小步骤,其中HuggingFace对此提供了一些工具集,具体如图:

HuggingFace开发流程和提供的工具集
因为一些原因可能无法连接到huggingface的服务器,所以可以在代码片中加入这一段来连接国内镜像

import os
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'

1. 准备数据集

1.1 加载编码工具

这里我们选择微调的是IDEA-CCNL/Erlangshen-Roberta-330M-Sentiment模型,这个是一个情感分析模型,本身已经做的特别好了,其实微调意义已经不大甚至可能适得其反,但是这里仅为记录微调过程而并非真正需要优化模型。由于模型与编码器经常是成对出现,所以这里加载编码器也是选择IDEA-CCNL/Erlangshen-Roberta-330M-Sentiment

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("IDEA-CCNL/Erlangshen-Roberta-330M-Sentiment")

这里可以测试一下:

tokenizer(
    ['房东已经不养猫了', '今天真的要减肥了'],
    truncation=True,
    max_length=512,
)

输出如下:

{'input_ids': [[101, 2791, 691, 2347, 5307, 679, 1075, 4344, 749, 102], [101, 791, 1921, 4696, 4638, 6206, 1121, 5503, 749, 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]]}

解释一下这个编码结果:

  1. input_ids
  • 将文本转换为数字序列的token ID
  • 每个ID对应词表中的一个token(词或子词)
  1. token_type_ids (也叫segment_ids)
  • 用于区分输入中不同的句子或文本段
  • 通常用0和1标记,0表示第一个句子,1表示第二个句子
  • 在单句任务中全部为0
  1. attention_mask
  • 用于标记哪些token应该被注意(1),哪些应该被忽略(0)
  • 主要用于处理变长序列的padding情况
  • 实际token为1,padding token为0

1.2 加载数据集

# from datasets import load_from_disk
from datasets import load_dataset

# dataset = load_from_disk("/kaggle/working/Huggingface_Toturials/data/ChnSentiCorp")
dataset = load_dataset('lansinuote/ChnSentiCorp')
dataset['train'] = dataset['train'].shuffle().select(range(2000))
dataset['test'] = dataset['test'].shuffle().select(range(100))

加载数据集部分可以直接从网站一键下载,也可以手动下载了从磁盘载入,这里使用的是ChnSentiCorp,这里为简化运算,只取随机2000行,可以打印一下dataset结果如下

DatasetDict({
    train: Dataset({
        features: ['text', 'label'],
        num_rows: 2000
    })
    validation: Dataset({
        features: ['text', 'label'],
        num_rows: 1200
    })
    test: Dataset({
        features: ['text', 'label'],
        num_rows: 100
    })
})

1.3 数据集预处理

用刚刚加载进来的编码器编码

def f(data):
    return tokenizer.batch_encode_plus(data['text'], truncation=True, max_length=512)

dataset = dataset.map(f, batched=True, remove_columns=['text'], batch_size=1000, num_proc=3)

打印dataset可以看到:

DatasetDict({
    train: Dataset({
        features: ['label', 'input_ids', 'token_type_ids', 'attention_mask'],
        num_rows: 2000
    })
    validation: Dataset({
        features: ['label', 'input_ids', 'token_type_ids', 'attention_mask'],
        num_rows: 1200
    })
    test: Dataset({
        features: ['label', 'input_ids', 'token_type_ids', 'attention_mask'],
        num_rows: 100
    })
})

模型一般对句子的长度有所限制,因此将长度超过512的句子截断或者过滤,这里为了编码方便简单的选择了删掉长度不合格的句子。

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

2. 定义模型和训练工具

2.1 加载预训练模型

先将模型加载进来

from transformers import AutoModelForSequenceClassification
import torch

model = AutoModelForSequenceClassification.from_pretrained("IDEA-CCNL/Erlangshen-Roberta-330M-Sentiment", num_labels=2)

简单计算下参数量

sum(p.numel() for p in model.parameters()) / 1e6

结果:

325.524482

参数量大概是325.5M

模型加载进来后进行简单的试算

data = {
    'input_ids': torch.ones(1, 10, dtype=torch.long),
    'attention_mask': torch.ones(1, 10, dtype=torch.long),
    'token_type_ids': torch.ones(1, 10, dtype=torch.long),
    'labels': torch.ones(1, dtype=torch.long)
}
out = model(**data)
out.loss, out.logits.shape

2.2 加载评价函数

import evaluate
metric = evaluate.load("accuracy")

这个评价函数接受的主要参数是一个预测值和一个标签值,与模型的输出不符,因此我们需要做一些处理。

import numpy as np

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=1)
    acc = metric.compute(predictions=predictions, references=labels)
    return acc

测试一下这个函数

from transformers.trainer_utils import EvalPrediction

eval_pred = EvalPrediction(predictions=np.array([[0, 1], [2, 3], [4, 5], [6, 7]]),
                           label_ids=np.array([1, 1, 0, 1]))
compute_metrics(eval_pred) 

结果:

{'accuracy': 0.75}

2.3 定义训练函数

定义训练参数

from transformers import Trainer, TrainingArguments
import accelerate
# 参数
training_args = TrainingArguments(
    output_dir="./output_dir",
    evaluation_strategy="steps",
    learning_rate=2e-5,
    per_device_train_batch_size=4,
    per_device_eval_batch_size=4,
    num_train_epochs=2,
    weight_decay=0.01,
    eval_steps=20,
    no_cuda=False,
    report_to='none',
)

注意:report_to='none',在用colab或者kaggle时注意要加上,不然会让你输入api key,比较麻烦

构建训练器

from transformers import Trainer
from transformers import DataCollatorWithPadding

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=dataset['train'],
    eval_dataset=dataset['test'],
    data_collator=DataCollatorWithPadding(tokenizer),
    compute_metrics=compute_metrics,
)

上面的训练器中出现了一个常用的DataCollatorWithPadding对象,它的主要功能是将不同长度的序列补齐到同一长度,自动处理padding,使得一个batch内的所有样本长度一致。这里可以测试一下

# 测试数据整理函数
data_collator = DataCollatorWithPadding(tokenizer)
data = dataset['train'][:5]
for i in data['input_ids']:
    print(len(i))
data = data_collator(data)
for k, v in data.items():
    print(k, v.shape)

结果:

103
162
171
51
95
input_ids torch.Size([5, 171])
token_type_ids torch.Size([5, 171])
attention_mask torch.Size([5, 171])
labels torch.Size([5])

长度全部都补齐到171了

可以解码看看

tokenizer.decode(data['input_ids'][0])  # 解码

结果:

'[CLS] 看 了 两 边 , 第 一 感 觉 是 - - 很 一 般 。 内 容 上 , 真 不 敢 苟 同 , 还 号 称 是 学 术 明 星 , 于 丹 的 同 志 的 见 解 真 让 我 张 了 见 识 ! 页 数 大 可 以 压 缩 到 50 页 , 何 必 浪 费 纸 张 呢 ? 难 道 孔 夫 子 没 教 育 你 怎 么 搞 环 保 ? 评 论 到 此 结 束 , 懒 得 浪 费 我 得 笔 墨 ! [SEP] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]'

3. 训练和测试函数

在训练前,先看看模型本身的能力

trainer.evaluate()  # 评估

结果

{'eval_loss': 0.2859102189540863,
 'eval_accuracy': 0.97,
 'eval_runtime': 5.3759,
 'eval_samples_per_second': 18.602,
 'eval_steps_per_second': 2.418}

模型本身的准确率就有0.97,已经非常优秀了,本文目的不在于优化模型。

训练模型

trainer.train()

结果

 [500/500 09:48, Epoch 2/2]
Step	Training Loss	Validation Loss	Accuracy
20	No log	0.628869	0.940000
40	No log	0.231194	0.980000
60	No log	0.496170	0.930000
80	No log	0.381901	0.950000
100	No log	0.326569	0.940000
120	No log	0.262761	0.950000
140	No log	0.305643	0.960000
160	No log	0.266394	0.960000
180	No log	0.251125	0.960000
200	No log	0.268621	0.950000
220	No log	0.188149	0.980000
240	No log	0.365949	0.950000
260	No log	0.420138	0.940000
280	No log	0.337165	0.940000
300	No log	0.343916	0.950000
320	No log	0.427644	0.950000
340	No log	0.543159	0.930000
360	No log	0.514463	0.930000
380	No log	0.450759	0.940000
400	No log	0.422249	0.940000
420	No log	0.437221	0.940000
440	No log	0.448282	0.950000
460	No log	0.447407	0.950000
480	No log	0.447090	0.950000
500	0.068800	0.447007	0.950000

测试

trainer.evaluate()

4. 一键复制的python代码

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("IDEA-CCNL/Erlangshen-Roberta-330M-Sentiment")
from datasets import load_from_disk
from datasets import load_dataset
import torch
from transformers import AutoModelForSequenceClassification
import evaluate
import numpy as np
from transformers.trainer_utils import EvalPrediction

dataset = load_dataset('lansinuote/ChnSentiCorp')
dataset['train'] = dataset['train'].shuffle().select(range(2000))
dataset['test'] = dataset['test'].shuffle().select(range(100))

def f(data):
    return tokenizer.batch_encode_plus(data['text'], truncation=True, max_length=512)

dataset = dataset.map(f, batched=True, remove_columns=['text'], batch_size=1000, num_proc=3)

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

model = AutoModelForSequenceClassification.from_pretrained("IDEA-CCNL/Erlangshen-Roberta-330M-Sentiment", num_labels=2)

metric = evaluate.load("accuracy")

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=1)
    acc = metric.compute(predictions=predictions, references=labels)
    return acc


# 定义训练函数
from transformers import Trainer, TrainingArguments
import accelerate
# 参数
training_args = TrainingArguments(
    output_dir="./output_dir",
    evaluation_strategy="steps",
    learning_rate=2e-5,
    per_device_train_batch_size=4,
    per_device_eval_batch_size=4,
    num_train_epochs=2,
    weight_decay=0.01,
    eval_steps=20,
    no_cuda=False,
    report_to='none',
)
# 训练器
from transformers import Trainer
from transformers import DataCollatorWithPadding

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=dataset['train'],
    eval_dataset=dataset['test'],
    data_collator=DataCollatorWithPadding(tokenizer),
    compute_metrics=compute_metrics,
)
trainer.train()
trainer.evaluate()  

标签:log,No,微调,HuggingFace,dataset,情感,PAD,import,data
From: https://blog.csdn.net/ooblack/article/details/143385930

相关文章

  • IT软件部落-Emoji表情字符大全增强你的表达能力-记事本也可以有情感,总有一个您用得上,
    这是手绘的吗?不,它是Emoji表情字符,就是普通的文本,你不相信? ......
  • 刚面完字节!问了大模型微调SFT,估计凉了
    最近这一两周不少互联网公司都已经开始秋招提前批面试了。不同以往的是,当前职场环境已不再是那个双向奔赴时代了。求职者在变多,HC在变少,岗位要求还更高了。最近,我们又陆续整理了很多大厂的面试题,帮助一些球友解惑答疑,分享技术面试中的那些弯弯绕绕。总结如下:《大模型面......
  • LLAMAFACTORY:一键优化大型语言模型微调的利器
    人工智能咨询培训老师叶梓转载标明出处模型适配到特定的下游任务,通常需要进行微调(fine-tuning),这一过程往往需要大量的计算资源。为了解决这一问题,来自北京航空航天大学和北京大学的研究人员共同开发了LLAMAFACTORY,这是一个统一的框架,集成了多种前沿的高效训练方法,使得用户可......
  • 基于AIACC加速器快速实现LLaMA-7B指令微调
    本文基于Alpaca提供了一套LLaMA-7B模型在阿里云ECS上进行指令微调的训练方案,最终可以获得性能更贴近具体使用场景的语言模型。背景信息LLaMA(LargeLanguageModelMetaAI )是MetaAI在2023年2月发布的开放使用预训练语言模型(LargeLanguageModel,LLM),其参数量包含7B到65B的......
  • 计算机毕业设计Python+大模型微博情感分析 微博舆情预测 微博爬虫 微博大数据 舆情分
    温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!《Python+大模型微博情感分析》开题报告一、研究背景与意义随着互联网技术的飞速发展,社交媒体平台......
  • 计算机毕业设计Spark+大模型某音视频情感分析 某音可视化 某音舆情监测 预测算法 某音
    《Spark+大模型抖音视频情感分析》开题报告一、研究背景与意义随着移动互联网和社交媒体的快速发展,短视频平台如抖音(TikTok)已成为全球范围内广受欢迎的娱乐和信息获取渠道。用户在这些平台上发布的视频内容涵盖了娱乐、教育、新闻等各个领域,形成了海量的用户行为数据和视频内......
  • 一文读懂RAG和LLM微调,教你结合业务场景落地LLM应用
    随着大家对大型语言模型(LLM)的兴趣激增,许多开发者也在构建基于LLM的应用。当直接使用Prompt驱动的LLM表现不如预期时,问题就出现了:如何提高LLM应用的可用性。这时我们需要权衡:是选择检索增强生成(Retrieval-AugmentedGeneration缩写RAG)还是模型微调来改善结果?01在深入探......
  • CogVideo---CogVideoX-微调代码源码解析-四-
    CogVideo&CogVideoX微调代码源码解析(四)ContributionGuideTheremaystillbemanyincompleteaspectsinthisproject.Welookforwardtoyourcontributionstotherepositoryinthefollowingareas.Ifyoucompletetheworkmentionedaboveandarewillingto......
  • CogVideo---CogVideoX-微调代码源码解析-十一-
    CogVideo&CogVideoX微调代码源码解析(十一).\cogvideo-finetune\sat\sgm\modules\encoders\__init__.py请提供需要注释的代码,我将为您添加注释。.\cogvideo-finetune\sat\sgm\modules\video_attention.py#导入PyTorch库importtorch#从上级模块导入必要的组件from.......
  • CogVideo---CogVideoX-微调代码源码解析-十三-
    CogVideo&CogVideoX微调代码源码解析(十三)VideoCaptionTypically,mostvideodatadoesnotcomewithcorrespondingdescriptivetext,soitisnecessarytoconvertthevideodataintotextualdescriptionstoprovidetheessentialtrainingdatafortext-to-vid......