Bert实战---情感分类

1.情感分析语料预处理

  使用酒店评论语料,正面评论和负面评论各5000条,用BERT参数这么大的模型, 训练会产生严重过拟合,,泛化能力差的情况, 这也是我们下面需要解决的问题; 

2.sigmoid二分类

  回顾在BERT的训练中Next Sentence Prediction中, 我们取出[cls]对应的那一条向量, 然后把他映射成1个数值并用sigmoid函数激活:
y^=sigmoid(Linear(cls_vector))y^(0, 1)

3.动态学习率和提前终止(early stop)

  训练方式是,每个epoch,用训练集训练。对模型性能的衡量标准是AUC, AUC的衡量标准对二分类非常易用。当前epoch训练完毕之后, 用测试集衡量当前训练结果,并记下当前epochAUC, 如果当前的AUC较上一个epoch没有提升,那就降低学习率,实际操作是让当前的学习率降低1/5, 直到10epoch测试集的AUC都没有提升, 就终止训练。
  初始学习率是1e6, 因为我们是在维基百科预训练语料的基础上进行训练的, 属于下游任务,只需要微调预训练模型就好。

4.解决过拟合问题

  但在实际操作中, 使用y^=sigmoid(Linear(cls_vector))y^(0, 1)的方式, 发现虽然在训练集和测试集上AUC都很高, 但实际随便输入一些从各种网上随便找的一些酒店评论后, 发现泛化能力不好. 这是因为训练数据集非常小,即使区分训练集和测试集,但因为整体数据形态比较单一,模型遇到自己没见过的情况就很容易无法做出正确判断,为了提高模型的泛化性能,尝试了另一种模型结构:

 

(1)mean-max-pool

一种把隐藏层的序列转换为一条向量的方式,其实就是沿着sequence length 的维度分别求均值和max,之后拼起来成为一条向量,之后同样映射成一个值再激活。

Xhidden:[batch_size, seq_len, embedding_dim]
mean_pooled=mean(Xhidden, dimension=seq_len)[batch_size, embedding_dim]
max_pooled=max(Xhidden, dimension=seq_len)[batch_size, embedding_dim]
mean_max_pooled=concatenate(mean_pooled, max_pooled, dimension=embedding_dim)[batch_size, embedding_dim2]

  上式中mean_max_pooled 也就是我们得到的一句话的数学表达,含有这句话的信息, 其实这也是一种DOC2VEC的方法, 也就是把一句话转换成一条向量,而且无论这句话有多长,转换出来向量的维度都是一样的,之后可以用这些向量做一些分类聚类等任务。

下一步我们同样做映射, 之后用sigmoid激活:
y^=sigmoid(Linear(mean_max_pooled))y^(0, 1)
怎样理解这样的操作呢, 隐藏层就是一句话的数学表达, 我们求均值和最大值正数学表达对这句话的平均响应, 和最大响应, 之后我们用线性映射来识别这些响应, 从而得到模型的推断结果。

(2)weight decay权重衰减

  其实就是L2 normalization,在PyTorch里有接口可以直接调用, 其实L2正则的作用就是防止参数的值变得过大或过小,我们可以设想一下,由于我们的训练数据很少,所以实际使用模型进行推断的时候有些字和词或者句子结构的组合模型都是没见过的, 模型里面参数的值很大的话会造成遇到某一些特别的句子或者词语的时候, 模型对句子的响应过大, 导致最终输出的值偏离实际, 其实我们希望模型更从容淡定一些, 所以我们加入L2 normalization.

  除此之外, 我们预训练的BERT有6个transformer block, 我们在情感分析的时候,只用了3个,因为后面实在是参数太多,容易导致过拟合,所以在第三个transformer block之后,就截出隐藏层进行pooling了,后面的transformer block都没有用到。

(3)dropout

dropout设为了0.4,因为模型参数是在是太多,所以在训练的时候直接让40%的参数失能,防止过拟合。

  经过以上方法, 模型训练集和测试机的AUC都达到了0.95以上, 而且经过实际的测试, 模型也可以基本比较正确的分辨出语句的情感极性.

5.阈值微调

  经过模型的推断, 输出的值介于0到1之间, 我们可以认为只要这个值在0.5以上, 就是正样本, 如果在0.5以下, 就是副样本, 其实这是不一定的, 0.5通常不是最佳的分类边界, 所以我写了一个用来寻找最佳阈值的脚本, 在./metrics/\_\_init\_\_.py里面.
  这个脚本的方法是从0.01到0.99定义99个阈值, 高于阈值算正样本, 低于算副样本, 然后与测试集计算f1 score, 之后选出可以使f1 score最高的阈值, 在训练中, 每一个epoch都会运行一次寻找阈值的脚本.

 

 

 

 

 

参考文献:

【1】BERT实战(源码分析+踩坑) - 知乎

【2】ymcui / Chinese-PreTrained-XLNet:预培训的中文XLNet(中文XLNet预训练模型)

【3】汉语自然语言处理-BERT的解读语言模型预训练-实践应用-transformer模型(二)-语料预处理-情感分析分类-数据增强-解决过拟合问题-深度学习训练技巧_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili

【4】Self-Attention & Transformer - w55100的博客 - CSDN博客

【5】使用google的Bert获得中文的词向量 - u014553172的博客 - CSDN博客

【6】aespresso/a_journey_into_math_of_ml: 汉语自然语言处理视频教程-开源学习资料

posted @   nxf_rabbit75  阅读(2737)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
1.情感分析语料预处理2.sigmoid二分类3.动态学习率和提前终止(early stop) 4.解决过拟合问题(1)mean-max-pool(2)weight decay权重衰减(3)dropout5.阈值微调
点击右上角即可分享
微信分享提示