BERT多类别情感分析的准确性较低?

时间:2020-07-21 00:02:40

标签: machine-learning nlp sentiment-analysis bert-language-model ktrain

我正在研究一个小型数据集,

  • 包含1500条新闻文章。

  • 所有这些文章均按照人的情感/积极程度在5分制上进行了人类排名。

  • 根据拼写错误进行清洁。在导入分析之前,我使用了Google工作表来检查拼写。仍然有一些字符编码不正确,但数量不多。

  • 平均长度大于512个字。

  • 数据集不平衡。

我认为这是一个多类分类问题,我想用此数据集微调BERT。为了做到这一点,我使用了Ktrain软件包,并且基本上遵循了该教程。下面是我的代码:

(x_train, y_train), (x_test, y_test), preproc = text.texts_from_array(
                                                                    x_train=x_train, 
                                                                    y_train=y_train,
                                                                    x_test=x_test, 
                                                                    y_test=y_test,
                                                                    class_names=categories,
                                                                    preprocess_mode='bert',
                                                                    maxlen= 510,
                                                                    max_features=35000)

model = text.text_classifier('bert', train_data=(x_train, y_train), preproc=preproc)
learner = ktrain.get_learner(model, train_data=(x_train, y_train), batch_size=6)
learner.fit_onecycle(2e-5, 4)

但是,我只能得到25%左右的验证精度,这太低了。

          precision-recall f1-score support

   1       0.33      0.40      0.36        75
   2       0.27      0.36      0.31        84
   3       0.23      0.24      0.23        58
   4       0.18      0.09      0.12        54
   5       0.33      0.04      0.07        24
accuracy                               0.27       295
macro avg          0.27      0.23      0.22       295
weighted avg       0.26      0.27      0.25       295

由于有些文章很长,所以我也尝试了头尾截断策略,但是,性能保持不变。

有人可以给我一些建议吗?

非常感谢您!

最佳

==================更新7.21 ================

按照Kartikey的建议,我尝试了find_lr。结果如下。看来2e ^ -5是一个合理的学习率。

simulating training for different learning rates... this may take a few 
moments...
Train on 1182 samples
Epoch 1/2
1182/1182 [==============================] - 223s 188ms/sample - loss: 1.6878 
- accuracy: 0.2487
Epoch 2/2
432/1182 [=========>....................] - ETA: 2:12 - loss: 3.4780 - 
accuracy: 0.2639
done.
Visually inspect loss plot and select learning rate associated with falling 
loss

learning rate.jpg

我只是尝试以一些权重运行它:

{0: 0,
 1: 0.8294736842105264,
 2: 0.6715909090909091,
 3: 1.0844036697247708,
 4: 1.1311004784688996,
 5: 2.0033898305084747}

这是结果。变化不大。

          precision    recall  f1-score   support

       1       0.43      0.27      0.33        88
       2       0.22      0.46      0.30        69
       3       0.19      0.09      0.13        64
       4       0.13      0.13      0.13        47
       5       0.16      0.11      0.13        28

accuracy                            0.24       296
macro avg       0.23      0.21      0.20       296
weighted avg    0.26      0.24      0.23       296

array([[24, 41,  9,  8,  6],
       [13, 32,  6, 12,  6],
       [ 9, 33,  6, 14,  2],
       [ 4, 25, 10,  6,  2],
       [ 6, 14,  0,  5,  3]])

==============更新7.22 ============

为了获得一些基线结果,我将5分制的分类问题分解为二进制的分类,这只是为了预测阳性或阴性。这次,准确性提高到55%左右。以下是我的策略的详细说明:

training data: 956 samples (excluding those classified as neutural)
truncation strategy: use the first 128 and last 128 tokens
(x_train,  y_train), (x_test, y_test), preproc_l1 = 
                     text.texts_from_array(x_train=x_train, y_train=y_train,    
                     x_test=x_test, y_test=y_test                      
                     class_names=categories_1,                      
                     preprocess_mode='bert',                                                          
                     maxlen=  256,                                                                  
                     max_features=35000)
