Spacy 的 BERT 模型不学习

Spacy's BERT model doesn't learn

我一直在尝试使用 spaCy 的预训练 BERT 模型 de_trf_bertbasecased_lg 来提高我的分类项目的准确性。我曾经使用 de_core_news_sm 从头开始​​构建模型,一切正常:我的准确率约为 70%。但现在我改用 BERT 预训练模型,准确率为 0%。我不相信它工作得这么糟糕,所以我假设我的代码只是有问题。我可能错过了一些重要的东西,但我不知道是什么。我以 this article 中的代码为例。

这是我的代码:

import spacy
from spacy.util import minibatch
from random import shuffle

spacy.require_gpu()
nlp = spacy.load('de_trf_bertbasecased_lg')

data = get_data()  # get_data() function returns a list with train data (I'll explain later how it looks)

textcat = nlp.create_pipe("trf_textcat", config={"exclusive_classes": False})

for category in categories:  # categories - a list of 21 different categories used for classification
    textcat.add_label(category)
nlp.add_pipe(textcat)

num = 0  # number used for counting batches
optimizer = nlp.resume_training()
for i in range(2):
    shuffle(data)
    losses = {}
    for batch in minibatch(data):
        texts, cats = zip(*batch)
        nlp.update(texts, cats, sgd=optimizer, losses=losses)
        num += 1

        if num % 10000 == 0:  # test model's performance every 10000 batches
            acc = test(nlp)  # function test() will be explained later
            print(f'Accuracy: {acc}')

nlp.to_disk('model/')

函数get_data()打开不同类别的文件,创建一个像这样的元组(text, {'cats' : {'category1': 0, 'category2':1, ...}}),将所有这些元组收集到一个数组中,然后返回给主函数。

函数 test(nlp) 打开包含测试数据的文件,预测文件中每一行的类别并检查预测是否正确。

同样,de_core_news_sm 一切正常,所以我很确定函数 get_data()test(nlp) 工作正常。上面的代码看起来像示例,但仍然有 0% accuracy.I 不明白我做错了什么。

在此先感谢您的帮助!

更新

为了理解上述问题,我决定只用几个例子来尝试这个模型(就像建议的那样 here)。这是代码:

import spacy
from spacy.util import minibatch
import random
import torch

train_data = [
    ("It is realy cool", {"cats": {"POSITIVE": 1.0, "NEGATIVE": 0.0}}),
    ("I hate it", {"cats": {"POSITIVE": 0.0, "NEGATIVE": 1.0}})
]

is_using_gpu = spacy.prefer_gpu()
if is_using_gpu:
    torch.set_default_tensor_type("torch.cuda.FloatTensor")

nlp = spacy.load("en_trf_bertbaseuncased_lg")
textcat = nlp.create_pipe("trf_textcat", config={"exclusive_classes": True})
for label in ("POSITIVE", "NEGATIVE"):
    textcat.add_label(label)
nlp.add_pipe(textcat)

optimizer = nlp.resume_training()
for i in range(10):
    random.shuffle(train_data)
    losses = {}
    for batch in minibatch(train_data):
        texts, cats = zip(*batch)
        nlp.update(texts, cats, sgd=optimizer, losses=losses)
    print(i, losses)
print()

test_data = [
    "It is really cool",
    "I hate it",
    "Great!",
    "I do not think this is cool"
]

for line in test_data:
    print(line)
    print(nlp(line).cats)

输出为:

0 {'trf_textcat': 0.125}
1 {'trf_textcat': 0.12423406541347504}
2 {'trf_textcat': 0.12188033014535904}
3 {'trf_textcat': 0.12363225221633911}
4 {'trf_textcat': 0.11996611207723618}
5 {'trf_textcat': 0.14696261286735535}
6 {'trf_textcat': 0.12320466339588165}
7 {'trf_textcat': 0.12096124142408371}
8 {'trf_textcat': 0.15916231274604797}
9 {'trf_textcat': 0.1238454058766365}

It is really cool
{'POSITIVE': 0.47827497124671936, 'NEGATIVE': 0.5217249989509583}
I hate it
{'POSITIVE': 0.47827598452568054, 'NEGATIVE': 0.5217240452766418}
Great!
{'POSITIVE': 0.4782750606536865, 'NEGATIVE': 0.5217249393463135}
I do not think this is cool
{'POSITIVE': 0.478275328874588, 'NEGATIVE': 0.5217246413230896}

不仅模型表现不好,损失也没有变小,所有测试句子的分数几乎相同。最重要的是:它甚至没有回答正确的问题,恰好在火车数据中。所以我的问题是:模型是否学习?我做错了什么?

有什么想法吗?

GitHub and it looks like there must be some optimizer parameters specified, just like in this example 上收到了我的问题的答案。