在上上周,我们的分类器实现主要是基于机器学习库 sklearn
,使用的也都是已经封装好了的类。在这周,我们将探索深度学习与神经网络,利用 bert 预训练模型并手动实现下游模型,来实现我们的分类器。
参考:
- https://www.bilibili.com/video/BV1a44y1H7Jc/
- https://zhuanlan.zhihu.com/p/364933751
- https://zhuanlan.zhihu.com/p/431796984
- https://zhuanlan.zhihu.com/p/493424507
step1
在 https://www.bilibili.com/video/BV1a44y1H7Jc/ 中,我们可以跟着视频提供的代码实现一个训练一轮并测试的分类器。视频已经说的比较清楚了,这里再回顾一下:我们首先用 bert-base-chinese
将文本处理成 token,再将 token 传入我们的下游模型进行训练。而我们的下游模型是基于预训练模型实现的,在视频中也是选取的 bert-base-chinese
作为预训练模型。而在训练一轮之后,我们发现我们的结果非常不理想,测试集上的预测准确率只有 70% 不到。因此,我们需要进一步优化。
step2
首先感谢 jpp 同学指出训练应该不止一轮,而要反复多轮次地训练。经过实践,在进行多轮训练,也就是把训练集多次喂给模型后,在测试集上的预测准确率确实有所提升。而这时一个整体上的方法。在此基础上,还有以下参数可以调整(也是我有所尝试的):
-
预训练模型的选择
bert-base-chinese
algolet/bert-large-chinese
allenai/longformer-base-4096
-
下游模型中的神经网络层
-
batch_size
- 16
- 32
-
max_length(预训练模型接受一句话的最大长度)
- 512
- 1024(仅
algolet/bert-large-chinese
可用) - 2048(仅
algolet/bert-large-chinese
可用)
预训练模型限制了能接受的最大的长度,而我们有不少数据都是超过这个长度的,所以实际上模型接受的只是句子的一部分。而默认情况下,则是从句首截取指定长度。这也是一开始遇到的一个问题。而可能的解决办法有三种:
-
requires_grad(是否梯度回传,即是否修改预训练模型的参数,也就是微调 bert)
-
learning_rate(梯度下降时的学习率)
- 1e-3
- 5e-5
- 5e-6
-
weight_decay(减少过拟合的可能,设置过大可能导致欠拟合)
- 1e-5
接下来就是对于每种参数测试了。由于算力原因,小编只能使用 Kaggle 和 Google colab 云端平台来运行代码。而迭代次数设置为了 100,所以一份代码的运行时间也非常久。