Results:
              precision    recall  f1-score   support

       1       0.65      0.80      0.72       151
       2       0.45      0.28      0.35        89

accuracy                               0.61       240
macro avg          0.55      0.54      0.53       240
weighted avg       0.58      0.61      0.58       240

array([[121,  30],
       [ 64,  25]])

但是,我认为55%的准确率仍然不能令人满意,比随机猜测要好一些。

============更新7.26 ============

根据Marcos Lima的建议,我在程序中增加了几个步骤:

  1. 在通过Ktrain pkg进行预处理之前,删除所有数字,标点和多余的空格。 (我以为Ktrain pkg会帮我做到这一点,但不确定)

  2. 我使用示例中任何文本的前384个令牌和后128个令牌。这就是我所说的“头+尾”策略。

  3. 任务仍然是二进制分类(正数与负数)

这是学习曲线图。它与我之前发布的相同。而且看起来与马科斯·利马(Marcos Lima)发表的那本书完全不同:

The updated learning curve

下面是我的结果,可能是我得到的最好的结果。

begin training using onecycle policy with max lr of 1e-05...
Train on 1405 samples
Epoch 1/4
1405/1405 [==============================] - 186s 133ms/sample - loss: 0.7220 
- accuracy: 0.5431
Epoch 2/4
1405/1405 [==============================] - 167s 119ms/sample - loss: 0.6866 
- accuracy: 0.5843
Epoch 3/4
1405/1405 [==============================] - 166s 118ms/sample - loss: 0.6565 
- accuracy: 0.6335
Epoch 4/4
1405/1405 [==============================] - 166s 118ms/sample - loss: 0.5321 
- accuracy: 0.7587

             precision    recall  f1-score   support

       1       0.77      0.69      0.73       241
       2       0.46      0.56      0.50       111

accuracy                           0.65       352
macro avg       0.61      0.63      0.62       352
weighted avg       0.67      0.65      0.66       352

array([[167,  74],
       [ 49,  62]])

注意:我认为pkg很难很好地完成我的任务的原因可能是该任务就像分类和情感分析的结合。新闻文章的经典分类任务是对新闻所属的类别进行分类,例如,生物学,经济学,体育。不同类别中使用的词非常不同。另一方面,对情绪进行分类的经典示例是分析Yelp或IMDB评论。我的猜测是,这些文本在表达情感时非常简单,而在我的样本《经济新闻》中,这些文本在出版之前就经过了精心整理和井井有条,因此,该情感可能总是以某种隐性方式出现,而BERT可能无法检测到。

3 个答案:

答案 0 :(得分:1)

尝试超参数优化。

在进行learner.fit_onecycle(2e-5, 4)之前。试试:learner.lr_find(show_plot=True, max_epochs=2)

所有班级的体重都在20%左右吗? 也许尝试以下这种方式:

MODEL_NAME = 'bert'
t = text.Transformer(MODEL_NAME, maxlen=500, class_names=train_b.target_names)

.....
.....

# the one we got most wrong
learner.view_top_losses(n=1, preproc=t)

对于上述班级,增加体重。

验证集是分层抽样还是随机抽样?

答案 1 :(得分:1)

学习曲线的形式不是预期的。

LR curve for a similar problem 我的曲线(上方)表明TR应该在1e-5左右,但是您的TR是平坦的。

尝试预处理您的数据:

  • 删除数字和表情符号。
  • 重新检查数据中是否有错误(通常在y_train中)。
  • 如果您的语言不是英语,请使用您的语言模型或多语言。

您说的是

平均长度大于512个字。

请尝试以512个令牌长的方式破坏每个文本,因为当BERT模型将其截断时,您可能会丢失很多分类信息。

答案 2 :(得分:0)

尝试将问题视为文本回归任务,例如this Yelp sentiment model,该任务是使用 ktrain 训练的。