HuggingFace模型微调训练
前言
BERT,这位“语言天才”,它通过海量文本数据的预训练,学会了如何理解语言的上下文关系,仿佛是一个经过无数书籍洗礼的“语言大师”。借助Hugging Face的transformers库,我们只需为BERT“微调”一下,就能让它精准捕捉中文文本中的情绪脉络。本文详细的描述了整个神经网络从数据准备到训练的全过程,可以更好的理解模型的架构,以及如何来做一个自己的下游任务。
一、数据准备
数据集使用huggingface上下载的情感二分类文本数据。
1. load_dataset
load_dataset是hf提供的在线加载。
下载下来数据,它会是训练集,验证集,测试集做好了分类,每个文件里都是以arrow为后缀的文件。每个文件里都是arrow。
2. load_from_disk
下来的数据是hf格式的,需要转成csv的格式。
load_from_disk是本地加载数据。
from datasets import load_dataset,load_from_disk
#在线加载数据
dataset = load_dataset(path="NousResearch/hermes-function-calling-v1",split="train")
print(dataset)
#转存为CSV格式
dataset.to_csv(path_or_buf=r"D:\demo\data\hermes-function-calling-v1.csv")
#加载csv格式数据
# dataset = load_dataset(path="csv",data_files=r"D:\demo\data\hermes-function-calling-v1.csv")
# print(dataset)
#加载缓存数据
dataset = load_from_disk(r"D:\demo\data\ChnSentiCorp")
print(dataset)
test_data = dataset["train"]
for data in test_data:
print(data)
数据集的样式,就是一个二分类的情感分析,0是负面,1是正面,截取几条,就是如下样式。
{
'text': '键盘手感没有开始的时候好了, 散热一般,机器硬盘温度一度达到58度', 'label': 0}
{
'text': '10多年来住过的近百家3星酒店中,这家酒店的服务、房间、餐饮简直是“好”的无话可说!!! 向大堂经理反映问题,大堂经理的答复是“去315投诉吧”(入住当天是3月12日),真强悍!!!', 'label': 0}
{
'text': '1.上了半天网,都上不去,问酒店,答曰坏了。气愤! 2.晚上入住适逢变天,天气变冷,开了半天空调,竟然还是冷风,问酒店,答曰晚上关空调。晕!床上只有一床单被,到处找被子,无。问酒店要,半小时催了三次电话才来。还是冷,要求在加一床被子,服务员去后再也没回,打到总台,又等了半天,回复没被子了。不把顾客当人啊。 3.一晚没睡成,凌晨5点多,被不知道哪里来的低沉的轰鸣声吵醒。在房间找了半天没查出哪里来得声音,叫来服务员,(半小时催了三四次才来,人都要疯掉)。六点多服务员才来,也解决不了。就这么一夜没睡。买气受来了。 4.到总台要求当班经理来解释,换了几个人来,说了几遍,酒店不断去落实事情真相,最后才来一个自称客服经理的,说却有其事,表示道歉,做了一小时的冷板凳,一口热水没喝,口都讲干了。这就是他们的诚意。 总结:硬件老旧,服务太差。', 'label': 0}
{
'text': '该酒店达不到五星水准。价格高,环境差,服务一般', 'label': 0}
二、构建、设计模型
1. 编码
1,AutoTokenizer
适用于所有分词器,不管是BERT模型,GPT,还是transformer等。
2,BertTokenizer
只适用于BERT模型
3,token.batch_encode_plus
编码,讲文本转为计算机可识别的向量数值。
字典也是从hf上下载,这里用的是models–bert-base-chinese,里面包含了中文模型的识别,model.safetensors,和一个中文分词器所用的向量表vacab.txt。
模型目录里面模型和字典
字典就是vocab.txt,总共21128个编码。
里面主要是汉字编码,还有一些日语平假名片假名和特殊符号。
讲文本转向量代码示例
from transformers import AutoTokenizer,BertTokenizer
#加载字典和分词器
token = BertTokenizer.from_pretrained(r"D:\demo\model\bert-base-chinese\models--bert-base-chinese\snapshots\c30a6ed22ab4564dc1e3b2ecbf6e766b0611a33f")
# print(token)
sents = ["价格在这个地段属于适中, 附近有早餐店,小饭店, 比较方便,无早也无所",
"房间不错,只是上网速度慢得无法忍受,打开一个网页要等半小时,连邮件都无法收。另前台工作人员服务态度是很好,只是效率有得改善。"]
#批量编码句子
out = token.batch_encode_plus(
batch_text_or_text_pairs=[sents[0],sents[1]],
add_special_tokens=True,
#当句子长度大于max_length时,截断
truncation=True,
max_length=50,
#一律补0到max_length长度,因为我们给到的数据是一个矩阵,所以多退少补。
padding="max_length",
#可取值为tf,pt,np,默认为list
return_tensors=None,
#返回attention_mask
return_attention_mask=True,
return_token_type_ids=True,
return_special_tokens_mask=True,
#返回length长度
return_length=True
)
#input_ids 就是编码后的词
#token_type_ids第一个句子和特殊符号的位置是0,第二个句子的位置1()只针对于上下文编码
#special_tokens_mask 特殊符号的位置是1,其他位置是0
# print(out)
for k,v in out.items():
print(k,";",v)
#解码文本数据
print(token.decode(out["input_ids"][0]),token.decode(out["input_ids"][1]))
打印输出这两句话,可以看到每个字都转成了vocab里面对应的向量,先打印编码,然后再打印解吗,和我们输入做对比,看看是否编解码正确。[CLS]对应的就是101,语句的开头,[SEP]102语句结尾,[PAD]就是补全的0.
C:\Users\gyton\anaconda3\envs\langchain-learn\python.exe G:\demo\token_test.py
input_ids ; [[101, 817, 3419, 1762, 6821, 702, 1765, 3667, 2247, 754, 6844, 704, 117, 7353, 6818, 3300, 3193, 7623, 2421, 117, 2207, 7649, 2421, 117, 3683, 6772, 3175, 912, 117, 3187, 3193, 738, 3187, 2792, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [101, 2791, 7313, 679, 7231, 117, 1372, 3221, 677, 5381, 6862, 2428, 2714, 2533, 3187, 3791,