总流程图

baseline讲解

 这个baseline没有注释对我这种初学者来说真的很头痛。不能明白某个函数为什么这么用,不能明白某个变量为什么起这个名字(因为不知道一些专业术语所以会对这些感到很疑惑)。花了很久时间总算理解了baseline的意思。下面对baseline分文件进行阐述。

generate_data.py

 这个脚本用于生成训练数据和验证数据。
 这个文件中有多个函数,一个split_dataset(dev_data_cnt=5000),该函数具有一个参数dev_data_cnt,即为每个任务的验证数据的条数,在这里缺省是5000条。
split_dataset会将每个任务下的total.csv文件进行切分,切分出dev_data_cnt条存入验证文件,剩下的数据作为训练数据存入训练文件中。
 另一个函数generate_data的作用有:
– 生成每个任务的验证数据文件和训练数据文件的json格式版
– 生成存储每个任务的label的json文件
– 生成存储每个任务的label的权重的json文件。这里的权重我没有使用上因为权重这块的使用我还没有查阅到相关论文或者其他资料。
 在命令行下执行
“`python ./generate_data.py“`即可运行该脚本生成本次baseline需要的数据

train.py

 生成数据文件之后第二步就可以进行训练了。所以执行train.py即可。train.py中调用了其他文件中的类或者是方法,在被调用时进行介绍。
 train.py中只有一个train的函数,下面对该函数进行介绍:
 train函数的定义

 train(epochs=1, batchSize=4, lr=0.0001, device='cuda:0', accumulate=True, a_step=16, load_saved=False, file_path='./saved_best.pt', use_dtp=False, pretrained_model='./bert_pretrain_model', tokenizer_model='bert-base-chinese', weighted_loss=False)

具体参数就不一一解释了。
 首先生成网络`my_net`和`tokenizer`,这里已经将bert模型的权重文件和vocab下载下来了,所以从本地加载相关参数。

my_net

 my_net是Net的一个实例,其定义在net.py文件中,Net的架构为一层bert,一层attention_layer,一个Softmax层,一个dropout层, 三个fc层分别对应三个不同的任务。

 forward函数中,首先将input_ids, token_type_ids, attention_mask输入bert层,得到bert输出中的第一个元素temp,大小为batchsize* 句子长度*768,baseline提取temp的[:, 0, :]即句子中CLS的embedding表示来表示句意作为每个句子的特征。接着不同任务得到各自句子的embedding表示作为各自的数据,对于每个任务,将句子的embedding输入attention_layer,再经过softmax和dropout,再与每个句子的embedding相乘得到每个句子对于每个标签的softmax的值。因为有三个任务,所以最后返回三个任务的每个句子的softmax的结果。

 接着在train.py中读取之前切分的数据,在这里读取json格式的数据。并生成一个数据迭代器data_generator用来提供每个batch训练时的数据,并生成一个loss_object的计算对象用于每次训练时计算误差值。

 接着进行n个epoch的训练,在这里为了快速出结果,我将epoch的数量设置为1,所以我只训练一个epoch。在每个epoch的训练中,首先调用了model.train(),这个的作用是设置batchnorm层和dropout层会被使用,而在验证的时候我们则调用model.eval()固定batchnorm层和dropout层进行验证。接下来就是利用数据迭代器data_generator为每个batch的训练提供固定格式的数据进行训练,并利用loss_object进行误差的计算,在这里我们采用的是crossentropy计算误差,然后更新模型的参数。
 在训练时,我们保存f1分数最高的模型保存下来,以供分类的时候使用。

inference.py

 这个脚本就是调用已经保存下来的模型去对测试数据进行分类,流程很简单,首先加载保存下来的模型,接着不断的获取测试数据传入模型进行分类即可,最终生成3个任务的json文件。
 我们进入submission文件夹,将三个json文件压缩成result.zip即可打包进一个docker镜像提交即可。

 进行baseline的训练之后进行提交,首次分数为

成绩一般般。

改进

句子的embedding

 在网上查阅资料,发现将bert最后一层的输出,即每个词的embedding求均值作为句子的特征比提取CLS的embedding作为句子的特征更好,于是将句子特征改为句子中每个词的embedding的均值再次进行实验。

本次提交的结果如下图:

比之前的提交高了0.01分,不过鉴于epoch只有1,不能保证这一定算作模型的改进,但至少分数还是高了些。

Roberta

 Roberta模型是基于bert的改进模型。从hugging face上下载中文roberta的模型权重到本地,再将模型修改为chinese-roberta-wwm-ext。再次进行训练,在训练的时候就发现准确率上升得很快,感觉可以上一波大分,以下为成绩截图:

目前排在LB的30名

 后来经过询问排名更高的学长,学长给出了修改隐藏层维度、修改学习率(更小的学习率)和添加warmup的建议,目前还没有去实现,先记录下来。

参考资料:
1. model.train()的使用: https://www.cnblogs.com/wupiao/articles/13287061.html
2. bert的输出: https://blog.csdn.net/iterate7/article/details/108959082

分类: datawhale

0 条评论

发表评论