【 基于transformer的歌词分类】


前言

Huggingface Transformers库是Huggingface公司在github上开源的基于Transformers结构开发的预训练NLP框架。其一直致力于大规模预训练模型应用的平民化,让开发者能够方便使用SOTA的模型,而非受困于训练的算力资源。其打造了一个开放的平台,提供了大量的Models,datasets以及如何快速使用的api,同时也欢迎开发者上传自己的模型和数据集。目前已有超过39000个models,在github上transformer库也超过61k星,可见其火热程度。随着transformer在其他领域出色的表现,目前Huggingface Transformers的任务和模型除了Natural Language Processing,也延申到Multimodal,Audio,Computer Vision,Reinforcement Learning等领域。


一、任务说明

Huggingface Transformers库 官方文档有较完整的说明以及相关视频教程。但一些细节处理问题并没有详细说明和例程,中文的应用也相对较少。所以本文以一个作词人风格分类的任务,把几个关键技术点串联起来,包括数据加载,处理,模型,分词,训练,评价,推理。

任务输入:一段歌词
任务输出:哪个作词人的风格。
如图:
在这里插入图片描述
text列是输入的歌词
prediction是模型预测的写词人风格
true_label是真实标签
score是置信度

二、几个概念的理解

dataset:数据集类,提供了很多数据处理接口,如load_dataset,map,split等,可以很方便高效地处理数据集
model:模型,可通过from_pretrained 方法直接加载huggingface上的模型
tokenizer:分词类,同样可通过from_pretrained方法直接加载。每种模型都有对应的vocab词典以及对应分词方法,所以这里加载的模型name或路径需要跟加载model时的参数保持一致。
Pipeline:快速推理通道,不是所有模型都支持
autoclass:主要分为两类:AutoTokenizer+和AutoModel+,通过这两类的from_pretrained来加载分词器和模型
Metrics:评价类,可通过load_metric加载预定义的Metrics。定义好评价函数后在调用训练接口Trainer时赋值给compute_metrics,则训练过程会计算相关的predictions
TrainingArguments:训练参数,搬运官网的说明:TrainingArguments is the subset of the arguments we use in our example scripts which relate to the training loop itself.
Trainer:训练类,参数包括模型,训练参数,训练集,验证集,compute_metrics
以上接口均可在官网doc里找到:https://huggingface.co/docs.

三、自定义数据集的处理和加载

加载自定义数据集:

1.数据来源

音乐数据,可在github搜一下QQMusicSpider

2.数据处理

2.1定义labels

为方便验证效果,筛选了6位优秀写词人的作品,分别是 [‘林夕’, ‘方文山’, ‘黄霑’, ‘罗大佑’, ‘李宗盛’, ‘黄伟文’],并以每个写词人命名json文件分开存放,如下图:
写词人json
json文件格式如下图:
在这里插入图片描述

2.2合并

把所有写词人的数据合并到一个大的json里面。由于我们用于分类的歌词一般是歌词句子而不是整首歌词,所以把每首歌歌词进行了分句,并两两拼接。如下图:在这里插入图片描述

3.load和split

huggingface的数据集是Dataset类型,所以需要将json数据转换为Dataset。这里使用transformer库自带的load_dataset方法进行转换。并且利用train_test_split对数据集按8:1:1进行训练集,验证集,测试集的切分。测试集不参与训练过程,只用于检查模型性能。

def json2tranformers_data(self):
        m_dataset = load_dataset('json', data_files=self.all_data_path)['train']
        
		# train_test_split默认能够shuffle数据,无需人工再打乱
        split_dataset = m_dataset.train_test_split(test_size=0.1)
        train_dataset = split_dataset['train']
        train_split_dataset = train_dataset.train_test_split(test_size=0.1)

        # 训练集保存到本地
        train_dataset = train_split_dataset['train']
        train_dataset.to_csv('data/train_data.csv')

        # 验证集保存到本地
        eval_dataset = train_split_dataset['test']
        eval_dataset.to_csv('data/eval_data.csv')

        # 测试集保存到本地
        test_dataset = split_dataset['test']
        test_dataset.to_csv('data/test_data.csv')

最后产生可在数据集下载

四、训练

1.定义模型和tokenizer

如何选择模型:在models里,筛选task为fill_mask,Languages为zh。如图:在这里插入图片描述
选择一个作为我们finetune的模型,本文以hfl/rbt3为例,其是3层网络的 RoBERTa-wwm-ext 。原理不在这里展开,感兴趣可以看论文:https://arxiv.org/abs/1906.08101。注意每个model都有其对应的tokenizer方法,必须一一匹配。
定义模型和tokenizer的代码如下:

tokenizer = AutoTokenizer.from_pretrained("hfl/rbt3")
model = AutoModelForSequenceClassification.from_pretrained("hfl/rbt3", num_labels=6)

2.load&map数据

代码如下:

def preprocess_function(self, examples):
    return self.tokenizer(examples["text"], truncation=True)

train_dataset = load_dataset('csv', data_files='data/train_data.csv')['train']
eval_dataset = load_dataset('csv', data_files='data/eval_data.csv')['train']

tokenized_train_dataset = train_dataset.map(self.preprocess_function, batched=True)
tokenized_eval_dataset = eval_dataset.map(self.preprocess_function, batched=True)

3.训练参数

代码如下:

training_args = TrainingArguments(
            output_dir="./results",
            learning_rate=2e-5,
            per_device_train_batch_size=96,
            per_device_eval_batch_size=96,
            num_train_epochs=5,
            weight_decay=0.01,
            save_steps=2000
        )

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_train_dataset,
    eval_dataset=tokenized_eval_dataset,
    tokenizer=tokenizer,
    data_collator=data_collator,
)

trainer.train()

五、评价指标及效果

dataset类提供了许多评价方法,使用list_metrics()可查看

from datasets import list_metrics
metrics_list = list_metrics()
print(metrics_list)

我使用了load_metric(“accuracy”)的方法,代表的准确率:

def evaluate(self):
    from transformers.pipelines.base import KeyDataset

    test_dataset = load_dataset('csv', data_files='data/test_data.csv')['train']
    references = [label['label'] for label in test_dataset]

    predictions = []
    kd = KeyDataset(test_dataset, "text")
    for out in tqdm(self.pipe(kd)):
        predictions.append(int(out['label'][-1]))

    accuracy_metric = load_metric("accuracy")

    results = accuracy_metric.compute(references=references, predictions=predictions)
    print(results)
    return results

最终,模型在测试集上的表现为91%:
在这里插入图片描述

总结

以上就是整个文本分类finetune的过程,本文仅仅介绍了transformer的文本分类训练过程和简单的应用。而没有对原理,模型,参数,优化方法进行深入的研究。未来有时间再根据实际任务进行探究。
训练的代码可参考lyric-classification

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值