Это вторая часть другого вопроса, который я разместил. Однако они достаточно разные, чтобы представлять собой отдельные вопросы, но могут быть связаны.
Предыдущий вопрос Построение пользовательского распознавания именованных сущностей с помощью Spacy с использованием случайного текста в качестве образца
Я создал собственное распознавание именованных сущностей (NER), используя метод, описанный в предыдущем вопросе. Отсюда я просто скопировал метод построения NER с веб-сайта Spacy (в разделе «Распознавание именованных сущностей» на этом веб-сайте https://spacy.io/usage/training#ner)
настраиваемый NER работает, вроде как. Если я предложу токенизировать текст, лемматизировать слова (так, чтобы «клубника» превратилась в «клубнику»), он может подобрать сущность. Однако на этом все заканчивается. Иногда он улавливает две сущности, но очень редко.
Могу ли я что-нибудь сделать, чтобы повысить его точность?
Вот код (у меня TRAIN_DATA в этом формате, но для продуктов питания
TRAIN_DATA = [
("Uber blew through $1 million a week", {"entities": [(0, 4, "ORG")]}),
("Google rebrands its business apps", {"entities": [(0, 6, "ORG")]})]
)
Данные находятся в объекте train_food
import spacy
import nltk
nlp = spacy.blank("en")
#Create a built-in pipeline components and add them in the pipeline
if "ner" not in nlp.pipe_names:
ner = nlp.create_pipe("ner")
nlp.add_pipe(ner, last =True)
else:
ner =nlp.get_pipe("ner")
##Testing for food
for _, annotations in train_food:
for ent in annotations.get("entities"):
ner.add_label(ent[2])
# get names of other pipes to disable them during training
pipe_exceptions = ["ner", "trf_wordpiecer", "trf_tok2vec"]
other_pipes = [pipe for pipe in nlp.pipe_names if pipe not in pipe_exceptions]
model="en"
n_iter= 20
# only train NER
with nlp.disable_pipes(*other_pipes), warnings.catch_warnings():
# show warnings for misaligned entity spans once
warnings.filterwarnings("once", category=UserWarning, module='spacy')
# reset and initialize the weights randomly – but only if we're
# training a new model
nlp.begin_training()
for itn in range(n_iter):
random.shuffle(train_food)
losses = {}
# batch up the examples using spaCy's minibatch
batches = minibatch(train_food, size=compounding(4.0, 32.0, 1.001))
for batch in batches:
texts, annotations = zip(*batch)
nlp.update(
texts, # batch of texts
annotations, # batch of annotations
drop=0.5, # dropout - make it harder to memorise data
losses=losses,
)
print("Losses", losses)
text = "mike went to the supermarket today. he went and bought a potatoes, carrots, towels, garlic, soap, perfume, a fridge, a tomato, tomatoes and tuna."
После этого, используя текст в качестве образца, я запустил этот код
def text_processor(text):
text = text.lower()
token = nltk.word_tokenize(text)
ls = []
for x in token:
p = lemmatizer.lemmatize(x)
ls.append(f"{p}")
new_text = " ".join(map(str,ls))
return new_text
def ner (text):
new_text = text_processor(text)
tokenizer = nltk.PunktSentenceTokenizer()
sentences = tokenizer.tokenize(new_text)
for sentence in sentences:
doc = nlp(sentence)
for ent in doc.ents:
print(ent.text, ent.label_)
ner(text)
Результат in
potato FOOD
carrot FOOD
Выполнение следующего кода
ner("mike went to the supermarket today. he went and bought garlic and tuna")
Результаты в
garlic FOOD
В идеале я хочу, чтобы NER собирал картофель, морковь и гарли c. Что я могу сделать?
Спасибо
Ка